/**
   * Handle Verbose Trouble Status events for the EyezOn Envisalink 3/2DS DSC Alarm Interface.
   *
   * @param event
   */
  private void verboseTroubleStatusHandler(EventObject event) {
    DSCAlarmEvent dscAlarmEvent = (DSCAlarmEvent) event;
    DSCAlarmMessage dscAlarmMessage = dscAlarmEvent.getDSCAlarmMessage();
    String[] channelTypes = {
      PANEL_SERVICE_REQUIRED,
      PANEL_AC_TROUBLE,
      PANEL_TELEPHONE_TROUBLE,
      PANEL_FTC_TROUBLE,
      PANEL_ZONE_FAULT,
      PANEL_ZONE_TAMPER,
      PANEL_ZONE_LOW_BATTERY,
      PANEL_TIME_LOSS
    };

    String channel;
    ChannelUID channelUID = null;

    int bitField =
        Integer.decode("0x" + dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA));
    int[] masks = {1, 2, 4, 8, 16, 32, 64, 128};
    int[] bits = new int[8];

    for (int i = 0; i < 8; i++) {
      bits[i] = bitField & masks[i];

      channel = channelTypes[i];

      if (channel != "") {
        channelUID = new ChannelUID(getThing().getUID(), channel);
        updateProperties(channelUID, bits[i] != 0 ? 1 : 0, "");
        updateChannel(channelUID);
      }
    }
  }
  /**
   * Handle Keypad LED events for the EyezOn Envisalink 3/2DS DSC Alarm Interface
   *
   * @param event
   */
  private void keypadLEDStateEventHandler(EventObject event) {
    DSCAlarmEvent dscAlarmEvent = (DSCAlarmEvent) event;
    DSCAlarmMessage apiMessage = dscAlarmEvent.getDSCAlarmMessage();
    String[] channelTypes = {
      KEYPAD_READY_LED,
      KEYPAD_ARMED_LED,
      KEYPAD_MEMORY_LED,
      KEYPAD_BYPASS_LED,
      KEYPAD_TROUBLE_LED,
      KEYPAD_PROGRAM_LED,
      KEYPAD_FIRE_LED,
      KEYPAD_BACKLIGHT_LED
    };

    String channel;
    ChannelUID channelUID = null;
    DSCAlarmCode apiCode =
        DSCAlarmCode.getDSCAlarmCodeValue(apiMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));

    int bitField = Integer.decode("0x" + apiMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA));
    int[] masks = {1, 2, 4, 8, 16, 32, 64, 128};
    int[] bits = new int[8];

    for (int i = 0; i < 8; i++) {
      bits[i] = bitField & masks[i];

      channel = channelTypes[i];

      if (channel != "") {

        channelUID = new ChannelUID(getThing().getUID(), channel);

        switch (apiCode) {
          case KeypadLEDState: /* 510 */
            updateProperties(channelUID, bits[i] != 0 ? 1 : 0, "");
            break;
          case KeypadLEDFlashState: /* 511 */
            if (bits[i] != 0) {
              updateProperties(channelUID, 2, "");
            }
            break;
          default:
            break;
        }

        updateChannel(channelUID);
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public void dscAlarmEventReceived(EventObject event, Thing thing) {

    if (thing != null) {
      if (getThing() == thing) {
        DSCAlarmEvent dscAlarmEvent = (DSCAlarmEvent) event;
        DSCAlarmMessage apiMessage = dscAlarmEvent.getDSCAlarmMessage();

        ChannelUID channelUID = null;
        DSCAlarmCode apiCode =
            DSCAlarmCode.getDSCAlarmCodeValue(
                apiMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));
        String apiData = apiMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA);

        logger.debug("dscAlarmEventRecieved(): Thing - {}   Command - {}", thing.getUID(), apiCode);

        switch (apiCode) {
          case KeypadLEDState: /* 510 */
          case KeypadLEDFlashState: /* 511 */
            keypadLEDStateEventHandler(event);
            break;
          case LEDStatus: /* 903 */
            int aData = Integer.parseInt(apiData.substring(0, 1));
            int state =
                Integer.parseInt(
                    apiMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA).substring(1));
            switch (aData) {
              case 1:
                channelUID = new ChannelUID(getThing().getUID(), KEYPAD_READY_LED);
                properties.setLEDState(LEDStateType.READY_LED_STATE, state);
                updateChannel(channelUID);
                break;
              case 2:
                channelUID = new ChannelUID(getThing().getUID(), KEYPAD_ARMED_LED);
                properties.setLEDState(LEDStateType.ARMED_LED_STATE, state);
                updateChannel(channelUID);
                break;
              case 3:
                channelUID = new ChannelUID(getThing().getUID(), KEYPAD_MEMORY_LED);
                properties.setLEDState(LEDStateType.MEMORY_LED_STATE, state);
                updateChannel(channelUID);
                break;
              case 4:
                channelUID = new ChannelUID(getThing().getUID(), KEYPAD_BYPASS_LED);
                properties.setLEDState(LEDStateType.BYPASS_LED_STATE, state);
                updateChannel(channelUID);
                break;
              case 5:
                channelUID = new ChannelUID(getThing().getUID(), KEYPAD_TROUBLE_LED);
                properties.setLEDState(LEDStateType.TROUBLE_LED_STATE, state);
                updateChannel(channelUID);
                break;
              case 6:
                channelUID = new ChannelUID(getThing().getUID(), KEYPAD_PROGRAM_LED);
                properties.setLEDState(LEDStateType.PROGRAM_LED_STATE, state);
                updateChannel(channelUID);
                break;
              case 7:
                channelUID = new ChannelUID(getThing().getUID(), KEYPAD_FIRE_LED);
                properties.setLEDState(LEDStateType.FIRE_LED_STATE, state);
                updateChannel(channelUID);
                break;
              case 8:
                channelUID = new ChannelUID(getThing().getUID(), KEYPAD_BACKLIGHT_LED);
                properties.setLEDState(LEDStateType.BACKLIGHT_LED_STATE, state);
                updateChannel(channelUID);
                break;
              case 9:
                channelUID = new ChannelUID(getThing().getUID(), KEYPAD_AC_LED);
                properties.setLEDState(LEDStateType.AC_LED_STATE, state);
                updateChannel(channelUID);
                break;
              default:
                break;
            }
          default:
            break;
        }
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public void dscAlarmEventReceived(EventObject event, Thing thing) {

    if (thing != null) {
      DSCAlarmEvent dscAlarmEvent = (DSCAlarmEvent) event;
      DSCAlarmMessage dscAlarmMessage = dscAlarmEvent.getDSCAlarmMessage();
      setTimeStampState(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.TIME_STAMP));
      boolean suppressPanelMsg = false;

      if (getThing() == thing) {
        ChannelUID channelUID = null;
        DSCAlarmCode apiCode =
            DSCAlarmCode.getDSCAlarmCodeValue(
                dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));
        logger.debug("dscAlarmEventRecieved(): Thing - {}   Command - {}", thing.getUID(), apiCode);

        int state = 0;

        switch (apiCode) {
          case CommandAcknowledge: /* 500 */
            if (getSuppressAcknowledgementMsgs()) {
              suppressPanelMsg = true;
            }
            break;
          case SystemError: /* 502 */
            panelSystemError(dscAlarmMessage);
            break;
          case TimeDateBroadcast: /* 550 */
            channelUID = new ChannelUID(getThing().getUID(), PANEL_TIME);
            String panelTime = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA);
            updateProperties(channelUID, state, panelTime);
            updateChannel(channelUID);

            channelUID = new ChannelUID(getThing().getUID(), PANEL_TIME_BROADCAST);
            updateProperties(channelUID, 1, "");
            updateChannel(channelUID);

            if (getSuppressAcknowledgementMsgs()) {
              suppressPanelMsg = true;
            }

            break;
          case FireKeyAlarm: /* 621 */
            state = 1;
          case FireKeyRestored: /* 622 */
            channelUID = new ChannelUID(getThing().getUID(), PANEL_FIRE_KEY_ALARM);
            updateProperties(channelUID, state, "");
            updateChannel(channelUID);
            break;
          case AuxiliaryKeyAlarm: /* 623 */
            state = 1;
          case AuxiliaryKeyRestored: /* 624 */
            channelUID = new ChannelUID(getThing().getUID(), PANEL_AUX_KEY_ALARM);
            updateProperties(channelUID, state, "");
            updateChannel(channelUID);
            break;
          case PanicKeyAlarm: /* 625 */
            state = 1;
          case PanicKeyRestored: /* 626 */
            channelUID = new ChannelUID(getThing().getUID(), PANEL_PANIC_KEY_ALARM);
            updateProperties(channelUID, state, "");
            updateChannel(channelUID);
            break;
          case AuxiliaryInputAlarm: /* 631 */
            state = 1;
          case AuxiliaryInputAlarmRestored: /* 632 */
            channelUID = new ChannelUID(getThing().getUID(), PANEL_AUX_INPUT_ALARM);
            updateProperties(channelUID, state, "");
            updateChannel(channelUID);
            break;
          case TroubleLEDOn: /* 840 */
            channelUID = new ChannelUID(getThing().getUID(), PANEL_TROUBLE_LED);
            updateProperties(channelUID, 1, "");
            updateChannel(channelUID);
            break;
          case TroubleLEDOff: /* 841 */
            channelUID = new ChannelUID(getThing().getUID(), PANEL_SERVICE_REQUIRED);
            updateProperties(channelUID, 0, "");
            updateChannel(channelUID);

            channelUID = new ChannelUID(getThing().getUID(), PANEL_AC_TROUBLE);
            updateProperties(channelUID, 0, "");
            updateChannel(channelUID);

            channelUID = new ChannelUID(getThing().getUID(), PANEL_TELEPHONE_TROUBLE);
            updateProperties(channelUID, 0, "");
            updateChannel(channelUID);

            channelUID = new ChannelUID(getThing().getUID(), PANEL_FTC_TROUBLE);
            updateProperties(channelUID, 0, "");
            updateChannel(channelUID);

            channelUID = new ChannelUID(getThing().getUID(), PANEL_ZONE_FAULT);
            updateProperties(channelUID, 0, "");
            updateChannel(channelUID);

            channelUID = new ChannelUID(getThing().getUID(), PANEL_ZONE_TAMPER);
            updateProperties(channelUID, 0, "");
            updateChannel(channelUID);

            channelUID = new ChannelUID(getThing().getUID(), PANEL_ZONE_LOW_BATTERY);
            updateProperties(channelUID, 0, "");
            updateChannel(channelUID);

            channelUID = new ChannelUID(getThing().getUID(), PANEL_TIME_LOSS);
            updateProperties(channelUID, 0, "");
            updateChannel(channelUID);

            channelUID = new ChannelUID(getThing().getUID(), PANEL_TROUBLE_LED);
            updateProperties(channelUID, 0, "");
            updateChannel(channelUID);
            break;
          case PanelBatteryTrouble: /* 800 */
          case PanelACTrouble: /* 802 */
          case SystemBellTrouble: /* 806 */
          case TLMLine1Trouble: /* 810 */
          case TLMLine2Trouble: /* 812 */
          case FTCTrouble: /* 814 */
          case GeneralDeviceLowBattery: /* 821 */
          case WirelessKeyLowBatteryTrouble: /* 825 */
          case HandheldKeypadLowBatteryTrouble: /* 827 */
          case GeneralSystemTamper: /* 829 */
          case HomeAutomationTrouble: /* 831 */
          case KeybusFault: /* 896 */
            channelUID = new ChannelUID(getThing().getUID(), PANEL_TROUBLE_MESSAGE);
            updateProperties(
                channelUID, 0, dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DESCRIPTION));
            updateChannel(channelUID);
            break;
          case PanelBatteryTroubleRestore: /* 801 */
          case PanelACRestore: /* 803 */
          case SystemBellTroubleRestore: /* 807 */
          case TLMLine1TroubleRestore: /* 811 */
          case TLMLine2TroubleRestore: /* 813 */
          case GeneralDeviceLowBatteryRestore: /* 822 */
          case WirelessKeyLowBatteryTroubleRestore: /* 826 */
          case HandheldKeypadLowBatteryTroubleRestore: /* 828 */
          case GeneralSystemTamperRestore: /* 830 */
          case HomeAutomationTroubleRestore: /* 832 */
          case KeybusFaultRestore: /* 897 */
            channelUID = new ChannelUID(getThing().getUID(), PANEL_TROUBLE_MESSAGE);
            updateProperties(channelUID, 0, "");
            updateChannel(channelUID);
            break;
          case VerboseTroubleStatus: /* 849 */
            verboseTroubleStatusHandler(event);
            break;
          case CodeRequired: /* 900 */
            dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.CodeSend, getUserCode());
            break;
          default:
            break;
        }
      }

      if (!suppressPanelMsg) {
        setPanelMessage(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DESCRIPTION));
      }
    }
  }