added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.dscalarm-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-dscalarm" description="DSCAlarm Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-serial</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.dscalarm/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The DSCAlarmBinding class defines common constants, which are used across the whole binding.
|
||||
*
|
||||
* @author Russell Stephens - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DSCAlarmBindingConstants {
|
||||
|
||||
// Binding ID
|
||||
public static final String BINDING_ID = "dscalarm";
|
||||
|
||||
// List of bridge device types
|
||||
public static final String ENVISALINK_BRIDGE = "envisalink";
|
||||
public static final String IT100_BRIDGE = "it100";
|
||||
public static final String TCPSERVER_BRIDGE = "tcpserver";
|
||||
|
||||
// List of DSC Alarm device types
|
||||
public static final String PANEL = "panel";
|
||||
public static final String PARTITION = "partition";
|
||||
public static final String ZONE = "zone";
|
||||
public static final String KEYPAD = "keypad";
|
||||
|
||||
// List of all Bridge Thing Type UIDs
|
||||
public static final ThingTypeUID ENVISALINKBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, ENVISALINK_BRIDGE);
|
||||
public static final ThingTypeUID IT100BRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, IT100_BRIDGE);
|
||||
public static final ThingTypeUID TCPSERVERBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, TCPSERVER_BRIDGE);
|
||||
|
||||
// List of all DSC Alarm Thing Type UIDs
|
||||
public static final ThingTypeUID PANEL_THING_TYPE = new ThingTypeUID(BINDING_ID, PANEL);
|
||||
public static final ThingTypeUID PARTITION_THING_TYPE = new ThingTypeUID(BINDING_ID, PARTITION);
|
||||
public static final ThingTypeUID ZONE_THING_TYPE = new ThingTypeUID(BINDING_ID, ZONE);
|
||||
public static final ThingTypeUID KEYPAD_THING_TYPE = new ThingTypeUID(BINDING_ID, KEYPAD);
|
||||
|
||||
// List of all Channel IDs
|
||||
public static final String BRIDGE_RESET = "bridge_reset";
|
||||
public static final String SEND_COMMAND = "send_command";
|
||||
|
||||
public static final String PANEL_MESSAGE = "panel_message";
|
||||
public static final String PANEL_COMMAND = "panel_command";
|
||||
public static final String PANEL_SYSTEM_ERROR = "panel_system_error";
|
||||
|
||||
public static final String PANEL_TROUBLE_MESSAGE = "panel_trouble_message";
|
||||
public static final String PANEL_TROUBLE_LED = "panel_trouble_led";
|
||||
public static final String PANEL_SERVICE_REQUIRED = "panel_service_required";
|
||||
public static final String PANEL_AC_TROUBLE = "panel_ac_trouble";
|
||||
public static final String PANEL_TELEPHONE_TROUBLE = "panel_telephone_trouble";
|
||||
public static final String PANEL_FTC_TROUBLE = "panel_ftc_trouble";
|
||||
public static final String PANEL_ZONE_FAULT = "panel_zone_fault";
|
||||
public static final String PANEL_ZONE_TAMPER = "panel_zone_tamper";
|
||||
public static final String PANEL_ZONE_LOW_BATTERY = "panel_zone_low_battery";
|
||||
public static final String PANEL_TIME_LOSS = "panel_time_loss";
|
||||
|
||||
public static final String PANEL_TIME = "panel_time";
|
||||
public static final String PANEL_TIME_STAMP = "panel_time_stamp";
|
||||
public static final String PANEL_TIME_BROADCAST = "panel_time_broadcast";
|
||||
public static final String PANEL_FIRE_KEY_ALARM = "panel_fire_key_alarm";
|
||||
public static final String PANEL_PANIC_KEY_ALARM = "panel_panic_key_alarm";
|
||||
public static final String PANEL_AUX_KEY_ALARM = "panel_aux_key_alarm";
|
||||
public static final String PANEL_AUX_INPUT_ALARM = "panel_aux_input_alarm";
|
||||
|
||||
public static final String PARTITION_STATUS = "partition_status";
|
||||
public static final String PARTITION_ARM_MODE = "partition_arm_mode";
|
||||
public static final String PARTITION_ARMED = "partition_armed";
|
||||
public static final String PARTITION_ENTRY_DELAY = "partition_entry_delay";
|
||||
public static final String PARTITION_EXIT_DELAY = "partition_exit_delay";
|
||||
public static final String PARTITION_IN_ALARM = "partition_in_alarm";
|
||||
public static final String PARTITION_OPENING_CLOSING_MODE = "partition_opening_closing_mode";
|
||||
|
||||
public static final String ZONE_STATUS = "zone_status";
|
||||
public static final String ZONE_MESSAGE = "zone_message";
|
||||
public static final String ZONE_BYPASS_MODE = "zone_bypass_mode";
|
||||
public static final String ZONE_IN_ALARM = "zone_in_alarm";
|
||||
public static final String ZONE_TAMPER = "zone_tamper";
|
||||
public static final String ZONE_FAULT = "zone_fault";
|
||||
public static final String ZONE_TRIPPED = "zone_tripped";
|
||||
|
||||
public static final String KEYPAD_READY_LED = "keypad_ready_led";
|
||||
public static final String KEYPAD_ARMED_LED = "keypad_armed_led";
|
||||
public static final String KEYPAD_MEMORY_LED = "keypad_memory_led";
|
||||
public static final String KEYPAD_BYPASS_LED = "keypad_bypass_led";
|
||||
public static final String KEYPAD_TROUBLE_LED = "keypad_trouble_led";
|
||||
public static final String KEYPAD_PROGRAM_LED = "keypad_program_led";
|
||||
public static final String KEYPAD_FIRE_LED = "keypad_fire_led";
|
||||
public static final String KEYPAD_BACKLIGHT_LED = "keypad_backlight_led";
|
||||
public static final String KEYPAD_AC_LED = "keypad_ac_led";
|
||||
public static final String KEYPAD_LCD_UPDATE = "keypad_lcd_update";
|
||||
public static final String KEYPAD_LCD_CURSOR = "keypad_lcd_cursor";
|
||||
|
||||
// Set of all supported Thing Type UIDs
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream
|
||||
.of(ENVISALINKBRIDGE_THING_TYPE, IT100BRIDGE_THING_TYPE, TCPSERVERBRIDGE_THING_TYPE,
|
||||
PANEL_THING_TYPE, PARTITION_THING_TYPE, ZONE_THING_TYPE, KEYPAD_THING_TYPE)
|
||||
.collect(Collectors.toSet()));
|
||||
|
||||
// Set of all supported Bridge Type UIDs
|
||||
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(ENVISALINKBRIDGE_THING_TYPE, IT100BRIDGE_THING_TYPE, TCPSERVERBRIDGE_THING_TYPE)
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Enumerator for DSCAlarm Command and Message Codes.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public enum DSCAlarmCode {
|
||||
// Command Codes
|
||||
Poll("000", "Poll", "000: The poll command."),
|
||||
StatusReport("001", "Status Report", "001: Request a status report command."),
|
||||
LabelsRequest("002", "Labels Request", "002: IT-100 labels request command."),
|
||||
NetworkLogin("005", "Network Login", "005: Envisalink login command."),
|
||||
DumpZoneTimers("008", "Dump Zone Timers", "008: Dump the internal Envisalink Zone Timers command."),
|
||||
SetTimeDate("010", "Set Time and Date", "010: Set the time and date command."),
|
||||
CommandOutputControl("020", "Command Output Control", "020: Activate the selected Command Output command."),
|
||||
PartitionArmControlAway("030", "Partition Arm Control - Away", "030: Arm the partition in AWAY mode."),
|
||||
PartitionArmControlStay("031", "Partition Arm Control - Stay", "031: Arm the partition in STAY mode."),
|
||||
PartitionArmControlZeroEntryDelay("032", "Partition Arm Control - Zero Entry Delay",
|
||||
"032: Arm the partition with zero entry delay."),
|
||||
PartitionArmControlWithUserCode("033", "Partition Arm Control - With User Code",
|
||||
"033: Arm the partition with user code."),
|
||||
PartitionDisarmControl("040", "Partition Disarm Control", "040: Disarm the partition with user code."),
|
||||
TimeStampControl("055", "Time Stamp Control", "055: Prepend all messages with a timestamp."),
|
||||
TimeDateBroadcastControl("056", "Time/Date Broadcast Control",
|
||||
"056: Periodically transmit system time broadcasts."),
|
||||
TemperatureBroadcastControl("057", "Temperature Broadcast Control",
|
||||
"057: Periodically transmit the interior and exterior temperatures."),
|
||||
VirtualKeypadControl("058", "Virtual Keypad Control", "058: Enable/Disable the virtual keypad command."),
|
||||
TriggerPanicAlarm("060", "Trigger Panic Alarm",
|
||||
"060: Emulates the FAP (Fire, Ambulance, Police) panic keys on a DSC keypad."),
|
||||
KeyStroke("070", "Key Stroke", "070: Send a single keystroke on Partition 1 only."),
|
||||
KeySequence("071", "Key Stroke Sequence", "071: Send a keystroke string."),
|
||||
EnterUserCodeProgramming("072", "Enter User Code Programming",
|
||||
"072: Cause the partition to enter user code (*5) programming."),
|
||||
EnterUserProgramming("073", "Enter User Programming",
|
||||
"073: Cause the partition to enter user code (*6) programming."),
|
||||
KeepAlive("074", "Keep Alive", "074: Reset the time-out timer on the panel."),
|
||||
BaudRateChange("080", "Baud Rate Change", "080: Change the baud rate on the IT-100."),
|
||||
GetTemperatureSetPoint("095", "Get Temperature Set Points", "095: Request the thermostat temperature set points."),
|
||||
TemperatureChange("096", "Temperature Change", "096: Change the thermostat temperature."),
|
||||
SaveTemperatureSetting("097", "Save Temperature Setting", "097: Save the thermostat temperature."),
|
||||
CodeSend("200", "Code Send", "200: Send a user code."),
|
||||
|
||||
// Message Codes
|
||||
CommandAcknowledge("500", "Command Acknowledge", "500: A command has been received successfully."),
|
||||
CommandError("501", "Command Error", "501: A command has been received with a bad checksum."),
|
||||
SystemError("502", "System Error", "502: An error has been detected."),
|
||||
LoginResponse("505", "Login Interaction",
|
||||
"505: Login response (failed=0, success=1, time out=2, password request=3)."),
|
||||
KeypadLEDState("510", "Keypad LED State - Partition 1 Only",
|
||||
"510: A change of state in the Partition 1 keypad LEDs."),
|
||||
KeypadLEDFlashState("511", "Keypad LED Flash State - Partition 1 Only",
|
||||
"511: A change of state in the Partition 1 keypad LEDs as to whether to flash or not."),
|
||||
TimeDateBroadcast("550", "Time-Date Broadcast", "550: The current security system time."),
|
||||
RingDetected("560", "Ring Detected", "560: A ring on the telephone line."),
|
||||
IndoorTemperatureBroadcast("561", "Indoor Temperature Broadcast",
|
||||
"561: The interior temperature and the thermostat number."),
|
||||
OutdoorTemperatureBroadcast("562", "Outdoor Temperature Broadcast",
|
||||
"562: The exterior temperature and the thermostat number."),
|
||||
ThermostatSetPoints("563", "Thermostat Set Points",
|
||||
"563: Cooling and heating set points and the thermostat number."),
|
||||
BroadcastLabels("570", "Broadcast Labels", "570: Labels stored in the DSC Alarm."),
|
||||
BaudRateSet("580", "Baud Rate Set", "580: Baud Rate of the serial interface."),
|
||||
|
||||
ZoneAlarm("601", "Zone Alarm", "601: A zone has gone into alarm."),
|
||||
ZoneAlarmRestore("602", "Zone Alarm Restore", "602: A zone alarm has been restored."),
|
||||
ZoneTamper("603", "Zone Tamper", "603: A zone has a tamper condition."),
|
||||
ZoneTamperRestore("604", "Zone Tamper Restored", "604: A zone tamper condition has been restored."),
|
||||
ZoneFault("605", "Zone Fault", "605: A zone has a fault condition."),
|
||||
ZoneFaultRestore("606", "Zone Fault Restored", "606: A zone fault condition has been restored."),
|
||||
ZoneOpen("609", "Zone Open", "609: General status of the zone - open."),
|
||||
ZoneRestored("610", "Zone Restored", "610: General status of the zone - restored."),
|
||||
EnvisalinkZoneTimerDump("615", "Envisalink Zone Timer Dump",
|
||||
"615: The raw zone timers used inside the Envisalink."),
|
||||
DuressAlarm("620", "Duress Alarm", "620: A duress code has been entered on a system keypad."),
|
||||
FireKeyAlarm("621", "Fire Key Alarm", "621: A Fire key alarm has been activated."),
|
||||
FireKeyRestored("622", "Fire Key Alarm Restore", "622: A Fire key alarm has been restored."),
|
||||
AuxiliaryKeyAlarm("623", "Auxiliary Key Alarm", "623: An Auxiliary key alarm has been activated."),
|
||||
AuxiliaryKeyRestored("624", "Auxiliary Key Alarm Restore", "624: An Auxiliary key alarm has been restored."),
|
||||
PanicKeyAlarm("625", "Panic Key Alarm", "625: A Panic key alarm has been activated."),
|
||||
PanicKeyRestored("626", "Panic Key Alarm Restore", "626: A Panic key alarm has been restored."),
|
||||
AuxiliaryInputAlarm("631", "2-Wire Smoke/Aux Alarm", "631: A 2-wire smoke/Auxiliary alarm has been activated."),
|
||||
AuxiliaryInputAlarmRestored("632", "2-Wire Smoke/Aux Alarm Restore",
|
||||
"632: A 2-wire smoke/Auxiliary alarm has been restored."),
|
||||
PartitionReady("650", "Partition Ready", "650: Partition can now be armed."),
|
||||
PartitionNotReady("651", "Partition Not Ready", "651: Partition can not be armed."),
|
||||
PartitionArmed("652", "Partition Armed", "652: Partition has been armed."),
|
||||
PartitionReadyForceArming("653", "Partition Ready - Force Arming Enabled",
|
||||
"653: Partition can now be armed (Force Arming Enabled)."),
|
||||
PartitionInAlarm("654", "Partition In Alarm", "654: A partition is in alarm."),
|
||||
PartitionDisarmed("655", "Partition Disarmed", "655: A partition has been disarmed."),
|
||||
ExitDelayInProgress("656", "Exit Delay in Progress", "656: A partition is in Exit Delay."),
|
||||
EntryDelayInProgress("657", "Entry Delay in Progress", "657: A partition is in Entry Delay."),
|
||||
KeypadLockout("658", "Keypad Lock-out", "658: A partition is in Keypad Lockout."),
|
||||
PartitionFailedToArm("659", "Partition Failed to Arm", "659: An attempt to arm the partition has failed."),
|
||||
PGMOutputInProgress("660", "PGM Output is in Progress", "660: *71, *72, *73, or *74 has been pressed."),
|
||||
ChimeEnabled("663", "Chime Enabled", "663: The door chime feature has been enabled."),
|
||||
ChimeDisabled("664", "Chime Disabled", "664: The door chime feature has been disabled."),
|
||||
InvalidAccessCode("670", "Invalid Access Code", "670: An access code that was entered was invalid."),
|
||||
FunctionNotAvailable("671", "Function Not Available", "671: A function that was selected is not available."),
|
||||
FailureToArm("672", "Failure to Arm", "672: An attempt was made to arm the partition and it failed."),
|
||||
PartitionBusy("673", "Partition is Busy", "673: The partition is busy."),
|
||||
SystemArmingInProgress("674", "System Arming in Progress",
|
||||
"674: This system is auto-arming and is in arm warning delay."),
|
||||
SystemInInstallerMode("680", "System in Installers Mode", "680: The whole system is in installers mode."),
|
||||
|
||||
UserClosing("700", "User Closing", "700: A partition has been armed by a user."),
|
||||
SpecialClosing("701", "Special Closing",
|
||||
"701: A partition has been armed by one of the following methods: Quick Arm, Auto Arm, Keyswitch, DLS software, Wireless Key."),
|
||||
PartialClosing("702", "Partial Closing",
|
||||
"702: A partition has been armed but one or more zones have been bypassed."),
|
||||
UserOpening("750", "User Opening", "750: A partition has been disarmed by a user."),
|
||||
SpecialOpening("751", "Special Opening",
|
||||
"751: A partition has been disarmed by one of the following methods: Quick Arm, Auto Arm, Keyswitch, DLS software, Wireless Key."),
|
||||
|
||||
PanelBatteryTrouble("800", "Panel Battery Trouble", "800: The panel has a low battery."),
|
||||
PanelBatteryTroubleRestore("801", "Panel Battery Trouble Restore",
|
||||
"801: The panel low battery trouble has been restored."),
|
||||
PanelACTrouble("802", "Panel AC Trouble", "802: AC power to the panel has been removed."),
|
||||
PanelACRestore("803", "Panel AC Restore", "803: AC power to the panel has been restored."),
|
||||
SystemBellTrouble("806", "System Bell Trouble",
|
||||
"806: An open circuit has been detected across the bell terminals."),
|
||||
SystemBellTroubleRestore("807", "System Bell Trouble Restore", "807: The bell trouble has been restored."),
|
||||
TLMLine1Trouble("810", "TML Line 1 Trouble", "810: The phone line is a open or shorted condition."),
|
||||
TLMLine1TroubleRestore("811", "TML Line 1 Trouble Restore",
|
||||
"811: The phone line trouble condition has been restored."),
|
||||
TLMLine2Trouble("812", "TML Line 2 Trouble", "812: The phone line is a open or shorted condition."),
|
||||
TLMLine2TroubleRestore("813", "TML Line 2 Trouble Restore",
|
||||
"813: The phone line trouble condition has been restored."),
|
||||
FTCTrouble("814", "FTC Trouble",
|
||||
"814: The panel has failed to communicate successfully to the monitoring station."),
|
||||
BufferNearFull("816", "Buffer Near Full",
|
||||
"816: The panel event buffer is 75% full from when it was last uploaded to DLS."),
|
||||
GeneralDeviceLowBattery("821", "General Device Low Battery", "821: A wireless zone has a low battery."),
|
||||
GeneralDeviceLowBatteryRestore("822", "General Device Low Battery Restore",
|
||||
"822: A wireless zone has a low battery."),
|
||||
WirelessKeyLowBatteryTrouble("825", "Wireless Key Low Battery Trouble", "825: A wireless key has a low battery."),
|
||||
WirelessKeyLowBatteryTroubleRestore("826", "Wireless Key Low Battery Trouble Restore",
|
||||
"826: A wireless key low battery condition has been restored."),
|
||||
HandheldKeypadLowBatteryTrouble("827", "Handheld Keypad Low Battery Trouble",
|
||||
"827: A handhekd keypad has a low battery."),
|
||||
HandheldKeypadLowBatteryTroubleRestore("828", "Handheld Keypad Low Battery Trouble Restore",
|
||||
"828: A handhekd keypad low battery condition has been restored."),
|
||||
GeneralSystemTamper("829", "General System Tamper", "829: A tamper has occurred with a system module."),
|
||||
GeneralSystemTamperRestore("830", "General System Tamper Restore",
|
||||
"830: A general system Tamper has been restored."),
|
||||
HomeAutomationTrouble("831", "Home Automation Trouble", "831: Escort 5580 module trouble."),
|
||||
HomeAutomationTroubleRestore("832", "Home Automation Trouble Restore",
|
||||
"832: Escort 5580 module trouble has been restored."),
|
||||
TroubleLEDOn("840", "Trouble LED ON", "840: The trouble LED on a keypad is ON."),
|
||||
TroubleLEDOff("841", "Trouble LED OFF", "841: The trouble LED on a keypad is OFF."),
|
||||
FireTroubleAlarm("842", "Fire Trouble Alarm", "842: Fire trouble alarm."),
|
||||
FireTroubleAlarmRestore("843", "Fire Trouble Alarm Restore", "843: Fire trouble alarm restored."),
|
||||
VerboseTroubleStatus("849", "Verbose Trouble Status",
|
||||
"849: a trouble appears on the system and roughly every 5 minutes until the trouble is cleared."),
|
||||
KeybusFault("896", "Keybus Fault", "896: Keybus fault condition."),
|
||||
KeybusFaultRestore("897", "Keybus Fault Restore", "897: Keybus fault has been restored."),
|
||||
|
||||
CodeRequired("900", "Code Required", "900: Tells the API to enter an access code."),
|
||||
LCDUpdate("901", "LCD Update", "901: Text of the IT-100 menu has changed."),
|
||||
LCDCursor("902", "LCD Cursor", "902: Cursor position has changed."),
|
||||
LEDStatus("903", "LED Status", "903: LED Status has changed."),
|
||||
BeepStatus("904", "Beep Status", "904: Beep status sent."),
|
||||
ToneStatus("905", "Tone Status", "905: Tone status sent."),
|
||||
BuzzerStatus("906", "Buzzer Status", "906: Buzzer status sent."),
|
||||
DoorChimeStatus("907", "Door Chime Status", "907: Door Chime status sent."),
|
||||
SoftwareVersion("908", "Software Version", "908: Current software version."),
|
||||
CommandOutputPressed("912", "Command Output Pressed", "912: Tells the API to enter an access code."),
|
||||
MasterCodeRequired("921", "Master Code Required", "921: Tells the API to enter a master access code."),
|
||||
InstallersCodeRequired("922", "Installers Code Required", "922: Tells the API to enter an installers access code."),
|
||||
|
||||
UnknownCode("-1", "Unknown Code", "Unknown code received.");
|
||||
|
||||
private String code;
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Lookup map to get a DSCAlarmCode value from its string code.
|
||||
*/
|
||||
private static Map<String, DSCAlarmCode> codeToDSCAlarmCodeValue;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param code
|
||||
*/
|
||||
private DSCAlarmCode(String code, String name, String description) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the lookup map that gets a DSCAlarmCode value from a string code.
|
||||
*/
|
||||
private static void initMapping() {
|
||||
codeToDSCAlarmCodeValue = new HashMap<>();
|
||||
for (DSCAlarmCode s : values()) {
|
||||
codeToDSCAlarmCodeValue.put(s.code, s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The DSC Alarm command/message code string (example '005').
|
||||
*/
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* The DSC Alarm command/message name string (example 'Poll Command').
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The DSC Alarm command/message description string.
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup function to return the DSCAlarmCode value based on the string code. Returns 'UnknownCode' if the string
|
||||
* code is not found.
|
||||
*
|
||||
* @param code
|
||||
* @return enum value
|
||||
*/
|
||||
public static DSCAlarmCode getDSCAlarmCodeValue(String code) {
|
||||
DSCAlarmCode dscAlarmCode;
|
||||
|
||||
if (codeToDSCAlarmCodeValue == null) {
|
||||
initMapping();
|
||||
}
|
||||
|
||||
dscAlarmCode = codeToDSCAlarmCodeValue.get(code);
|
||||
|
||||
if (dscAlarmCode == null) {
|
||||
dscAlarmCode = UnknownCode;
|
||||
}
|
||||
|
||||
return dscAlarmCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
/**
|
||||
* Event for Receiving API Messages.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public class DSCAlarmEvent extends EventObject {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private DSCAlarmMessage dscAlarmMessage;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param source
|
||||
*/
|
||||
public DSCAlarmEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the the received API Message to the event.
|
||||
*
|
||||
* @param dscAlarmMessage
|
||||
*/
|
||||
public void dscAlarmEventMessage(DSCAlarmMessage dscAlarmMessage) {
|
||||
this.dscAlarmMessage = dscAlarmMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API Message event from the DSC Alarm System.
|
||||
*
|
||||
* @return apiMessage
|
||||
*/
|
||||
public DSCAlarmMessage getDSCAlarmMessage() {
|
||||
return dscAlarmMessage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,606 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal;
|
||||
|
||||
import java.util.EnumMap;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A class that processes DSC Alarm Messages.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public class DSCAlarmMessage {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DSCAlarmMessage.class);
|
||||
|
||||
private static final EnumMap<DSCAlarmCode, MessageParameters> DSCALARM_MESSAGE_PARAMETERS = new EnumMap<>(
|
||||
DSCAlarmCode.class);
|
||||
|
||||
public enum DSCAlarmMessageType {
|
||||
PANEL_EVENT,
|
||||
PARTITION_EVENT,
|
||||
ZONE_EVENT,
|
||||
KEYPAD_EVENT
|
||||
}
|
||||
|
||||
public enum DSCAlarmMessageInfoType {
|
||||
MESSAGE,
|
||||
NAME,
|
||||
DESCRIPTION,
|
||||
CODE,
|
||||
TIME_STAMP,
|
||||
PARTITION,
|
||||
ZONE,
|
||||
DATA,
|
||||
MODE,
|
||||
USER,
|
||||
ERROR
|
||||
}
|
||||
|
||||
private DSCAlarmMessageType messageType = DSCAlarmMessageType.PANEL_EVENT;
|
||||
|
||||
private String message = "";
|
||||
private String name = "";
|
||||
private String description = "";
|
||||
private String codeReceived = "";
|
||||
private String timeStamp = "";
|
||||
private String partition = "0";
|
||||
private String zone = "0";
|
||||
private String data = "";
|
||||
private String mode = "";
|
||||
private String user = "";
|
||||
private String error = "";
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param message
|
||||
* - the message received
|
||||
*/
|
||||
public DSCAlarmMessage(String message) {
|
||||
this.message = message;
|
||||
processDSCAlarmMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the incoming DSC Alarm message and extracts the information.
|
||||
*/
|
||||
private void processDSCAlarmMessage() {
|
||||
DSCAlarmCode dscAlarmCode;
|
||||
|
||||
if (message.length() > 3) {
|
||||
try {
|
||||
if (message.length() >= 8 && message.charAt(2) == ':' && message.charAt(5) == ':') {
|
||||
timeStamp = message.substring(0, 8);
|
||||
message = message.substring(9, message.length() - 2);
|
||||
} else {
|
||||
message = message.substring(0, message.length() - 2);
|
||||
}
|
||||
|
||||
codeReceived = message.substring(0, 3);
|
||||
|
||||
if (message.length() >= 4) {
|
||||
data = message.substring(3);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("processDSCAlarmMessage(): Error processing message: ({}) ", message, e);
|
||||
return;
|
||||
}
|
||||
|
||||
dscAlarmCode = DSCAlarmCode.getDSCAlarmCodeValue(codeReceived);
|
||||
|
||||
if (dscAlarmCode != null) {
|
||||
name = dscAlarmCode.getName();
|
||||
description = dscAlarmCode.getDescription();
|
||||
|
||||
MessageParameters messageParms = DSCALARM_MESSAGE_PARAMETERS.get(dscAlarmCode);
|
||||
|
||||
if (messageParms != null) {
|
||||
boolean hasPartition = messageParms.hasPartition();
|
||||
boolean hasZone = messageParms.hasZone();
|
||||
|
||||
if (hasPartition) {
|
||||
partition = message.substring(3, 4);
|
||||
}
|
||||
|
||||
if (hasZone) {
|
||||
if (hasPartition) {
|
||||
zone = message.substring(4);
|
||||
} else {
|
||||
zone = message.substring(3);
|
||||
}
|
||||
}
|
||||
|
||||
messageType = messageParms.getType();
|
||||
}
|
||||
|
||||
switch (dscAlarmCode) {
|
||||
case SystemError: /* 502 */
|
||||
int systemErrorCode = 0;
|
||||
systemErrorCode = Integer.parseInt(data);
|
||||
switch (systemErrorCode) {
|
||||
case 1:
|
||||
error = "Receive Buffer Overrun";
|
||||
break;
|
||||
case 2:
|
||||
error = "Receive Buffer Overflow";
|
||||
break;
|
||||
case 3:
|
||||
error = "Transmit Buffer Overflow";
|
||||
break;
|
||||
case 10:
|
||||
error = "Keybus Transmit Buffer Overrun";
|
||||
break;
|
||||
case 11:
|
||||
error = "Keybus Transmit Time Timeout";
|
||||
break;
|
||||
case 12:
|
||||
error = "Keybus Transmit Mode Timeout";
|
||||
break;
|
||||
case 13:
|
||||
error = "Keybus Transmit Keystring Timeout";
|
||||
break;
|
||||
case 14:
|
||||
error = "Keybus Interface Not Functioning";
|
||||
break;
|
||||
case 15:
|
||||
error = "Keybus Busy - Attempting to Disarm or Arm with user code";
|
||||
break;
|
||||
case 16:
|
||||
error = "Keybus Busy – Lockout";
|
||||
break;
|
||||
case 17:
|
||||
error = "Keybus Busy – Installers Mode";
|
||||
break;
|
||||
case 18:
|
||||
error = "Keybus Busy - General Busy";
|
||||
break;
|
||||
case 20:
|
||||
error = "API Command Syntax Error";
|
||||
break;
|
||||
case 21:
|
||||
error = "API Command Partition Error - Requested Partition is out of bounds";
|
||||
break;
|
||||
case 22:
|
||||
error = "API Command Not Supported";
|
||||
break;
|
||||
case 23:
|
||||
error = "API System Not Armed - Sent in response to a disarm command";
|
||||
break;
|
||||
case 24:
|
||||
error = "API System Not Ready to Arm - System is either not-secure, in exit-delay, or already armed";
|
||||
break;
|
||||
case 25:
|
||||
error = "API Command Invalid Length";
|
||||
break;
|
||||
case 26:
|
||||
error = "API User Code not Required";
|
||||
break;
|
||||
case 27:
|
||||
error = "API Invalid Characters in Command - No alpha characters are allowed except for checksum";
|
||||
break;
|
||||
case 28:
|
||||
error = "API Virtual Keypad is Disabled";
|
||||
break;
|
||||
case 29:
|
||||
error = "API Not Valid Parameter";
|
||||
break;
|
||||
case 30:
|
||||
error = "API Keypad Does Not Come Out of Blank Mode";
|
||||
break;
|
||||
case 31:
|
||||
error = "API IT-100 is Already in Thermostat Menu";
|
||||
break;
|
||||
case 32:
|
||||
error = "API IT-100 is NOT in Thermostat Menu";
|
||||
break;
|
||||
case 33:
|
||||
error = "API No Response From Thermostat or Escort Module";
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
error = "No Error";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PartitionArmed: /* 652 */
|
||||
mode = message.substring(4);
|
||||
if (mode.equals("0")) {
|
||||
name += " (Away)";
|
||||
} else if (mode.equals("1")) {
|
||||
name += " (Stay)";
|
||||
} else if (mode.equals("2")) {
|
||||
name += " (ZEA)";
|
||||
} else if (mode.equals("3")) {
|
||||
name += " (ZES)";
|
||||
}
|
||||
messageType = DSCAlarmMessageType.PARTITION_EVENT;
|
||||
break;
|
||||
case UserClosing: /* 700 */
|
||||
user = message.substring(4);
|
||||
name = name.concat(": " + user);
|
||||
description = codeReceived + ": Partition " + String.valueOf(partition)
|
||||
+ " has been armed by user " + user + ".";
|
||||
messageType = DSCAlarmMessageType.PARTITION_EVENT;
|
||||
break;
|
||||
case UserOpening: /* 750 */
|
||||
user = message.substring(4);
|
||||
name = name.concat(": " + user);
|
||||
description = codeReceived + ": Partition " + String.valueOf(partition)
|
||||
+ " has been disarmed by user " + user + ".";
|
||||
messageType = DSCAlarmMessageType.PARTITION_EVENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
"parseAPIMessage(): Message Received ({}) - Code: {}, Name: {}, Description: {}, Data: {}\r\n",
|
||||
message, codeReceived, name, description, data);
|
||||
}
|
||||
} else {
|
||||
codeReceived = "-1";
|
||||
data = "";
|
||||
dscAlarmCode = DSCAlarmCode.getDSCAlarmCodeValue(codeReceived);
|
||||
name = dscAlarmCode.getName();
|
||||
description = dscAlarmCode.getDescription();
|
||||
logger.debug("parseAPIMessage(): Invalid Message Received");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DSCAlarm Message Type.
|
||||
*
|
||||
* @return messageType
|
||||
*/
|
||||
public DSCAlarmMessageType getDSCAlarmMessageType() {
|
||||
return messageType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Information from A DSC Alarm Message
|
||||
*
|
||||
* @param dscAlarmMessageInfoType
|
||||
* @return String
|
||||
*/
|
||||
public String getMessageInfo(DSCAlarmMessageInfoType dscAlarmMessageInfoType) {
|
||||
String info = "";
|
||||
|
||||
switch (dscAlarmMessageInfoType) {
|
||||
case MESSAGE:
|
||||
info = message;
|
||||
break;
|
||||
case NAME:
|
||||
info = name;
|
||||
break;
|
||||
case DESCRIPTION:
|
||||
info = description;
|
||||
break;
|
||||
case CODE:
|
||||
info = codeReceived;
|
||||
break;
|
||||
case TIME_STAMP:
|
||||
info = timeStamp;
|
||||
break;
|
||||
case PARTITION:
|
||||
info = partition;
|
||||
break;
|
||||
case ZONE:
|
||||
info = zone;
|
||||
break;
|
||||
case DATA:
|
||||
info = data;
|
||||
break;
|
||||
case MODE:
|
||||
info = mode;
|
||||
break;
|
||||
case USER:
|
||||
info = timeStamp;
|
||||
break;
|
||||
case ERROR:
|
||||
info = error;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of a APIMessage.
|
||||
*
|
||||
* @return APIMessage string
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("Code: \"");
|
||||
sb.append(codeReceived);
|
||||
sb.append("\"");
|
||||
|
||||
sb.append(", Name: \"");
|
||||
sb.append(name);
|
||||
sb.append("\"");
|
||||
|
||||
sb.append(", Description: \"");
|
||||
sb.append(description);
|
||||
sb.append("\"");
|
||||
|
||||
if (!timeStamp.equals("")) {
|
||||
sb.append(", Time Stamp: ");
|
||||
sb.append(timeStamp);
|
||||
}
|
||||
|
||||
if (!partition.equals("0")) {
|
||||
sb.append(", Partition: ");
|
||||
sb.append(partition);
|
||||
}
|
||||
|
||||
if (!zone.equals("0")) {
|
||||
sb.append(", Zone: ");
|
||||
sb.append(zone);
|
||||
}
|
||||
|
||||
if (!data.equals("")) {
|
||||
sb.append(", Data: ");
|
||||
sb.append(data);
|
||||
}
|
||||
|
||||
if (!mode.equals("")) {
|
||||
sb.append(", Mode: ");
|
||||
sb.append(mode);
|
||||
}
|
||||
|
||||
if (!user.equals("")) {
|
||||
sb.append(", user: ");
|
||||
sb.append(user);
|
||||
}
|
||||
|
||||
if (!error.equals("")) {
|
||||
sb.append(", error: ");
|
||||
sb.append(error);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static class MessageParameters {
|
||||
private boolean partition;
|
||||
private boolean zone;
|
||||
private DSCAlarmMessageType type;
|
||||
|
||||
MessageParameters(DSCAlarmMessageType type, boolean partition, boolean zone) {
|
||||
this.type = type;
|
||||
this.partition = partition;
|
||||
this.zone = zone;
|
||||
}
|
||||
|
||||
public DSCAlarmMessageType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean hasPartition() {
|
||||
return partition;
|
||||
}
|
||||
|
||||
public boolean hasZone() {
|
||||
return zone;
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.CommandAcknowledge,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.CommandError,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.SystemError,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.LoginResponse,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.KeypadLEDState,
|
||||
new MessageParameters(DSCAlarmMessageType.KEYPAD_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.KeypadLEDFlashState,
|
||||
new MessageParameters(DSCAlarmMessageType.KEYPAD_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.TimeDateBroadcast,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.RingDetected,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.IndoorTemperatureBroadcast,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.OutdoorTemperatureBroadcast,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ThermostatSetPoints,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.BroadcastLabels,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.BaudRateSet,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ZoneAlarm,
|
||||
new MessageParameters(DSCAlarmMessageType.ZONE_EVENT, true, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ZoneAlarmRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.ZONE_EVENT, true, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ZoneTamper,
|
||||
new MessageParameters(DSCAlarmMessageType.ZONE_EVENT, true, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ZoneTamperRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.ZONE_EVENT, true, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ZoneFault,
|
||||
new MessageParameters(DSCAlarmMessageType.ZONE_EVENT, false, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ZoneFaultRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.ZONE_EVENT, false, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ZoneOpen,
|
||||
new MessageParameters(DSCAlarmMessageType.ZONE_EVENT, false, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ZoneRestored,
|
||||
new MessageParameters(DSCAlarmMessageType.ZONE_EVENT, false, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.EnvisalinkZoneTimerDump,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.DuressAlarm,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.FireKeyAlarm,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.FireKeyRestored,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.AuxiliaryKeyAlarm,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.AuxiliaryKeyRestored,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PanicKeyAlarm,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PanicKeyRestored,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.AuxiliaryInputAlarm,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.AuxiliaryInputAlarmRestored,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PartitionReady,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PartitionNotReady,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PartitionArmed,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PartitionReadyForceArming,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PartitionInAlarm,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PartitionDisarmed,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ExitDelayInProgress,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.EntryDelayInProgress,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.KeypadLockout,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PartitionFailedToArm,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PGMOutputInProgress,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ChimeEnabled,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ChimeDisabled,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.InvalidAccessCode,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.FunctionNotAvailable,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.FailureToArm,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PartitionBusy,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.SystemArmingInProgress,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.SystemInInstallerMode,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.UserClosing,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.SpecialClosing,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PartialClosing,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.UserOpening,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.SpecialOpening,
|
||||
new MessageParameters(DSCAlarmMessageType.PARTITION_EVENT, true, false));
|
||||
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PanelBatteryTrouble,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PanelBatteryTroubleRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PanelACTrouble,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.PanelACRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.SystemBellTrouble,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.SystemBellTroubleRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.TLMLine1Trouble,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.TLMLine1TroubleRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.TLMLine2Trouble,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.TLMLine2TroubleRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.FTCTrouble,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.BufferNearFull,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.GeneralDeviceLowBattery,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.GeneralDeviceLowBatteryRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.WirelessKeyLowBatteryTrouble,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.WirelessKeyLowBatteryTroubleRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.HandheldKeypadLowBatteryTrouble,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.HandheldKeypadLowBatteryTroubleRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, true));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.GeneralSystemTamper,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.GeneralSystemTamperRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.HomeAutomationTrouble,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.HomeAutomationTroubleRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.TroubleLEDOn,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.TroubleLEDOff,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, true, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.FireTroubleAlarm,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.FireTroubleAlarmRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.VerboseTroubleStatus,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.KeybusFault,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.KeybusFaultRestore,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.CodeRequired,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.LCDUpdate,
|
||||
new MessageParameters(DSCAlarmMessageType.KEYPAD_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.LCDCursor,
|
||||
new MessageParameters(DSCAlarmMessageType.KEYPAD_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.LEDStatus,
|
||||
new MessageParameters(DSCAlarmMessageType.KEYPAD_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.BeepStatus,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.ToneStatus,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.BuzzerStatus,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.DoorChimeStatus,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.SoftwareVersion,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.CommandOutputPressed,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.MasterCodeRequired,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
DSCALARM_MESSAGE_PARAMETERS.put(DSCAlarmCode.InstallersCodeRequired,
|
||||
new MessageParameters(DSCAlarmMessageType.PANEL_EVENT, false, false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.config;
|
||||
|
||||
/**
|
||||
* Configuration class for the DSC Alarm Panel Thing.
|
||||
*
|
||||
* @author Russell Stephens - Initial contribution
|
||||
*/
|
||||
|
||||
public class DSCAlarmPanelConfiguration {
|
||||
|
||||
// Panel Thing constants
|
||||
public static final String USER_CODE = "userCode";
|
||||
public static final String SUPPRESS_ACK_MSGS = "suppressAcknowledgementMsgs";
|
||||
|
||||
/**
|
||||
* The Panel User Code. Default is 1234;
|
||||
*/
|
||||
public String userCode;
|
||||
|
||||
/**
|
||||
* Suppress Acknowledgement messages when received
|
||||
*/
|
||||
public boolean suppressAcknowledgementMsgs;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.config;
|
||||
|
||||
/**
|
||||
* Configuration class for the DSC Alarm Partition Thing.
|
||||
*
|
||||
* @author Russell Stephens - Initial contribution
|
||||
*/
|
||||
|
||||
public class DSCAlarmPartitionConfiguration {
|
||||
|
||||
// Partition Thing constants
|
||||
public static final String PARTITION_NUMBER = "partitionNumber";
|
||||
|
||||
/**
|
||||
* The Partition Number. Can be in the range of 1-8. This is a required parameter for a partition.
|
||||
*/
|
||||
public Integer partitionNumber;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.config;
|
||||
|
||||
/**
|
||||
* Configuration class for the DSC Alarm Zone Thing.
|
||||
*
|
||||
* @author Russell Stephens - Initial contribution
|
||||
*/
|
||||
|
||||
public class DSCAlarmZoneConfiguration {
|
||||
|
||||
// Zone Thing constants
|
||||
public static final String PARTITION_NUMBER = "partitionNumber";
|
||||
public static final String ZONE_NUMBER = "zoneNumber";
|
||||
|
||||
/**
|
||||
* The Partition Number. Can be in the range of 1-8. This is not required. Defaults to 1.
|
||||
*/
|
||||
public Integer partitionNumber;
|
||||
|
||||
/**
|
||||
* The Zone Number. Can be in the range of 1-64. This is a required parameter for a zone.
|
||||
*/
|
||||
public Integer zoneNumber;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.config;
|
||||
|
||||
/**
|
||||
* Configuration class for the EyezOn Envisalink 3/2DS Ethernet TCP interface bridge, used to connect to the DSC Alarm
|
||||
* system.
|
||||
*
|
||||
* @author Russell Stephens - Initial contribution
|
||||
*/
|
||||
|
||||
public class EnvisalinkBridgeConfiguration {
|
||||
|
||||
// Envisalink Bridge Thing constants
|
||||
public static final String IP_ADDRESS = "ipAddress";
|
||||
public static final String PORT = "port";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String CONNECTION_TIMEOUT = "connectionTimeout";
|
||||
public static final String POLL_PERIOD = "pollPeriod";
|
||||
|
||||
/**
|
||||
* The IP address of the Envisalink Ethernet 3/2DS TCP interface
|
||||
*/
|
||||
public String ipAddress;
|
||||
|
||||
/**
|
||||
* The port number of the Envisalink Ethernet 3/2DS TCP interface
|
||||
*/
|
||||
public Integer port;
|
||||
|
||||
/**
|
||||
* The password of the Envisalink Ethernet 3/2DS TCP interface
|
||||
*/
|
||||
public String password;
|
||||
|
||||
/**
|
||||
* The Socket connection timeout for the Envisalink Ethernet 3/2DS TCP interface
|
||||
*/
|
||||
public Integer connectionTimeout;
|
||||
|
||||
/**
|
||||
* The Panel Poll Period. Can be set in range 1-15 minutes. Default is 1 minute;
|
||||
*/
|
||||
public Integer pollPeriod;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.config;
|
||||
|
||||
/**
|
||||
* Configuration class for the DSC IT100 RS232 Serial interface bridge, used to connect to the DSC Alarm system.
|
||||
*
|
||||
* @author Russell Stephens - Initial contribution
|
||||
*/
|
||||
|
||||
public class IT100BridgeConfiguration {
|
||||
|
||||
// IT-100 Bridge Thing constants
|
||||
public static final String SERIAL_PORT = "serialPort";
|
||||
public static final String BAUD = "baud";
|
||||
public static final String POLL_PERIOD = "pollPeriod";
|
||||
|
||||
/**
|
||||
* DSC IT100 port name for a serial connection. Valid values are e.g. COM1 for Windows and /dev/ttyS0 or
|
||||
* /dev/ttyUSB0 for Linux.
|
||||
*/
|
||||
public String serialPort;
|
||||
|
||||
/**
|
||||
* DSC IT100 baud rate for serial connections. Valid values are 9600 (default), 19200, 38400, 57600, and 115200.
|
||||
*/
|
||||
public Integer baud;
|
||||
|
||||
/**
|
||||
* The Panel Poll Period. Can be set in range 1-15 minutes. Default is 1 minute;
|
||||
*/
|
||||
public Integer pollPeriod;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.config;
|
||||
|
||||
/**
|
||||
* Configuration class for the TCP Server bridge, used to connect to the DSC Alarm system.
|
||||
*
|
||||
* @author Russell Stephens - Initial contribution
|
||||
*/
|
||||
|
||||
public class TCPServerBridgeConfiguration {
|
||||
|
||||
// TCP Server Bridge Thing constants
|
||||
public static final String IP_ADDRESS = "ipAddress";
|
||||
public static final String PORT = "port";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String CONNECTION_TIMEOUT = "connectionTimeout";
|
||||
public static final String POLL_PERIOD = "pollPeriod";
|
||||
public static final String PROTOCOL = "protocol";
|
||||
|
||||
/**
|
||||
* The IP address of the TCP Server
|
||||
*/
|
||||
public String ipAddress;
|
||||
|
||||
/**
|
||||
* The port number of the TCP Server
|
||||
*/
|
||||
public Integer port;
|
||||
|
||||
/**
|
||||
* The Socket connection timeout for the TCP Server
|
||||
*/
|
||||
public Integer connectionTimeout;
|
||||
|
||||
/**
|
||||
* The Panel Poll Period. Can be set in range 1-15 minutes. Default is 1 minute;
|
||||
*/
|
||||
public Integer pollPeriod;
|
||||
|
||||
/**
|
||||
* The Protocol Type - 1 for IT-100 API or 2 for Envisalink TPI.
|
||||
*/
|
||||
public Integer protocol;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.discovery;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants;
|
||||
import org.openhab.binding.dscalarm.internal.config.EnvisalinkBridgeConfiguration;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class is responsible for discovering the EyezOn Envisalink 3/2DS Ethernet interface.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*
|
||||
*/
|
||||
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.dscalarm")
|
||||
public class DSCAlarmBridgeDiscovery extends AbstractDiscoveryService {
|
||||
private final Logger logger = LoggerFactory.getLogger(DSCAlarmBridgeDiscovery.class);
|
||||
|
||||
private EnvisalinkBridgeDiscovery envisalinkBridgeDiscovery = new EnvisalinkBridgeDiscovery(this);
|
||||
|
||||
public DSCAlarmBridgeDiscovery() {
|
||||
super(DSCAlarmBindingConstants.SUPPORTED_BRIDGE_THING_TYPES_UIDS, 15, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
logger.trace("Start DSC Alarm Bridge discovery.");
|
||||
scheduler.execute(envisalinkBridgeDiscoveryRunnable);
|
||||
}
|
||||
|
||||
private Runnable envisalinkBridgeDiscoveryRunnable = () -> {
|
||||
envisalinkBridgeDiscovery.discoverBridge();
|
||||
};
|
||||
|
||||
/**
|
||||
* Method to add an Envisalink Bridge to the Smarthome Inbox.
|
||||
*
|
||||
* @param ipAddress
|
||||
*/
|
||||
public void addEnvisalinkBridge(String ipAddress) {
|
||||
logger.trace("addBridge(): Adding new Envisalink Bridge on {} to Smarthome inbox", ipAddress);
|
||||
|
||||
String bridgeID = ipAddress.replace('.', '_');
|
||||
Map<String, Object> properties = new HashMap<>(0);
|
||||
properties.put(EnvisalinkBridgeConfiguration.IP_ADDRESS, ipAddress);
|
||||
|
||||
try {
|
||||
ThingUID thingUID = new ThingUID(DSCAlarmBindingConstants.ENVISALINKBRIDGE_THING_TYPE, bridgeID);
|
||||
|
||||
thingDiscovered(DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withLabel("EyezOn Envisalink Bridge - " + ipAddress).build());
|
||||
|
||||
logger.trace("addBridge(): '{}' was added to Smarthome inbox.", thingUID);
|
||||
} catch (Exception e) {
|
||||
logger.error("addBridge(): Error", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.discovery;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmEvent;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage.DSCAlarmMessageInfoType;
|
||||
import org.openhab.binding.dscalarm.internal.config.DSCAlarmPartitionConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.config.DSCAlarmZoneConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.handler.DSCAlarmBaseBridgeHandler;
|
||||
import org.openhab.binding.dscalarm.internal.handler.DSCAlarmThingType;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class is responsible for discovering DSC Alarm Things via the bridge.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*
|
||||
*/
|
||||
public class DSCAlarmDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DSCAlarmDiscoveryService.class);
|
||||
|
||||
/**
|
||||
* DSC Alarm Bridge handler.
|
||||
*/
|
||||
DSCAlarmBaseBridgeHandler dscAlarmBridgeHandler;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param dscAlarmBridgeHandler
|
||||
*/
|
||||
public DSCAlarmDiscoveryService(DSCAlarmBaseBridgeHandler dscAlarmBridgeHandler) {
|
||||
super(DSCAlarmBindingConstants.SUPPORTED_THING_TYPES_UIDS, 15, true);
|
||||
this.dscAlarmBridgeHandler = dscAlarmBridgeHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates the Discovery Service.
|
||||
*/
|
||||
public void activate() {
|
||||
dscAlarmBridgeHandler.registerDiscoveryService(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates the Discovery Service.
|
||||
*/
|
||||
@Override
|
||||
public void deactivate() {
|
||||
dscAlarmBridgeHandler.unregisterDiscoveryService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add a Thing to the Smarthome Inbox.
|
||||
*
|
||||
* @param bridge
|
||||
* @param dscAlarmThingType
|
||||
* @param event
|
||||
*/
|
||||
public void addThing(Bridge bridge, DSCAlarmThingType dscAlarmThingType, DSCAlarmEvent event) {
|
||||
logger.trace("addThing(): Adding new DSC Alarm {} to the smarthome inbox", dscAlarmThingType.getLabel());
|
||||
|
||||
ThingUID thingUID = null;
|
||||
String thingID = "";
|
||||
String thingLabel = "";
|
||||
Map<String, Object> properties = null;
|
||||
|
||||
int partitionNumber = Integer
|
||||
.parseInt(event.getDSCAlarmMessage().getMessageInfo(DSCAlarmMessageInfoType.PARTITION));
|
||||
int zoneNumber = Integer.parseInt(event.getDSCAlarmMessage().getMessageInfo(DSCAlarmMessageInfoType.ZONE));
|
||||
|
||||
switch (dscAlarmThingType) {
|
||||
case PANEL:
|
||||
thingID = "panel";
|
||||
thingLabel = "Panel";
|
||||
thingUID = new ThingUID(DSCAlarmBindingConstants.PANEL_THING_TYPE, bridge.getUID(), thingID);
|
||||
break;
|
||||
case PARTITION:
|
||||
if (partitionNumber >= 1 && partitionNumber <= 8) {
|
||||
thingID = "partition" + String.valueOf(partitionNumber);
|
||||
thingLabel = "Partition " + String.valueOf(partitionNumber);
|
||||
properties = new HashMap<>(0);
|
||||
thingUID = new ThingUID(DSCAlarmBindingConstants.PARTITION_THING_TYPE, bridge.getUID(), thingID);
|
||||
properties.put(DSCAlarmPartitionConfiguration.PARTITION_NUMBER, partitionNumber);
|
||||
}
|
||||
|
||||
break;
|
||||
case ZONE:
|
||||
if (zoneNumber >= 1 && zoneNumber <= 64) {
|
||||
thingID = "zone" + String.valueOf(zoneNumber);
|
||||
thingLabel = "Zone " + String.valueOf(zoneNumber);
|
||||
properties = new HashMap<>(0);
|
||||
thingUID = new ThingUID(DSCAlarmBindingConstants.ZONE_THING_TYPE, bridge.getUID(), thingID);
|
||||
properties.put(DSCAlarmZoneConfiguration.ZONE_NUMBER, zoneNumber);
|
||||
}
|
||||
break;
|
||||
case KEYPAD:
|
||||
thingID = "keypad";
|
||||
thingLabel = "Keypad";
|
||||
thingUID = new ThingUID(DSCAlarmBindingConstants.KEYPAD_THING_TYPE, bridge.getUID(), thingID);
|
||||
break;
|
||||
}
|
||||
|
||||
if (thingUID != null) {
|
||||
DiscoveryResult discoveryResult;
|
||||
|
||||
if (properties != null) {
|
||||
discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withBridge(bridge.getUID()).withLabel(thingLabel).build();
|
||||
} else {
|
||||
discoveryResult = DiscoveryResultBuilder.create(thingUID).withBridge(bridge.getUID())
|
||||
.withLabel(thingLabel).build();
|
||||
}
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
} else {
|
||||
logger.debug("addThing(): Unable to Add DSC Alarm Thing to Inbox!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
// Can be ignored here as discovery is via the bridge
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.discovery;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
import org.apache.commons.net.util.SubnetUtils;
|
||||
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class is responsible for discovering the EyezOn Envisalink 3/2DS Ethernet interface.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*
|
||||
*/
|
||||
public class EnvisalinkBridgeDiscovery {
|
||||
private final Logger logger = LoggerFactory.getLogger(EnvisalinkBridgeDiscovery.class);
|
||||
|
||||
static final int ENVISALINK_BRIDGE_PORT = 4025;
|
||||
static final int CONNECTION_TIMEOUT = 10;
|
||||
static final int SO_TIMEOUT = 15000;
|
||||
static final String ENVISALINK_DISCOVERY_RESPONSE = "505";
|
||||
|
||||
private DSCAlarmBridgeDiscovery dscAlarmBridgeDiscovery = null;
|
||||
private String ipAddress;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public EnvisalinkBridgeDiscovery(DSCAlarmBridgeDiscovery dscAlarmBridgeDiscovery) {
|
||||
this.dscAlarmBridgeDiscovery = dscAlarmBridgeDiscovery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for Bridge Discovery.
|
||||
*/
|
||||
public synchronized void discoverBridge() {
|
||||
logger.debug("Starting Envisalink Bridge Discovery.");
|
||||
|
||||
SubnetUtils subnetUtils = null;
|
||||
SubnetInfo subnetInfo = null;
|
||||
long lowIP = 0;
|
||||
long highIP = 0;
|
||||
|
||||
try {
|
||||
InetAddress localHost = InetAddress.getLocalHost();
|
||||
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
|
||||
subnetUtils = new SubnetUtils(localHost.getHostAddress() + "/"
|
||||
+ networkInterface.getInterfaceAddresses().get(0).getNetworkPrefixLength());
|
||||
subnetInfo = subnetUtils.getInfo();
|
||||
lowIP = convertIPToNumber(subnetInfo.getLowAddress());
|
||||
highIP = convertIPToNumber(subnetInfo.getHighAddress());
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.error("discoverBridge(): Illegal Argument Exception - {}", e.toString());
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
logger.error("discoverBridge(): Error - Unable to get Subnet Information! {}", e.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug(" Local IP Address: {} - {}", subnetInfo.getAddress(),
|
||||
convertIPToNumber(subnetInfo.getAddress()));
|
||||
logger.debug(" Subnet: {} - {}", subnetInfo.getNetworkAddress(),
|
||||
convertIPToNumber(subnetInfo.getNetworkAddress()));
|
||||
logger.debug(" Network Prefix: {}", subnetInfo.getCidrSignature().split("/")[1]);
|
||||
logger.debug(" Network Mask: {}", subnetInfo.getNetmask());
|
||||
logger.debug(" Low IP: {}", convertNumberToIP(lowIP));
|
||||
logger.debug(" High IP: {}", convertNumberToIP(highIP));
|
||||
|
||||
for (long ip = lowIP; ip <= highIP; ip++) {
|
||||
try (Socket socket = new Socket()) {
|
||||
ipAddress = convertNumberToIP(ip);
|
||||
|
||||
socket.setReuseAddress(true);
|
||||
socket.setReceiveBufferSize(32);
|
||||
socket.connect(new InetSocketAddress(ipAddress, ENVISALINK_BRIDGE_PORT), CONNECTION_TIMEOUT);
|
||||
if (socket.isConnected()) {
|
||||
String message = "";
|
||||
socket.setSoTimeout(SO_TIMEOUT);
|
||||
try (BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
|
||||
message = input.readLine();
|
||||
} catch (SocketTimeoutException e) {
|
||||
logger.debug("discoverBridge(): No Message Read from Socket at [{}] - {}", ipAddress,
|
||||
e.getMessage());
|
||||
continue;
|
||||
} catch (Exception e) {
|
||||
logger.debug("discoverBridge(): Exception Reading from Socket at [{}]! {}", ipAddress,
|
||||
e.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (message.substring(0, 3).equals(ENVISALINK_DISCOVERY_RESPONSE)) {
|
||||
logger.debug("discoverBridge(): Bridge Found - [{}]! Message - '{}'", ipAddress, message);
|
||||
dscAlarmBridgeDiscovery.addEnvisalinkBridge(ipAddress);
|
||||
} else {
|
||||
logger.debug("discoverBridge(): No Response from Connection - [{}]! Message - '{}'",
|
||||
ipAddress, message);
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.debug("discoverBridge(): Illegal Argument Exception - {}", e.toString());
|
||||
} catch (SocketTimeoutException e) {
|
||||
logger.trace("discoverBridge(): No Connection on Port 4025! [{}]", ipAddress);
|
||||
} catch (SocketException e) {
|
||||
logger.debug("discoverBridge(): Socket Exception! [{}] - {}", ipAddress, e.toString());
|
||||
} catch (IOException e) {
|
||||
logger.debug("discoverBridge(): IO Exception! [{}] - {}", ipAddress, e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an IP address to a number.
|
||||
*
|
||||
* @param ipAddress
|
||||
* @return
|
||||
*/
|
||||
private long convertIPToNumber(String ipAddress) {
|
||||
String octets[] = ipAddress.split("\\.");
|
||||
|
||||
if (octets.length != 4) {
|
||||
throw new IllegalArgumentException("Invalid IP address: " + ipAddress);
|
||||
}
|
||||
|
||||
long ip = 0;
|
||||
|
||||
for (int i = 3; i >= 0; i--) {
|
||||
long octet = Long.parseLong(octets[3 - i]);
|
||||
|
||||
if (octet != (octet & 0xff)) {
|
||||
throw new IllegalArgumentException("Invalid IP address: " + ipAddress);
|
||||
}
|
||||
|
||||
ip |= octet << (i * 8);
|
||||
}
|
||||
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a number to an IP address.
|
||||
*
|
||||
* @param ip
|
||||
* @return
|
||||
*/
|
||||
private String convertNumberToIP(long ip) {
|
||||
StringBuilder ipAddress = new StringBuilder(15);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
||||
ipAddress.insert(0, Long.toString(ip & 0xff));
|
||||
|
||||
if (i < 3) {
|
||||
ipAddress.insert(0, '.');
|
||||
}
|
||||
|
||||
ip = ip >> 8;
|
||||
}
|
||||
|
||||
return ipAddress.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.factory;
|
||||
|
||||
import static org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants.SUPPORTED_THING_TYPES_UIDS;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants;
|
||||
import org.openhab.binding.dscalarm.internal.config.DSCAlarmPartitionConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.config.DSCAlarmZoneConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.config.EnvisalinkBridgeConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.config.IT100BridgeConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.config.TCPServerBridgeConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.discovery.DSCAlarmDiscoveryService;
|
||||
import org.openhab.binding.dscalarm.internal.handler.DSCAlarmBaseBridgeHandler;
|
||||
import org.openhab.binding.dscalarm.internal.handler.EnvisalinkBridgeHandler;
|
||||
import org.openhab.binding.dscalarm.internal.handler.IT100BridgeHandler;
|
||||
import org.openhab.binding.dscalarm.internal.handler.KeypadThingHandler;
|
||||
import org.openhab.binding.dscalarm.internal.handler.PanelThingHandler;
|
||||
import org.openhab.binding.dscalarm.internal.handler.PartitionThingHandler;
|
||||
import org.openhab.binding.dscalarm.internal.handler.TCPServerBridgeHandler;
|
||||
import org.openhab.binding.dscalarm.internal.handler.ZoneThingHandler;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link DSCAlarmHandlerFactory} is responsible for creating things and thing. handlers.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.dscalarm")
|
||||
public class DSCAlarmHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DSCAlarmHandlerFactory.class);
|
||||
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegistrations = new HashMap<>();
|
||||
|
||||
private final SerialPortManager serialPortManager;
|
||||
|
||||
@Activate
|
||||
public DSCAlarmHandlerFactory(final @Reference SerialPortManager serialPortManager) {
|
||||
this.serialPortManager = serialPortManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID,
|
||||
ThingUID bridgeUID) {
|
||||
if (DSCAlarmBindingConstants.ENVISALINKBRIDGE_THING_TYPE.equals(thingTypeUID)) {
|
||||
ThingUID envisalinkBridgeUID = getEnvisalinkBridgeThingUID(thingTypeUID, thingUID, configuration);
|
||||
logger.debug("createThing(): ENVISALINK_BRIDGE: Creating an '{}' type Thing - {}", thingTypeUID,
|
||||
envisalinkBridgeUID.getId());
|
||||
return super.createThing(thingTypeUID, configuration, envisalinkBridgeUID, null);
|
||||
} else if (DSCAlarmBindingConstants.IT100BRIDGE_THING_TYPE.equals(thingTypeUID)) {
|
||||
ThingUID it100BridgeUID = getIT100BridgeThingUID(thingTypeUID, thingUID, configuration);
|
||||
logger.debug("createThing(): IT100_BRIDGE: Creating an '{}' type Thing - {}", thingTypeUID,
|
||||
it100BridgeUID.getId());
|
||||
return super.createThing(thingTypeUID, configuration, it100BridgeUID, null);
|
||||
} else if (DSCAlarmBindingConstants.TCPSERVERBRIDGE_THING_TYPE.equals(thingTypeUID)) {
|
||||
ThingUID tcpServerBridgeUID = getTCPServerBridgeThingUID(thingTypeUID, thingUID, configuration);
|
||||
logger.debug("createThing(): TCP_SERVER_BRIDGE: Creating an '{}' type Thing - {}", thingTypeUID,
|
||||
tcpServerBridgeUID.getId());
|
||||
return super.createThing(thingTypeUID, configuration, tcpServerBridgeUID, null);
|
||||
} else if (DSCAlarmBindingConstants.PANEL_THING_TYPE.equals(thingTypeUID)) {
|
||||
ThingUID panelThingUID = getDSCAlarmPanelUID(thingTypeUID, thingUID, configuration, bridgeUID);
|
||||
logger.debug("createThing(): PANEL_THING: Creating '{}' type Thing - {}", thingTypeUID,
|
||||
panelThingUID.getId());
|
||||
return super.createThing(thingTypeUID, configuration, panelThingUID, bridgeUID);
|
||||
} else if (DSCAlarmBindingConstants.PARTITION_THING_TYPE.equals(thingTypeUID)) {
|
||||
ThingUID partitionThingUID = getDSCAlarmPartitionUID(thingTypeUID, thingUID, configuration, bridgeUID);
|
||||
logger.debug("createThing(): PARTITION_THING: Creating '{}' type Thing - {}", thingTypeUID,
|
||||
partitionThingUID.getId());
|
||||
return super.createThing(thingTypeUID, configuration, partitionThingUID, bridgeUID);
|
||||
} else if (DSCAlarmBindingConstants.ZONE_THING_TYPE.equals(thingTypeUID)) {
|
||||
ThingUID zoneThingUID = getDSCAlarmZoneUID(thingTypeUID, thingUID, configuration, bridgeUID);
|
||||
logger.debug("createThing(): ZONE_THING: Creating '{}' type Thing - {}", thingTypeUID,
|
||||
zoneThingUID.getId());
|
||||
return super.createThing(thingTypeUID, configuration, zoneThingUID, bridgeUID);
|
||||
} else if (DSCAlarmBindingConstants.KEYPAD_THING_TYPE.equals(thingTypeUID)) {
|
||||
ThingUID keypadThingUID = getDSCAlarmKeypadUID(thingTypeUID, thingUID, configuration, bridgeUID);
|
||||
logger.debug("createThing(): KEYPAD_THING: Creating '{}' type Thing - {}", thingTypeUID,
|
||||
keypadThingUID.getId());
|
||||
return super.createThing(thingTypeUID, configuration, keypadThingUID, bridgeUID);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"createThing(): The thing type " + thingTypeUID + " is not supported by the DSC Alarm binding.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Envisalink Bridge Thing UID.
|
||||
*
|
||||
* @param thingTypeUID
|
||||
* @param thingUID
|
||||
* @param configuration
|
||||
* @return thingUID
|
||||
*/
|
||||
private ThingUID getEnvisalinkBridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID,
|
||||
Configuration configuration) {
|
||||
if (thingUID == null) {
|
||||
String ipAddress = (String) configuration.get(EnvisalinkBridgeConfiguration.IP_ADDRESS);
|
||||
String bridgeID = ipAddress.replace('.', '_');
|
||||
thingUID = new ThingUID(thingTypeUID, bridgeID);
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IT-100 Bridge Thing UID.
|
||||
*
|
||||
* @param thingTypeUID
|
||||
* @param thingUID
|
||||
* @param configuration
|
||||
* @return thingUID
|
||||
*/
|
||||
private ThingUID getIT100BridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration) {
|
||||
if (thingUID == null) {
|
||||
String serialPort = (String) configuration.get(IT100BridgeConfiguration.SERIAL_PORT);
|
||||
String bridgeID = serialPort.replace('.', '_');
|
||||
thingUID = new ThingUID(thingTypeUID, bridgeID);
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IT-100 Bridge Thing UID.
|
||||
*
|
||||
* @param thingTypeUID
|
||||
* @param thingUID
|
||||
* @param configuration
|
||||
* @return thingUID
|
||||
*/
|
||||
private ThingUID getTCPServerBridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID,
|
||||
Configuration configuration) {
|
||||
if (thingUID == null) {
|
||||
String ipAddress = (String) configuration.get(TCPServerBridgeConfiguration.IP_ADDRESS);
|
||||
String port = (String) configuration.get(TCPServerBridgeConfiguration.PORT);
|
||||
String bridgeID = ipAddress.replace('.', '_') + "_" + port;
|
||||
thingUID = new ThingUID(thingTypeUID, bridgeID);
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Panel Thing UID.
|
||||
*
|
||||
* @param thingTypeUID
|
||||
* @param thingUID
|
||||
* @param configuration
|
||||
* @param bridgeUID
|
||||
* @return thingUID
|
||||
*/
|
||||
private ThingUID getDSCAlarmPanelUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
|
||||
ThingUID bridgeUID) {
|
||||
if (thingUID == null) {
|
||||
String panelId = "panel";
|
||||
thingUID = new ThingUID(thingTypeUID, panelId, bridgeUID.getId());
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Partition Thing UID.
|
||||
*
|
||||
* @param thingTypeUID
|
||||
* @param thingUID
|
||||
* @param configuration
|
||||
* @param bridgeUID
|
||||
* @return thingUID
|
||||
*/
|
||||
private ThingUID getDSCAlarmPartitionUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
|
||||
ThingUID bridgeUID) {
|
||||
if (thingUID == null) {
|
||||
String partitionId = "partition"
|
||||
+ (String) configuration.get(DSCAlarmPartitionConfiguration.PARTITION_NUMBER);
|
||||
thingUID = new ThingUID(thingTypeUID, partitionId, bridgeUID.getId());
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Zone Thing UID.
|
||||
*
|
||||
* @param thingTypeUID
|
||||
* @param thingUID
|
||||
* @param configuration
|
||||
* @param bridgeUID
|
||||
* @return thingUID
|
||||
*/
|
||||
private ThingUID getDSCAlarmZoneUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
|
||||
ThingUID bridgeUID) {
|
||||
if (thingUID == null) {
|
||||
String zoneId = "zone" + (String) configuration.get(DSCAlarmZoneConfiguration.ZONE_NUMBER);
|
||||
thingUID = new ThingUID(thingTypeUID, zoneId, bridgeUID.getId());
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Keypad Thing UID.
|
||||
*
|
||||
* @param thingTypeUID
|
||||
* @param thingUID
|
||||
* @param configuration
|
||||
* @param bridgeUID
|
||||
* @return thingUID
|
||||
*/
|
||||
private ThingUID getDSCAlarmKeypadUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
|
||||
ThingUID bridgeUID) {
|
||||
if (thingUID == null) {
|
||||
String keypadId = "keypad";
|
||||
thingUID = new ThingUID(thingTypeUID, keypadId, bridgeUID.getId());
|
||||
}
|
||||
return thingUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Thing Discovery Service for a bridge.
|
||||
*
|
||||
* @param dscAlarmBridgeHandler
|
||||
*/
|
||||
private void registerDSCAlarmDiscoveryService(DSCAlarmBaseBridgeHandler dscAlarmBridgeHandler) {
|
||||
DSCAlarmDiscoveryService discoveryService = new DSCAlarmDiscoveryService(dscAlarmBridgeHandler);
|
||||
discoveryService.activate();
|
||||
|
||||
ServiceRegistration<?> discoveryServiceRegistration = bundleContext
|
||||
.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>());
|
||||
discoveryServiceRegistrations.put(dscAlarmBridgeHandler.getThing().getUID(), discoveryServiceRegistration);
|
||||
|
||||
logger.debug("registerDSCAlarmDiscoveryService(): Bridge Handler - {}, Class Name - {}, Discovery Service - {}",
|
||||
dscAlarmBridgeHandler, DiscoveryService.class.getName(), discoveryService);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(DSCAlarmBindingConstants.ENVISALINKBRIDGE_THING_TYPE)) {
|
||||
EnvisalinkBridgeHandler handler = new EnvisalinkBridgeHandler((Bridge) thing);
|
||||
registerDSCAlarmDiscoveryService(handler);
|
||||
logger.debug("createHandler(): ENVISALINKBRIDGE_THING: ThingHandler created for {}", thingTypeUID);
|
||||
return handler;
|
||||
} else if (thingTypeUID.equals(DSCAlarmBindingConstants.IT100BRIDGE_THING_TYPE)) {
|
||||
IT100BridgeHandler handler = new IT100BridgeHandler((Bridge) thing, serialPortManager);
|
||||
registerDSCAlarmDiscoveryService(handler);
|
||||
logger.debug("createHandler(): IT100BRIDGE_THING: ThingHandler created for {}", thingTypeUID);
|
||||
return handler;
|
||||
} else if (thingTypeUID.equals(DSCAlarmBindingConstants.TCPSERVERBRIDGE_THING_TYPE)) {
|
||||
TCPServerBridgeHandler handler = new TCPServerBridgeHandler((Bridge) thing);
|
||||
registerDSCAlarmDiscoveryService(handler);
|
||||
logger.debug("createHandler(): TCPSERVERBRIDGE_THING: ThingHandler created for {}", thingTypeUID);
|
||||
return handler;
|
||||
} else if (thingTypeUID.equals(DSCAlarmBindingConstants.PANEL_THING_TYPE)) {
|
||||
logger.debug("createHandler(): PANEL_THING: ThingHandler created for {}", thingTypeUID);
|
||||
return new PanelThingHandler(thing);
|
||||
} else if (thingTypeUID.equals(DSCAlarmBindingConstants.PARTITION_THING_TYPE)) {
|
||||
logger.debug("createHandler(): PARTITION_THING: ThingHandler created for {}", thingTypeUID);
|
||||
return new PartitionThingHandler(thing);
|
||||
} else if (thingTypeUID.equals(DSCAlarmBindingConstants.ZONE_THING_TYPE)) {
|
||||
logger.debug("createHandler(): ZONE_THING: ThingHandler created for {}", thingTypeUID);
|
||||
return new ZoneThingHandler(thing);
|
||||
} else if (thingTypeUID.equals(DSCAlarmBindingConstants.KEYPAD_THING_TYPE)) {
|
||||
logger.debug("createHandler(): KEYPAD_THING: ThingHandler created for {}", thingTypeUID);
|
||||
return new KeypadThingHandler(thing);
|
||||
} else {
|
||||
logger.debug("createHandler(): ThingHandler not found for {}", thingTypeUID);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeHandler(ThingHandler thingHandler) {
|
||||
ServiceRegistration<?> discoveryServiceRegistration = discoveryServiceRegistrations
|
||||
.get(thingHandler.getThing().getUID());
|
||||
|
||||
if (discoveryServiceRegistration != null) {
|
||||
DSCAlarmDiscoveryService discoveryService = (DSCAlarmDiscoveryService) bundleContext
|
||||
.getService(discoveryServiceRegistration.getReference());
|
||||
discoveryService.deactivate();
|
||||
discoveryServiceRegistration.unregister();
|
||||
discoveryServiceRegistration = null;
|
||||
discoveryServiceRegistrations.remove(thingHandler.getThing().getUID());
|
||||
}
|
||||
|
||||
super.removeHandler(thingHandler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,845 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
import static org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmCode;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmEvent;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage.DSCAlarmMessageInfoType;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage.DSCAlarmMessageType;
|
||||
import org.openhab.binding.dscalarm.internal.config.DSCAlarmPartitionConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.config.DSCAlarmZoneConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.discovery.DSCAlarmDiscoveryService;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Abstract class for a DSC Alarm Bridge Handler.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public abstract class DSCAlarmBaseBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DSCAlarmBaseBridgeHandler.class);
|
||||
|
||||
/** The DSC Alarm bridge type. */
|
||||
private DSCAlarmBridgeType dscAlarmBridgeType = null;
|
||||
|
||||
/** The DSC Alarm bridge type. */
|
||||
private DSCAlarmProtocol dscAlarmProtocol = null;
|
||||
|
||||
/** The DSC Alarm Discovery Service. */
|
||||
private DSCAlarmDiscoveryService dscAlarmDiscoveryService = null;
|
||||
|
||||
/** The Panel Thing handler for the bridge. */
|
||||
private DSCAlarmBaseThingHandler panelThingHandler = null;
|
||||
|
||||
/** Connection status for the bridge. */
|
||||
private boolean connected = false;
|
||||
|
||||
/** Determines if things have changed. */
|
||||
private boolean thingsHaveChanged = false;
|
||||
|
||||
/** Determines if all things have been initialized. */
|
||||
private boolean allThingsInitialized = false;
|
||||
|
||||
/** Thing count. */
|
||||
private int thingCount = 0;
|
||||
|
||||
/** Password for bridge connection authentication. */
|
||||
private String password = null;
|
||||
|
||||
/** User Code for some DSC Alarm commands. */
|
||||
private String userCode = null;
|
||||
|
||||
// Polling variables
|
||||
protected int pollPeriod = 0;
|
||||
private long pollElapsedTime = 0;
|
||||
private long pollStartTime = 0;
|
||||
private long refreshInterval = 5000;
|
||||
|
||||
private ScheduledFuture<?> pollingTask;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param bridge
|
||||
* @param dscAlarmBridgeType
|
||||
*/
|
||||
DSCAlarmBaseBridgeHandler(Bridge bridge, DSCAlarmBridgeType dscAlarmBridgeType, DSCAlarmProtocol dscAlarmProtocol) {
|
||||
super(bridge);
|
||||
this.dscAlarmBridgeType = dscAlarmBridgeType;
|
||||
this.dscAlarmProtocol = dscAlarmProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bridge type.
|
||||
*/
|
||||
public DSCAlarmBridgeType getBridgeType() {
|
||||
return dscAlarmBridgeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the protocol.
|
||||
*
|
||||
* @param dscAlarmProtocol
|
||||
*/
|
||||
public void setProtocol(DSCAlarmProtocol dscAlarmProtocol) {
|
||||
this.dscAlarmProtocol = dscAlarmProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol.
|
||||
*/
|
||||
public DSCAlarmProtocol getProtocol() {
|
||||
return dscAlarmProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bridge type.
|
||||
*
|
||||
* @param dscAlarmBridgeType
|
||||
*/
|
||||
public void setBridgeType(DSCAlarmBridgeType dscAlarmBridgeType) {
|
||||
this.dscAlarmBridgeType = dscAlarmBridgeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
if (this.pollPeriod > 15) {
|
||||
this.pollPeriod = 15;
|
||||
} else if (this.pollPeriod < 1) {
|
||||
this.pollPeriod = 1;
|
||||
}
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
startPolling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
stopPolling();
|
||||
closeConnection();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Discovery Service.
|
||||
*
|
||||
* @param discoveryService
|
||||
*/
|
||||
public void registerDiscoveryService(DSCAlarmDiscoveryService discoveryService) {
|
||||
if (discoveryService == null) {
|
||||
throw new IllegalArgumentException("registerDiscoveryService(): Illegal Argument. Not allowed to be Null!");
|
||||
} else {
|
||||
this.dscAlarmDiscoveryService = discoveryService;
|
||||
logger.trace("registerDiscoveryService(): Discovery Service Registered!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the Discovery Service.
|
||||
*/
|
||||
public void unregisterDiscoveryService() {
|
||||
dscAlarmDiscoveryService = null;
|
||||
logger.trace("unregisterDiscoveryService(): Discovery Service Unregistered!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect The Bridge.
|
||||
*/
|
||||
private void connect() {
|
||||
openConnection();
|
||||
|
||||
if (isConnected()) {
|
||||
if (dscAlarmBridgeType != DSCAlarmBridgeType.Envisalink) {
|
||||
onConnected();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs when connected.
|
||||
*/
|
||||
public void onConnected() {
|
||||
logger.debug("onConnected(): Bridge Connected!");
|
||||
|
||||
setBridgeStatus(true);
|
||||
|
||||
thingsHaveChanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect The Bridge.
|
||||
*/
|
||||
private void disconnect() {
|
||||
closeConnection();
|
||||
|
||||
if (!isConnected()) {
|
||||
setBridgeStatus(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Connected.
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return this.connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Connected.
|
||||
*/
|
||||
public void setConnected(boolean connected) {
|
||||
this.connected = connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Bridge Status.
|
||||
*
|
||||
* @param isOnline
|
||||
*/
|
||||
public void setBridgeStatus(boolean isOnline) {
|
||||
logger.debug("setBridgeStatus(): Setting Bridge to {}", isOnline ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
|
||||
|
||||
updateStatus(isOnline ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
|
||||
|
||||
ChannelUID channelUID = new ChannelUID(getThing().getUID(), BRIDGE_RESET);
|
||||
updateState(channelUID, isOnline ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for opening a connection to DSC Alarm.
|
||||
*/
|
||||
abstract void openConnection();
|
||||
|
||||
/**
|
||||
* Method for closing a connection to DSC Alarm.
|
||||
*/
|
||||
abstract void closeConnection();
|
||||
|
||||
/**
|
||||
* Method for writing to an open DSC Alarm connection.
|
||||
*
|
||||
* @param writeString
|
||||
* @param doNotLog
|
||||
*/
|
||||
public abstract void write(String writeString, boolean doNotLog);
|
||||
|
||||
/**
|
||||
* Method for reading from an open DSC Alarm connection.
|
||||
*/
|
||||
public abstract String read();
|
||||
|
||||
/**
|
||||
* Get Bridge Password.
|
||||
*/
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Bridge Password.
|
||||
*
|
||||
* @param password
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Panel User Code.
|
||||
*/
|
||||
public String getUserCode() {
|
||||
return this.userCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Panel User Code.
|
||||
*
|
||||
* @param userCode
|
||||
*/
|
||||
public void setUserCode(String userCode) {
|
||||
this.userCode = userCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to start the polling task.
|
||||
*/
|
||||
private void startPolling() {
|
||||
logger.debug("Starting DSC Alarm Polling Task.");
|
||||
if (pollingTask == null || pollingTask.isCancelled()) {
|
||||
pollingTask = scheduler.scheduleWithFixedDelay(this::polling, 0, refreshInterval, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to stop the polling task.
|
||||
*/
|
||||
private void stopPolling() {
|
||||
logger.debug("Stopping DSC Alarm Polling Task.");
|
||||
if (pollingTask != null && !pollingTask.isCancelled()) {
|
||||
pollingTask.cancel(true);
|
||||
pollingTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for polling the DSC Alarm System.
|
||||
*/
|
||||
public synchronized void polling() {
|
||||
logger.debug("DSC Alarm Polling Task - '{}' is {}", getThing().getUID(), getThing().getStatus());
|
||||
|
||||
if (isConnected()) {
|
||||
if (pollStartTime == 0) {
|
||||
pollStartTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
pollElapsedTime = ((System.currentTimeMillis() - pollStartTime) / 1000) / 60;
|
||||
|
||||
// Send Poll command to the DSC Alarm if idle for 'pollPeriod'
|
||||
// minutes
|
||||
if (pollElapsedTime >= pollPeriod) {
|
||||
sendCommand(DSCAlarmCode.Poll);
|
||||
pollStartTime = 0;
|
||||
}
|
||||
|
||||
checkThings();
|
||||
|
||||
if (thingsHaveChanged && allThingsInitialized) {
|
||||
this.setBridgeStatus(isConnected());
|
||||
thingsHaveChanged = false;
|
||||
// Get a status report from DSC Alarm.
|
||||
sendCommand(DSCAlarmCode.StatusReport);
|
||||
}
|
||||
} else {
|
||||
logger.error("Not Connected to the DSC Alarm!");
|
||||
connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if things have changed.
|
||||
*/
|
||||
public void checkThings() {
|
||||
logger.debug("Checking Things!");
|
||||
|
||||
allThingsInitialized = true;
|
||||
|
||||
List<Thing> things = getThing().getThings();
|
||||
|
||||
if (things.size() != thingCount) {
|
||||
thingsHaveChanged = true;
|
||||
thingCount = things.size();
|
||||
}
|
||||
|
||||
for (Thing thing : things) {
|
||||
|
||||
DSCAlarmBaseThingHandler handler = (DSCAlarmBaseThingHandler) thing.getHandler();
|
||||
|
||||
if (handler != null) {
|
||||
logger.debug("***Checking '{}' - Status: {}, Initialized: {}", thing.getUID(), thing.getStatus(),
|
||||
handler.isThingHandlerInitialized());
|
||||
|
||||
if (!handler.isThingHandlerInitialized() || thing.getStatus() != ThingStatus.ONLINE) {
|
||||
allThingsInitialized = false;
|
||||
}
|
||||
|
||||
if (handler.getDSCAlarmThingType().equals(DSCAlarmThingType.PANEL)) {
|
||||
if (panelThingHandler == null) {
|
||||
panelThingHandler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
logger.error("checkThings(): Thing handler not found!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a Thing.
|
||||
*
|
||||
* @param dscAlarmThingType
|
||||
* @param partitionId
|
||||
* @param zoneId
|
||||
* @return thing
|
||||
*/
|
||||
public Thing findThing(DSCAlarmThingType dscAlarmThingType, int partitionId, int zoneId) {
|
||||
List<Thing> things = getThing().getThings();
|
||||
|
||||
Thing thing = null;
|
||||
|
||||
for (Thing t : things) {
|
||||
try {
|
||||
Configuration config = t.getConfiguration();
|
||||
DSCAlarmBaseThingHandler handler = (DSCAlarmBaseThingHandler) t.getHandler();
|
||||
|
||||
if (handler != null) {
|
||||
DSCAlarmThingType handlerDSCAlarmThingType = handler.getDSCAlarmThingType();
|
||||
|
||||
if (handlerDSCAlarmThingType != null) {
|
||||
if (handlerDSCAlarmThingType.equals(dscAlarmThingType)) {
|
||||
switch (handlerDSCAlarmThingType) {
|
||||
case PANEL:
|
||||
case KEYPAD:
|
||||
thing = t;
|
||||
logger.debug("findThing(): Thing Found - {}, {}, {}", t, handler,
|
||||
handlerDSCAlarmThingType);
|
||||
return thing;
|
||||
case PARTITION:
|
||||
BigDecimal partitionNumber = (BigDecimal) config
|
||||
.get(DSCAlarmPartitionConfiguration.PARTITION_NUMBER);
|
||||
if (partitionId == partitionNumber.intValue()) {
|
||||
thing = t;
|
||||
logger.debug("findThing(): Thing Found - {}, {}, {}", t, handler,
|
||||
handlerDSCAlarmThingType);
|
||||
return thing;
|
||||
}
|
||||
break;
|
||||
case ZONE:
|
||||
BigDecimal zoneNumber = (BigDecimal) config
|
||||
.get(DSCAlarmZoneConfiguration.ZONE_NUMBER);
|
||||
if (zoneId == zoneNumber.intValue()) {
|
||||
thing = t;
|
||||
logger.debug("findThing(): Thing Found - {}, {}, {}", t, handler,
|
||||
handlerDSCAlarmThingType);
|
||||
return thing;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("findThing(): Error Seaching Thing - {} ", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return thing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an incoming message from the DSC Alarm System.
|
||||
*
|
||||
* @param incomingMessage
|
||||
*/
|
||||
public synchronized void handleIncomingMessage(String incomingMessage) {
|
||||
if (incomingMessage != null && !incomingMessage.isEmpty()) {
|
||||
DSCAlarmMessage dscAlarmMessage = new DSCAlarmMessage(incomingMessage);
|
||||
DSCAlarmMessageType dscAlarmMessageType = dscAlarmMessage.getDSCAlarmMessageType();
|
||||
|
||||
logger.debug("handleIncomingMessage(): Message received: {} - {}", incomingMessage,
|
||||
dscAlarmMessage.toString());
|
||||
|
||||
DSCAlarmEvent event = new DSCAlarmEvent(this);
|
||||
event.dscAlarmEventMessage(dscAlarmMessage);
|
||||
DSCAlarmThingType dscAlarmThingType = null;
|
||||
int partitionId = 0;
|
||||
int zoneId = 0;
|
||||
|
||||
DSCAlarmCode dscAlarmCode = DSCAlarmCode
|
||||
.getDSCAlarmCodeValue(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));
|
||||
|
||||
if (panelThingHandler != null) {
|
||||
panelThingHandler.setPanelMessage(dscAlarmMessage);
|
||||
}
|
||||
|
||||
if (dscAlarmCode == DSCAlarmCode.LoginResponse) {
|
||||
String dscAlarmMessageData = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA);
|
||||
if (dscAlarmMessageData.equals("3")) {
|
||||
sendCommand(DSCAlarmCode.NetworkLogin);
|
||||
// onConnected();
|
||||
} else if (dscAlarmMessageData.equals("1")) {
|
||||
onConnected();
|
||||
}
|
||||
return;
|
||||
} else if (dscAlarmCode == DSCAlarmCode.CommandAcknowledge) {
|
||||
String dscAlarmMessageData = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA);
|
||||
if (dscAlarmMessageData.equals("000")) {
|
||||
setBridgeStatus(true);
|
||||
}
|
||||
}
|
||||
|
||||
switch (dscAlarmMessageType) {
|
||||
case PANEL_EVENT:
|
||||
dscAlarmThingType = DSCAlarmThingType.PANEL;
|
||||
break;
|
||||
case PARTITION_EVENT:
|
||||
dscAlarmThingType = DSCAlarmThingType.PARTITION;
|
||||
partitionId = Integer
|
||||
.parseInt(event.getDSCAlarmMessage().getMessageInfo(DSCAlarmMessageInfoType.PARTITION));
|
||||
break;
|
||||
case ZONE_EVENT:
|
||||
dscAlarmThingType = DSCAlarmThingType.ZONE;
|
||||
zoneId = Integer.parseInt(event.getDSCAlarmMessage().getMessageInfo(DSCAlarmMessageInfoType.ZONE));
|
||||
break;
|
||||
case KEYPAD_EVENT:
|
||||
dscAlarmThingType = DSCAlarmThingType.KEYPAD;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (dscAlarmThingType != null) {
|
||||
Thing thing = findThing(dscAlarmThingType, partitionId, zoneId);
|
||||
|
||||
logger.debug("handleIncomingMessage(): Thing Search - '{}'", thing);
|
||||
|
||||
if (thing != null) {
|
||||
DSCAlarmBaseThingHandler thingHandler = (DSCAlarmBaseThingHandler) thing.getHandler();
|
||||
|
||||
if (thingHandler != null) {
|
||||
if (thingHandler.isThingHandlerInitialized() && thing.getStatus() == ThingStatus.ONLINE) {
|
||||
thingHandler.dscAlarmEventReceived(event, thing);
|
||||
|
||||
} else {
|
||||
logger.debug("handleIncomingMessage(): Thing '{}' Not Refreshed!", thing.getUID());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.debug("handleIncomingMessage(): Thing Not Found! Send to Discovery Service!");
|
||||
|
||||
if (dscAlarmDiscoveryService != null) {
|
||||
dscAlarmDiscoveryService.addThing(getThing(), dscAlarmThingType, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.debug("handleIncomingMessage(): No Message Received!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("handleCommand(): Command Received - {} {}.", channelUID, command);
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isConnected()) {
|
||||
switch (channelUID.getId()) {
|
||||
case BRIDGE_RESET:
|
||||
if (command == OnOffType.OFF) {
|
||||
disconnect();
|
||||
}
|
||||
break;
|
||||
case SEND_COMMAND:
|
||||
if (!command.toString().isEmpty()) {
|
||||
String[] tokens = command.toString().split(",");
|
||||
|
||||
String cmd = tokens[0];
|
||||
String data = "";
|
||||
if (tokens.length > 1) {
|
||||
data = tokens[1];
|
||||
}
|
||||
|
||||
sendDSCAlarmCommand(cmd, data);
|
||||
|
||||
updateState(channelUID, new StringType(""));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to send a sequence of key presses one at a time using the '070' command.
|
||||
*
|
||||
* @param keySequence
|
||||
*/
|
||||
private boolean sendKeySequence(String keySequence) {
|
||||
logger.debug("sendKeySequence(): Sending key sequence '{}'.", keySequence);
|
||||
|
||||
boolean sent = false;
|
||||
|
||||
for (char key : keySequence.toCharArray()) {
|
||||
sent = sendCommand(DSCAlarmCode.KeyStroke, String.valueOf(key));
|
||||
|
||||
if (!sent) {
|
||||
return sent;
|
||||
}
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a DSC Alarm command
|
||||
*
|
||||
* @param command
|
||||
* @param data
|
||||
*/
|
||||
public boolean sendDSCAlarmCommand(String command, String data) {
|
||||
logger.debug("sendDSCAlarmCommand(): Attempting to send DSC Alarm Command: command - {} - data: {}", command,
|
||||
data);
|
||||
|
||||
DSCAlarmCode dscAlarmCode = DSCAlarmCode.getDSCAlarmCodeValue(command);
|
||||
|
||||
if (dscAlarmProtocol.equals(DSCAlarmProtocol.IT100_API) && dscAlarmCode.equals(DSCAlarmCode.KeySequence)) {
|
||||
return sendKeySequence(data);
|
||||
} else {
|
||||
return sendCommand(dscAlarmCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an API command to the DSC Alarm system.
|
||||
*
|
||||
* @param dscAlarmCode
|
||||
* @param dscAlarmData
|
||||
* @return successful
|
||||
*/
|
||||
public boolean sendCommand(DSCAlarmCode dscAlarmCode, String... dscAlarmData) {
|
||||
boolean successful = false;
|
||||
boolean validCommand = false;
|
||||
|
||||
String command = dscAlarmCode.getCode();
|
||||
String data = "";
|
||||
boolean confidentialData = false;
|
||||
|
||||
switch (dscAlarmCode) {
|
||||
case Poll: /* 000 */
|
||||
case StatusReport: /* 001 */
|
||||
validCommand = true;
|
||||
break;
|
||||
case LabelsRequest: /* 002 */
|
||||
if (!dscAlarmProtocol.equals(DSCAlarmProtocol.IT100_API)) {
|
||||
break;
|
||||
}
|
||||
validCommand = true;
|
||||
break;
|
||||
case NetworkLogin: /* 005 */
|
||||
if (!dscAlarmProtocol.equals(DSCAlarmProtocol.ENVISALINK_TPI)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (password == null) {
|
||||
logger.error("sendCommand(): No password!");
|
||||
break;
|
||||
}
|
||||
data = password;
|
||||
confidentialData = true;
|
||||
validCommand = true;
|
||||
break;
|
||||
case DumpZoneTimers: /* 008 */
|
||||
if (!dscAlarmProtocol.equals(DSCAlarmProtocol.ENVISALINK_TPI)) {
|
||||
break;
|
||||
}
|
||||
validCommand = true;
|
||||
break;
|
||||
case SetTimeDate: /* 010 */
|
||||
Date date = new Date();
|
||||
SimpleDateFormat dateTime = new SimpleDateFormat("HHmmMMddYY");
|
||||
data = dateTime.format(date);
|
||||
validCommand = true;
|
||||
break;
|
||||
case CommandOutputControl: /* 020 */
|
||||
if (dscAlarmData[0] == null || !dscAlarmData[0].matches("[1-8]")) {
|
||||
logger.error(
|
||||
"sendCommand(): Partition number must be a single character string from 1 to 8, it was: {}",
|
||||
dscAlarmData[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dscAlarmData[1] == null || !dscAlarmData[1].matches("[1-4]")) {
|
||||
logger.error(
|
||||
"sendCommand(): Output number must be a single character string from 1 to 4, it was: {}",
|
||||
dscAlarmData[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
data = dscAlarmData[0];
|
||||
validCommand = true;
|
||||
break;
|
||||
case KeepAlive: /* 074 */
|
||||
if (!dscAlarmProtocol.equals(DSCAlarmProtocol.ENVISALINK_TPI)) {
|
||||
break;
|
||||
}
|
||||
case PartitionArmControlAway: /* 030 */
|
||||
case PartitionArmControlStay: /* 031 */
|
||||
case PartitionArmControlZeroEntryDelay: /* 032 */
|
||||
if (dscAlarmData[0] == null || !dscAlarmData[0].matches("[1-8]")) {
|
||||
logger.error(
|
||||
"sendCommand(): Partition number must be a single character string from 1 to 8, it was: {}",
|
||||
dscAlarmData[0]);
|
||||
break;
|
||||
}
|
||||
data = dscAlarmData[0];
|
||||
validCommand = true;
|
||||
break;
|
||||
case PartitionArmControlWithUserCode: /* 033 */
|
||||
case PartitionDisarmControl: /* 040 */
|
||||
if (dscAlarmData[0] == null || !dscAlarmData[0].matches("[1-8]")) {
|
||||
logger.error(
|
||||
"sendCommand(): Partition number must be a single character string from 1 to 8, it was: {}",
|
||||
dscAlarmData[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (userCode == null || userCode.length() < 4 || userCode.length() > 6) {
|
||||
logger.error("sendCommand(): User Code is invalid, must be between 4 and 6 chars");
|
||||
break;
|
||||
}
|
||||
|
||||
if (dscAlarmProtocol.equals(DSCAlarmProtocol.IT100_API)) {
|
||||
data = dscAlarmData[0] + String.format("%-6s", userCode).replace(' ', '0');
|
||||
} else {
|
||||
data = dscAlarmData[0] + userCode;
|
||||
}
|
||||
|
||||
confidentialData = true;
|
||||
validCommand = true;
|
||||
break;
|
||||
case VirtualKeypadControl: /* 058 */
|
||||
if (!dscAlarmProtocol.equals(DSCAlarmProtocol.IT100_API)) {
|
||||
break;
|
||||
}
|
||||
case TimeStampControl: /* 055 */
|
||||
case TimeDateBroadcastControl: /* 056 */
|
||||
case TemperatureBroadcastControl: /* 057 */
|
||||
if (dscAlarmData[0] == null || !dscAlarmData[0].matches("[0-1]")) {
|
||||
logger.error("sendCommand(): Value must be a single character string of 0 or 1: {}",
|
||||
dscAlarmData[0]);
|
||||
break;
|
||||
}
|
||||
data = dscAlarmData[0];
|
||||
validCommand = true;
|
||||
break;
|
||||
case TriggerPanicAlarm: /* 060 */
|
||||
if (dscAlarmData[0] == null || !dscAlarmData[0].matches("[1-3]")) {
|
||||
logger.error("sendCommand(): FAPcode must be a single character string from 1 to 3, it was: {}",
|
||||
dscAlarmData[1]);
|
||||
break;
|
||||
}
|
||||
data = dscAlarmData[0];
|
||||
validCommand = true;
|
||||
break;
|
||||
case KeyStroke: /* 070 */
|
||||
if (dscAlarmProtocol.equals(DSCAlarmProtocol.ENVISALINK_TPI)) {
|
||||
if (dscAlarmData[0] == null || dscAlarmData[0].length() != 1
|
||||
|| !dscAlarmData[0].matches("[0-9]|A|#|\\*")) {
|
||||
logger.error(
|
||||
"sendCommand(): \'keystroke\' must be a single character string from 0 to 9, *, #, or A, it was: {}",
|
||||
dscAlarmData[0]);
|
||||
break;
|
||||
}
|
||||
} else if (dscAlarmProtocol.equals(DSCAlarmProtocol.IT100_API)) {
|
||||
if (dscAlarmData[0] == null || dscAlarmData[0].length() != 1
|
||||
|| !dscAlarmData[0].matches("[0-9]|\\*|#|F|A|P|[a-e]|<|>|=|\\^|L")) {
|
||||
logger.error(
|
||||
"sendCommand(): \'keystroke\' must be a single character string from 0 to 9, *, #, F, A, P, a to e, <, >, =, or ^, it was: {}",
|
||||
dscAlarmData[0]);
|
||||
break;
|
||||
} else if (dscAlarmData[0].equals("L")) { /* Long Key Press */
|
||||
try {
|
||||
Thread.sleep(1500);
|
||||
data = "^";
|
||||
validCommand = true;
|
||||
break;
|
||||
} catch (InterruptedException e) {
|
||||
logger.error("sendCommand(): \'keystroke\': Error with Long Key Press!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
data = dscAlarmData[0];
|
||||
validCommand = true;
|
||||
break;
|
||||
case KeySequence: /* 071 */
|
||||
if (!dscAlarmProtocol.equals(DSCAlarmProtocol.ENVISALINK_TPI)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (dscAlarmData[0] == null || dscAlarmData[0].length() > 6
|
||||
|| !dscAlarmData[0].matches("(\\d|#|\\*)+")) {
|
||||
logger.error(
|
||||
"sendCommand(): \'keysequence\' must be a string of up to 6 characters consiting of 0 to 9, *, or #, it was: {}",
|
||||
dscAlarmData[0]);
|
||||
break;
|
||||
}
|
||||
data = dscAlarmData[0];
|
||||
validCommand = true;
|
||||
break;
|
||||
case CodeSend: /* 200 */
|
||||
if (userCode == null || userCode.length() < 4 || userCode.length() > 6) {
|
||||
logger.error("sendCommand(): Access Code is invalid, must be between 4 and 6 chars");
|
||||
break;
|
||||
}
|
||||
|
||||
data = userCode;
|
||||
confidentialData = true;
|
||||
validCommand = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
validCommand = false;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (validCommand) {
|
||||
String cmd = dscAlarmCommand(command, data);
|
||||
write(cmd, confidentialData);
|
||||
successful = true;
|
||||
logger.debug("sendCommand(): '{}' Command Sent - {}", dscAlarmCode, confidentialData ? "***" : cmd);
|
||||
} else {
|
||||
logger.error("sendCommand(): Command '{}' Not Sent - Invalid!", dscAlarmCode);
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
private String dscAlarmCommand(String command, String data) {
|
||||
int sum = 0;
|
||||
|
||||
String cmd = command + data;
|
||||
|
||||
for (int i = 0; i < cmd.length(); i++) {
|
||||
char c = cmd.charAt(i);
|
||||
sum += c;
|
||||
}
|
||||
|
||||
sum &= 0xFF;
|
||||
|
||||
String strChecksum = Integer.toHexString(sum >> 4) + Integer.toHexString(sum & 0xF);
|
||||
|
||||
return cmd + strChecksum.toUpperCase() + "\r\n";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
import static org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants.PANEL_MESSAGE;
|
||||
|
||||
import java.util.EventObject;
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmCode;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage.DSCAlarmMessageInfoType;
|
||||
import org.openhab.binding.dscalarm.internal.config.DSCAlarmPanelConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.config.DSCAlarmPartitionConfiguration;
|
||||
import org.openhab.binding.dscalarm.internal.config.DSCAlarmZoneConfiguration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Abstract class for a DSC Alarm Thing Handler.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public abstract class DSCAlarmBaseThingHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DSCAlarmBaseThingHandler.class);
|
||||
|
||||
/** Bridge Handler for the Thing. */
|
||||
public DSCAlarmBaseBridgeHandler dscAlarmBridgeHandler = null;
|
||||
|
||||
/** DSC Alarm Thing type. */
|
||||
private DSCAlarmThingType dscAlarmThingType = null;
|
||||
|
||||
/** DSC Alarm Properties. */
|
||||
|
||||
private boolean thingHandlerInitialized = false;
|
||||
|
||||
/** User Code for some DSC Alarm commands. */
|
||||
private String userCode = null;
|
||||
|
||||
/** Suppress Acknowledge messages when received. */
|
||||
private boolean suppressAcknowledgementMsgs = false;
|
||||
|
||||
/** Partition Number. */
|
||||
private int partitionNumber;
|
||||
|
||||
/** Zone Number. */
|
||||
private int zoneNumber;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param thing
|
||||
*/
|
||||
public DSCAlarmBaseThingHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing DSC Alarm Thing handler - Thing Type: {}; Thing ID: {}.", dscAlarmThingType,
|
||||
this.getThing().getUID());
|
||||
|
||||
getConfiguration(dscAlarmThingType);
|
||||
|
||||
Bridge bridge = getBridge();
|
||||
initializeThingHandler(bridge != null ? bridge.getStatus() : null);
|
||||
this.setThingHandlerInitialized(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Thing {} disposed.", getThing().getUID());
|
||||
this.setThingHandlerInitialized(false);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to Initialize Thing Handler.
|
||||
*/
|
||||
private void initializeThingHandler(ThingStatus bridgeStatus) {
|
||||
if (getDSCAlarmBridgeHandler() != null && bridgeStatus != null) {
|
||||
if (bridgeStatus == ThingStatus.ONLINE) {
|
||||
Thing thing = getThing();
|
||||
List<Channel> channels = thing.getChannels();
|
||||
logger.debug("initializeThingHandler(): Initialize Thing Handler - {}", thing.getUID());
|
||||
|
||||
for (Channel channel : channels) {
|
||||
if (channel.getAcceptedItemType().equals("DateTime")) {
|
||||
updateChannel(channel.getUID(), 0, "0000010100");
|
||||
} else {
|
||||
updateChannel(channel.getUID(), 0, "");
|
||||
}
|
||||
}
|
||||
|
||||
if (dscAlarmThingType.equals(DSCAlarmThingType.PANEL)) {
|
||||
dscAlarmBridgeHandler.setUserCode(getUserCode());
|
||||
}
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
|
||||
logger.debug("initializeThingHandler(): Thing Handler Initialized - {}", thing.getUID());
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
logger.debug("initializeThingHandler(): Thing '{}' is set to OFFLINE because bridge is OFFLINE",
|
||||
thing.getUID());
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
|
||||
logger.debug("initializeThingHandler(): Thing '{}' is set to OFFLINE because bridge is uninitialized",
|
||||
thing.getUID());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Bridge Handler for the DSC Alarm.
|
||||
*
|
||||
* @return dscAlarmBridgeHandler
|
||||
*/
|
||||
public synchronized DSCAlarmBaseBridgeHandler getDSCAlarmBridgeHandler() {
|
||||
if (this.dscAlarmBridgeHandler == null) {
|
||||
Bridge bridge = getBridge();
|
||||
|
||||
if (bridge == null) {
|
||||
logger.debug("getDSCAlarmBridgeHandler(): Unable to get bridge!");
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.debug("getDSCAlarmBridgeHandler(): Bridge for '{}' - '{}'", getThing().getUID(), bridge.getUID());
|
||||
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
|
||||
if (handler instanceof DSCAlarmBaseBridgeHandler) {
|
||||
this.dscAlarmBridgeHandler = (DSCAlarmBaseBridgeHandler) handler;
|
||||
} else {
|
||||
logger.debug("getDSCAlarmBridgeHandler(): Unable to get bridge handler!");
|
||||
}
|
||||
}
|
||||
|
||||
return this.dscAlarmBridgeHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to Update a Channel
|
||||
*
|
||||
* @param channel
|
||||
* @param state
|
||||
* @param description
|
||||
*/
|
||||
public abstract void updateChannel(ChannelUID channel, int state, String description);
|
||||
|
||||
/**
|
||||
* Receives DSC Alarm Events from the bridge.
|
||||
*
|
||||
* @param event.
|
||||
* @param thing
|
||||
*/
|
||||
public abstract void dscAlarmEventReceived(EventObject event, Thing thing);
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
logger.debug("bridgeStatusChanged(): Bridge Status: '{}' - Thing '{}' Status: '{}'!", bridgeStatusInfo,
|
||||
getThing().getUID(), getThing().getStatus());
|
||||
initializeThingHandler(bridgeStatusInfo.getStatus());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the thing configuration.
|
||||
*
|
||||
* @param dscAlarmDeviceType
|
||||
*/
|
||||
private void getConfiguration(DSCAlarmThingType dscAlarmDeviceType) {
|
||||
switch (dscAlarmDeviceType) {
|
||||
case PANEL:
|
||||
DSCAlarmPanelConfiguration panelConfiguration = getConfigAs(DSCAlarmPanelConfiguration.class);
|
||||
setUserCode(panelConfiguration.userCode);
|
||||
setSuppressAcknowledgementMsgs(panelConfiguration.suppressAcknowledgementMsgs);
|
||||
break;
|
||||
case PARTITION:
|
||||
DSCAlarmPartitionConfiguration partitionConfiguration = getConfigAs(
|
||||
DSCAlarmPartitionConfiguration.class);
|
||||
setPartitionNumber(partitionConfiguration.partitionNumber.intValue());
|
||||
break;
|
||||
case ZONE:
|
||||
DSCAlarmZoneConfiguration zoneConfiguration = getConfigAs(DSCAlarmZoneConfiguration.class);
|
||||
setPartitionNumber(zoneConfiguration.partitionNumber.intValue());
|
||||
setZoneNumber(zoneConfiguration.zoneNumber.intValue());
|
||||
break;
|
||||
case KEYPAD:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSC Alarm Thing type.
|
||||
*
|
||||
* @return dscAlarmThingType
|
||||
*/
|
||||
public DSCAlarmThingType getDSCAlarmThingType() {
|
||||
return dscAlarmThingType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the DSC Alarm Thing type.
|
||||
*
|
||||
* @param dscAlarmDeviceType
|
||||
*/
|
||||
public void setDSCAlarmThingType(DSCAlarmThingType dscAlarmDeviceType) {
|
||||
if (dscAlarmDeviceType == null) {
|
||||
String thingType = getThing().getThingTypeUID().toString().split(":")[1];
|
||||
this.dscAlarmThingType = DSCAlarmThingType.getDSCAlarmThingType(thingType);
|
||||
} else {
|
||||
this.dscAlarmThingType = dscAlarmDeviceType;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get suppressAcknowledgementMsgs.
|
||||
*
|
||||
* @return suppressAcknowledgementMsgs
|
||||
*/
|
||||
public boolean getSuppressAcknowledgementMsgs() {
|
||||
return suppressAcknowledgementMsgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set suppressAcknowledgementMsgs.
|
||||
*
|
||||
* @param suppressAckMsgs
|
||||
*/
|
||||
public void setSuppressAcknowledgementMsgs(boolean suppressAckMsgs) {
|
||||
this.suppressAcknowledgementMsgs = suppressAckMsgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Partition Number.
|
||||
*
|
||||
* @return partitionNumber
|
||||
*/
|
||||
public int getPartitionNumber() {
|
||||
return partitionNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Partition Number.
|
||||
*
|
||||
* @param partitionNumber
|
||||
*/
|
||||
public void setPartitionNumber(int partitionNumber) {
|
||||
this.partitionNumber = partitionNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Zone Number.
|
||||
*
|
||||
* @return zoneNumber
|
||||
*/
|
||||
public int getZoneNumber() {
|
||||
return zoneNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Zone Number.
|
||||
*
|
||||
* @param zoneNumber
|
||||
*/
|
||||
public void setZoneNumber(int zoneNumber) {
|
||||
this.zoneNumber = zoneNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get User Code.
|
||||
*
|
||||
* @return userCode
|
||||
*/
|
||||
public String getUserCode() {
|
||||
return userCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set User Code.
|
||||
*
|
||||
* @param userCode
|
||||
*/
|
||||
public void setUserCode(String userCode) {
|
||||
this.userCode = userCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Channel by ChannelUID.
|
||||
*
|
||||
* @param channelUID
|
||||
*/
|
||||
public Channel getChannel(ChannelUID channelUID) {
|
||||
Channel channel = null;
|
||||
|
||||
List<Channel> channels = getThing().getChannels();
|
||||
|
||||
for (Channel ch : channels) {
|
||||
if (channelUID == ch.getUID()) {
|
||||
channel = ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Thing Handler refresh status.
|
||||
*
|
||||
* @return thingRefresh
|
||||
*/
|
||||
public boolean isThingHandlerInitialized() {
|
||||
return thingHandlerInitialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Thing Handler refresh status.
|
||||
*
|
||||
* @param deviceInitialized
|
||||
*/
|
||||
public void setThingHandlerInitialized(boolean refreshed) {
|
||||
this.thingHandlerInitialized = refreshed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set the panel message.
|
||||
*
|
||||
* @param dscAlarmMessage
|
||||
*/
|
||||
public void setPanelMessage(DSCAlarmMessage dscAlarmMessage) {
|
||||
ChannelUID channelUID = new ChannelUID(getThing().getUID(), PANEL_MESSAGE);
|
||||
String message = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DESCRIPTION);
|
||||
DSCAlarmCode dscAlarmCode = DSCAlarmCode
|
||||
.getDSCAlarmCodeValue(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));
|
||||
|
||||
if ((dscAlarmCode == DSCAlarmCode.CommandAcknowledge || dscAlarmCode == DSCAlarmCode.TimeDateBroadcast)
|
||||
&& getSuppressAcknowledgementMsgs()) {
|
||||
return;
|
||||
} else {
|
||||
updateChannel(channelUID, 0, message);
|
||||
logger.debug("setPanelMessage(): Panel Message Set to - {}", message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
/**
|
||||
* Enum class for the different bridge types.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public enum DSCAlarmBridgeType {
|
||||
Envisalink,
|
||||
IT100,
|
||||
TCPServer
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
/**
|
||||
* Enum class for the different DSC Alarm Protocol types.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public enum DSCAlarmProtocol {
|
||||
ENVISALINK_TPI,
|
||||
IT100_API
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Used to map thing types from the binding string to a ENUM value.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public enum DSCAlarmThingType {
|
||||
PANEL("panel"),
|
||||
PARTITION("partition"),
|
||||
ZONE("zone"),
|
||||
KEYPAD("keypad");
|
||||
|
||||
private String label;
|
||||
|
||||
/**
|
||||
* Lookup map to get a DSCAlarmDeviceType from its label.
|
||||
*/
|
||||
private static Map<String, DSCAlarmThingType> labelToDSCAlarmThingType;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param label
|
||||
*/
|
||||
private DSCAlarmThingType(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a HashMap that maps the string label to a DSCAlarmDeviceType enum value.
|
||||
*/
|
||||
private static void initMapping() {
|
||||
labelToDSCAlarmThingType = new HashMap<>();
|
||||
for (DSCAlarmThingType s : values()) {
|
||||
labelToDSCAlarmThingType.put(s.label, s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label of the DSCAlarmItemType Values enumeration.
|
||||
*
|
||||
* @return the label
|
||||
*/
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup function based on the binding type label. Returns null if the binding type is not found.
|
||||
*
|
||||
* @param label
|
||||
* @return enum value
|
||||
*/
|
||||
public static DSCAlarmThingType getDSCAlarmThingType(String label) {
|
||||
if (labelToDSCAlarmThingType == null) {
|
||||
initMapping();
|
||||
}
|
||||
return labelToDSCAlarmThingType.get(label);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.config.EnvisalinkBridgeConfiguration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The bridge handler for the EyezOn Envisalink 3/2DS Ethernet interface.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
|
||||
public class EnvisalinkBridgeHandler extends DSCAlarmBaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EnvisalinkBridgeHandler.class);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param bridge
|
||||
*/
|
||||
public EnvisalinkBridgeHandler(Bridge bridge) {
|
||||
super(bridge, DSCAlarmBridgeType.Envisalink, DSCAlarmProtocol.ENVISALINK_TPI);
|
||||
}
|
||||
|
||||
// Variables for TCP connection.
|
||||
private String ipAddress;
|
||||
private int tcpPort;
|
||||
private int connectionTimeout;
|
||||
private Socket tcpSocket = null;
|
||||
private OutputStreamWriter tcpOutput = null;
|
||||
private BufferedReader tcpInput = null;
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing the Envisalink Bridge handler.");
|
||||
|
||||
EnvisalinkBridgeConfiguration configuration = getConfigAs(EnvisalinkBridgeConfiguration.class);
|
||||
|
||||
if (configuration.ipAddress == null || configuration.ipAddress.trim().isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Set an IP address in the thing configuration.");
|
||||
} else if (configuration.port == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Set a TCP port in the thing configuration.");
|
||||
} else {
|
||||
ipAddress = configuration.ipAddress.trim();
|
||||
tcpPort = configuration.port.intValue();
|
||||
setPassword(configuration.password);
|
||||
connectionTimeout = configuration.connectionTimeout.intValue();
|
||||
pollPeriod = configuration.pollPeriod.intValue();
|
||||
|
||||
super.initialize();
|
||||
|
||||
logger.debug("Envisalink Bridge Handler Initialized");
|
||||
logger.debug(" IP Address: {},", ipAddress);
|
||||
logger.debug(" Port: {},", tcpPort);
|
||||
logger.debug(" PollPeriod: {},", pollPeriod);
|
||||
logger.debug(" Connection Timeout: {}.", connectionTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openConnection() {
|
||||
try {
|
||||
closeConnection();
|
||||
|
||||
logger.debug("openConnection(): Connecting to Envisalink ");
|
||||
|
||||
tcpSocket = new Socket();
|
||||
SocketAddress tpiSocketAddress = new InetSocketAddress(ipAddress, tcpPort);
|
||||
tcpSocket.connect(tpiSocketAddress, connectionTimeout);
|
||||
tcpOutput = new OutputStreamWriter(tcpSocket.getOutputStream(), "US-ASCII");
|
||||
tcpInput = new BufferedReader(new InputStreamReader(tcpSocket.getInputStream()));
|
||||
|
||||
Thread tcpListener = new Thread(new TCPListener());
|
||||
tcpListener.start();
|
||||
|
||||
setConnected(true);
|
||||
} catch (UnknownHostException unknownHostException) {
|
||||
logger.error("openConnection(): Unknown Host Exception: {}", unknownHostException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (SocketException socketException) {
|
||||
logger.error("openConnection(): Socket Exception: {}", socketException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (IOException ioException) {
|
||||
logger.error("openConnection(): IO Exception: {}", ioException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (Exception exception) {
|
||||
logger.error("openConnection(): Unable to open a connection: {} ", exception.getMessage(), exception);
|
||||
setConnected(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String writeString, boolean doNotLog) {
|
||||
try {
|
||||
logger.debug("write(): Attempting to Send Message: {}", doNotLog ? "***" : writeString);
|
||||
tcpOutput.write(writeString);
|
||||
tcpOutput.flush();
|
||||
} catch (IOException ioException) {
|
||||
logger.error("write(): {}", ioException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (Exception exception) {
|
||||
logger.error("write(): Unable to write to socket: {} ", exception.getMessage(), exception);
|
||||
setConnected(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String read() {
|
||||
String message = "";
|
||||
|
||||
try {
|
||||
message = tcpInput.readLine();
|
||||
logger.debug("read(): Message Received: {}", message);
|
||||
} catch (IOException ioException) {
|
||||
logger.error("read(): IO Exception: {}", ioException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (Exception exception) {
|
||||
logger.error("read(): Exception: {} ", exception.getMessage(), exception);
|
||||
setConnected(false);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection() {
|
||||
try {
|
||||
if (tcpSocket != null) {
|
||||
logger.debug("closeConnection(): Closing Socket!");
|
||||
tcpSocket.close();
|
||||
tcpSocket = null;
|
||||
tcpInput = null;
|
||||
tcpOutput = null;
|
||||
}
|
||||
setConnected(false);
|
||||
logger.debug("closeConnection(): Closed TCP Connection!");
|
||||
} catch (IOException ioException) {
|
||||
logger.error("closeConnection(): Unable to close connection - {}", ioException.getMessage());
|
||||
} catch (Exception exception) {
|
||||
logger.error("closeConnection(): Error closing connection - {}", exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IP Address of the Envisalink
|
||||
*
|
||||
* @return ipAddress
|
||||
*/
|
||||
public String getIPAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* TCPMessageListener: Receives messages from the DSC Alarm Panel API.
|
||||
*/
|
||||
private class TCPListener implements Runnable {
|
||||
private final Logger logger = LoggerFactory.getLogger(TCPListener.class);
|
||||
|
||||
/**
|
||||
* Run method. Runs the MessageListener thread
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
String messageLine;
|
||||
|
||||
try {
|
||||
while (isConnected()) {
|
||||
if ((messageLine = read()) != null) {
|
||||
try {
|
||||
handleIncomingMessage(messageLine);
|
||||
} catch (Exception e) {
|
||||
logger.error("TCPListener(): Message not handled by bridge: {}", e.getMessage());
|
||||
}
|
||||
} else {
|
||||
setConnected(false);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("TCPListener(): Unable to read message: {} ", e.getMessage(), e);
|
||||
closeConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.TooManyListenersException;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.config.IT100BridgeConfiguration;
|
||||
import org.openhab.core.io.transport.serial.PortInUseException;
|
||||
import org.openhab.core.io.transport.serial.SerialPort;
|
||||
import org.openhab.core.io.transport.serial.SerialPortEvent;
|
||||
import org.openhab.core.io.transport.serial.SerialPortEventListener;
|
||||
import org.openhab.core.io.transport.serial.SerialPortIdentifier;
|
||||
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||
import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The bridge handler for the DSC IT100 RS232 Serial interface.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
|
||||
public class IT100BridgeHandler extends DSCAlarmBaseBridgeHandler implements SerialPortEventListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(IT100BridgeHandler.class);
|
||||
private final SerialPortManager serialPortManager;
|
||||
|
||||
private String serialPortName = "";
|
||||
private int baudRate;
|
||||
private SerialPort serialPort = null;
|
||||
private OutputStreamWriter serialOutput = null;
|
||||
private BufferedReader serialInput = null;
|
||||
|
||||
public IT100BridgeHandler(Bridge bridge, SerialPortManager serialPortManager) {
|
||||
super(bridge, DSCAlarmBridgeType.IT100, DSCAlarmProtocol.IT100_API);
|
||||
this.serialPortManager = serialPortManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing the DSC IT100 Bridge handler.");
|
||||
|
||||
IT100BridgeConfiguration configuration = getConfigAs(IT100BridgeConfiguration.class);
|
||||
|
||||
if (configuration.serialPort == null || configuration.serialPort.trim().isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Set a serial port in the thing configuration.");
|
||||
} else {
|
||||
serialPortName = configuration.serialPort.trim();
|
||||
baudRate = configuration.baud.intValue();
|
||||
pollPeriod = configuration.pollPeriod.intValue();
|
||||
|
||||
super.initialize();
|
||||
|
||||
logger.debug("IT100 Bridge Handler Initialized.");
|
||||
logger.debug(" Serial Port: {},", serialPortName);
|
||||
logger.debug(" Baud: {},", baudRate);
|
||||
logger.debug(" PollPeriod: {},", pollPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openConnection() {
|
||||
logger.debug("openConnection(): Connecting to IT-100");
|
||||
|
||||
SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(serialPortName);
|
||||
if (portIdentifier == null) {
|
||||
logger.error("openConnection(): No Such Port: {}", serialPort);
|
||||
setConnected(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
SerialPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
|
||||
|
||||
serialPort = commPort;
|
||||
serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
|
||||
SerialPort.PARITY_NONE);
|
||||
serialPort.enableReceiveThreshold(1);
|
||||
serialPort.disableReceiveTimeout();
|
||||
|
||||
serialOutput = new OutputStreamWriter(serialPort.getOutputStream(), "US-ASCII");
|
||||
serialInput = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
|
||||
|
||||
setSerialEventHandler(this);
|
||||
|
||||
setConnected(true);
|
||||
} catch (PortInUseException portInUseException) {
|
||||
logger.error("openConnection(): Port in Use Exception: {}", portInUseException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (UnsupportedCommOperationException unsupportedCommOperationException) {
|
||||
logger.error("openConnection(): Unsupported Comm Operation Exception: {}",
|
||||
unsupportedCommOperationException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (UnsupportedEncodingException unsupportedEncodingException) {
|
||||
logger.error("openConnection(): Unsupported Encoding Exception: {}",
|
||||
unsupportedEncodingException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (IOException ioException) {
|
||||
logger.error("openConnection(): IO Exception: {}", ioException.getMessage());
|
||||
setConnected(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String writeString, boolean doNotLog) {
|
||||
try {
|
||||
serialOutput.write(writeString);
|
||||
serialOutput.flush();
|
||||
logger.debug("write(): Message Sent: {}", doNotLog ? "***" : writeString);
|
||||
} catch (IOException ioException) {
|
||||
logger.error("write(): {}", ioException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (Exception exception) {
|
||||
logger.error("write(): Unable to write to serial port: {} ", exception.getMessage(), exception);
|
||||
setConnected(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String read() {
|
||||
String message = "";
|
||||
|
||||
try {
|
||||
message = readLine();
|
||||
logger.debug("read(): Message Received: {}", message);
|
||||
} catch (IOException ioException) {
|
||||
logger.error("read(): IO Exception: {} ", ioException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (Exception exception) {
|
||||
logger.error("read(): Exception: {} ", exception.getMessage(), exception);
|
||||
setConnected(false);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a line from the Input Stream.
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private String readLine() throws IOException {
|
||||
return serialInput.readLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection() {
|
||||
logger.debug("closeConnection(): Closing Serial Connection!");
|
||||
|
||||
if (serialPort == null) {
|
||||
setConnected(false);
|
||||
return;
|
||||
}
|
||||
|
||||
serialPort.removeEventListener();
|
||||
|
||||
if (serialInput != null) {
|
||||
try {
|
||||
serialInput.close();
|
||||
} catch (IOException e) {
|
||||
logger.debug("Error while closing the input stream: {}", e.getMessage());
|
||||
}
|
||||
serialInput = null;
|
||||
}
|
||||
|
||||
if (serialOutput != null) {
|
||||
try {
|
||||
serialOutput.close();
|
||||
} catch (IOException e) {
|
||||
logger.debug("Error while closing the output stream: {}", e.getMessage());
|
||||
}
|
||||
serialOutput = null;
|
||||
}
|
||||
|
||||
serialPort.close();
|
||||
serialPort = null;
|
||||
|
||||
setConnected(false);
|
||||
logger.debug("close(): Serial Connection Closed!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Serial Port Name of the IT-100
|
||||
*
|
||||
* @return serialPortName
|
||||
*/
|
||||
public String getSerialPortName() {
|
||||
return serialPortName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives Serial Port Events and reads Serial Port Data.
|
||||
*
|
||||
* @param serialPortEvent
|
||||
*/
|
||||
@Override
|
||||
public synchronized void serialEvent(SerialPortEvent serialPortEvent) {
|
||||
if (serialPortEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
|
||||
try {
|
||||
String messageLine = serialInput.readLine();
|
||||
handleIncomingMessage(messageLine);
|
||||
} catch (IOException ioException) {
|
||||
logger.error("serialEvent(): IO Exception: {}", ioException.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the serial event handler.
|
||||
*
|
||||
* @param serialPortEventListenser
|
||||
*/
|
||||
private void setSerialEventHandler(SerialPortEventListener serialPortEventListenser) {
|
||||
try {
|
||||
// Add the serial port event listener
|
||||
serialPort.addEventListener(serialPortEventListenser);
|
||||
serialPort.notifyOnDataAvailable(true);
|
||||
} catch (TooManyListenersException tooManyListenersException) {
|
||||
logger.error("setSerialEventHandler(): Too Many Listeners Exception: {}",
|
||||
tooManyListenersException.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
import static org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants.*;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmCode;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmEvent;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage.DSCAlarmMessageInfoType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This is a class for handling a Zone type Thing.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public class KeypadThingHandler extends DSCAlarmBaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(KeypadThingHandler.class);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param thing
|
||||
*/
|
||||
public KeypadThingHandler(Thing thing) {
|
||||
super(thing);
|
||||
setDSCAlarmThingType(DSCAlarmThingType.KEYPAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannel(ChannelUID channelUID, int state, String description) {
|
||||
logger.debug("updateChannel(): Keypad Channel UID: {}", channelUID);
|
||||
if (channelUID != null) {
|
||||
switch (channelUID.getId()) {
|
||||
case KEYPAD_READY_LED:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case KEYPAD_ARMED_LED:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case KEYPAD_MEMORY_LED:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case KEYPAD_BYPASS_LED:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case KEYPAD_TROUBLE_LED:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case KEYPAD_PROGRAM_LED:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case KEYPAD_FIRE_LED:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case KEYPAD_BACKLIGHT_LED:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case KEYPAD_AC_LED:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case KEYPAD_LCD_UPDATE:
|
||||
case KEYPAD_LCD_CURSOR:
|
||||
updateState(channelUID, new StringType(description));
|
||||
break;
|
||||
default:
|
||||
logger.debug("updateChannel(): Keypad Channel not updated - {}.", channelUID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 dscAlarmMessage = 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 dscAlarmCode = DSCAlarmCode
|
||||
.getDSCAlarmCodeValue(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));
|
||||
|
||||
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);
|
||||
|
||||
switch (dscAlarmCode) {
|
||||
case KeypadLEDState: /* 510 */
|
||||
updateChannel(channelUID, bits[i] != 0 ? 1 : 0, "");
|
||||
break;
|
||||
case KeypadLEDFlashState: /* 511 */
|
||||
if (bits[i] != 0) {
|
||||
updateChannel(channelUID, 2, "");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dscAlarmEventReceived(EventObject event, Thing thing) {
|
||||
if (thing != null) {
|
||||
if (getThing() == thing) {
|
||||
DSCAlarmEvent dscAlarmEvent = (DSCAlarmEvent) event;
|
||||
DSCAlarmMessage dscAlarmMessage = dscAlarmEvent.getDSCAlarmMessage();
|
||||
|
||||
ChannelUID channelUID = null;
|
||||
DSCAlarmCode dscAlarmCode = DSCAlarmCode
|
||||
.getDSCAlarmCodeValue(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));
|
||||
String dscAlarmMessageData = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA);
|
||||
|
||||
logger.debug("dscAlarmEventRecieved(): Thing - {} Command - {}", thing.getUID(), dscAlarmCode);
|
||||
|
||||
switch (dscAlarmCode) {
|
||||
case KeypadLEDState: /* 510 */
|
||||
case KeypadLEDFlashState: /* 511 */
|
||||
keypadLEDStateEventHandler(event);
|
||||
break;
|
||||
case LCDUpdate: /* 901 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_LCD_UPDATE);
|
||||
updateChannel(channelUID, 0, dscAlarmMessageData);
|
||||
break;
|
||||
case LCDCursor: /* 902 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_LCD_CURSOR);
|
||||
updateChannel(channelUID, 0, dscAlarmMessageData);
|
||||
break;
|
||||
case LEDStatus: /* 903 */
|
||||
int data = Integer.parseInt(dscAlarmMessageData.substring(0, 1));
|
||||
int state = Integer
|
||||
.parseInt(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA).substring(1));
|
||||
switch (data) {
|
||||
case 1:
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_READY_LED);
|
||||
updateChannel(channelUID, state, "");
|
||||
break;
|
||||
case 2:
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_ARMED_LED);
|
||||
updateChannel(channelUID, state, "");
|
||||
break;
|
||||
case 3:
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_MEMORY_LED);
|
||||
updateChannel(channelUID, state, "");
|
||||
break;
|
||||
case 4:
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_BYPASS_LED);
|
||||
updateChannel(channelUID, state, "");
|
||||
break;
|
||||
case 5:
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_TROUBLE_LED);
|
||||
updateChannel(channelUID, state, "");
|
||||
break;
|
||||
case 6:
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_PROGRAM_LED);
|
||||
updateChannel(channelUID, state, "");
|
||||
break;
|
||||
case 7:
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_FIRE_LED);
|
||||
updateChannel(channelUID, state, "");
|
||||
break;
|
||||
case 8:
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_BACKLIGHT_LED);
|
||||
updateChannel(channelUID, state, "");
|
||||
break;
|
||||
case 9:
|
||||
channelUID = new ChannelUID(getThing().getUID(), KEYPAD_AC_LED);
|
||||
updateChannel(channelUID, state, "");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,585 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
import static org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants.*;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.EventObject;
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmCode;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmEvent;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage.DSCAlarmMessageInfoType;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This is a class for handling a Panel type Thing.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public class PanelThingHandler extends DSCAlarmBaseThingHandler {
|
||||
|
||||
private static final int PANEL_COMMAND_POLL = 0;
|
||||
private static final int PANEL_COMMAND_STATUS_REPORT = 1;
|
||||
private static final int PANEL_COMMAND_LABELS_REQUEST = 2;
|
||||
private static final int PANEL_COMMAND_DUMP_ZONE_TIMERS = 8;
|
||||
private static final int PANEL_COMMAND_SET_TIME_DATE = 10;
|
||||
private static final int PANEL_COMMAND_CODE_SEND = 200;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PanelThingHandler.class);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param thing
|
||||
*/
|
||||
public PanelThingHandler(Thing thing) {
|
||||
super(thing);
|
||||
setDSCAlarmThingType(DSCAlarmThingType.PANEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannel(ChannelUID channelUID, int state, String description) {
|
||||
logger.debug("updateChannel(): Panel Channel UID: {}", channelUID);
|
||||
|
||||
boolean trigger;
|
||||
boolean trouble;
|
||||
boolean boolState;
|
||||
OnOffType onOffType;
|
||||
|
||||
if (channelUID != null) {
|
||||
switch (channelUID.getId()) {
|
||||
case PANEL_MESSAGE:
|
||||
updateState(channelUID, new StringType(description));
|
||||
break;
|
||||
case PANEL_SYSTEM_ERROR:
|
||||
updateState(channelUID, new StringType(description));
|
||||
break;
|
||||
case PANEL_TIME:
|
||||
Date date = null;
|
||||
SimpleDateFormat sdfReceived = new SimpleDateFormat("hhmmMMddyy");
|
||||
|
||||
try {
|
||||
date = sdfReceived.parse(description);
|
||||
} catch (ParseException e) {
|
||||
logger.warn("updateChannel(): Parse Exception occurred while trying to parse date string: {}. ",
|
||||
e.getMessage());
|
||||
}
|
||||
|
||||
if (date != null) {
|
||||
SimpleDateFormat sdfUpdate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
String systemTime = sdfUpdate.format(date);
|
||||
updateState(channelUID, new DateTimeType(systemTime));
|
||||
}
|
||||
|
||||
break;
|
||||
case PANEL_TIME_STAMP:
|
||||
boolState = state != 0;
|
||||
onOffType = boolState ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_TIME_BROADCAST:
|
||||
boolState = state != 0;
|
||||
onOffType = boolState ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_COMMAND:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case PANEL_TROUBLE_MESSAGE:
|
||||
updateState(channelUID, new StringType(description));
|
||||
break;
|
||||
case PANEL_TROUBLE_LED:
|
||||
boolState = state != 0;
|
||||
onOffType = boolState ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_SERVICE_REQUIRED:
|
||||
trouble = state != 0;
|
||||
onOffType = trouble ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_AC_TROUBLE:
|
||||
trouble = state != 0;
|
||||
onOffType = trouble ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_TELEPHONE_TROUBLE:
|
||||
trouble = state != 0;
|
||||
onOffType = trouble ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_FTC_TROUBLE:
|
||||
trouble = state != 0;
|
||||
onOffType = trouble ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_ZONE_FAULT:
|
||||
trouble = state != 0;
|
||||
onOffType = trouble ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_ZONE_TAMPER:
|
||||
trouble = state != 0;
|
||||
onOffType = trouble ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_ZONE_LOW_BATTERY:
|
||||
trouble = state != 0;
|
||||
onOffType = trouble ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_TIME_LOSS:
|
||||
trouble = state != 0;
|
||||
onOffType = trouble ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_FIRE_KEY_ALARM:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_PANIC_KEY_ALARM:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_AUX_KEY_ALARM:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PANEL_AUX_INPUT_ALARM:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
default:
|
||||
logger.debug("updateChannel(): Panel Channel not updated - {}.", channelUID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("handleCommand(): Command Received - {} {}.", channelUID, command);
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dscAlarmBridgeHandler != null && dscAlarmBridgeHandler.isConnected()) {
|
||||
int cmd;
|
||||
|
||||
switch (channelUID.getId()) {
|
||||
case PANEL_COMMAND:
|
||||
cmd = Integer.parseInt(command.toString());
|
||||
handlePanelCommand(cmd);
|
||||
updateState(channelUID, new StringType(String.valueOf(-1)));
|
||||
break;
|
||||
case PANEL_TIME_STAMP:
|
||||
if (command instanceof OnOffType) {
|
||||
cmd = command == OnOffType.ON ? 1 : 0;
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.TimeStampControl, String.valueOf(cmd));
|
||||
updateState(channelUID, (OnOffType) command);
|
||||
}
|
||||
break;
|
||||
case PANEL_TIME_BROADCAST:
|
||||
if (command instanceof OnOffType) {
|
||||
cmd = command == OnOffType.ON ? 1 : 0;
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.TimeDateBroadcastControl, String.valueOf(cmd));
|
||||
updateState(channelUID, (OnOffType) command);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to handle PANEL_COMMAND
|
||||
*
|
||||
* @param cmd
|
||||
*/
|
||||
private void handlePanelCommand(int cmd) {
|
||||
switch (cmd) {
|
||||
case PANEL_COMMAND_POLL:
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.Poll);
|
||||
break;
|
||||
case PANEL_COMMAND_STATUS_REPORT:
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.StatusReport);
|
||||
break;
|
||||
case PANEL_COMMAND_LABELS_REQUEST:
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.LabelsRequest);
|
||||
break;
|
||||
case PANEL_COMMAND_DUMP_ZONE_TIMERS:
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.DumpZoneTimers);
|
||||
break;
|
||||
case PANEL_COMMAND_SET_TIME_DATE:
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.SetTimeDate);
|
||||
break;
|
||||
case PANEL_COMMAND_CODE_SEND:
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.CodeSend, getUserCode());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set the time stamp state.
|
||||
*
|
||||
* @param timeStamp
|
||||
*/
|
||||
private void setTimeStampState(String timeStamp) {
|
||||
int state = 0;
|
||||
ChannelUID channelUID = new ChannelUID(getThing().getUID(), PANEL_TIME_STAMP);
|
||||
|
||||
boolean isTimeStamp = timeStamp != "";
|
||||
|
||||
if ((timeStamp == "" && !isTimeStamp) || (timeStamp != "" && isTimeStamp)) {
|
||||
logger.debug("setTimeStampState(): Already Set: {}", timeStamp);
|
||||
return;
|
||||
} else if (timeStamp != "") {
|
||||
state = 1;
|
||||
}
|
||||
|
||||
updateChannel(channelUID, state, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set Channel PANEL_SYSTEM_ERROR.
|
||||
*
|
||||
* @param properties
|
||||
* @param dscAlarmMessage
|
||||
*/
|
||||
private void panelSystemError(DSCAlarmMessage dscAlarmMessage) {
|
||||
ChannelUID channelUID = new ChannelUID(getThing().getUID(), PANEL_SYSTEM_ERROR);
|
||||
int systemErrorCode = 0;
|
||||
String systemErrorDescription = "";
|
||||
|
||||
if (dscAlarmMessage != null) {
|
||||
systemErrorCode = Integer.parseInt(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA));
|
||||
switch (systemErrorCode) {
|
||||
case 1:
|
||||
systemErrorDescription = "Receive Buffer Overrun";
|
||||
break;
|
||||
case 2:
|
||||
systemErrorDescription = "Receive Buffer Overflow";
|
||||
break;
|
||||
case 3:
|
||||
systemErrorDescription = "Transmit Buffer Overflow";
|
||||
break;
|
||||
case 10:
|
||||
systemErrorDescription = "Keybus Transmit Buffer Overrun";
|
||||
break;
|
||||
case 11:
|
||||
systemErrorDescription = "Keybus Transmit Time Timeout";
|
||||
break;
|
||||
case 12:
|
||||
systemErrorDescription = "Keybus Transmit Mode Timeout";
|
||||
break;
|
||||
case 13:
|
||||
systemErrorDescription = "Keybus Transmit Keystring Timeout";
|
||||
break;
|
||||
case 14:
|
||||
systemErrorDescription = "Keybus Interface Not Functioning";
|
||||
break;
|
||||
case 15:
|
||||
systemErrorDescription = "Keybus Busy - Attempting to Disarm or Arm with user code";
|
||||
break;
|
||||
case 16:
|
||||
systemErrorDescription = "Keybus Busy – Lockout";
|
||||
break;
|
||||
case 17:
|
||||
systemErrorDescription = "Keybus Busy – Installers Mode";
|
||||
break;
|
||||
case 18:
|
||||
systemErrorDescription = "Keybus Busy - General Busy";
|
||||
break;
|
||||
case 20:
|
||||
systemErrorDescription = "API Command Syntax Error";
|
||||
break;
|
||||
case 21:
|
||||
systemErrorDescription = "API Command Partition Error - Requested Partition is out of bounds";
|
||||
break;
|
||||
case 22:
|
||||
systemErrorDescription = "API Command Not Supported";
|
||||
break;
|
||||
case 23:
|
||||
systemErrorDescription = "API System Not Armed - Sent in response to a disarm command";
|
||||
break;
|
||||
case 24:
|
||||
systemErrorDescription = "API System Not Ready to Arm - System is either not-secure, in exit-delay, or already armed";
|
||||
break;
|
||||
case 25:
|
||||
systemErrorDescription = "API Command Invalid Length";
|
||||
break;
|
||||
case 26:
|
||||
systemErrorDescription = "API User Code not Required";
|
||||
break;
|
||||
case 27:
|
||||
systemErrorDescription = "API Invalid Characters in Command - No alpha characters are allowed except for checksum";
|
||||
break;
|
||||
case 28:
|
||||
systemErrorDescription = "API Virtual Keypad is Disabled";
|
||||
break;
|
||||
case 29:
|
||||
systemErrorDescription = "API Not Valid Parameter";
|
||||
break;
|
||||
case 30:
|
||||
systemErrorDescription = "API Keypad Does Not Come Out of Blank Mode";
|
||||
break;
|
||||
case 31:
|
||||
systemErrorDescription = "API IT-100 is Already in Thermostat Menu";
|
||||
break;
|
||||
case 32:
|
||||
systemErrorDescription = "API IT-100 is NOT in Thermostat Menu";
|
||||
break;
|
||||
case 33:
|
||||
systemErrorDescription = "API No Response From Thermostat or Escort Module";
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
systemErrorDescription = "No Error";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String errorMessage = String.format("%03d", systemErrorCode) + ": " + systemErrorDescription;
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_SYSTEM_ERROR);
|
||||
updateState(channelUID, new StringType(errorMessage));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
updateChannel(channelUID, bits[i] != 0 ? 1 : 0, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores all partitions that are in alarm after special panel alarm conditions have been restored.
|
||||
*
|
||||
* @param dscAlarmCode
|
||||
*/
|
||||
private void restorePartitionsInAlarm(DSCAlarmCode dscAlarmCode) {
|
||||
logger.debug("restorePartitionsInAlarm(): DSC Alarm Code: {}!", dscAlarmCode.toString());
|
||||
|
||||
ChannelUID channelUID = null;
|
||||
|
||||
if (dscAlarmCode == DSCAlarmCode.FireKeyRestored || dscAlarmCode == DSCAlarmCode.AuxiliaryKeyRestored
|
||||
|| dscAlarmCode == DSCAlarmCode.PanicKeyRestored
|
||||
|| dscAlarmCode == DSCAlarmCode.AuxiliaryInputAlarmRestored) {
|
||||
List<Thing> things = dscAlarmBridgeHandler.getThing().getThings();
|
||||
for (Thing thg : things) {
|
||||
if (thg.getThingTypeUID().equals(PARTITION_THING_TYPE)) {
|
||||
DSCAlarmBaseThingHandler handler = (DSCAlarmBaseThingHandler) thg.getHandler();
|
||||
if (handler != null) {
|
||||
channelUID = new ChannelUID(thg.getUID(), PARTITION_IN_ALARM);
|
||||
handler.updateChannel(channelUID, 0, "");
|
||||
|
||||
logger.debug("restorePartitionsInAlarm(): Partition In Alarm Restored: {}!", thg.getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dscAlarmEventReceived(EventObject event, Thing thing) {
|
||||
if (thing != null) {
|
||||
DSCAlarmEvent dscAlarmEvent = (DSCAlarmEvent) event;
|
||||
DSCAlarmMessage dscAlarmMessage = dscAlarmEvent.getDSCAlarmMessage();
|
||||
String dscAlarmMessageData = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA);
|
||||
setTimeStampState(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.TIME_STAMP));
|
||||
|
||||
if (getThing() == thing) {
|
||||
ChannelUID channelUID = null;
|
||||
DSCAlarmCode dscAlarmCode = DSCAlarmCode
|
||||
.getDSCAlarmCodeValue(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));
|
||||
logger.debug("dscAlarmEventRecieved(): Thing - {} Command - {}", thing.getUID(), dscAlarmCode);
|
||||
|
||||
int state = 0;
|
||||
|
||||
switch (dscAlarmCode) {
|
||||
case CommandAcknowledge: /* 500 */
|
||||
break;
|
||||
case SystemError: /* 502 */
|
||||
int errorCode = Integer.parseInt(dscAlarmMessageData);
|
||||
|
||||
if (errorCode == 23 || errorCode == 24) {
|
||||
List<Thing> things = dscAlarmBridgeHandler.getThing().getThings();
|
||||
for (Thing thg : things) {
|
||||
if (thg.getThingTypeUID().equals(PARTITION_THING_TYPE)) {
|
||||
DSCAlarmBaseThingHandler handler = (DSCAlarmBaseThingHandler) thg.getHandler();
|
||||
if (handler != null) {
|
||||
channelUID = new ChannelUID(thg.getUID(), PARTITION_ARM_MODE);
|
||||
handler.updateChannel(channelUID, 0, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
panelSystemError(dscAlarmMessage);
|
||||
break;
|
||||
case TimeDateBroadcast: /* 550 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_TIME);
|
||||
String panelTime = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DATA);
|
||||
updateChannel(channelUID, state, panelTime);
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_TIME_BROADCAST);
|
||||
updateChannel(channelUID, 1, "");
|
||||
break;
|
||||
case FireKeyAlarm: /* 621 */
|
||||
state = 1;
|
||||
case FireKeyRestored: /* 622 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_FIRE_KEY_ALARM);
|
||||
updateChannel(channelUID, state, "");
|
||||
restorePartitionsInAlarm(dscAlarmCode);
|
||||
break;
|
||||
case AuxiliaryKeyAlarm: /* 623 */
|
||||
state = 1;
|
||||
case AuxiliaryKeyRestored: /* 624 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_AUX_KEY_ALARM);
|
||||
updateChannel(channelUID, state, "");
|
||||
restorePartitionsInAlarm(dscAlarmCode);
|
||||
break;
|
||||
case PanicKeyAlarm: /* 625 */
|
||||
state = 1;
|
||||
case PanicKeyRestored: /* 626 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_PANIC_KEY_ALARM);
|
||||
updateChannel(channelUID, state, "");
|
||||
restorePartitionsInAlarm(dscAlarmCode);
|
||||
break;
|
||||
case AuxiliaryInputAlarm: /* 631 */
|
||||
state = 1;
|
||||
case AuxiliaryInputAlarmRestored: /* 632 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_AUX_INPUT_ALARM);
|
||||
updateChannel(channelUID, state, "");
|
||||
restorePartitionsInAlarm(dscAlarmCode);
|
||||
break;
|
||||
case TroubleLEDOn: /* 840 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_TROUBLE_LED);
|
||||
updateChannel(channelUID, 1, "");
|
||||
break;
|
||||
case TroubleLEDOff: /* 841 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_SERVICE_REQUIRED);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_AC_TROUBLE);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_TELEPHONE_TROUBLE);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_FTC_TROUBLE);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_ZONE_FAULT);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_ZONE_TAMPER);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_ZONE_LOW_BATTERY);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_TIME_LOSS);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PANEL_TROUBLE_LED);
|
||||
updateChannel(channelUID, 0, "");
|
||||
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);
|
||||
updateChannel(channelUID, 0,
|
||||
dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DESCRIPTION));
|
||||
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);
|
||||
updateChannel(channelUID, 0, "");
|
||||
break;
|
||||
case VerboseTroubleStatus: /* 849 */
|
||||
verboseTroubleStatusHandler(event);
|
||||
break;
|
||||
case CodeRequired: /* 900 */
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.CodeSend, getUserCode());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
import static org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants.*;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmCode;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmEvent;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage.DSCAlarmMessageInfoType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This is a class for handling a Partition type Thing.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public class PartitionThingHandler extends DSCAlarmBaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PartitionThingHandler.class);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param thing
|
||||
*/
|
||||
public PartitionThingHandler(Thing thing) {
|
||||
super(thing);
|
||||
setDSCAlarmThingType(DSCAlarmThingType.PARTITION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannel(ChannelUID channelUID, int state, String description) {
|
||||
logger.debug("updateChannel(): Panel Channel UID: {}", channelUID);
|
||||
|
||||
boolean trigger;
|
||||
OnOffType onOffType;
|
||||
|
||||
if (channelUID != null) {
|
||||
switch (channelUID.getId()) {
|
||||
case PARTITION_STATUS:
|
||||
updateState(channelUID, new StringType(description));
|
||||
break;
|
||||
case PARTITION_ARM_MODE:
|
||||
updateState(channelUID, new DecimalType(state));
|
||||
break;
|
||||
case PARTITION_ARMED:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PARTITION_ENTRY_DELAY:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PARTITION_EXIT_DELAY:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PARTITION_IN_ALARM:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case PARTITION_OPENING_CLOSING_MODE:
|
||||
updateState(channelUID, new StringType(description));
|
||||
break;
|
||||
default:
|
||||
logger.debug("updateChannel(): Partition Channel not updated - {}.", channelUID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("handleCommand(): Command Received - {} {}.", channelUID, command);
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dscAlarmBridgeHandler != null && dscAlarmBridgeHandler.isConnected()) {
|
||||
switch (channelUID.getId()) {
|
||||
case PARTITION_ARM_MODE:
|
||||
int partitionNumber = getPartitionNumber();
|
||||
if (command.toString().equals("0")) {
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.PartitionDisarmControl,
|
||||
String.valueOf(partitionNumber));
|
||||
} else if (command.toString().equals("1")) {
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.PartitionArmControlAway,
|
||||
String.valueOf(partitionNumber));
|
||||
} else if (command.toString().equals("2")) {
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.PartitionArmControlStay,
|
||||
String.valueOf(partitionNumber));
|
||||
} else if (command.toString().equals("3")) {
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.PartitionArmControlZeroEntryDelay,
|
||||
String.valueOf(partitionNumber));
|
||||
} else if (command.toString().equals("4")) {
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.PartitionArmControlZeroEntryDelay,
|
||||
String.valueOf(partitionNumber));
|
||||
} else if (command.toString().equals("5")) {
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.PartitionArmControlWithUserCode,
|
||||
String.valueOf(partitionNumber));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set Partition Status.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
private void partitionStatus(String message) {
|
||||
updateState(new ChannelUID(getThing().getUID(), PARTITION_STATUS), new StringType(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set Partition Close Open Mode.
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
private void partitionOpenCloseModeEventHandler(EventObject event) {
|
||||
DSCAlarmEvent dscAlarmEvent = (DSCAlarmEvent) event;
|
||||
DSCAlarmMessage dscAlarmMessage = dscAlarmEvent.getDSCAlarmMessage();
|
||||
DSCAlarmCode dscAlarmCode = DSCAlarmCode
|
||||
.getDSCAlarmCodeValue(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));
|
||||
ChannelUID channelUID = null;
|
||||
int state = 0; /*
|
||||
* 0=None, 1=User Closing, 2=Special Closing, 3=Partial Closing, 4=User Opening, 5=Special
|
||||
* Opening
|
||||
*/
|
||||
|
||||
String strStatus = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.NAME);
|
||||
|
||||
switch (dscAlarmCode) {
|
||||
case UserClosing: /* 700 */
|
||||
state = 1;
|
||||
break;
|
||||
case SpecialClosing: /* 701 */
|
||||
state = 2;
|
||||
break;
|
||||
case PartialClosing: /* 702 */
|
||||
state = 3;
|
||||
break;
|
||||
case UserOpening: /* 750 */
|
||||
state = 4;
|
||||
break;
|
||||
case SpecialOpening: /* 751 */
|
||||
state = 5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_OPENING_CLOSING_MODE);
|
||||
updateChannel(channelUID, state, strStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dscAlarmEventReceived(EventObject event, Thing thing) {
|
||||
if (thing != null) {
|
||||
if (getThing() == thing) {
|
||||
DSCAlarmEvent dscAlarmEvent = (DSCAlarmEvent) event;
|
||||
DSCAlarmMessage dscAlarmMessage = dscAlarmEvent.getDSCAlarmMessage();
|
||||
|
||||
ChannelUID channelUID = null;
|
||||
DSCAlarmCode dscAlarmCode = DSCAlarmCode
|
||||
.getDSCAlarmCodeValue(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));
|
||||
String dscAlarmMessageName = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.NAME);
|
||||
String dscAlarmMessageMode = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.MODE);
|
||||
|
||||
logger.debug("dscAlarmEventRecieved(): Thing - {} Command - {}", thing.getUID(), dscAlarmCode);
|
||||
|
||||
switch (dscAlarmCode) {
|
||||
case PartitionReady: /* 650 */
|
||||
case PartitionNotReady: /* 651 */
|
||||
case PartitionReadyForceArming: /* 653 */
|
||||
case SystemArmingInProgress: /* 674 */
|
||||
partitionStatus(dscAlarmMessageName);
|
||||
break;
|
||||
case PartitionArmed: /* 652 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_ARMED);
|
||||
updateChannel(channelUID, 1, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_ENTRY_DELAY);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_EXIT_DELAY);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
/*
|
||||
* arm mode:0=disarmed, 1=away armed, 2=stay armed, 3=away no delay, 4=stay no delay, 5=with
|
||||
* user code
|
||||
*/
|
||||
int armMode = Integer.parseInt(dscAlarmMessageMode) + 1;
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_ARM_MODE);
|
||||
updateChannel(channelUID, armMode, "");
|
||||
|
||||
partitionStatus(dscAlarmMessageName);
|
||||
break;
|
||||
case PartitionDisarmed: /* 655 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_ARMED);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_ENTRY_DELAY);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_EXIT_DELAY);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_IN_ALARM);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_ARM_MODE);
|
||||
updateChannel(channelUID, 0, "");
|
||||
|
||||
partitionStatus(dscAlarmMessageName);
|
||||
break;
|
||||
case PartitionInAlarm: /* 654 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_IN_ALARM);
|
||||
updateChannel(channelUID, 1, "");
|
||||
|
||||
partitionStatus(dscAlarmMessageName);
|
||||
break;
|
||||
case ExitDelayInProgress: /* 656 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_EXIT_DELAY);
|
||||
updateChannel(channelUID, 1, "");
|
||||
break;
|
||||
case EntryDelayInProgress: /* 657 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_ENTRY_DELAY);
|
||||
updateChannel(channelUID, 1, "");
|
||||
break;
|
||||
case FailureToArm: /* 672 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), PARTITION_ARM_MODE);
|
||||
updateChannel(channelUID, 0, "");
|
||||
partitionStatus(dscAlarmMessageName);
|
||||
break;
|
||||
case UserClosing: /* 700 */
|
||||
case SpecialClosing: /* 701 */
|
||||
case PartialClosing: /* 702 */
|
||||
case UserOpening: /* 750 */
|
||||
case SpecialOpening: /* 751 */
|
||||
partitionOpenCloseModeEventHandler(event);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.config.TCPServerBridgeConfiguration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The bridge handler for a TCP Server to connect to a DSC IT100 RS232 Serial interface over a network.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
|
||||
public class TCPServerBridgeHandler extends DSCAlarmBaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(TCPServerBridgeHandler.class);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param bridge
|
||||
*/
|
||||
public TCPServerBridgeHandler(Bridge bridge) {
|
||||
super(bridge, DSCAlarmBridgeType.TCPServer, DSCAlarmProtocol.IT100_API);
|
||||
}
|
||||
|
||||
// Variables for TCP connection.
|
||||
private String ipAddress;
|
||||
private int tcpPort;
|
||||
private int connectionTimeout;
|
||||
private int protocol;
|
||||
private Socket tcpSocket = null;
|
||||
private OutputStreamWriter tcpOutput = null;
|
||||
private BufferedReader tcpInput = null;
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing the TCP Server Bridge handler.");
|
||||
|
||||
TCPServerBridgeConfiguration configuration = getConfigAs(TCPServerBridgeConfiguration.class);
|
||||
|
||||
if (configuration.ipAddress == null || configuration.ipAddress.trim().isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Set an IP address in the thing configuration.");
|
||||
} else if (configuration.port == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Set a TCP port in the thing configuration.");
|
||||
} else {
|
||||
ipAddress = configuration.ipAddress.trim();
|
||||
tcpPort = configuration.port.intValue();
|
||||
connectionTimeout = configuration.connectionTimeout.intValue();
|
||||
pollPeriod = configuration.pollPeriod.intValue();
|
||||
protocol = configuration.protocol.intValue();
|
||||
|
||||
if (this.protocol == 2) {
|
||||
setProtocol(DSCAlarmProtocol.ENVISALINK_TPI);
|
||||
} else {
|
||||
setProtocol(DSCAlarmProtocol.IT100_API);
|
||||
}
|
||||
|
||||
super.initialize();
|
||||
|
||||
logger.debug("TCP Server Bridge Handler Initialized");
|
||||
logger.debug(" IP Address: {},", ipAddress);
|
||||
logger.debug(" Port: {},", tcpPort);
|
||||
logger.debug(" PollPeriod: {},", pollPeriod);
|
||||
logger.debug(" Connection Timeout: {}.", connectionTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openConnection() {
|
||||
try {
|
||||
closeConnection();
|
||||
|
||||
logger.debug("openConnection(): Connecting to Envisalink ");
|
||||
|
||||
tcpSocket = new Socket();
|
||||
SocketAddress tpiSocketAddress = new InetSocketAddress(ipAddress, tcpPort);
|
||||
tcpSocket.connect(tpiSocketAddress, connectionTimeout);
|
||||
tcpOutput = new OutputStreamWriter(tcpSocket.getOutputStream(), "US-ASCII");
|
||||
tcpInput = new BufferedReader(new InputStreamReader(tcpSocket.getInputStream()));
|
||||
|
||||
Thread tcpListener = new Thread(new TCPListener());
|
||||
tcpListener.start();
|
||||
|
||||
setConnected(true);
|
||||
} catch (UnknownHostException unknownHostException) {
|
||||
logger.error("openConnection(): Unknown Host Exception: {}", unknownHostException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (SocketException socketException) {
|
||||
logger.error("openConnection(): Socket Exception: {}", socketException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (IOException ioException) {
|
||||
logger.error("openConnection(): IO Exception: {}", ioException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (Exception exception) {
|
||||
logger.error("openConnection(): Unable to open a connection: {} ", exception.getMessage(), exception);
|
||||
setConnected(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String writeString, boolean doNotLog) {
|
||||
try {
|
||||
tcpOutput.write(writeString);
|
||||
tcpOutput.flush();
|
||||
logger.debug("write(): Message Sent: {}", doNotLog ? "***" : writeString);
|
||||
} catch (IOException ioException) {
|
||||
logger.error("write(): {}", ioException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (Exception exception) {
|
||||
logger.error("write(): Unable to write to socket: {} ", exception.getMessage(), exception);
|
||||
setConnected(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String read() {
|
||||
String message = "";
|
||||
|
||||
try {
|
||||
message = tcpInput.readLine();
|
||||
logger.debug("read(): Message Received: {}", message);
|
||||
} catch (IOException ioException) {
|
||||
logger.error("read(): IO Exception: {}", ioException.getMessage());
|
||||
setConnected(false);
|
||||
} catch (Exception exception) {
|
||||
logger.error("read(): Exception: {} ", exception.getMessage(), exception);
|
||||
setConnected(false);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection() {
|
||||
try {
|
||||
if (tcpSocket != null) {
|
||||
tcpSocket.close();
|
||||
tcpSocket = null;
|
||||
tcpInput = null;
|
||||
tcpOutput = null;
|
||||
}
|
||||
setConnected(false);
|
||||
logger.debug("closeConnection(): Closed TCP Connection!");
|
||||
} catch (IOException ioException) {
|
||||
logger.error("closeConnection(): Unable to close connection - {}", ioException.getMessage());
|
||||
} catch (Exception exception) {
|
||||
logger.error("closeConnection(): Error closing connection - {}", exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TCPMessageListener: Receives messages from the DSC Alarm Panel API.
|
||||
*/
|
||||
private class TCPListener implements Runnable {
|
||||
private final Logger logger = LoggerFactory.getLogger(TCPListener.class);
|
||||
|
||||
/**
|
||||
* Run method. Runs the MessageListener thread
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
String messageLine;
|
||||
|
||||
try {
|
||||
while (isConnected()) {
|
||||
if ((messageLine = read()) != null) {
|
||||
try {
|
||||
handleIncomingMessage(messageLine);
|
||||
} catch (Exception e) {
|
||||
logger.error("TCPListener(): Message not handled by bridge: {}", e.getMessage());
|
||||
}
|
||||
} else {
|
||||
setConnected(false);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("TCPListener(): Unable to read message: {} ", e.getMessage(), e);
|
||||
closeConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dscalarm.internal.handler;
|
||||
|
||||
import static org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants.*;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmCode;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmEvent;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage;
|
||||
import org.openhab.binding.dscalarm.internal.DSCAlarmMessage.DSCAlarmMessageInfoType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This is a class for handling a Zone type Thing.
|
||||
*
|
||||
* @author Russell Stephens - Initial Contribution
|
||||
*/
|
||||
public class ZoneThingHandler extends DSCAlarmBaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ZoneThingHandler.class);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param thing
|
||||
*/
|
||||
public ZoneThingHandler(Thing thing) {
|
||||
super(thing);
|
||||
setDSCAlarmThingType(DSCAlarmThingType.ZONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannel(ChannelUID channelUID, int state, String description) {
|
||||
logger.debug("updateChannel(): Zone Channel UID: {}", channelUID);
|
||||
|
||||
boolean trigger;
|
||||
OnOffType onOffType;
|
||||
OpenClosedType openClosedType;
|
||||
|
||||
if (channelUID != null) {
|
||||
switch (channelUID.getId()) {
|
||||
case ZONE_MESSAGE:
|
||||
updateState(channelUID, new StringType(description));
|
||||
break;
|
||||
case ZONE_STATUS:
|
||||
openClosedType = (state > 0) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
|
||||
updateState(channelUID, openClosedType);
|
||||
break;
|
||||
case ZONE_BYPASS_MODE:
|
||||
onOffType = (state > 0) ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case ZONE_IN_ALARM:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case ZONE_TAMPER:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case ZONE_FAULT:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
case ZONE_TRIPPED:
|
||||
trigger = state != 0;
|
||||
onOffType = trigger ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
break;
|
||||
default:
|
||||
logger.debug("updateChannel(): Zone Channel not updated - {}.", channelUID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("handleCommand(): Command Received - {} {}.", channelUID, command);
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dscAlarmBridgeHandler != null && dscAlarmBridgeHandler.isConnected()
|
||||
&& channelUID.getId().equals(ZONE_BYPASS_MODE)) {
|
||||
String data = String.valueOf(getPartitionNumber()) + "*1" + String.format("%02d", getZoneNumber()) + "#";
|
||||
|
||||
dscAlarmBridgeHandler.sendCommand(DSCAlarmCode.KeySequence, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set Zone Message.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
private void zoneMessage(String message) {
|
||||
updateState(new ChannelUID(getThing().getUID(), ZONE_MESSAGE), new StringType(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dscAlarmEventReceived(EventObject event, Thing thing) {
|
||||
if (thing != null) {
|
||||
if (getThing().equals(thing)) {
|
||||
DSCAlarmEvent dscAlarmEvent = (DSCAlarmEvent) event;
|
||||
DSCAlarmMessage dscAlarmMessage = dscAlarmEvent.getDSCAlarmMessage();
|
||||
|
||||
ChannelUID channelUID = null;
|
||||
DSCAlarmCode dscAlarmCode = DSCAlarmCode
|
||||
.getDSCAlarmCodeValue(dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.CODE));
|
||||
logger.debug("dscAlarmEventRecieved(): Thing - {} Command - {}", thing.getUID(), dscAlarmCode);
|
||||
|
||||
int state = 0;
|
||||
String status = "";
|
||||
|
||||
switch (dscAlarmCode) {
|
||||
case ZoneAlarm: /* 601 */
|
||||
state = 1;
|
||||
status = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DESCRIPTION);
|
||||
case ZoneAlarmRestore: /* 602 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), ZONE_IN_ALARM);
|
||||
updateChannel(channelUID, state, "");
|
||||
zoneMessage(status);
|
||||
break;
|
||||
case ZoneTamper: /* 603 */
|
||||
state = 1;
|
||||
status = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DESCRIPTION);
|
||||
case ZoneTamperRestore: /* 604 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), ZONE_TAMPER);
|
||||
updateChannel(channelUID, state, "");
|
||||
zoneMessage(status);
|
||||
break;
|
||||
case ZoneFault: /* 605 */
|
||||
state = 1;
|
||||
status = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DESCRIPTION);
|
||||
case ZoneFaultRestore: /* 606 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), ZONE_FAULT);
|
||||
updateChannel(channelUID, state, "");
|
||||
zoneMessage(status);
|
||||
break;
|
||||
case ZoneOpen: /* 609 */
|
||||
state = 1;
|
||||
status = dscAlarmMessage.getMessageInfo(DSCAlarmMessageInfoType.DESCRIPTION);
|
||||
case ZoneRestored: /* 610 */
|
||||
channelUID = new ChannelUID(getThing().getUID(), ZONE_TRIPPED);
|
||||
updateChannel(channelUID, state, "");
|
||||
|
||||
channelUID = new ChannelUID(getThing().getUID(), ZONE_STATUS);
|
||||
updateChannel(channelUID, state, "");
|
||||
zoneMessage(status);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="dscalarm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>DSCAlarm Binding</name>
|
||||
<description>The DSCAlarm binding interfaces with a DSC PowerSeries Alarm System through the EyezOn Envisalink 3/2DS
|
||||
interface or the DSC IT-100 RS-232 interface.</description>
|
||||
<author>Russell Stephens</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="dscalarm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- bridge -->
|
||||
<channel-type id="reset">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Reset</label>
|
||||
<description>Reset Switch</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="command">
|
||||
<item-type>String</item-type>
|
||||
<label>Send Command</label>
|
||||
<description>Sends a DSC Alarm Command</description>
|
||||
</channel-type>
|
||||
|
||||
<!-- keypad -->
|
||||
<channel-type id="led">
|
||||
<item-type>Number</item-type>
|
||||
<label>Keypad LED</label>
|
||||
<description>Keypad LED (0=Off, 1=On, 2=Flashing)</description>
|
||||
<state pattern="%d" readOnly="true">
|
||||
<options>
|
||||
<option value="0">Off</option>
|
||||
<option value="1">On</option>
|
||||
<option value="2">Flashing</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<!-- panel -->
|
||||
<channel-type id="panel_command">
|
||||
<item-type>Number</item-type>
|
||||
<label>Panel Command</label>
|
||||
<description>Send Command</description>
|
||||
<state pattern="%d">
|
||||
<options>
|
||||
<option value="-1">None</option>
|
||||
<option value="0">Poll</option>
|
||||
<option value="1">Status Report</option>
|
||||
<option value="2">Labels Request (Serial Only)</option>
|
||||
<option value="8">Dump Zone Timers (TCP Only)</option>
|
||||
<option value="10">Set Time/Date</option>
|
||||
<option value="200">Send User Code</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="time">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Time</label>
|
||||
<description>Time</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="state">
|
||||
<item-type>Switch</item-type>
|
||||
<label>State</label>
|
||||
<description>State (On/Off)</description>
|
||||
</channel-type>
|
||||
|
||||
<!-- partition -->
|
||||
<channel-type id="arm_mode">
|
||||
<item-type>Number</item-type>
|
||||
<label>Arm Mode</label>
|
||||
<description>Arm Mode</description>
|
||||
<state pattern="%d">
|
||||
<options>
|
||||
<option value="0">Disarm</option>
|
||||
<option value="1">Away</option>
|
||||
<option value="2">Stay</option>
|
||||
<option value="3">Zero</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<!-- zone -->
|
||||
<channel-type id="zone_status">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Zone Status</label>
|
||||
<description>Zone Status (Open/Closed)</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="bypass_mode">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Bypass Mode</label>
|
||||
<description>Bypass Mode (OFF=Armed, ON=Bypassed)</description>
|
||||
</channel-type>
|
||||
|
||||
<!-- common -->
|
||||
<channel-type id="message">
|
||||
<item-type>String</item-type>
|
||||
<label>Message</label>
|
||||
<description>Message Received</description>
|
||||
<state pattern="%s" readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="status">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Status</label>
|
||||
<description>Status</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="dscalarm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<bridge-type id="envisalink">
|
||||
<label>EyezOn Envisalink</label>
|
||||
<description>This bridge represents the EyezOn Envlisalink 3/2D
|
||||
Ethernet interface.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="bridge_reset" typeId="reset">
|
||||
<label>Reset Envisalink</label>
|
||||
<description>Resets the Envisalink</description>
|
||||
</channel>
|
||||
<channel id="send_command" typeId="command">
|
||||
<label>Send Command</label>
|
||||
<description>Sends a DSC Alarm Command</description>
|
||||
</channel>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<context>network-address</context>
|
||||
<label>IP Address</label>
|
||||
<description>The IP address of the EyezOn Envlisalink 3/2D Ethernet
|
||||
interface.</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="port" type="integer" required="false">
|
||||
<label>Port</label>
|
||||
<description>The TCP port to the EyezOn Envlisalink 3/2D Ethernet
|
||||
interface.</description>
|
||||
<default>4025</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="password" type="text" required="false">
|
||||
<context>password</context>
|
||||
<label>Password</label>
|
||||
<description>The Password to login to the EyezOn Envlisalink 3/2D
|
||||
Ethernet interface.</description>
|
||||
<default>user</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="connectionTimeout" type="integer" required="false">
|
||||
<label>Connection Timeout</label>
|
||||
<description>TCP Socket Connection Timeout (milliseconds).</description>
|
||||
<default>5000</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="pollPeriod" type="integer" required="false" min="1" max="15">
|
||||
<label>Poll Period</label>
|
||||
<description>The Poll Period (minutes).</description>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="dscalarm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<bridge-type id="it100">
|
||||
<label>DSC IT-100</label>
|
||||
<description>This bridge represents the DSC IT-100 Serial interface.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="bridge_reset" typeId="reset">
|
||||
<label>Reset IT100</label>
|
||||
<description>Resets the IT100</description>
|
||||
</channel>
|
||||
<channel id="send_command" typeId="command">
|
||||
<label>Send Command</label>
|
||||
<description>Sends a DSC Alarm Command</description>
|
||||
</channel>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="serialPort" type="text" required="true">
|
||||
<context>serial-port</context>
|
||||
<limitToOptions>false</limitToOptions>
|
||||
<label>IT-100 Bridge Serial Port</label>
|
||||
<description>The serial port name for the DSC IT-100. Valid values
|
||||
are e.g. COM1 for Windows and /dev/ttyS0 or
|
||||
/dev/ttyUSB0 for Linux.</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="baud" type="integer" required="false">
|
||||
<label>Baud Rate</label>
|
||||
<description>The baud rate of the DSC IT-100. Valid values are 9600
|
||||
(default), 19200, 38400, 57600, and 115200.</description>
|
||||
<default>9600</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="pollPeriod" type="integer" required="false" min="1" max="15">
|
||||
<label>Poll Period</label>
|
||||
<description>The Poll Period.</description>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="dscalarm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="keypad">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="envisalink"/>
|
||||
<bridge-type-ref id="it100"/>
|
||||
<bridge-type-ref id="tcpserver"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>DSC Alarm Keypad</label>
|
||||
<description>Represents the central administrative unit of the DSC Alarm System.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="keypad_ready_led" typeId="led">
|
||||
<label>Keypad Ready LED</label>
|
||||
<description>Keypad Ready LED (0=Off, 1=On, 2=Flashing)</description>
|
||||
</channel>
|
||||
<channel id="keypad_armed_led" typeId="led">
|
||||
<label>Keypad Armed LED</label>
|
||||
<description>Keypad Armed LED (0=Off, 1=On, 2=Flashing)</description>
|
||||
</channel>
|
||||
<channel id="keypad_memory_led" typeId="led">
|
||||
<label>Keypad Memory LED</label>
|
||||
<description>Keypad Memory LED (0=Off, 1=On, 2=Flashing)</description>
|
||||
</channel>
|
||||
<channel id="keypad_bypass_led" typeId="led">
|
||||
<label>Keypad Bypass LED</label>
|
||||
<description>Keypad Bypass LED (0=Off, 1=On, 2=Flashing)</description>
|
||||
</channel>
|
||||
<channel id="keypad_trouble_led" typeId="led">
|
||||
<label>Keypad Trouble LED</label>
|
||||
<description>Keypad Trouble LED (0=Off, 1=On, 2=Flashing)</description>
|
||||
</channel>
|
||||
<channel id="keypad_program_led" typeId="led">
|
||||
<label>Keypad Program LED</label>
|
||||
<description>Keypad Program LED (0=Off, 1=On, 2=Flashing)</description>
|
||||
</channel>
|
||||
<channel id="keypad_fire_led" typeId="led">
|
||||
<label>Keypad Fire LED</label>
|
||||
<description>Keypad Fire LED (0=Off, 1=On, 2=Flashing)</description>
|
||||
</channel>
|
||||
<channel id="keypad_backlight_led" typeId="led">
|
||||
<label>Keypad Backlight LED</label>
|
||||
<description>Keypad Backlight LED (0=Off, 1=On, 2=Flashing)</description>
|
||||
</channel>
|
||||
<channel id="keypad_ac_led" typeId="led">
|
||||
<label>Keypad AC LED</label>
|
||||
<description>Keypad AC LED (0=Off, 1=On, 2=Flashing)</description>
|
||||
</channel>
|
||||
<channel id="keypad_lcd_update" typeId="message">
|
||||
<label>Keypad LCD Update</label>
|
||||
<description>Keypad LCD Menu Changes</description>
|
||||
</channel>
|
||||
<channel id="keypad_lcd_cursor" typeId="message">
|
||||
<label>Keypad LCD Cursor</label>
|
||||
<description>Keypad LCD Cursor Position Changes</description>
|
||||
</channel>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="dscalarm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="panel">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="envisalink"/>
|
||||
<bridge-type-ref id="it100"/>
|
||||
<bridge-type-ref id="tcpserver"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>DSC Alarm Panel</label>
|
||||
<description>The basic representation of the DSC Alarm System.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="panel_message" typeId="message">
|
||||
<label>Panel Message</label>
|
||||
<description>Message Received</description>
|
||||
</channel>
|
||||
<channel id="panel_command" typeId="panel_command">
|
||||
<label>Panel Command</label>
|
||||
<description>Send Selected Command</description>
|
||||
</channel>
|
||||
<channel id="panel_system_error" typeId="message">
|
||||
<label>Panel System Error</label>
|
||||
<description>System Error</description>
|
||||
</channel>
|
||||
<channel id="panel_trouble_message" typeId="message">
|
||||
<label>Panel Trouble Message</label>
|
||||
<description>Trouble Message</description>
|
||||
</channel>
|
||||
<channel id="panel_trouble_led" typeId="status">
|
||||
<label>Panel Trouble LED</label>
|
||||
<description>Trouble LED State</description>
|
||||
</channel>
|
||||
<channel id="panel_service_required" typeId="status">
|
||||
<label>Panel Service Required</label>
|
||||
<description>Service Required Trouble Condition</description>
|
||||
</channel>
|
||||
<channel id="panel_ac_trouble" typeId="status">
|
||||
<label>Panel AC Trouble</label>
|
||||
<description>Service AC Trouble Condition</description>
|
||||
</channel>
|
||||
<channel id="panel_telephone_trouble" typeId="status">
|
||||
<label>Panel Telephone Line Trouble</label>
|
||||
<description>Service Telephone Line Trouble Condition</description>
|
||||
</channel>
|
||||
<channel id="panel_ftc_trouble" typeId="status">
|
||||
<label>Panel FTC Trouble</label>
|
||||
<description>Service Fail to Communicate Trouble Condition</description>
|
||||
</channel>
|
||||
<channel id="panel_zone_fault" typeId="status">
|
||||
<label>Panel Zone Fault</label>
|
||||
<description>Service Zone Fault Trouble Condition</description>
|
||||
</channel>
|
||||
<channel id="panel_zone_tamper" typeId="status">
|
||||
<label>Panel Zone Tamper</label>
|
||||
<description>Service Zone Tamper Trouble Condition</description>
|
||||
</channel>
|
||||
<channel id="panel_zone_low_battery" typeId="status">
|
||||
<label>Panel Zone Low Battery</label>
|
||||
<description>Service Zone Low Battery Trouble Condition</description>
|
||||
</channel>
|
||||
<channel id="panel_time_loss" typeId="status">
|
||||
<label>Panel Time Loss</label>
|
||||
<description>Service Time Loss Trouble Condition</description>
|
||||
</channel>
|
||||
<channel id="panel_time" typeId="time">
|
||||
<label>Panel Time</label>
|
||||
<description>Panel Time</description>
|
||||
</channel>
|
||||
<channel id="panel_time_stamp" typeId="state">
|
||||
<label>Panel Time Stamp</label>
|
||||
<description>Panel Time Stamp</description>
|
||||
</channel>
|
||||
<channel id="panel_time_broadcast" typeId="state">
|
||||
<label>Panel Time Broadcast</label>
|
||||
<description>Panel Time Broadcast</description>
|
||||
</channel>
|
||||
<channel id="panel_fire_key_alarm" typeId="status">
|
||||
<label>Panel Fire Key Alarm</label>
|
||||
<description>Panel Fire Key Alarm</description>
|
||||
</channel>
|
||||
<channel id="panel_panic_key_alarm" typeId="status">
|
||||
<label>Panel Panic Key Alarm</label>
|
||||
<description>Panel Panic Key Alarm</description>
|
||||
</channel>
|
||||
<channel id="panel_aux_key_alarm" typeId="status">
|
||||
<label>Panel Auxiliary Key Alarm</label>
|
||||
<description>Panel Auxiliary Key Alarm</description>
|
||||
</channel>
|
||||
<channel id="panel_aux_input_alarm" typeId="status">
|
||||
<label>Panel Auxiliary Input Alarm</label>
|
||||
<description>Panel Auxiliary Input Alarm</description>
|
||||
</channel>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="userCode" type="text" required="false">
|
||||
<context>password</context>
|
||||
<label>User Code</label>
|
||||
<description>The User Code.</description>
|
||||
<default>1234</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="suppressAcknowledgementMsgs" type="boolean" required="false">
|
||||
<label>Suppress Acknowledgement Messages</label>
|
||||
<description>Suppress Acknowledgement Messages When Received.</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="dscalarm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="partition">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="envisalink"/>
|
||||
<bridge-type-ref id="it100"/>
|
||||
<bridge-type-ref id="tcpserver"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>DSC Alarm Partition</label>
|
||||
<description>Represents a controllable area within a DSC Alarm System.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="partition_status" typeId="message">
|
||||
<label>Partition Status</label>
|
||||
<description>Partition Status</description>
|
||||
</channel>
|
||||
<channel id="partition_arm_mode" typeId="arm_mode">
|
||||
<label>Partition Arm Mode</label>
|
||||
<description>Partition Arm Mode</description>
|
||||
</channel>
|
||||
<channel id="partition_armed" typeId="status">
|
||||
<label>Partition Armed Status</label>
|
||||
<description>Partition Armed Status (ON=Armed, OFF=Disarmed)</description>
|
||||
</channel>
|
||||
<channel id="partition_entry_delay" typeId="status">
|
||||
<label>Partition Entry Delay</label>
|
||||
<description>Partition In Entry Delay Mode</description>
|
||||
</channel>
|
||||
<channel id="partition_exit_delay" typeId="status">
|
||||
<label>Partition Exit Delay</label>
|
||||
<description>Partition In Exit Delay Mode</description>
|
||||
</channel>
|
||||
<channel id="partition_in_alarm" typeId="status">
|
||||
<label>Partition in Alarm</label>
|
||||
<description>Partition In Alarm</description>
|
||||
</channel>
|
||||
<channel id="partition_opening_closing_mode" typeId="message">
|
||||
<label>Partition Opening/Closing Mode</label>
|
||||
<description>Partition Opening/Closing Mode ("User Closing", "Special Closing", "Partial Closing", "User Opening",
|
||||
"Special Opening")</description>
|
||||
</channel>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="partitionNumber" type="integer" required="true" min="1" max="8">
|
||||
<label>Partition Number</label>
|
||||
<description>The Partition Number (1-8).</description>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="dscalarm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<bridge-type id="tcpserver">
|
||||
<label>TCP Server</label>
|
||||
<description>This bridge represents a TCP Server
|
||||
Ethernet interface.
|
||||
</description>
|
||||
|
||||
<channels>
|
||||
<channel id="bridge_reset" typeId="reset">
|
||||
<label>Reset TCP Server</label>
|
||||
<description>Resets the TCP Server</description>
|
||||
</channel>
|
||||
<channel id="send_command" typeId="command">
|
||||
<label>Send Command</label>
|
||||
<description>Sends a DSC Alarm Command</description>
|
||||
</channel>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<context>network-address</context>
|
||||
<label>IP Address</label>
|
||||
<description>The IP address of the TCP Server.</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="port" type="integer" required="true">
|
||||
<label>Port</label>
|
||||
<description>The TCP port to the TCP Server.</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="connectionTimeout" type="integer" required="false">
|
||||
<label>Connection Timeout</label>
|
||||
<description>TCP Socket Connection Timeout (milliseconds).</description>
|
||||
<default>5000</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="pollPeriod" type="integer" required="false" min="1" max="15">
|
||||
<label>Poll Period</label>
|
||||
<description>The Poll Period (minutes).</description>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="protocol" type="integer" required="false" min="1" max="2">
|
||||
<label>Protocol</label>
|
||||
<description>The protocol used to interact with the DSC Alarm. Valid options are 'IT100 API' and 'Envisalink TPI'.
|
||||
The default is 'IT100 API'.</description>
|
||||
<options>
|
||||
<option value="1">IT100 API</option>
|
||||
<option value="2">Envisalink TPI</option>
|
||||
</options>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="dscalarm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="zone">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="envisalink"/>
|
||||
<bridge-type-ref id="it100"/>
|
||||
<bridge-type-ref id="tcpserver"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>DSC Alarm Zone</label>
|
||||
<description>Represents a physical device such as a door, window, or motion sensor.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="zone_status" typeId="zone_status">
|
||||
<label>Zone Status</label>
|
||||
<description>Zone Status (Open/Closed)</description>
|
||||
</channel>
|
||||
<channel id="zone_message" typeId="message">
|
||||
<label>Zone Message</label>
|
||||
<description>Zone Message</description>
|
||||
</channel>
|
||||
<channel id="zone_bypass_mode" typeId="bypass_mode">
|
||||
<label>Zone Bypass Mode</label>
|
||||
<description>Zone Bypass Mode (OFF=Armed, ON=Bypassed)</description>
|
||||
</channel>
|
||||
<channel id="zone_in_alarm" typeId="status">
|
||||
<label>Zone in Alarm</label>
|
||||
<description>Zone In Alarm</description>
|
||||
</channel>
|
||||
<channel id="zone_tamper" typeId="status">
|
||||
<label>Zone Tamper</label>
|
||||
<description>Zone Tamper</description>
|
||||
</channel>
|
||||
<channel id="zone_fault" typeId="status">
|
||||
<label>Zone Fault</label>
|
||||
<description>Zone Fault</description>
|
||||
</channel>
|
||||
<channel id="zone_tripped" typeId="status">
|
||||
<label>Zone Tripped</label>
|
||||
<description>Zone Tripped</description>
|
||||
</channel>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="partitionNumber" type="integer" min="1" max="8">
|
||||
<label>Partition Number</label>
|
||||
<description>The Partition Number (1-8).</description>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="zoneNumber" type="integer" required="true" min="1" max="64">
|
||||
<label>Zone Number</label>
|
||||
<description>The Zone Number (1-64).</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user