added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
32
bundles/org.openhab.binding.caddx/.classpath
Normal file
32
bundles/org.openhab.binding.caddx/.classpath
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
bundles/org.openhab.binding.caddx/.project
Normal file
23
bundles/org.openhab.binding.caddx/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.caddx</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
13
bundles/org.openhab.binding.caddx/NOTICE
Normal file
13
bundles/org.openhab.binding.caddx/NOTICE
Normal file
@@ -0,0 +1,13 @@
|
||||
This content is produced and maintained by the openHAB project.
|
||||
|
||||
* Project home: https://www.openhab.org
|
||||
|
||||
== Declared Project Licenses
|
||||
|
||||
This program and the accompanying materials are made available under the terms
|
||||
of the Eclipse Public License 2.0 which is available at
|
||||
https://www.eclipse.org/legal/epl-2.0/.
|
||||
|
||||
== Source Code
|
||||
|
||||
https://github.com/openhab/openhab2-addons
|
||||
273
bundles/org.openhab.binding.caddx/README.md
Normal file
273
bundles/org.openhab.binding.caddx/README.md
Normal file
@@ -0,0 +1,273 @@
|
||||
# Caddx Binding
|
||||
|
||||
The Caddx binding is used for communicating with the Caddx alarm panels. Also known as Interlogix.
|
||||
|
||||
It provides connectivity to the NetworX alarm panels via a RS-232 serial connection to the NX-584E interface or directly to the NX-8E.
|
||||
|
||||
## Supported Things
|
||||
|
||||
This binding supports the following Thing types
|
||||
|
||||
| Thing | Thing Type | Description |
|
||||
|------------|------------|------------------------------------------------------------------------|
|
||||
| bridge | Bridge | The RS-232 interface. |
|
||||
| panel | Thing | The basic representation of the alarm System. |
|
||||
| partition | Thing | Represents a controllable area within the alarm system. |
|
||||
| zone | Thing | Represents a physical device such as a door, window, or motion sensor. |
|
||||
| keypad | Thing | Represents a keypad. (Not yet functional) |
|
||||
|
||||
## Discovery
|
||||
|
||||
First the bridge must be **manually** defined. The serial port, baud rate and protocol have to be set correctly to match the respective configuration of the panel (see below Prerequisites section).
|
||||
After the bridge is manually added and available to openHAB, the binding will automatically start to discover partitions and zones and add them to the discovery inbox.
|
||||
|
||||
Note:
|
||||
There is currently no support to discover the available keypads.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
For the binding to work the panel has also to be programmed appropriately.
|
||||
|
||||
### Programming locations for the NX-8E control panel
|
||||
|
||||
| Location | Segment | Value | Description |
|
||||
|----------|---------|-------------|--------------------------------------------------------------------------------------------------------|
|
||||
| 207 | 1 | 1 | Serial Port selector |
|
||||
| 208 | 1 | 0 - 4 | Baud rate table<br>0 = 2400 Baud<br>1 = 4800 Baud<br>2 = 9600 Baud<br>3 = 19200 Baud<br>4 = 38400 Baud |
|
||||
| 209 | 1 | Off/On | Home automation protocol<br>1 = Off: Binary. On: ASCII. |
|
||||
| 210 | 1 | 2,5,6,7,8 | Enabling the Transitions |
|
||||
| 210 | 2 | 1,2,3,4 | |
|
||||
| 211 | 1 | 2,4,5,6,7,8 | Programming the Command/Request enables |
|
||||
| 211 | 2 | 1,2,3,4,5 | (Flags 4 and 5 are not yet functional. Can be ignored.) |
|
||||
| 211 | 3 | | |
|
||||
| 211 | 4 | 5,7,8 | |
|
||||
| 212 | 1 | 192 | Programming the LCD keypad address. (Not yet functional. Can be ignored.) |
|
||||
|
||||
### Programming locations for the NX-584E home automation module
|
||||
|
||||
| Location | Segment | Value | Description |
|
||||
|----------|---------|-------------|--------------------------------------------------------------------------------------------------------|
|
||||
| 0 | 1 | Off/On | Home automation protocol<br>1 = Off: Binary. On: ASCII. |
|
||||
| 1 | 1 | 0 - 4 | Baud rate table<br>0 = 600 Baud<br>1 = 1200 Baud<br>2 = 2400 Baud<br>3 = 4800 Baud<br>4 = 9600 Baud<br>5 = 19200 Baud<br>6 = 38400 Baud<br>7 = 76800 Baud |
|
||||
| 2 | 1 | 2,5,6,7,8 | Enabling the Transitions |
|
||||
| 2 | 2 | 1,2,3,4 | |
|
||||
| 3 | 1 | 2,4,5,6,7,8 | Programming the Command/Request enables |
|
||||
| 3 | 2 | 1,2,3,4,5 | (Flags 4 and 5 are not yet functional. Can be ignored.) |
|
||||
| 3 | 3 | | |
|
||||
| 3 | 4 | 5,7,8 | |
|
||||
| 4 | 1 | 192 | Programming the LCD keypad address. (Not yet functional. Can be ignored.) |
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
The things can be configured either through the online configuration utility via discovery, or manually through the configuration file.
|
||||
The following table shows the available configuration parameters for each thing.
|
||||
|
||||
| Thing | Configuration Parameters |
|
||||
|-----------|------------------------------------------------------------------------------------------------|
|
||||
| bridge | `serialPort` - Serial port for the bridge - Required |
|
||||
| | `protocol` - Protocol used for the communication (Binary, Ascii) - Required - Default = Binary |
|
||||
| | `baud` - Baud rate of the bridge - Required - Default = 9600 |
|
||||
| partition | `partitionNumber` - Partition number (1-8) - Required |
|
||||
| zone | `zoneNumber` - Zone number (1-192) - Required |
|
||||
| keypad | `keypadAddress` - Keypad address (192-255) - Required |
|
||||
|
||||
A full example is further below.
|
||||
|
||||
## Channels
|
||||
|
||||
Caddx Alarm things support a variety of channels as seen below in the following table:
|
||||
|
||||
| Channel | Item Type | Type | Description |
|
||||
|--------------------------------------------------|-----------|---------------------|--------------------------------------------|
|
||||
| send_Command | String | Command | Send a command to the panel |
|
||||
| panel_firmware_version | String | Configuration | Firmware version |
|
||||
| panel_log_message_n_0 | String | Runtime | Log message 10 |
|
||||
| panel_log_message_n_1 | String | Runtime | Log message 9 |
|
||||
| panel_log_message_n_2 | String | Runtime | Log message 8 |
|
||||
| panel_log_message_n_3 | String | Runtime | Log message 7 |
|
||||
| panel_log_message_n_4 | String | Runtime | Log message 6 |
|
||||
| panel_log_message_n_5 | String | Runtime | Log message 5 |
|
||||
| panel_log_message_n_6 | String | Runtime | Log message 4 |
|
||||
| panel_log_message_n_7 | String | Runtime | Log message 3 |
|
||||
| panel_log_message_n_8 | String | Runtime | Log message 2 |
|
||||
| panel_log_message_n_9 | String | Runtime | Log message 1 |
|
||||
| panel_interface_configuration_message | Switch | Configuration | Interface Configuration Message |
|
||||
| panel_zone_status_message | Switch | Configuration | Zone Status Message |
|
||||
| panel_zones_snapshot_message | Switch | Configuration | Zones Snapshot Message |
|
||||
| panel_partition_status_message | Switch | Configuration | Partition Status Message |
|
||||
| panel_partitions_snapshot_message | Switch | Configuration | Partitions Snapshot Message |
|
||||
| panel_system_status_message | Switch | Configuration | System Status Message |
|
||||
| panel_x10_message_received | Switch | Configuration | X-10 Message Received |
|
||||
| panel_log_event_message | Switch | Configuration | Log Event Message |
|
||||
| panel_keypad_message_received | Switch | Configuration | Keypad Message Received |
|
||||
| panel_interface_configuration_request | Switch | Configuration | Interface Configuration Request |
|
||||
| panel_zone_name_request | Switch | Configuration | Zone Name Request |
|
||||
| panel_zone_status_request | Switch | Configuration | Zone Status Request |
|
||||
| panel_zones_snapshot_request | Switch | Configuration | Zones Snapshot Request |
|
||||
| panel_partition_status_request | Switch | Configuration | Partition Status Request |
|
||||
| panel_partitions_snapshot_request | Switch | Configuration | Partitions Snapshot Request |
|
||||
| panel_system_status_request | Switch | Configuration | System Status Request |
|
||||
| panel_send_x10_message | Switch | Configuration | Send X-10 Message |
|
||||
| panel_log_event_request | Switch | Configuration | Log Event Request |
|
||||
| panel_send_keypad_text_message | Switch | Configuration | Send Keypad Text Message |
|
||||
| panel_keypad_terminal_mode_request | Switch | Configuration | Keypad Terminal Mode Request |
|
||||
| panel_program_data_request | Switch | Configuration | Program Data Request |
|
||||
| panel_program_data_command | Switch | Configuration | Program Data Command |
|
||||
| panel_user_information_request_with_pin | Switch | Configuration | User Information Request with PIN |
|
||||
| panel_user_information_request_without_pin | Switch | Configuration | User Information Request without PIN |
|
||||
| panel_set_user_code_command_with_pin | Switch | Configuration | Set User Code Command with PIN |
|
||||
| panel_set_user_code_command_without_pin | Switch | Configuration | Set User Code Command without PIN |
|
||||
| panel_set_user_authorization_command_with_pin | Switch | Configuration | Set User Authorization Command with PIN |
|
||||
| panel_set_user_authorization_command_without_pin | Switch | Configuration | Set User Authorization Command without PIN |
|
||||
| panel_store_communication_event_command | Switch | Configuration | Store Communication Event Command |
|
||||
| panel_set_clock_calendar_command | Switch | Configuration | Set Clock / Calendar Command |
|
||||
| panel_primary_keypad_function_with_pin | Switch | Configuration | Primary Keypad Function with PIN |
|
||||
| panel_primary_keypad_function_without_pin | Switch | Configuration | Primary Keypad Function without PIN |
|
||||
| panel_secondary_keypad_function | Switch | Configuration | Secondary Keypad Function |
|
||||
| panel_zone_bypass_toggle | Switch | Configuration | Zone Bypass Toggle |
|
||||
| partition_bypass_code_required | Switch | Partition Condition | Bypass code required |
|
||||
| partition_fire_trouble | Switch | Partition Condition | Fire trouble |
|
||||
| partition_fire | Switch | Partition Condition | Fire |
|
||||
| partition_pulsing_buzzer | Switch | Partition Condition | Pulsing Buzzer |
|
||||
| partition_tlm_fault_memory | Switch | Partition Condition | TLM fault memory |
|
||||
| partition_armed | Switch | Partition Condition | Armed |
|
||||
| partition_instant | Switch | Partition Condition | Instant |
|
||||
| partition_previous_alarm | Switch | Partition Condition | Previous Alarm |
|
||||
| partition_siren_on | Switch | Partition Condition | Siren on |
|
||||
| partition_steady_siren_on | Switch | Partition Condition | Steady siren on |
|
||||
| partition_alarm_memory | Switch | Partition Condition | Alarm memory |
|
||||
| partition_tamper | Switch | Partition Condition | Tamper |
|
||||
| partition_cancel_command_entered | Switch | Partition Condition | Cancel command entered |
|
||||
| partition_code_entered | Switch | Partition Condition | Code entered |
|
||||
| partition_cancel_pending | Switch | Partition Condition | Cancel pending |
|
||||
| partition_silent_exit_enabled | Switch | Partition Condition | Silent exit enabled |
|
||||
| partition_entryguard | Switch | Partition Condition | Entryguard (stay mode) |
|
||||
| partition_chime_mode_on | Switch | Partition Condition | Chime mode on |
|
||||
| partition_entry | Switch | Partition Condition | Entry |
|
||||
| partition_delay_expiration_warning | Switch | Partition Condition | Delay expiration warning |
|
||||
| partition_exit1 | Switch | Partition Condition | Exit1 |
|
||||
| partition_exit2 | Switch | Partition Condition | Exit2 |
|
||||
| partition_led_extinguish | Switch | Partition Condition | LED extinguish |
|
||||
| partition_cross_timing | Switch | Partition Condition | Cross timing |
|
||||
| partition_recent_closing_being_timed | Switch | Partition Condition | Recent closing being timed |
|
||||
| partition_exit_error_triggered | Switch | Partition Condition | Exit error triggered |
|
||||
| partition_auto_home_inhibited | Switch | Partition Condition | Auto home inhibited |
|
||||
| partition_sensor_low_battery | Switch | Partition Condition | Sensor low battery |
|
||||
| partition_sensor_lost_supervision | Switch | Partition Condition | Sensor lost supervision |
|
||||
| partition_zone_bypassed | Switch | Partition Condition | Zone bypassed |
|
||||
| partition_force_arm_triggered_by_auto_arm | Switch | Partition Condition | Force arm triggered by auto arm |
|
||||
| partition_ready_to_arm | Switch | Partition Condition | Ready to arm |
|
||||
| partition_ready_to_force_arm | Switch | Partition Condition | Ready to force arm |
|
||||
| partition_valid_pin_accepted | Switch | Partition Condition | Valid PIN accepted |
|
||||
| partition_chime_on | Switch | Partition Condition | Chime on (sounding) |
|
||||
| partition_error_beep | Switch | Partition Condition | Error beep (triple beep) |
|
||||
| partition_tone_on | Switch | Partition Condition | Tone on (activation tone) |
|
||||
| partition_entry1 | Switch | Partition Condition | Entry 1 |
|
||||
| partition_open_period | Switch | Partition Condition | Open period |
|
||||
| partition_alarm_sent_using_phone_number_1 | Switch | Partition Condition | Alarm sent using phone number 1 |
|
||||
| partition_alarm_sent_using_phone_number_2 | Switch | Partition Condition | Alarm sent using phone number 2 |
|
||||
| partition_alarm_sent_using_phone_number_3 | Switch | Partition Condition | Alarm sent using phone number 3 |
|
||||
| partition_cancel_report_is_in_the_stack | Switch | Partition Condition | Cancel report is in the stack |
|
||||
| partition_keyswitch_armed | Switch | Partition Condition | Keyswitch armed |
|
||||
| partition_delay_trip_in_progress | Switch | Partition Condition | Delay Trip in progress (common zone) |
|
||||
| partition_secondary_command | Number | Command | Partition Secondary Command |
|
||||
| zone_partition2 | Switch | Configuration | Partition 2 |
|
||||
| zone_partition3 | Switch | Configuration | Partition 3 |
|
||||
| zone_partition1 | Switch | Configuration | Partition 1 |
|
||||
| zone_partition4 | Switch | Configuration | Partition 4 |
|
||||
| zone_partition5 | Switch | Configuration | Partition 5 |
|
||||
| zone_partition6 | Switch | Configuration | Partition 6 |
|
||||
| zone_partition7 | Switch | Configuration | Partition 7 |
|
||||
| zone_partition8 | Switch | Configuration | Partition 8 |
|
||||
| zone_name | String | Configuration | Name |
|
||||
| zone_fire | Switch | Configuration | Fire |
|
||||
| zone_24hour | Switch | Configuration | 24 Hour |
|
||||
| zone_key_switch | Switch | Configuration | Key-switch |
|
||||
| zone_follower | Switch | Configuration | Follower |
|
||||
| zone_entry_exit_delay_1 | Switch | Configuration | Entry / exit delay 1 |
|
||||
| zone_entry_exit_delay_2 | Switch | Configuration | Entry / exit delay 2 |
|
||||
| zone_interior | Switch | Configuration | Interior |
|
||||
| zone_local_only | Switch | Configuration | Local only |
|
||||
| zone_keypad_sounder | Switch | Configuration | Keypad Sounder |
|
||||
| zone_yelping_siren | Switch | Configuration | Yelping siren |
|
||||
| zone_steady_siren | Switch | Configuration | Steady siren |
|
||||
| zone_chime | Switch | Configuration | Chime |
|
||||
| zone_bypassable | Switch | Configuration | Bypassable |
|
||||
| zone_group_bypassable | Switch | Configuration | Group bypassable |
|
||||
| zone_force_armable | Switch | Configuration | Force armable |
|
||||
| zone_entry_guard | Switch | Configuration | Entry guard |
|
||||
| zone_fast_loop_response | Switch | Configuration | Fast loop response |
|
||||
| zone_double_eol_tamper | Switch | Configuration | Double EOL tamper |
|
||||
| zone_type_trouble | Switch | Configuration | Trouble |
|
||||
| zone_cross_zone | Switch | Configuration | Cross zone |
|
||||
| zone_dialer_delay | Switch | Configuration | Dialer delay |
|
||||
| zone_swinger_shutdown | Switch | Configuration | Swinger shutdown |
|
||||
| zone_restorable | Switch | Configuration | Restorable |
|
||||
| zone_listen_in | Switch | Configuration | Listen in |
|
||||
| zone_faulted | Contact | Zone Condition | Faulted (or delayed trip) |
|
||||
| zone_tampered | Switch | Zone Condition | Tampered |
|
||||
| zone_trouble | Switch | Zone Condition | Trouble |
|
||||
| zone_bypassed | Switch | Zone Condition | Bypassed |
|
||||
| zone_inhibited | Switch | Zone Condition | Inhibited (force armed) |
|
||||
| zone_low_battery | Switch | Zone Condition | Low battery |
|
||||
| zone_loss_of_supervision | Switch | Zone Condition | Loss of supervision |
|
||||
| zone_alarm_memory | Switch | Zone Condition | Alarm memory |
|
||||
| zone_bypass_memory | Switch | Zone Condition | Bypass memory |
|
||||
|
||||
## Full Example
|
||||
|
||||
The following is an example of a things file (caddx.things):
|
||||
|
||||
```
|
||||
Bridge caddx:bridge:thebridge "Bridge" [ protocol="Binary", serialPort="/dev/ttyUSB0", baudrate=38400 ] {
|
||||
Thing partition partition1 "Groundfloor alarm" [ partitionNumber=1 ]
|
||||
Thing zone zone1 "Livingroom motion sensor" [ zoneNumber=1 ]
|
||||
Thing zone zone2 "Bedroom motion sensor" [ zoneNumber=2 ]
|
||||
Thing zone zone3 "Guestroom motion sensor" [ zoneNumber=3 ]
|
||||
Thing zone zone4 "Livingroom window" [ zoneNumber=4 ]
|
||||
Thing zone zone5 "Bedroom window" [ zoneNumber=5 ]
|
||||
Thing zone zone6 "Guestroom window" [ zoneNumber=6 ]
|
||||
}
|
||||
```
|
||||
|
||||
The following is an example of an items file (caddx.items):
|
||||
|
||||
```
|
||||
Group:Contact:OR(OPEN,CLOSED) MotionSensors "Motion Sensors [%s]" <motion>
|
||||
Group:Contact:OR(OPEN,CLOSED) Windows "Windows open [%s]" <window>
|
||||
|
||||
Contact Bedroom_Motion "Bedroom [%s]" <motion> (MotionSensors) { channel="caddx:zone:thebridge:zone1:zone_faulted" }
|
||||
Contact Livingroom_Motion "Livingroom [%s]" <motion> (MotionSensors) { channel="caddx:zone:thebridge:zone2:zone_faulted" }
|
||||
Contact Guestroom_Motion "Guestroom [%s]" <motion> (MotionSensors) { channel="caddx:zone:thebridge:zone3:zone_faulted" }
|
||||
Contact Bedroom_Window "Bedroom Window [%s]" <window> (Windows) { channel="caddx:zone:thebridge:zone4:zone_faulted" }
|
||||
Contact Livingroom_Window "Livinroom Window [%s]" <window> (Windows) { channel="caddx:zone:thebridge:zone5:zone_faulted" }
|
||||
Contact Guestroom_Window "Guestroom Window [%s]" <window> (Windows) { channel="caddx:zone:thebridge:zone6:zone_faulted" }
|
||||
|
||||
Switch Partition1_Armed "Armed [%s]" <groundfloor> { channel="caddx:partition:thebridge:partition1:partition_armed" }
|
||||
Switch Partition1_EntryGuard "Entry Guard [%s]" <groundfloor> { channel="caddx:partition:thebridge:partition1:partition_entryguard" }
|
||||
```
|
||||
|
||||
The following is an example of a sitemap file (home.sitemap):
|
||||
|
||||
```
|
||||
sitemap home label="Home" {
|
||||
Frame label="Ground floor" {
|
||||
Text item=Partition1_Armed
|
||||
Text item=Partition1_EntryGuard
|
||||
|
||||
Text item=MotionSensors
|
||||
Text label="Motion Sensors (detailed)" {
|
||||
Text item=Bedroom_Motion
|
||||
Text item=Livingroom_Motion
|
||||
Text item=Guestroom_Motion
|
||||
}
|
||||
|
||||
Text item=Windows
|
||||
Text label="Windows (detailed)" {
|
||||
Text item=Bedroom_Window
|
||||
Text item=Livingroom_Window
|
||||
Text item=Guestroom_Window
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
17
bundles/org.openhab.binding.caddx/pom.xml
Normal file
17
bundles/org.openhab.binding.caddx/pom.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.caddx</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Caddx Binding</name>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.caddx-${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-caddx" description="Caddx 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.caddx/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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.caddx.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 {@link CaddxBindingConstants} class is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CaddxBindingConstants {
|
||||
// Binding ID
|
||||
private static final String BINDING_ID = "caddx";
|
||||
|
||||
// List of bridge device types
|
||||
public static final String CADDX_BRIDGE = "bridge";
|
||||
|
||||
// List of 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 CADDXBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, CADDX_BRIDGE);
|
||||
|
||||
// List of all 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);
|
||||
|
||||
// Bridge
|
||||
// Commands
|
||||
// Channels
|
||||
public static final String SEND_COMMAND = "send_command";
|
||||
|
||||
// Panel
|
||||
// Commands
|
||||
public static final String PANEL_INTERFACE_CONFIGURATION_REQUEST = "panel_interface_configuration_request";
|
||||
public static final String PANEL_SYSTEM_STATUS_REQUEST = "panel_system_status_request";
|
||||
public static final String PANEL_LOG_EVENT_REQUEST = "panel_log_event_request";
|
||||
// Channels
|
||||
public static final String PANEL_FIRMWARE_VERSION = "panel_firmware_version";
|
||||
public static final String PANEL_LOG_MESSAGE_N_0 = "panel_log_message_n_0";
|
||||
|
||||
// Partition
|
||||
// Commands
|
||||
public static final String PARTITION_STATUS_REQUEST = "partition_status_request";
|
||||
public static final String PARTITION_PRIMARY_COMMAND_WITH_PIN = "partition_primary_command_with_pin";
|
||||
public static final String PARTITION_SECONDARY_COMMAND = "partition_secondary_command";
|
||||
// Channels
|
||||
public static final String PARTITION_ARMED = "partition_armed";
|
||||
public static final String PARTITION_PRIMARY = "partition_primary";
|
||||
public static final String PARTITION_SECONDARY = "partition_secondary";
|
||||
|
||||
// Zone
|
||||
// Commands
|
||||
public static final String ZONE_STATUS_REQUEST = "zone_status_request";
|
||||
public static final String ZONE_NAME_REQUEST = "zone_name_request";
|
||||
// Channels
|
||||
public static final String ZONE_NAME = "zone_name";
|
||||
public static final String ZONE_FAULTED = "zone_faulted";
|
||||
public static final String ZONE_BYPASSED = "zone_bypassed";
|
||||
|
||||
// Keypad
|
||||
|
||||
// Set of all supported Thing Type UIDs
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream
|
||||
.of(CADDXBRIDGE_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(CADDXBRIDGE_THING_TYPE).collect(Collectors.toSet()));
|
||||
}
|
||||
@@ -0,0 +1,477 @@
|
||||
/**
|
||||
* 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.caddx.internal;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.TooManyListenersException;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
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.util.HexUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CaddxCommunicator} is responsible for the asynchronous serial communication
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CaddxCommunicator implements SerialPortEventListener {
|
||||
private final Logger logger = LoggerFactory.getLogger(CaddxCommunicator.class);
|
||||
|
||||
private final SerialPortManager portManager;
|
||||
private final Set<CaddxPanelListener> listenerQueue = new HashSet<>();
|
||||
private final Deque<CaddxMessage> messages = new LinkedBlockingDeque<>();
|
||||
private final SynchronousQueue<CaddxMessage> exchanger = new SynchronousQueue<>();
|
||||
private final Thread communicator;
|
||||
private final CaddxProtocol protocol;
|
||||
private final String serialPortName;
|
||||
private final int baudRate;
|
||||
private final SerialPort serialPort;
|
||||
private final InputStream in;
|
||||
private final OutputStream out;
|
||||
|
||||
// Receiver state variables
|
||||
private boolean inMessage = false;
|
||||
private boolean haveFirstByte = false;
|
||||
private int messageBufferLength = 0;
|
||||
private byte[] message;
|
||||
private int messageBufferIndex = 0;
|
||||
private boolean unStuff = false;
|
||||
private int tempAsciiByte = 0;
|
||||
|
||||
public CaddxCommunicator(SerialPortManager portManager, CaddxProtocol protocol, String serialPortName, int baudRate)
|
||||
throws UnsupportedCommOperationException, PortInUseException, IOException, TooManyListenersException {
|
||||
this.portManager = portManager;
|
||||
this.protocol = protocol;
|
||||
this.serialPortName = serialPortName;
|
||||
this.baudRate = baudRate;
|
||||
|
||||
SerialPortIdentifier portIdentifier = this.portManager.getIdentifier(serialPortName);
|
||||
if (portIdentifier == null) {
|
||||
throw new IOException("Cannot get the port identifier.");
|
||||
}
|
||||
serialPort = portIdentifier.open(this.getClass().getName(), 2000);
|
||||
serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
|
||||
serialPort.enableReceiveThreshold(1);
|
||||
serialPort.disableReceiveTimeout();
|
||||
|
||||
InputStream localIn = serialPort.getInputStream();
|
||||
if (localIn == null) {
|
||||
logger.warn("Cannot get the input stream of the serial port");
|
||||
throw new IOException("Input stream is null");
|
||||
}
|
||||
in = localIn;
|
||||
|
||||
OutputStream localOut = serialPort.getOutputStream();
|
||||
if (localOut == null) {
|
||||
logger.warn("Cannot get the output stream of the serial port");
|
||||
throw new IOException("Output stream is null");
|
||||
}
|
||||
out = localOut;
|
||||
|
||||
serialPort.notifyOnDataAvailable(true);
|
||||
serialPort.addEventListener(this);
|
||||
|
||||
communicator = new Thread(this::messageDispatchLoop, "Caddx Communicator");
|
||||
communicator.setDaemon(true);
|
||||
communicator.start();
|
||||
|
||||
message = new byte[0];
|
||||
|
||||
logger.trace("CaddxCommunicator communication thread started successfully for {}", serialPortName);
|
||||
}
|
||||
|
||||
public CaddxProtocol getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public String getSerialPortName() {
|
||||
return serialPortName;
|
||||
}
|
||||
|
||||
public int getBaudRate() {
|
||||
return baudRate;
|
||||
}
|
||||
|
||||
public void addListener(CaddxPanelListener listener) {
|
||||
listenerQueue.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message to panel. Asynchronous, i.e. returns immediately.
|
||||
* Messages are sent only when panel is ready (i.e. sent an
|
||||
* acknowledgment to last message), but no checks are implemented that
|
||||
* the message was correctly received and executed.
|
||||
*
|
||||
* @param msg Data to be sent to panel. First byte is message type.
|
||||
* Fletcher sum is computed and appended by transmit.
|
||||
*/
|
||||
public void transmit(CaddxMessage msg) {
|
||||
messages.add(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds this message before any others in the queue.
|
||||
* Used by receiver to send ACKs.
|
||||
*
|
||||
* @param msg The message
|
||||
*/
|
||||
public void transmitFirst(CaddxMessage msg) {
|
||||
messages.addFirst(msg);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
logger.trace("CaddxCommunicator stopping");
|
||||
|
||||
// kick thread out of waiting for FIFO
|
||||
communicator.interrupt();
|
||||
|
||||
// Close the streams first to unblock blocked reads and writes
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
|
||||
// Wait until communication thread exits
|
||||
try {
|
||||
communicator.join(3000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
// Also close the serial port
|
||||
serialPort.removeEventListener();
|
||||
serialPort.close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private void messageDispatchLoop() {
|
||||
int @Nullable [] expectedMessageNumbers = null;
|
||||
|
||||
@Nullable
|
||||
CaddxMessage outgoingMessage = null;
|
||||
boolean skipTransmit = true;
|
||||
|
||||
try {
|
||||
// loop until the thread is interrupted, sending out messages
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
// Initialize the state
|
||||
outgoingMessage = null;
|
||||
expectedMessageNumbers = null;
|
||||
|
||||
if (!skipTransmit) {
|
||||
// send next outgoing message if we have one
|
||||
outgoingMessage = messages.poll();
|
||||
if (outgoingMessage != null) {
|
||||
logger.trace("CaddxCommunicator.run() Outgoing message: {}", outgoingMessage.getMessageType());
|
||||
|
||||
byte[] msg = outgoingMessage.getMessageFrameBytes(protocol);
|
||||
out.write(msg);
|
||||
out.flush();
|
||||
|
||||
expectedMessageNumbers = outgoingMessage.getReplyMessageNumbers();
|
||||
|
||||
// Log message
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("->: {}", outgoingMessage.getName());
|
||||
logger.debug("->: {}", HexUtils
|
||||
.bytesToHex(outgoingMessage.getMessageFrameBytes(CaddxProtocol.Binary), " "));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.trace("CaddxCommunicator.run() skipTransmit: true");
|
||||
skipTransmit = false;
|
||||
}
|
||||
|
||||
// Check for an incoming message
|
||||
CaddxMessage incomingMessage = null;
|
||||
try {
|
||||
incomingMessage = exchanger.poll(3, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("CaddxCommunicator.run() InterruptedException caught.");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
// Log
|
||||
if (incomingMessage == null) {
|
||||
if (expectedMessageNumbers == null) { // Nothing expected, Nothing received we continue
|
||||
logger.trace("CaddxCommunicator.run(): Nothing expected, Nothing received we continue");
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("<-: {}", incomingMessage.getName());
|
||||
logger.debug("<-: {}",
|
||||
HexUtils.bytesToHex(incomingMessage.getMessageFrameBytes(CaddxProtocol.Binary), " "));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we wait for a reply
|
||||
if (expectedMessageNumbers == null) {
|
||||
if (incomingMessage != null) { // Nothing expected. Message received.
|
||||
logger.trace("CaddxCommunicator.run() Nothing expected, Message received");
|
||||
|
||||
// Check if Acknowledgement handling is required.
|
||||
if (incomingMessage.hasAcknowledgementFlag()) {
|
||||
if (incomingMessage.isChecksumCorrect()) {
|
||||
// send ACK
|
||||
transmitFirst(new CaddxMessage(CaddxMessageType.POSITIVE_ACKNOWLEDGE, ""));
|
||||
} else {
|
||||
// Send NAK
|
||||
transmitFirst(new CaddxMessage(CaddxMessageType.NEGATIVE_ACKNOWLEDGE, ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (incomingMessage == null) {
|
||||
logger.trace("CaddxCommunicator.run() Message expected. Nothing received");
|
||||
|
||||
// Message expected. Nothing received
|
||||
if (outgoingMessage != null) {
|
||||
transmitFirst(outgoingMessage); // put message in queue again
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
logger.trace("CaddxCommunicator.run() Message expected. Message received");
|
||||
|
||||
// Message expected. Message received.
|
||||
int receivedMessageType = incomingMessage.getMessageType();
|
||||
boolean isMessageExpected = IntStream.of(expectedMessageNumbers)
|
||||
.anyMatch(x -> x == receivedMessageType);
|
||||
|
||||
if (!isMessageExpected) {
|
||||
logger.trace("Non expected message received exp:{}, recv: {}", expectedMessageNumbers,
|
||||
receivedMessageType);
|
||||
|
||||
// Non expected reply received
|
||||
if (outgoingMessage != null) {
|
||||
transmitFirst(outgoingMessage); // put message in queue again
|
||||
skipTransmit = true; // Skip the transmit on the next cycle to receive the panel message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inform the listeners
|
||||
if (incomingMessage != null) {
|
||||
if (incomingMessage.isChecksumCorrect()) {
|
||||
for (CaddxPanelListener listener : listenerQueue) {
|
||||
listener.caddxMessage(this, incomingMessage);
|
||||
}
|
||||
} else {
|
||||
logger.warn(
|
||||
"CaddxCommunicator.run() Received packet checksum does not match. in: {} {}, calc {} {}",
|
||||
incomingMessage.getChecksum1In(), incomingMessage.getChecksum2In(),
|
||||
incomingMessage.getChecksum1Calc(), incomingMessage.getChecksum2Calc());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.debug("CaddxCommunicator.run() IOException. Stopping sender thread. {}", getSerialPortName());
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
logger.warn("CaddxCommunicator.run() Sender thread stopped. {}", getSerialPortName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler to receive the data from the serial port
|
||||
*
|
||||
* @param SerialPortEvent serialPortEvent The event that occurred on the serial port
|
||||
*/
|
||||
@Override
|
||||
public void serialEvent(@Nullable SerialPortEvent serialPortEvent) {
|
||||
if (serialPortEvent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (serialPortEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
|
||||
logger.trace("Data receiving from the serial port");
|
||||
if (protocol == CaddxProtocol.Binary) {
|
||||
receiveInBinaryProtocol(serialPortEvent);
|
||||
} else {
|
||||
receiveInAsciiProtocol(serialPortEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int readByte(InputStream stream) throws IOException {
|
||||
int b = -1;
|
||||
|
||||
if (stream.available() > 0) {
|
||||
b = stream.read();
|
||||
}
|
||||
if (b == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private int readAsciiByte(InputStream stream) throws IOException {
|
||||
if (!haveFirstByte) { // this is the 1st digit
|
||||
int b = readByte(in);
|
||||
tempAsciiByte = (b >= 0x30 && b <= 0x39) ? (b - 0x30) * 0x10 : (b - 0x37) * 0x10;
|
||||
haveFirstByte = true;
|
||||
}
|
||||
|
||||
if (haveFirstByte) { // this is the 2nd digit
|
||||
int b = readByte(in);
|
||||
tempAsciiByte += (b >= 0x30 && b <= 0x39) ? (b - 0x30) : (b - 0x37);
|
||||
haveFirstByte = false;
|
||||
}
|
||||
|
||||
return tempAsciiByte;
|
||||
}
|
||||
|
||||
private void loopUntilByteIsRead(InputStream stream, int byteToRead) throws IOException {
|
||||
int b = 0;
|
||||
do {
|
||||
b = readByte(in);
|
||||
} while (b != byteToRead);
|
||||
}
|
||||
|
||||
private void offerCaddxMessage() throws InterruptedException {
|
||||
logger.trace("Offering received message");
|
||||
|
||||
// Full message received in data byte array
|
||||
CaddxMessage caddxMessage = new CaddxMessage(message, true);
|
||||
if (!exchanger.offer(caddxMessage, 3, TimeUnit.SECONDS)) {
|
||||
logger.debug("Offered message was not received");
|
||||
}
|
||||
}
|
||||
|
||||
private void receiveInBinaryProtocol(SerialPortEvent serialPortEvent) {
|
||||
try {
|
||||
// Read the start byte
|
||||
if (!inMessage) // skip until 0x7E
|
||||
{
|
||||
loopUntilByteIsRead(in, 0x7e);
|
||||
|
||||
inMessage = true;
|
||||
messageBufferLength = 0;
|
||||
}
|
||||
logger.trace("CaddxCommunicator.handleBinaryProtocol() Got start byte");
|
||||
|
||||
// Read the message length
|
||||
if (messageBufferLength == 0) {
|
||||
int b = readByte(in);
|
||||
messageBufferLength = b + 2; // add two bytes for the checksum
|
||||
message = new byte[messageBufferLength];
|
||||
messageBufferIndex = 0;
|
||||
}
|
||||
logger.trace("CaddxCommunicator.handleBinaryProtocol() Got message length {}", messageBufferLength);
|
||||
|
||||
// Read the message
|
||||
do {
|
||||
int b = readByte(in);
|
||||
message[messageBufferIndex] = (byte) b;
|
||||
|
||||
if (message[messageBufferIndex] == 0x7D) {
|
||||
unStuff = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unStuff) {
|
||||
message[messageBufferIndex] |= 0x20;
|
||||
unStuff = false;
|
||||
}
|
||||
|
||||
messageBufferIndex++;
|
||||
} while (messageBufferIndex < messageBufferLength);
|
||||
|
||||
// Offer the message
|
||||
offerCaddxMessage();
|
||||
|
||||
logger.trace("CaddxCommunicator.handleBinaryProtocol() Got message {}", message[0]);
|
||||
} catch (EOFException e) {
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
} catch (InterruptedException e) {
|
||||
logger.trace("InterruptedException caught.");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
// Initialize state for a new reception
|
||||
inMessage = false;
|
||||
messageBufferLength = 0;
|
||||
messageBufferIndex = 0;
|
||||
unStuff = false;
|
||||
}
|
||||
|
||||
private void receiveInAsciiProtocol(SerialPortEvent serialPortEvent) {
|
||||
try {
|
||||
// Read the start byte
|
||||
if (!inMessage) {
|
||||
loopUntilByteIsRead(in, 0x0a);
|
||||
|
||||
inMessage = true;
|
||||
haveFirstByte = false;
|
||||
messageBufferLength = 0;
|
||||
}
|
||||
logger.trace("CaddxCommunicator.handleAsciiProtocol() Got start byte");
|
||||
|
||||
// Read the message length
|
||||
if (messageBufferLength == 0) {
|
||||
int b = readAsciiByte(in);
|
||||
messageBufferLength = b + 2; // add 2 bytes for the checksum
|
||||
message = new byte[messageBufferLength];
|
||||
}
|
||||
logger.trace("CaddxCommunicator.handleAsciiProtocol() Got message length {}", messageBufferLength);
|
||||
|
||||
// Read the message
|
||||
do {
|
||||
int b = readAsciiByte(in);
|
||||
message[messageBufferIndex] = (byte) b;
|
||||
messageBufferIndex++;
|
||||
} while (messageBufferIndex < messageBufferLength);
|
||||
|
||||
// Offer the message
|
||||
offerCaddxMessage();
|
||||
|
||||
logger.trace("CaddxCommunicator.handleAsciiProtocol() Got message {}", message[0]);
|
||||
} catch (EOFException e) {
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
} catch (InterruptedException e) {
|
||||
logger.trace("InterruptedException caught.");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
// Initialize state for a new reception
|
||||
inMessage = false;
|
||||
messageBufferLength = 0;
|
||||
messageBufferIndex = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.caddx.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Message Direction enumeration.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum CaddxDirection {
|
||||
IN,
|
||||
OUT
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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.caddx.internal;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Event for Receiving API Messages.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CaddxEvent extends EventObject {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final CaddxMessage caddxMessage;
|
||||
private final @Nullable Integer partition;
|
||||
private final @Nullable Integer zone;
|
||||
private final @Nullable Integer keypad;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param source
|
||||
*/
|
||||
public CaddxEvent(CaddxMessage caddxMessage, @Nullable Integer partition, @Nullable Integer zone,
|
||||
@Nullable Integer keypad) {
|
||||
super(caddxMessage);
|
||||
|
||||
this.caddxMessage = caddxMessage;
|
||||
this.partition = partition;
|
||||
this.zone = zone;
|
||||
this.keypad = keypad;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Message event from the Caddx Alarm System.
|
||||
*
|
||||
* @return message
|
||||
*/
|
||||
public CaddxMessage getCaddxMessage() {
|
||||
return caddxMessage;
|
||||
}
|
||||
|
||||
public @Nullable Integer getPartition() {
|
||||
return partition;
|
||||
}
|
||||
|
||||
public @Nullable Integer getZone() {
|
||||
return zone;
|
||||
}
|
||||
|
||||
public @Nullable Integer getKeypad() {
|
||||
return keypad;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,411 @@
|
||||
/**
|
||||
* 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.caddx.internal;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.util.HexUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A class that represents the Caddx Alarm Messages.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CaddxMessage {
|
||||
private final Logger logger = LoggerFactory.getLogger(CaddxMessage.class);
|
||||
private final CaddxMessageType caddxMessageType;
|
||||
private final Map<String, String> propertyMap = new HashMap<>();
|
||||
private final Map<String, String> idMap = new HashMap<>();
|
||||
private final byte[] message;
|
||||
private final boolean hasAcknowledgementFlag;
|
||||
private final byte checksum1In;
|
||||
private final byte checksum2In;
|
||||
private final byte checksum1Calc;
|
||||
private final byte checksum2Calc;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param message
|
||||
* - the message received
|
||||
*/
|
||||
public CaddxMessage(byte[] message, boolean withChecksum) {
|
||||
if (withChecksum && message.length < 3) {
|
||||
logger.debug("CaddxMessage: The message should be at least 3 bytes long.");
|
||||
throw new IllegalArgumentException("The message should be at least 3 bytes long");
|
||||
}
|
||||
if (!withChecksum && message.length < 1) {
|
||||
logger.debug("CaddxMessage: The message should be at least 1 byte long.");
|
||||
throw new IllegalArgumentException("The message should be at least 1 byte long");
|
||||
}
|
||||
|
||||
// Received data
|
||||
byte[] msg = message;
|
||||
|
||||
// Fill in the checksum
|
||||
if (withChecksum) {
|
||||
checksum1In = message[message.length - 2];
|
||||
checksum2In = message[message.length - 1];
|
||||
msg = Arrays.copyOf(message, message.length - 2);
|
||||
|
||||
byte[] fletcherSum = fletcher(msg);
|
||||
checksum1Calc = fletcherSum[0];
|
||||
checksum2Calc = fletcherSum[1];
|
||||
} else {
|
||||
byte[] fletcherSum = fletcher(msg);
|
||||
checksum1Calc = fletcherSum[0];
|
||||
checksum2Calc = fletcherSum[1];
|
||||
|
||||
checksum1In = checksum1Calc;
|
||||
checksum2In = checksum2Calc;
|
||||
}
|
||||
|
||||
// Fill in the message
|
||||
this.message = msg;
|
||||
|
||||
// Fill-in the acknowledgement flag
|
||||
if ((message[0] & 0x80) != 0) {
|
||||
hasAcknowledgementFlag = true;
|
||||
message[0] = (byte) (message[0] & 0x7f);
|
||||
} else {
|
||||
hasAcknowledgementFlag = false;
|
||||
}
|
||||
|
||||
// Fill-in the message type
|
||||
CaddxMessageType mt = CaddxMessageType.valueOfMessageType(message[0]);
|
||||
if (mt == null) {
|
||||
throw new IllegalArgumentException("Unknown message");
|
||||
}
|
||||
caddxMessageType = mt;
|
||||
|
||||
// Fill-in the properties
|
||||
processCaddxMessage();
|
||||
}
|
||||
|
||||
public CaddxMessage(CaddxMessageType type, String data) {
|
||||
int length = type.length;
|
||||
String[] tokens = data.split("\\,");
|
||||
if (length != 1 && tokens.length != length - 1) {
|
||||
logger.debug("token.length should be length-1. token.length={}, length={}", tokens.length, length);
|
||||
throw new IllegalArgumentException("CaddxMessage: data has not the correct format.");
|
||||
}
|
||||
|
||||
byte[] msg = new byte[length];
|
||||
msg[0] = (byte) type.number;
|
||||
for (int i = 0; i < length - 1; i++) {
|
||||
msg[i + 1] = (byte) Integer.decode(tokens[i]).intValue();
|
||||
}
|
||||
|
||||
// Fill-in the checksum
|
||||
byte[] fletcherSum = fletcher(msg);
|
||||
checksum1Calc = fletcherSum[0];
|
||||
checksum2Calc = fletcherSum[1];
|
||||
checksum1In = checksum1Calc;
|
||||
checksum2In = checksum2Calc;
|
||||
|
||||
// Fill-in the message
|
||||
this.message = msg;
|
||||
|
||||
// Fill-in the acknowledgement flag
|
||||
if ((message[0] & 0x80) != 0) {
|
||||
hasAcknowledgementFlag = true;
|
||||
message[0] = (byte) (message[0] & 0x7f);
|
||||
} else {
|
||||
hasAcknowledgementFlag = false;
|
||||
}
|
||||
|
||||
// Fill-in the message type
|
||||
this.caddxMessageType = type;
|
||||
|
||||
// Fill-in the properties
|
||||
processCaddxMessage();
|
||||
}
|
||||
|
||||
public byte getChecksum1In() {
|
||||
return checksum1In;
|
||||
}
|
||||
|
||||
public byte getChecksum2In() {
|
||||
return checksum2In;
|
||||
}
|
||||
|
||||
public byte getChecksum1Calc() {
|
||||
return checksum1Calc;
|
||||
}
|
||||
|
||||
public byte getChecksum2Calc() {
|
||||
return checksum2Calc;
|
||||
}
|
||||
|
||||
public CaddxMessageType getCaddxMessageType() {
|
||||
return caddxMessageType;
|
||||
}
|
||||
|
||||
public byte getMessageType() {
|
||||
return message[0];
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(caddxMessageType.name);
|
||||
switch (caddxMessageType) {
|
||||
case ZONE_STATUS_REQUEST:
|
||||
case ZONE_STATUS_MESSAGE:
|
||||
sb.append(" [Zone: ");
|
||||
sb.append(getPropertyById("zone_number"));
|
||||
sb.append("]");
|
||||
break;
|
||||
case LOG_EVENT_REQUEST:
|
||||
case LOG_EVENT_MESSAGE:
|
||||
sb.append(" [Event: ");
|
||||
sb.append(getPropertyById("panel_log_event_number"));
|
||||
sb.append("]");
|
||||
break;
|
||||
case PARTITION_STATUS_REQUEST:
|
||||
case PARTITION_STATUS_MESSAGE:
|
||||
sb.append(" [Partition: ");
|
||||
sb.append(getPropertyById("partition_number"));
|
||||
sb.append("]");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getPropertyValue(String property) {
|
||||
if (!propertyMap.containsKey(property)) {
|
||||
logger.debug("Message does not contain property [{}]", property);
|
||||
return "";
|
||||
}
|
||||
return propertyMap.get(property);
|
||||
}
|
||||
|
||||
public String getPropertyById(String id) {
|
||||
if (!idMap.containsKey(id)) {
|
||||
logger.debug("Message does not contain id [{}]", id);
|
||||
return "";
|
||||
}
|
||||
return idMap.get(id);
|
||||
}
|
||||
|
||||
public int @Nullable [] getReplyMessageNumbers() {
|
||||
return caddxMessageType.replyMessageNumbers;
|
||||
}
|
||||
|
||||
public CaddxSource getSource() {
|
||||
return getCaddxMessageType().source;
|
||||
}
|
||||
|
||||
public boolean isChecksumCorrect() {
|
||||
return checksum1In == checksum1Calc && checksum2In == checksum2Calc;
|
||||
}
|
||||
|
||||
public boolean isLengthCorrect() {
|
||||
return message.length == caddxMessageType.length;
|
||||
}
|
||||
|
||||
public boolean hasAcknowledgementFlag() {
|
||||
return hasAcknowledgementFlag;
|
||||
}
|
||||
|
||||
public byte[] getMessageFrameBytes(CaddxProtocol protocol) {
|
||||
if (protocol == CaddxProtocol.Binary) {
|
||||
return getMessageFrameBytesInBinary();
|
||||
} else {
|
||||
return getMessageFrameBytesInAscii();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getMessageBytes() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of a CaddxMessage.
|
||||
*
|
||||
* @return CaddxMessage string
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
CaddxMessageType mt = CaddxMessageType.valueOfMessageType(message[0]);
|
||||
if (mt == null) {
|
||||
return "Unknown message type";
|
||||
}
|
||||
|
||||
sb.append("Message: ");
|
||||
sb.append(String.format("%2s", Integer.toHexString(message[0])));
|
||||
sb.append(" ");
|
||||
sb.append(mt.name);
|
||||
sb.append(System.lineSeparator());
|
||||
|
||||
for (CaddxProperty p : mt.properties) {
|
||||
sb.append("\t").append(p.toString(message));
|
||||
sb.append(System.lineSeparator());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void putByteInBuffer(ByteBuffer frame, byte b) {
|
||||
if (b == 0x7e) {
|
||||
frame.put((byte) 0x7d);
|
||||
frame.put((byte) 0x5e);
|
||||
} else if (b == 0x7d) {
|
||||
frame.put((byte) 0x7d);
|
||||
frame.put((byte) 0x5d);
|
||||
} else {
|
||||
frame.put(b);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getByteBufferArray(ByteBuffer frame) {
|
||||
if (frame.hasArray()) {
|
||||
return frame.array();
|
||||
} else {
|
||||
byte[] byteArray = new byte[frame.capacity()];
|
||||
frame.position(0);
|
||||
frame.get(byteArray);
|
||||
return byteArray;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getMessageFrameBytesInBinary() {
|
||||
// Calculate bytes
|
||||
// 1 for the startbyte
|
||||
// 1 for the length
|
||||
// 2 for the checksum
|
||||
// n for the count of 0x7d and 0x7e occurrences in the message and checksum
|
||||
int additional = 4;
|
||||
for (int i = 0; i < message.length; i++) {
|
||||
if (message[i] == 0x7d || message[i] == 0x7e) {
|
||||
additional++;
|
||||
}
|
||||
}
|
||||
if (checksum1Calc == 0x7d || checksum1Calc == 0x7e) {
|
||||
additional++;
|
||||
}
|
||||
if (checksum2Calc == 0x7d || checksum2Calc == 0x7e) {
|
||||
additional++;
|
||||
}
|
||||
|
||||
ByteBuffer frame = ByteBuffer.allocate(message.length + additional);
|
||||
|
||||
// start character
|
||||
frame.put((byte) 0x7e);
|
||||
|
||||
// message length
|
||||
frame.put((byte) message.length);
|
||||
|
||||
// message
|
||||
for (int i = 0; i < message.length; i++) {
|
||||
putByteInBuffer(frame, message[i]);
|
||||
}
|
||||
|
||||
// 1st checksum byte
|
||||
putByteInBuffer(frame, checksum1Calc);
|
||||
|
||||
// 2nd checksum byte
|
||||
putByteInBuffer(frame, checksum2Calc);
|
||||
|
||||
return getByteBufferArray(frame);
|
||||
}
|
||||
|
||||
private byte[] getMessageFrameBytesInAscii() {
|
||||
// Calculate additional bytes
|
||||
// 1 for the start byte
|
||||
// 2 for the length
|
||||
// 4 for the checksum
|
||||
// 1 for the stop byte
|
||||
int additional = 8;
|
||||
|
||||
ByteBuffer frame = ByteBuffer.allocate(2 * message.length + additional);
|
||||
|
||||
// start character
|
||||
frame.put((byte) 0x0a);
|
||||
|
||||
// message length
|
||||
frame.put(HexUtils.byteToHex((byte) message.length));
|
||||
|
||||
// message
|
||||
for (int i = 0; i < message.length; i++) {
|
||||
frame.put(HexUtils.byteToHex(message[i]));
|
||||
}
|
||||
|
||||
// Checksum 1st byte
|
||||
frame.put(HexUtils.byteToHex(checksum1Calc));
|
||||
|
||||
// Checksum 2nd byte
|
||||
frame.put(HexUtils.byteToHex(checksum2Calc));
|
||||
|
||||
// Stop character
|
||||
frame.put((byte) 0x0d);
|
||||
|
||||
return getByteBufferArray(frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the incoming Caddx message and extracts the information.
|
||||
*/
|
||||
private void processCaddxMessage() {
|
||||
// fill the property lookup hashmaps
|
||||
for (CaddxProperty p : caddxMessageType.properties) {
|
||||
propertyMap.put(p.getName(), p.getValue(message));
|
||||
}
|
||||
for (CaddxProperty p : caddxMessageType.properties) {
|
||||
if (!"".equals(p.getId())) {
|
||||
idMap.put(p.getId(), p.getValue(message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the Fletcher checksum of the byte array.
|
||||
*
|
||||
* @param data The input byte array
|
||||
* @return Byte array with two elements. Checksum1 and Checksum2
|
||||
*/
|
||||
private byte[] fletcher(byte data[]) {
|
||||
int len = data.length;
|
||||
int sum1 = len, sum2 = len;
|
||||
for (int i = 0; i < len; i++) {
|
||||
int d = data[i] & 0xff;
|
||||
if (0xff - sum1 < d) {
|
||||
sum1 = (sum1 + 1) & 0xff;
|
||||
}
|
||||
sum1 = (sum1 + d) & 0xff;
|
||||
if (sum1 == 0xff) {
|
||||
sum1 = 0;
|
||||
}
|
||||
if (0xff - sum2 < sum1) {
|
||||
sum2 = (sum2 + 1) & 0xff;
|
||||
}
|
||||
sum2 = (sum2 + sum1) & 0xff;
|
||||
if (sum2 == 0xff) {
|
||||
sum2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return new byte[] { (byte) sum1, (byte) sum2 };
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.caddx.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Panel listener interface
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface CaddxPanelListener {
|
||||
public void caddxMessage(CaddxCommunicator communicator, CaddxMessage message);
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* 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.caddx.internal;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.CharacterIterator;
|
||||
import java.text.StringCharacterIterator;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Panel message property class
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CaddxProperty {
|
||||
// private
|
||||
private final String name;
|
||||
private final CaddxPropertyType type; // 'Int', 'String', 'Bit'
|
||||
private final int byteFrom;
|
||||
private final int byteLength;
|
||||
private final int bitFrom;
|
||||
private final int bitLength;
|
||||
private final boolean external;
|
||||
private final String id;
|
||||
|
||||
// Constructor
|
||||
public CaddxProperty(String id, int byteFrom, int byteLength, int bitFrom, int bitLength, CaddxPropertyType type,
|
||||
String name, boolean external) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.byteFrom = byteFrom;
|
||||
this.byteLength = byteLength;
|
||||
this.bitFrom = bitFrom;
|
||||
this.bitLength = bitLength;
|
||||
this.external = external;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public CaddxPropertyType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean getExternal() {
|
||||
return external;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getValue(byte[] message) {
|
||||
int mask;
|
||||
int val;
|
||||
|
||||
switch (type) {
|
||||
case INT:
|
||||
if (bitFrom == 0 && bitLength == 0) {
|
||||
mask = 255;
|
||||
val = message[byteFrom - 1] & mask;
|
||||
} else {
|
||||
mask = ((1 << ((bitLength - bitFrom))) - 1) << bitFrom;
|
||||
val = (message[byteFrom - 1] & mask) >> bitFrom;
|
||||
}
|
||||
|
||||
return Integer.toString(val);
|
||||
case STRING:
|
||||
byte[] str = Arrays.copyOfRange(message, byteFrom - 1, byteFrom + byteLength);
|
||||
return mapCaddxString(new String(str, StandardCharsets.US_ASCII));
|
||||
case BIT:
|
||||
return (((message[byteFrom - 1] & (1 << bitFrom)) > 0) ? "true" : "false");
|
||||
default:
|
||||
throw new IllegalArgumentException("type is unknown.");
|
||||
}
|
||||
}
|
||||
|
||||
public String toString(byte[] message) {
|
||||
int mask;
|
||||
int val;
|
||||
StringWriter sWriter = new StringWriter();
|
||||
PrintWriter pWriter = new PrintWriter(sWriter);
|
||||
|
||||
switch (type) {
|
||||
case INT:
|
||||
if (bitFrom == 0 && bitLength == 0) {
|
||||
mask = 255;
|
||||
val = message[byteFrom - 1];
|
||||
} else {
|
||||
mask = ((1 << ((bitLength - bitFrom) + 1)) - 1) << bitFrom;
|
||||
val = (message[byteFrom - 1] & mask) >> bitFrom;
|
||||
}
|
||||
|
||||
pWriter.printf("%s: %02x - %d - %c", name, val, val, Character.isValidCodePoint(val) ? val : 32);
|
||||
pWriter.flush();
|
||||
|
||||
return sWriter.toString();
|
||||
case STRING:
|
||||
pWriter.print(name);
|
||||
pWriter.print(": ");
|
||||
|
||||
byte[] a = Arrays.copyOfRange(message, byteFrom - 1, byteFrom + byteLength);
|
||||
pWriter.println(mapCaddxString(new String(a, StandardCharsets.US_ASCII)));
|
||||
pWriter.println();
|
||||
for (int i = 0; i < byteLength; i++) {
|
||||
pWriter.printf("%02x", message[byteFrom - 1 + i]);
|
||||
pWriter.print(" - ");
|
||||
pWriter.println((char) message[byteFrom - 1 + i]);
|
||||
}
|
||||
pWriter.flush();
|
||||
|
||||
return sWriter.toString();
|
||||
case BIT:
|
||||
pWriter.print(name);
|
||||
pWriter.print(": ");
|
||||
pWriter.print(((message[byteFrom - 1] & (1 << bitFrom)) > 0));
|
||||
pWriter.flush();
|
||||
|
||||
return sWriter.toString();
|
||||
default:
|
||||
pWriter.print("Unknown type: ");
|
||||
pWriter.print(type.toString());
|
||||
pWriter.flush();
|
||||
|
||||
return sWriter.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private String mapCaddxString(String str) {
|
||||
StringBuilder s = new StringBuilder(str.length());
|
||||
|
||||
CharacterIterator it = new StringCharacterIterator(str);
|
||||
for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) {
|
||||
switch (ch) {
|
||||
case 0xb7:
|
||||
s.append('Γ');
|
||||
break;
|
||||
case 0x10:
|
||||
s.append('Δ');
|
||||
break;
|
||||
case 0x13:
|
||||
s.append('Θ');
|
||||
break;
|
||||
case 0x14:
|
||||
s.append('Λ');
|
||||
break;
|
||||
case 0x12:
|
||||
s.append('Ξ');
|
||||
break;
|
||||
case 0xc8:
|
||||
s.append('Π');
|
||||
break;
|
||||
case 0x16:
|
||||
s.append('Σ');
|
||||
break;
|
||||
case 0xcc:
|
||||
s.append('Φ');
|
||||
break;
|
||||
case 0x17:
|
||||
s.append('Ψ');
|
||||
break;
|
||||
case 0x15:
|
||||
s.append('Ω');
|
||||
break;
|
||||
default:
|
||||
s.append(ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.caddx.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Message property types enumeration.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum CaddxPropertyType {
|
||||
INT,
|
||||
STRING,
|
||||
BIT
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.caddx.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Panel Protocol enumeration.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum CaddxProtocol {
|
||||
Binary,
|
||||
Ascii
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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.caddx.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Alarm component Source enumeration.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum CaddxSource {
|
||||
NONE,
|
||||
PANEL,
|
||||
KEYPAD,
|
||||
PARTITION,
|
||||
ZONE
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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.caddx.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.caddx.internal.CaddxProtocol;
|
||||
|
||||
/**
|
||||
* Configuration class for the Caddx RS232 Serial interface bridge.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class CaddxBridgeConfiguration {
|
||||
|
||||
// Caddx Bridge Thing constants
|
||||
public static final String PROTOCOL = "protocol";
|
||||
public static final String SERIAL_PORT = "serialPort";
|
||||
public static final String BAUD = "baud";
|
||||
|
||||
private CaddxProtocol protocol = CaddxProtocol.Binary;
|
||||
private @Nullable String serialPort;
|
||||
private int baudrate = 9600;
|
||||
|
||||
public CaddxProtocol getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public @Nullable String getSerialPort() {
|
||||
return serialPort;
|
||||
}
|
||||
|
||||
public int getBaudrate() {
|
||||
return baudrate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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.caddx.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Configuration class for the Caddx Keypad Thing.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class CaddxKeypadConfiguration {
|
||||
|
||||
// Keypad Thing constants
|
||||
public static final String KEYPAD_ADDRESS = "keypadAddress";
|
||||
|
||||
private int keypadAddress;
|
||||
|
||||
public int getKeypadAddress() {
|
||||
return keypadAddress;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.caddx.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Configuration class for the Caddx Partition Thing.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CaddxPartitionConfiguration {
|
||||
|
||||
// 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.
|
||||
*/
|
||||
private int partitionNumber;
|
||||
|
||||
/**
|
||||
* The User Number of the user that will execute commands against the partition.
|
||||
*/
|
||||
private int userNumber;
|
||||
|
||||
public int getPartitionNumber() {
|
||||
return partitionNumber;
|
||||
}
|
||||
|
||||
public int getUserNumber() {
|
||||
return userNumber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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.caddx.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Configuration class for the Caddx Zone Thing.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CaddxZoneConfiguration {
|
||||
|
||||
// Zone Thing constants
|
||||
public static final String ZONE_NUMBER = "zoneNumber";
|
||||
|
||||
/**
|
||||
* The Zone Number. Can be in the range of 1-192. Depends on the Panel model. This is a required parameter for a
|
||||
* zone.
|
||||
*/
|
||||
private int zoneNumber;
|
||||
|
||||
public int getZoneNumber() {
|
||||
return zoneNumber;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* 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.caddx.internal.discovery;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.caddx.internal.CaddxBindingConstants;
|
||||
import org.openhab.binding.caddx.internal.CaddxEvent;
|
||||
import org.openhab.binding.caddx.internal.config.CaddxKeypadConfiguration;
|
||||
import org.openhab.binding.caddx.internal.config.CaddxPartitionConfiguration;
|
||||
import org.openhab.binding.caddx.internal.config.CaddxZoneConfiguration;
|
||||
import org.openhab.binding.caddx.internal.handler.CaddxBridgeHandler;
|
||||
import org.openhab.binding.caddx.internal.handler.CaddxThingType;
|
||||
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.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class is responsible for discovering the supported Things.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CaddxDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService, DiscoveryService {
|
||||
private final Logger logger = LoggerFactory.getLogger(CaddxDiscoveryService.class);
|
||||
|
||||
private @Nullable CaddxBridgeHandler caddxBridgeHandler = null;
|
||||
|
||||
public CaddxDiscoveryService() {
|
||||
super(CaddxBindingConstants.SUPPORTED_THING_TYPES_UIDS, 15, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
// Discovery is performed implicitly via the CadxBridgeHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add a Thing to the Smarthome Inbox.
|
||||
*
|
||||
* @param bridge
|
||||
* @param caddxThingType
|
||||
* @param event
|
||||
*/
|
||||
public void addThing(Bridge bridge, CaddxThingType caddxThingType, CaddxEvent event) {
|
||||
ThingUID thingUID = null;
|
||||
String thingID = "";
|
||||
String thingLabel = "";
|
||||
Map<String, Object> properties = null;
|
||||
|
||||
Integer partition = event.getPartition();
|
||||
Integer zone = event.getZone();
|
||||
Integer keypad = event.getKeypad();
|
||||
String representationProperty = null;
|
||||
|
||||
switch (caddxThingType) {
|
||||
case PANEL:
|
||||
thingID = "panel";
|
||||
thingLabel = "Panel";
|
||||
thingUID = new ThingUID(CaddxBindingConstants.PANEL_THING_TYPE, bridge.getUID(), thingID);
|
||||
break;
|
||||
case PARTITION:
|
||||
thingID = "partition" + partition;
|
||||
thingLabel = "Partition " + partition;
|
||||
thingUID = new ThingUID(CaddxBindingConstants.PARTITION_THING_TYPE, bridge.getUID(), thingID);
|
||||
|
||||
if (partition != null) {
|
||||
properties = Collections.singletonMap(CaddxPartitionConfiguration.PARTITION_NUMBER, partition);
|
||||
representationProperty = CaddxPartitionConfiguration.PARTITION_NUMBER;
|
||||
}
|
||||
|
||||
break;
|
||||
case ZONE:
|
||||
thingID = "zone" + zone;
|
||||
thingLabel = "Zone " + zone;
|
||||
thingUID = new ThingUID(CaddxBindingConstants.ZONE_THING_TYPE, bridge.getUID(), thingID);
|
||||
|
||||
if (zone != null) {
|
||||
properties = Collections.singletonMap(CaddxZoneConfiguration.ZONE_NUMBER, zone);
|
||||
representationProperty = CaddxZoneConfiguration.ZONE_NUMBER;
|
||||
}
|
||||
break;
|
||||
case KEYPAD:
|
||||
thingID = "keypad";
|
||||
thingLabel = "Keypad";
|
||||
thingUID = new ThingUID(CaddxBindingConstants.KEYPAD_THING_TYPE, bridge.getUID(), thingID);
|
||||
|
||||
if (keypad != null) {
|
||||
properties = Collections.singletonMap(CaddxKeypadConfiguration.KEYPAD_ADDRESS, keypad);
|
||||
representationProperty = CaddxKeypadConfiguration.KEYPAD_ADDRESS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (thingUID != null) {
|
||||
DiscoveryResult discoveryResult;
|
||||
|
||||
if (properties != null && representationProperty != null) {
|
||||
discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withRepresentationProperty(representationProperty).withBridge(bridge.getUID())
|
||||
.withLabel(thingLabel).build();
|
||||
} else {
|
||||
discoveryResult = DiscoveryResultBuilder.create(thingUID).withBridge(bridge.getUID())
|
||||
.withLabel(thingLabel).build();
|
||||
}
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
} else {
|
||||
logger.warn("addThing(): Unable to Add Caddx Alarm Thing to Inbox!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates the Discovery Service.
|
||||
*/
|
||||
@Override
|
||||
public void activate() {
|
||||
CaddxBridgeHandler handler = caddxBridgeHandler;
|
||||
if (handler != null) {
|
||||
handler.registerDiscoveryService(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates the Discovery Service.
|
||||
*/
|
||||
@Override
|
||||
public void deactivate() {
|
||||
CaddxBridgeHandler handler = caddxBridgeHandler;
|
||||
if (handler != null) {
|
||||
handler.unregisterDiscoveryService();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
if (handler instanceof CaddxBridgeHandler) {
|
||||
caddxBridgeHandler = (CaddxBridgeHandler) handler;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return caddxBridgeHandler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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.caddx.internal.factory;
|
||||
|
||||
import static org.openhab.binding.caddx.internal.CaddxBindingConstants.SUPPORTED_THING_TYPES_UIDS;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.caddx.internal.CaddxBindingConstants;
|
||||
import org.openhab.binding.caddx.internal.handler.CaddxBridgeHandler;
|
||||
import org.openhab.binding.caddx.internal.handler.ThingHandlerKeypad;
|
||||
import org.openhab.binding.caddx.internal.handler.ThingHandlerPanel;
|
||||
import org.openhab.binding.caddx.internal.handler.ThingHandlerPartition;
|
||||
import org.openhab.binding.caddx.internal.handler.ThingHandlerZone;
|
||||
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.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
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 CaddxHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@Component(configurationPid = "binding.caddx", service = ThingHandlerFactory.class)
|
||||
@NonNullByDefault
|
||||
public class CaddxHandlerFactory extends BaseThingHandlerFactory {
|
||||
private final Logger logger = LoggerFactory.getLogger(CaddxHandlerFactory.class);
|
||||
private final SerialPortManager portManager;
|
||||
|
||||
@Activate
|
||||
public CaddxHandlerFactory(@Reference SerialPortManager portManager) {
|
||||
this.portManager = portManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(CaddxBindingConstants.CADDXBRIDGE_THING_TYPE)) {
|
||||
return new CaddxBridgeHandler(portManager, (Bridge) thing);
|
||||
} else if (thingTypeUID.equals(CaddxBindingConstants.PANEL_THING_TYPE)) {
|
||||
return new ThingHandlerPanel(thing);
|
||||
} else if (thingTypeUID.equals(CaddxBindingConstants.PARTITION_THING_TYPE)) {
|
||||
return new ThingHandlerPartition(thing);
|
||||
} else if (thingTypeUID.equals(CaddxBindingConstants.ZONE_THING_TYPE)) {
|
||||
return new ThingHandlerZone(thing);
|
||||
} else if (thingTypeUID.equals(CaddxBindingConstants.KEYPAD_THING_TYPE)) {
|
||||
return new ThingHandlerKeypad(thing);
|
||||
} else {
|
||||
logger.debug("createHandler(): ThingHandler not found for {}", thingTypeUID);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* 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.caddx.internal.handler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.caddx.internal.CaddxEvent;
|
||||
import org.openhab.binding.caddx.internal.config.CaddxKeypadConfiguration;
|
||||
import org.openhab.binding.caddx.internal.config.CaddxPartitionConfiguration;
|
||||
import org.openhab.binding.caddx.internal.config.CaddxZoneConfiguration;
|
||||
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.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 Caddx Thing Handler.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class CaddxBaseThingHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CaddxBaseThingHandler.class);
|
||||
|
||||
/** Bridge Handler for the Thing. */
|
||||
private @Nullable CaddxBridgeHandler caddxBridgeHandler = null;
|
||||
|
||||
/** Caddx Alarm Thing type. */
|
||||
private CaddxThingType caddxThingType;
|
||||
|
||||
/** Partition Number. */
|
||||
private int partitionNumber;
|
||||
|
||||
/** User Number. */
|
||||
private int userNumber;
|
||||
|
||||
/** Zone Number. */
|
||||
private int zoneNumber;
|
||||
|
||||
/** Keypad Address. */
|
||||
private int keypadAddress;
|
||||
|
||||
public CaddxBaseThingHandler(Thing thing, CaddxThingType caddxThingType) {
|
||||
super(thing);
|
||||
this.caddxThingType = caddxThingType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
getConfiguration(caddxThingType);
|
||||
|
||||
// set the Thing offline for now
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Bridge Handler for the Caddx system.
|
||||
*
|
||||
* @return CaddxBridgeHandler
|
||||
*/
|
||||
public @Nullable CaddxBridgeHandler getCaddxBridgeHandler() {
|
||||
if (this.caddxBridgeHandler == null) {
|
||||
Bridge bridge = getBridge();
|
||||
|
||||
if (bridge == null) {
|
||||
logger.debug("getCaddxBridgeHandler(): Unable to get bridge!");
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.trace("getCaddxBridgeHandler(): Bridge for '{}' - '{}'", getThing().getUID(), bridge.getUID());
|
||||
|
||||
ThingHandler handler = bridge.getHandler();
|
||||
|
||||
if (handler instanceof CaddxBridgeHandler) {
|
||||
this.caddxBridgeHandler = (CaddxBridgeHandler) handler;
|
||||
} else {
|
||||
logger.debug("getCaddxBridgeHandler(): Unable to get bridge handler!");
|
||||
}
|
||||
}
|
||||
|
||||
return this.caddxBridgeHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to Update a Channel
|
||||
*
|
||||
* @param channel
|
||||
* @param state
|
||||
* @param description
|
||||
*/
|
||||
public abstract void updateChannel(ChannelUID channel, String data);
|
||||
|
||||
/**
|
||||
* Receives Events from the bridge.
|
||||
*
|
||||
* @param event.
|
||||
* @param thing
|
||||
*/
|
||||
public abstract void caddxEventReceived(CaddxEvent event, Thing thing);
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the thing configuration.
|
||||
*
|
||||
* @param caddxThingType The Thing type
|
||||
*/
|
||||
private void getConfiguration(CaddxThingType caddxThingType) {
|
||||
switch (caddxThingType) {
|
||||
case PARTITION:
|
||||
CaddxPartitionConfiguration partitionConfiguration = getConfigAs(CaddxPartitionConfiguration.class);
|
||||
setPartitionNumber(partitionConfiguration.getPartitionNumber());
|
||||
setUserNumber(partitionConfiguration.getUserNumber());
|
||||
break;
|
||||
case ZONE:
|
||||
CaddxZoneConfiguration zoneConfiguration = getConfigAs(CaddxZoneConfiguration.class);
|
||||
setZoneNumber(zoneConfiguration.getZoneNumber());
|
||||
break;
|
||||
case KEYPAD:
|
||||
CaddxKeypadConfiguration keypadConfiguration = getConfigAs(CaddxKeypadConfiguration.class);
|
||||
setKeypadAddress(keypadConfiguration.getKeypadAddress());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Thing type.
|
||||
*
|
||||
* @return caddxThingType
|
||||
*/
|
||||
public CaddxThingType getCaddxThingType() {
|
||||
return caddxThingType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Partition Number.
|
||||
*
|
||||
* @return partitionNumber
|
||||
*/
|
||||
public int getPartitionNumber() {
|
||||
return partitionNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Partition Number.
|
||||
*
|
||||
* @param partitionNumber
|
||||
*/
|
||||
public void setPartitionNumber(int partitionNumber) {
|
||||
this.partitionNumber = partitionNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get User Number.
|
||||
*
|
||||
* @return userNumber
|
||||
*/
|
||||
public int getUserNumber() {
|
||||
return userNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set User Number.
|
||||
*
|
||||
* @param userNumber
|
||||
*/
|
||||
public void setUserNumber(int userNumber) {
|
||||
this.userNumber = userNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Zone Number.
|
||||
*
|
||||
* @return zoneNumber
|
||||
*/
|
||||
public int getZoneNumber() {
|
||||
return zoneNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Zone Number.
|
||||
*
|
||||
* @param zoneNumber
|
||||
*/
|
||||
public void setZoneNumber(int zoneNumber) {
|
||||
this.zoneNumber = zoneNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Keypad Address.
|
||||
*
|
||||
* @return keypadAddress
|
||||
*/
|
||||
public int getKeypadAddress() {
|
||||
return keypadAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Keypad Address.
|
||||
*
|
||||
* @param keypadAddress
|
||||
*/
|
||||
public void setKeypadAddress(int keypadAddress) {
|
||||
this.keypadAddress = keypadAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Channel by ChannelUID.
|
||||
*
|
||||
* @param channelUID
|
||||
*/
|
||||
public @Nullable 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
/**
|
||||
* 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.caddx.internal.handler;
|
||||
|
||||
import static org.openhab.binding.caddx.internal.CaddxBindingConstants.SEND_COMMAND;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.TooManyListenersException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.caddx.internal.CaddxBindingConstants;
|
||||
import org.openhab.binding.caddx.internal.CaddxCommunicator;
|
||||
import org.openhab.binding.caddx.internal.CaddxEvent;
|
||||
import org.openhab.binding.caddx.internal.CaddxMessage;
|
||||
import org.openhab.binding.caddx.internal.CaddxMessageType;
|
||||
import org.openhab.binding.caddx.internal.CaddxPanelListener;
|
||||
import org.openhab.binding.caddx.internal.CaddxProtocol;
|
||||
import org.openhab.binding.caddx.internal.CaddxSource;
|
||||
import org.openhab.binding.caddx.internal.config.CaddxBridgeConfiguration;
|
||||
import org.openhab.binding.caddx.internal.config.CaddxKeypadConfiguration;
|
||||
import org.openhab.binding.caddx.internal.config.CaddxPartitionConfiguration;
|
||||
import org.openhab.binding.caddx.internal.config.CaddxZoneConfiguration;
|
||||
import org.openhab.binding.caddx.internal.discovery.CaddxDiscoveryService;
|
||||
import org.openhab.core.io.transport.serial.PortInUseException;
|
||||
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||
import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
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.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The bridge handler for the Caddx RS232 Serial interface.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class CaddxBridgeHandler extends BaseBridgeHandler implements CaddxPanelListener {
|
||||
private final Logger logger = LoggerFactory.getLogger(CaddxBridgeHandler.class);
|
||||
|
||||
static final byte[] DISCOVERY_PARTITION_STATUS_REQUEST_0 = { 0x26, 0x00 };
|
||||
static final byte[] DISCOVERY_ZONES_SNAPSHOT_REQUEST_00 = { 0x25, 0x00 };
|
||||
static final byte[] DISCOVERY_ZONES_SNAPSHOT_REQUEST_10 = { 0x25, 0x10 };
|
||||
static final byte[] DISCOVERY_ZONES_SNAPSHOT_REQUEST_20 = { 0x25, 0x20 };
|
||||
static final byte[] DISCOVERY_PARTITIONS_SNAPSHOT_REQUEST = { 0x27 };
|
||||
|
||||
private final SerialPortManager portManager;
|
||||
private @Nullable CaddxDiscoveryService discoveryService = null;
|
||||
private CaddxProtocol protocol = CaddxProtocol.Binary;
|
||||
private String serialPortName = "";
|
||||
private int baudRate;
|
||||
private @Nullable CaddxCommunicator communicator = null;
|
||||
|
||||
// Things served by the bridge
|
||||
private Map<BigDecimal, Thing> thingZonesMap = new ConcurrentHashMap<>();
|
||||
private Map<BigDecimal, Thing> thingPartitionsMap = new ConcurrentHashMap<>();
|
||||
private Map<BigDecimal, Thing> thingKeypadsMap = new ConcurrentHashMap<>();
|
||||
private @Nullable Thing thingPanel = null;
|
||||
|
||||
public @Nullable CaddxDiscoveryService getDiscoveryService() {
|
||||
return discoveryService;
|
||||
}
|
||||
|
||||
public void setDiscoveryService(CaddxDiscoveryService discoveryService) {
|
||||
this.discoveryService = discoveryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param bridge
|
||||
*/
|
||||
public CaddxBridgeHandler(SerialPortManager portManager, Bridge bridge) {
|
||||
super(bridge);
|
||||
|
||||
this.portManager = portManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
CaddxBridgeConfiguration configuration = getConfigAs(CaddxBridgeConfiguration.class);
|
||||
|
||||
String portName = configuration.getSerialPort();
|
||||
if (portName == null) {
|
||||
logger.debug("Serial port is not defined in the configuration");
|
||||
return;
|
||||
}
|
||||
serialPortName = portName;
|
||||
protocol = configuration.getProtocol();
|
||||
baudRate = configuration.getBaudrate();
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
|
||||
// create & start panel interface
|
||||
logger.debug("Starting interface at port {} with baudrate {} and protocol {}", serialPortName, baudRate,
|
||||
protocol);
|
||||
|
||||
try {
|
||||
communicator = new CaddxCommunicator(portManager, protocol, serialPortName, baudRate);
|
||||
} catch (IOException | TooManyListenersException | UnsupportedCommOperationException | PortInUseException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Communication cannot be initialized. " + e.toString());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CaddxCommunicator comm = communicator;
|
||||
if (comm != null) {
|
||||
comm.addListener(this);
|
||||
|
||||
// Send discovery commands for the things
|
||||
comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_00, false));
|
||||
comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_10, false));
|
||||
comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_20, false));
|
||||
comm.transmit(new CaddxMessage(DISCOVERY_PARTITION_STATUS_REQUEST_0, false));
|
||||
comm.transmit(new CaddxMessage(DISCOVERY_PARTITIONS_SNAPSHOT_REQUEST, false));
|
||||
}
|
||||
|
||||
// list all channels
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("list all {} channels:", getThing().getChannels().size());
|
||||
for (Channel c : getThing().getChannels()) {
|
||||
logger.trace("Channel Type {} UID {}", c.getChannelTypeUID(), c.getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
CaddxCommunicator comm = communicator;
|
||||
if (comm != null) {
|
||||
comm.stop();
|
||||
comm = null;
|
||||
}
|
||||
|
||||
if (discoveryService != null) {
|
||||
unregisterDiscoveryService();
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public @Nullable Thing findThing(CaddxThingType caddxThingType, @Nullable Integer partition, @Nullable Integer zone,
|
||||
@Nullable Integer keypad) {
|
||||
switch (caddxThingType) {
|
||||
case PARTITION:
|
||||
if (partition != null) {
|
||||
return thingPartitionsMap.get(BigDecimal.valueOf(partition));
|
||||
}
|
||||
case ZONE:
|
||||
if (zone != null) {
|
||||
return thingZonesMap.get(BigDecimal.valueOf(zone));
|
||||
}
|
||||
case KEYPAD:
|
||||
if (keypad != null) {
|
||||
return thingKeypadsMap.get(BigDecimal.valueOf(keypad));
|
||||
}
|
||||
case PANEL:
|
||||
return thingPanel;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.trace("handleCommand(), channelUID: {}, command: {}", channelUID, command);
|
||||
|
||||
switch (channelUID.getId()) {
|
||||
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];
|
||||
}
|
||||
|
||||
sendCommand(cmd, data);
|
||||
|
||||
updateState(channelUID, new StringType(""));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logger.debug("Unknown command {}", command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command to the panel
|
||||
*
|
||||
* @param command The command to be send
|
||||
* @param data The associated command data
|
||||
*/
|
||||
public boolean sendCommand(String command, String data) {
|
||||
logger.trace("sendCommand(): Attempting to send Command: command - {} - data: {}", command, data);
|
||||
|
||||
CaddxMessage msg = null;
|
||||
|
||||
switch (command) {
|
||||
case CaddxBindingConstants.ZONE_BYPASSED:
|
||||
msg = new CaddxMessage(CaddxMessageType.ZONE_BYPASS_TOGGLE, data);
|
||||
break;
|
||||
case CaddxBindingConstants.ZONE_STATUS_REQUEST:
|
||||
msg = new CaddxMessage(CaddxMessageType.ZONE_STATUS_REQUEST, data);
|
||||
break;
|
||||
case CaddxBindingConstants.ZONE_NAME_REQUEST:
|
||||
msg = new CaddxMessage(CaddxMessageType.ZONE_NAME_REQUEST, data);
|
||||
break;
|
||||
case CaddxBindingConstants.PARTITION_STATUS_REQUEST:
|
||||
msg = new CaddxMessage(CaddxMessageType.PARTITION_STATUS_REQUEST, data);
|
||||
break;
|
||||
case CaddxBindingConstants.PARTITION_PRIMARY_COMMAND_WITH_PIN:
|
||||
msg = new CaddxMessage(CaddxMessageType.PRIMARY_KEYPAD_FUNCTION_WITH_PIN, data);
|
||||
break;
|
||||
case CaddxBindingConstants.PARTITION_SECONDARY_COMMAND:
|
||||
msg = new CaddxMessage(CaddxMessageType.SECONDARY_KEYPAD_FUNCTION, data);
|
||||
break;
|
||||
case CaddxBindingConstants.PANEL_SYSTEM_STATUS_REQUEST:
|
||||
msg = new CaddxMessage(CaddxMessageType.SYSTEM_STATUS_REQUEST, data);
|
||||
break;
|
||||
case CaddxBindingConstants.PANEL_INTERFACE_CONFIGURATION_REQUEST:
|
||||
msg = new CaddxMessage(CaddxMessageType.INTERFACE_CONFIGURATION_REQUEST, data);
|
||||
break;
|
||||
case CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST:
|
||||
msg = new CaddxMessage(CaddxMessageType.LOG_EVENT_REQUEST, data);
|
||||
break;
|
||||
default:
|
||||
logger.debug("Unknown command {}", command);
|
||||
return false;
|
||||
}
|
||||
|
||||
CaddxCommunicator comm = communicator;
|
||||
if (comm != null) {
|
||||
comm.transmit(msg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Discovery Service.
|
||||
*
|
||||
* @param discoveryService
|
||||
*/
|
||||
public void registerDiscoveryService(CaddxDiscoveryService discoveryService) {
|
||||
this.discoveryService = discoveryService;
|
||||
logger.trace("registerDiscoveryService(): Discovery Service Registered!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the Discovery Service.
|
||||
*/
|
||||
public void unregisterDiscoveryService() {
|
||||
logger.trace("unregisterDiscoveryService(): Discovery Service Unregistered!");
|
||||
discoveryService = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void caddxMessage(CaddxCommunicator communicator, CaddxMessage caddxMessage) {
|
||||
CaddxSource source = caddxMessage.getSource();
|
||||
|
||||
if (source != CaddxSource.NONE) {
|
||||
CaddxThingType caddxThingType = null;
|
||||
@Nullable
|
||||
Integer partition = null;
|
||||
@Nullable
|
||||
Integer zone = null;
|
||||
@Nullable
|
||||
Integer keypad = null;
|
||||
|
||||
switch (source) {
|
||||
case PANEL:
|
||||
caddxThingType = CaddxThingType.PANEL;
|
||||
break;
|
||||
case PARTITION:
|
||||
caddxThingType = CaddxThingType.PARTITION;
|
||||
partition = Integer.parseInt(caddxMessage.getPropertyById("partition_number")) + 1;
|
||||
break;
|
||||
case ZONE:
|
||||
caddxThingType = CaddxThingType.ZONE;
|
||||
zone = Integer.parseInt(caddxMessage.getPropertyById("zone_number")) + 1;
|
||||
break;
|
||||
case KEYPAD:
|
||||
caddxThingType = CaddxThingType.KEYPAD;
|
||||
keypad = Integer.parseInt(caddxMessage.getPropertyById("keypad_address"));
|
||||
break;
|
||||
default:
|
||||
logger.debug("Source has illegal value");
|
||||
return;
|
||||
}
|
||||
|
||||
CaddxEvent event = new CaddxEvent(caddxMessage, partition, zone, keypad);
|
||||
|
||||
// Find the thing
|
||||
Thing thing = findThing(caddxThingType, partition, zone, keypad);
|
||||
CaddxDiscoveryService discoveryService = getDiscoveryService();
|
||||
if (thing != null) {
|
||||
CaddxBaseThingHandler thingHandler = (CaddxBaseThingHandler) thing.getHandler();
|
||||
if (thingHandler != null) {
|
||||
thingHandler.caddxEventReceived(event, thing);
|
||||
}
|
||||
} else {
|
||||
if (discoveryService != null) {
|
||||
discoveryService.addThing(getThing(), caddxThingType, event);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle specific messages that add multiple discovered things
|
||||
if (discoveryService != null) {
|
||||
switch (caddxMessage.getCaddxMessageType()) {
|
||||
case PARTITIONS_SNAPSHOT_MESSAGE:
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
if (caddxMessage.getPropertyById("partition_" + i + "_valid").equals("true")) {
|
||||
thing = findThing(CaddxThingType.PARTITION, i, null, null);
|
||||
if (thing != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
event = new CaddxEvent(caddxMessage, i, null, null);
|
||||
discoveryService.addThing(getThing(), CaddxThingType.PARTITION, event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZONES_SNAPSHOT_MESSAGE:
|
||||
int zoneOffset = Integer.parseInt(caddxMessage.getPropertyById("zone_offset"));
|
||||
for (int i = 1; i <= 16; i++) {
|
||||
if (caddxMessage.getPropertyById("zone_" + i + "_trouble").equals("false")) {
|
||||
thing = findThing(CaddxThingType.ZONE, null, zoneOffset + i, null);
|
||||
if (thing != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
event = new CaddxEvent(caddxMessage, null, zoneOffset + i, null);
|
||||
discoveryService.addThing(getThing(), CaddxThingType.ZONE, event);
|
||||
} else {
|
||||
logger.debug("troubled zone: {}", zoneOffset + i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.singleton(CaddxDiscoveryService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) {
|
||||
if (childHandler instanceof ThingHandlerPartition) {
|
||||
BigDecimal id = (BigDecimal) childThing.getConfiguration()
|
||||
.get(CaddxPartitionConfiguration.PARTITION_NUMBER);
|
||||
thingPartitionsMap.put(id, childThing);
|
||||
} else if (childHandler instanceof ThingHandlerZone) {
|
||||
BigDecimal id = (BigDecimal) childThing.getConfiguration().get(CaddxZoneConfiguration.ZONE_NUMBER);
|
||||
thingZonesMap.put(id, childThing);
|
||||
} else if (childHandler instanceof ThingHandlerKeypad) {
|
||||
BigDecimal id = (BigDecimal) childThing.getConfiguration().get(CaddxKeypadConfiguration.KEYPAD_ADDRESS);
|
||||
thingKeypadsMap.put(id, childThing);
|
||||
} else if (childHandler instanceof ThingHandlerPanel) {
|
||||
thingPanel = childThing;
|
||||
}
|
||||
|
||||
super.childHandlerInitialized(childHandler, childThing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) {
|
||||
if (childHandler instanceof ThingHandlerPartition) {
|
||||
BigDecimal id = (BigDecimal) childThing.getConfiguration()
|
||||
.get(CaddxPartitionConfiguration.PARTITION_NUMBER);
|
||||
thingPartitionsMap.remove(id);
|
||||
} else if (childHandler instanceof ThingHandlerZone) {
|
||||
BigDecimal id = (BigDecimal) childThing.getConfiguration().get(CaddxZoneConfiguration.ZONE_NUMBER);
|
||||
thingZonesMap.remove(id);
|
||||
} else if (childHandler instanceof ThingHandlerKeypad) {
|
||||
BigDecimal id = (BigDecimal) childThing.getConfiguration().get(CaddxKeypadConfiguration.KEYPAD_ADDRESS);
|
||||
thingKeypadsMap.remove(id);
|
||||
} else if (childHandler instanceof ThingHandlerPanel) {
|
||||
thingPanel = null;
|
||||
}
|
||||
|
||||
super.childHandlerDisposed(childHandler, childThing);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.caddx.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Used to map thing types from the binding string to a ENUM value.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum CaddxThingType {
|
||||
PANEL,
|
||||
PARTITION,
|
||||
ZONE,
|
||||
KEYPAD;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* 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.caddx.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.caddx.internal.CaddxMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Used to parse panel log event messages.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LogEventMessage {
|
||||
private final Logger logger = LoggerFactory.getLogger(LogEventMessage.class);
|
||||
|
||||
public final String number;
|
||||
public final String size;
|
||||
public final String type;
|
||||
public final String zud;
|
||||
public final String partition;
|
||||
public final String month;
|
||||
public final String day;
|
||||
public final String hour;
|
||||
public final String minute;
|
||||
|
||||
LogEventMessage(CaddxMessage message) {
|
||||
this.number = message.getPropertyById("panel_log_event_number");
|
||||
this.size = message.getPropertyById("panel_log_event_size");
|
||||
this.type = message.getPropertyById("panel_log_event_type");
|
||||
this.zud = message.getPropertyById("panel_log_event_zud");
|
||||
this.partition = message.getPropertyById("panel_log_event_partition");
|
||||
this.month = message.getPropertyById("panel_log_event_month");
|
||||
this.day = message.getPropertyById("panel_log_event_day");
|
||||
this.hour = message.getPropertyById("panel_log_event_hour");
|
||||
this.minute = message.getPropertyById("panel_log_event_minute");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int eventType = Integer.parseInt(type);
|
||||
logger.trace("eventType received: {}", eventType);
|
||||
LogEventType logEventType = LogEventType.valueOfLogEventType(eventType);
|
||||
if (logEventType == null) {
|
||||
return "Unknown log event type received";
|
||||
}
|
||||
|
||||
// Date
|
||||
sb.append(String.format("%02d", Integer.parseInt(day))).append('-')
|
||||
.append(String.format("%02d", Integer.parseInt(month))).append(' ')
|
||||
.append(String.format("%02d", Integer.parseInt(hour))).append(':')
|
||||
.append(String.format("%02d", Integer.parseInt(minute))).append(' ');
|
||||
|
||||
sb.append(logEventType.description);
|
||||
if (logEventType.isPartitionValid) {
|
||||
sb.append(" Partition ").append(Integer.parseInt(partition) + 1);
|
||||
}
|
||||
|
||||
switch (logEventType.zud) {
|
||||
case None:
|
||||
break;
|
||||
case Zone:
|
||||
sb.append(" Zone ").append(Integer.parseInt(zud) + 1);
|
||||
break;
|
||||
case User:
|
||||
sb.append(" User ").append(Integer.parseInt(zud) + 1);
|
||||
break;
|
||||
case Device:
|
||||
sb.append(" Device ").append(zud);
|
||||
break;
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
} catch (NumberFormatException e) {
|
||||
logger.debug("LogEventMessage error. {}", e.getMessage(), e);
|
||||
return "logmessage cannot be constructed";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 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.caddx.internal.handler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* All the log event types
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum LogEventType {
|
||||
ALARM(0, ZoneUserDevice.Zone, true, "Alarm"),
|
||||
ALARM_RESTORE(1, ZoneUserDevice.Zone, true, "Alarm restore"),
|
||||
BYPASS(2, ZoneUserDevice.Zone, true, "Bypass"),
|
||||
BYPASS_RESTORE(3, ZoneUserDevice.Zone, true, "Bypass restore"),
|
||||
TAMPER(4, ZoneUserDevice.Zone, true, "Tamper"),
|
||||
TAMPER_RESTORE(5, ZoneUserDevice.Zone, true, "Tamper restore"),
|
||||
TROUBLE(6, ZoneUserDevice.Zone, true, "Trouble"),
|
||||
TROUBLE_RESTORE(7, ZoneUserDevice.Zone, true, "Trouble restore"),
|
||||
TX_LOW_BATTERY(8, ZoneUserDevice.Zone, true, "TX low battery"),
|
||||
TX_LOW_BATTERY_RESTORE(9, ZoneUserDevice.Zone, true, "TX low battery restore"),
|
||||
ZONE_LOST(10, ZoneUserDevice.Zone, true, "Zone lost"),
|
||||
ZONE_LOST_RESTORE(11, ZoneUserDevice.Zone, true, "Zone lost restore"),
|
||||
START_OF_CROSS_TIME(12, ZoneUserDevice.Zone, true, "Start of cross time"),
|
||||
SPECIAL_EXPANSION_EVENT(17, ZoneUserDevice.None, false, "Special expansion event"),
|
||||
DURESS(18, ZoneUserDevice.None, true, "Duress"),
|
||||
MANUAL_FIRE(19, ZoneUserDevice.None, true, "Manual fire"),
|
||||
AUXILIARY2_PANIC(20, ZoneUserDevice.None, true, "Auxiliary 2 panic"),
|
||||
PANIC(22, ZoneUserDevice.None, true, "Panic"),
|
||||
KEYPAD_TAMPER(23, ZoneUserDevice.None, true, "Keypad tamper"),
|
||||
CONTROL_BOX_TAMPER(24, ZoneUserDevice.Device, false, "Control box tamper"),
|
||||
CONTROL_BOX_TAMPER_RESTORE(25, ZoneUserDevice.Device, false, "Control box tamper restore"),
|
||||
AC_FAIL(26, ZoneUserDevice.Device, false, "AC fail"),
|
||||
AC_FAIL_RESTORE(27, ZoneUserDevice.Device, false, "AC fail restore"),
|
||||
LOW_BATTERY(28, ZoneUserDevice.Device, false, "Low battery"),
|
||||
LOW_BATTERY_RESTORE(29, ZoneUserDevice.Device, false, "Low battery restore"),
|
||||
OVER_CURRENT(30, ZoneUserDevice.Device, false, "Over-current"),
|
||||
OVER_CURRENT_RESTORE(31, ZoneUserDevice.Device, false, "Over-current restore"),
|
||||
SIREN_TAMPER(32, ZoneUserDevice.Device, false, "Siren tamper"),
|
||||
SIREN_TAMPER_RESTORE(33, ZoneUserDevice.Device, false, "Siren tamper restore"),
|
||||
TELEPHONE_FAULT(34, ZoneUserDevice.None, false, "Telephone fault"),
|
||||
TELEPHONE_FAULT_RESTORE(35, ZoneUserDevice.None, false, "Telephone fault restore"),
|
||||
EXPANDER_TROUBLE(36, ZoneUserDevice.Device, false, "Expander trouble"),
|
||||
EXPANDER_TROUBLE_RESTORE(37, ZoneUserDevice.Device, false, "Expander trouble restore"),
|
||||
FAIL_TO_COMMUNICATE(38, ZoneUserDevice.None, false, "Fail to communicate"),
|
||||
LOG_FULL(39, ZoneUserDevice.None, false, "Log full"),
|
||||
OPENING(40, ZoneUserDevice.User, true, "Opening"),
|
||||
CLOSING(41, ZoneUserDevice.User, true, "Closing"),
|
||||
EXIT_ERROR(42, ZoneUserDevice.User, true, "Exit error"),
|
||||
RECENT_CLOSING(43, ZoneUserDevice.User, true, "Recent closing"),
|
||||
AUTO_TEST(44, ZoneUserDevice.None, false, "Auto-test"),
|
||||
START_PROGRAM(45, ZoneUserDevice.None, false, "Start program"),
|
||||
END_PROGRAM(46, ZoneUserDevice.None, false, "End program"),
|
||||
START_DOWNLOAD(47, ZoneUserDevice.None, false, "Start download"),
|
||||
END_DOWNLOAD(48, ZoneUserDevice.None, false, "End download"),
|
||||
CANCEL(49, ZoneUserDevice.User, true, "Cancel"),
|
||||
GROUND_FAULT(50, ZoneUserDevice.None, false, "Ground fault"),
|
||||
GROUND_FAULT_RESTORE(51, ZoneUserDevice.None, false, "Ground fault restore"),
|
||||
MANUAL_TEST(52, ZoneUserDevice.None, false, "Manual test"),
|
||||
CLOSED_WITH_ZONES_BYPASSED(53, ZoneUserDevice.User, true, "Closed with zones bypassed"),
|
||||
START_OF_LISTEN_IN(54, ZoneUserDevice.None, false, "Start of listen in"),
|
||||
TECHNICIAN_ON_SITE(55, ZoneUserDevice.None, false, "Technician on site"),
|
||||
TECHNICIAN_LEFT(56, ZoneUserDevice.None, false, "Technician left"),
|
||||
CONTROL_POWER_UP(57, ZoneUserDevice.None, false, "Control power up"),
|
||||
FIRST_TO_OPEN(120, ZoneUserDevice.User, true, "First to open"),
|
||||
LAST_TO_CLOSE(121, ZoneUserDevice.User, true, "Last toC close"),
|
||||
PIN_ENTERED_WITH_BIT7_SET(122, ZoneUserDevice.User, true, "PIN entered with bit 7 set"),
|
||||
BEGIN_WALK_TEST(123, ZoneUserDevice.None, false, "Begin walk-test"),
|
||||
END_WALK_TEST(124, ZoneUserDevice.None, false, "End walk-test"),
|
||||
RE_EXIT(125, ZoneUserDevice.None, true, "Re-exit"),
|
||||
OUTPUT_TRIP(126, ZoneUserDevice.User, false, "Output trip"),
|
||||
DATA_LOST(127, ZoneUserDevice.None, false, "Data Lost");
|
||||
|
||||
private static final Map<Integer, LogEventType> BY_LOG_EVENT_TYPE = new HashMap<>();
|
||||
public final int eventType;
|
||||
public final ZoneUserDevice zud;
|
||||
public final boolean isPartitionValid;
|
||||
public final String description;
|
||||
|
||||
LogEventType(int eventType, ZoneUserDevice zud, boolean isPartitionValid, String description) {
|
||||
this.eventType = eventType;
|
||||
this.zud = zud;
|
||||
this.isPartitionValid = isPartitionValid;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
static {
|
||||
for (LogEventType logEventType : values()) {
|
||||
BY_LOG_EVENT_TYPE.put(logEventType.eventType, logEventType);
|
||||
}
|
||||
}
|
||||
|
||||
public static @Nullable LogEventType valueOfLogEventType(int eventType) {
|
||||
return BY_LOG_EVENT_TYPE.get(eventType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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.caddx.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.caddx.internal.CaddxEvent;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* This is a class for handling a Keypad type Thing.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ThingHandlerKeypad extends CaddxBaseThingHandler {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param thing
|
||||
*/
|
||||
public ThingHandlerKeypad(Thing thing) {
|
||||
super(thing, CaddxThingType.KEYPAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannel(ChannelUID channelUID, String data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void caddxEventReceived(CaddxEvent event, Thing thing) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
* 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.caddx.internal.handler;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.caddx.internal.CaddxBindingConstants;
|
||||
import org.openhab.binding.caddx.internal.CaddxEvent;
|
||||
import org.openhab.binding.caddx.internal.CaddxMessage;
|
||||
import org.openhab.binding.caddx.internal.CaddxMessageType;
|
||||
import org.openhab.binding.caddx.internal.CaddxProperty;
|
||||
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.thing.ThingStatus;
|
||||
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 Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ThingHandlerPanel extends CaddxBaseThingHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(ThingHandlerPanel.class);
|
||||
private @Nullable HashMap<String, String> panelLogMessagesMap = null;
|
||||
private @Nullable String communicatorStackPointer = null;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param thing
|
||||
*/
|
||||
public ThingHandlerPanel(Thing thing) {
|
||||
super(thing, CaddxThingType.PANEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannel(ChannelUID channelUID, String data) {
|
||||
if (channelUID.getId().equals(CaddxBindingConstants.PANEL_FIRMWARE_VERSION)
|
||||
|| channelUID.getId().startsWith("panel_log_message_")) {
|
||||
updateState(channelUID, new StringType(data));
|
||||
} else {
|
||||
// All Panel channels are OnOffType
|
||||
OnOffType onOffType;
|
||||
|
||||
onOffType = ("true".equals(data)) ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.trace("handleCommand(): Command Received - {} {}.", channelUID, command);
|
||||
|
||||
String cmd = null;
|
||||
String data = null;
|
||||
CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
|
||||
if (bridgeHandler == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
if (CaddxBindingConstants.PANEL_FIRMWARE_VERSION.equals(channelUID.getId())) {
|
||||
cmd = CaddxBindingConstants.PANEL_INTERFACE_CONFIGURATION_REQUEST;
|
||||
data = "";
|
||||
} else if (CaddxBindingConstants.PANEL_LOG_MESSAGE_N_0.equals(channelUID.getId())) {
|
||||
cmd = CaddxBindingConstants.PANEL_SYSTEM_STATUS_REQUEST;
|
||||
data = "";
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
bridgeHandler.sendCommand(cmd, data);
|
||||
} else {
|
||||
logger.debug("Unknown command {}", command);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void caddxEventReceived(CaddxEvent event, Thing thing) {
|
||||
logger.trace("caddxEventReceived(): Event Received - {}.", event);
|
||||
|
||||
if (getThing().equals(thing)) {
|
||||
CaddxMessage message = event.getCaddxMessage();
|
||||
CaddxMessageType mt = message.getCaddxMessageType();
|
||||
ChannelUID channelUID = null;
|
||||
|
||||
// Log event messages have special handling
|
||||
if (CaddxMessageType.SYSTEM_STATUS_MESSAGE.equals(mt)) {
|
||||
handleSystemStatusMessage(message);
|
||||
} else if (CaddxMessageType.LOG_EVENT_MESSAGE.equals(mt)) {
|
||||
handleLogEventMessage(message);
|
||||
} else {
|
||||
for (CaddxProperty p : mt.properties) {
|
||||
if (!p.getId().isEmpty()) {
|
||||
String value = message.getPropertyById(p.getId());
|
||||
channelUID = new ChannelUID(getThing().getUID(), p.getId());
|
||||
updateChannel(channelUID, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the pointer into the panel's log messages ring buffer
|
||||
* and sends the command for the retrieval of the last event_message
|
||||
*/
|
||||
private void handleSystemStatusMessage(CaddxMessage message) {
|
||||
// Get the bridge handler
|
||||
CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
|
||||
if (bridgeHandler == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String pointer = message.getPropertyById("panel_communicator_stack_pointer");
|
||||
communicatorStackPointer = pointer;
|
||||
|
||||
// build map of log message channels to event numbers
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
map.put(pointer, CaddxBindingConstants.PANEL_LOG_MESSAGE_N_0);
|
||||
bridgeHandler.sendCommand(CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, pointer);
|
||||
panelLogMessagesMap = map;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the panel log messages.
|
||||
* If the received event_number matches our communication stack pointer then this is the last panel message. The
|
||||
* channel gets updated and the required log message requests are generated for the update of the other log message
|
||||
* channels
|
||||
*/
|
||||
private void handleLogEventMessage(CaddxMessage message) {
|
||||
// Get the bridge handler
|
||||
CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
|
||||
if (bridgeHandler == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String eventNumberString = message.getPropertyById("panel_log_event_number");
|
||||
String eventSizeString = message.getPropertyById("panel_log_event_size");
|
||||
|
||||
// build the message
|
||||
LogEventMessage logEventMessage = new LogEventMessage(message);
|
||||
|
||||
logger.trace("Log_event: {}", logEventMessage);
|
||||
|
||||
// get the channel id from the map
|
||||
HashMap<String, String> logMap = panelLogMessagesMap;
|
||||
if (logMap != null && logMap.containsKey(eventNumberString)) {
|
||||
String id = logMap.get(eventNumberString);
|
||||
ChannelUID channelUID = new ChannelUID(getThing().getUID(), id);
|
||||
updateChannel(channelUID, logEventMessage.toString());
|
||||
}
|
||||
|
||||
if (communicatorStackPointer != null && eventNumberString.equals(communicatorStackPointer)) {
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
|
||||
int eventNumber = Integer.parseInt(eventNumberString);
|
||||
int eventSize = Integer.parseInt(eventSizeString);
|
||||
|
||||
// Retrieve at maximum the 10 last log messages from the panel
|
||||
int messagesToRetrieve = Math.min(eventSize, 10);
|
||||
for (int i = 1; i < messagesToRetrieve; i++) {
|
||||
eventNumber--;
|
||||
if (eventNumber < 0) {
|
||||
eventNumber = eventSize;
|
||||
}
|
||||
|
||||
map.put(Integer.toString(eventNumber), "panel_log_message_n_" + i);
|
||||
bridgeHandler.sendCommand(CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, Integer.toString(eventNumber));
|
||||
}
|
||||
|
||||
communicatorStackPointer = null;
|
||||
panelLogMessagesMap = map;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* 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.caddx.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.caddx.internal.CaddxBindingConstants;
|
||||
import org.openhab.binding.caddx.internal.CaddxEvent;
|
||||
import org.openhab.binding.caddx.internal.CaddxMessage;
|
||||
import org.openhab.binding.caddx.internal.CaddxMessageType;
|
||||
import org.openhab.binding.caddx.internal.CaddxProperty;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
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 Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ThingHandlerPartition extends CaddxBaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ThingHandlerPartition.class);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param thing
|
||||
*/
|
||||
public ThingHandlerPartition(Thing thing) {
|
||||
super(thing, CaddxThingType.PARTITION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannel(ChannelUID channelUID, String data) {
|
||||
if (CaddxBindingConstants.PARTITION_SECONDARY_COMMAND.equals(channelUID.getId())) {
|
||||
updateState(channelUID, new DecimalType(data));
|
||||
} else {
|
||||
OnOffType onOffType = ("true".equals(data)) ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("handleCommand(): Command Received - {} {}.", channelUID, command);
|
||||
|
||||
String cmd = null;
|
||||
String data = null;
|
||||
CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
|
||||
if (bridgeHandler == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
if (channelUID.getId().equals(CaddxBindingConstants.PARTITION_ARMED)) {
|
||||
cmd = CaddxBindingConstants.PARTITION_STATUS_REQUEST;
|
||||
data = String.format("%d", getPartitionNumber() - 1);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (channelUID.getId().equals(CaddxBindingConstants.PARTITION_SECONDARY_COMMAND)) {
|
||||
cmd = channelUID.getId();
|
||||
data = String.format("%s,%d", command.toString(), (1 << getPartitionNumber() - 1));
|
||||
} else {
|
||||
logger.debug("Unknown command {}", command);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.startsWith("-")) {
|
||||
bridgeHandler.sendCommand(cmd, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void caddxEventReceived(CaddxEvent event, Thing thing) {
|
||||
logger.trace("caddxEventReceived(): Event Received - {}", event);
|
||||
|
||||
if (getThing().equals(thing)) {
|
||||
CaddxMessage message = event.getCaddxMessage();
|
||||
CaddxMessageType mt = message.getCaddxMessageType();
|
||||
ChannelUID channelUID = null;
|
||||
|
||||
for (CaddxProperty p : mt.properties) {
|
||||
if (!p.getId().isEmpty()) {
|
||||
String value = message.getPropertyById(p.getId());
|
||||
channelUID = new ChannelUID(getThing().getUID(), p.getId());
|
||||
updateChannel(channelUID, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the command
|
||||
String value = "-1";
|
||||
channelUID = new ChannelUID(getThing().getUID(), CaddxBindingConstants.PARTITION_SECONDARY_COMMAND);
|
||||
updateChannel(channelUID, value);
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* 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.caddx.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.caddx.internal.CaddxBindingConstants;
|
||||
import org.openhab.binding.caddx.internal.CaddxEvent;
|
||||
import org.openhab.binding.caddx.internal.CaddxMessage;
|
||||
import org.openhab.binding.caddx.internal.CaddxMessageType;
|
||||
import org.openhab.binding.caddx.internal.CaddxProperty;
|
||||
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.thing.ThingStatus;
|
||||
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 Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ThingHandlerZone extends CaddxBaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ThingHandlerZone.class);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param thing
|
||||
*/
|
||||
public ThingHandlerZone(Thing thing) {
|
||||
super(thing, CaddxThingType.ZONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannel(ChannelUID channelUID, String data) {
|
||||
if (channelUID.getId().equals(CaddxBindingConstants.ZONE_NAME)) {
|
||||
getThing().setLabel(data);
|
||||
updateState(channelUID, new StringType(data));
|
||||
|
||||
logger.trace(" updateChannel: {} = {}", channelUID, data);
|
||||
} else if (channelUID.getId().equals(CaddxBindingConstants.ZONE_FAULTED)) {
|
||||
OpenClosedType openClosedType = ("true".equals(data)) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
|
||||
updateState(channelUID, openClosedType);
|
||||
|
||||
logger.trace(" updateChannel: {} = {}", channelUID, data);
|
||||
} else {
|
||||
OnOffType onOffType = ("true".equals(data)) ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(channelUID, onOffType);
|
||||
|
||||
logger.trace(" updateChannel: {} = {}", channelUID, onOffType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.trace("handleCommand(): Command Received - {} {}.", channelUID, command);
|
||||
|
||||
String cmd1 = null;
|
||||
String cmd2 = null;
|
||||
String data = null;
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
if (channelUID.getId().equals(CaddxBindingConstants.ZONE_FAULTED)) {
|
||||
cmd1 = CaddxBindingConstants.ZONE_STATUS_REQUEST;
|
||||
cmd2 = CaddxBindingConstants.ZONE_NAME_REQUEST;
|
||||
data = String.format("%d", getZoneNumber() - 1);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (channelUID.getId().equals(CaddxBindingConstants.ZONE_BYPASSED)) {
|
||||
cmd1 = channelUID.getId();
|
||||
cmd2 = CaddxBindingConstants.ZONE_STATUS_REQUEST;
|
||||
data = String.format("%d", getZoneNumber() - 1);
|
||||
} else {
|
||||
logger.debug("Unknown command {}", command);
|
||||
return;
|
||||
}
|
||||
|
||||
CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
|
||||
if (bridgeHandler == null) {
|
||||
return;
|
||||
}
|
||||
bridgeHandler.sendCommand(cmd1, data);
|
||||
bridgeHandler.sendCommand(cmd2, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void caddxEventReceived(CaddxEvent event, Thing thing) {
|
||||
logger.trace("caddxEventReceived(): Event Received - {}", event);
|
||||
|
||||
if (getThing().equals(thing)) {
|
||||
CaddxMessage message = event.getCaddxMessage();
|
||||
CaddxMessageType mt = message.getCaddxMessageType();
|
||||
ChannelUID channelUID = null;
|
||||
|
||||
for (CaddxProperty p : mt.properties) {
|
||||
logger.trace(" Checking property: {}", p.getName());
|
||||
|
||||
if (!p.getId().isEmpty()) {
|
||||
String value = message.getPropertyById(p.getId());
|
||||
channelUID = new ChannelUID(getThing().getUID(), p.getId());
|
||||
updateChannel(channelUID, value);
|
||||
|
||||
logger.trace(" updateChannel: {} = {}", channelUID, value);
|
||||
}
|
||||
}
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.caddx.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Zone, User, Device enumeration.
|
||||
*
|
||||
* @author Georgios Moutsos - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
enum ZoneUserDevice {
|
||||
None,
|
||||
Zone,
|
||||
User,
|
||||
Device
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="caddx" 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>Caddx Security Binding</name>
|
||||
<description>Binding for Caddx security system with RS232 serial interface.</description>
|
||||
<author>Georgios Moutsos</author>
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="caddx"
|
||||
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="bridge">
|
||||
<label>Caddx</label>
|
||||
<description>This bridge represents the Caddx Serial interface.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="send_command" typeId="command">
|
||||
<label>Send Command</label>
|
||||
<description>Sends an Alarm Panel Command</description>
|
||||
</channel>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="serialPort" type="text" required="true">
|
||||
<context>serial-port</context>
|
||||
<label>Caddx Bridge Serial Port</label>
|
||||
<description>The serial port name for the communication. Valid values
|
||||
are e.g. COM1 for Windows and /dev/ttyS0 or
|
||||
/dev/ttyUSB0 for Linux.</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="baudrate" type="integer" required="true">
|
||||
<label>Baud Rate</label>
|
||||
<description>The baud rate of the serial port. Valid values for the NX-584E are 600, 1200, 2400, 4800, 9600
|
||||
(default), 19200, 38400, and 76800. Valid values for the NX-8E are 2400, 4800, 9600
|
||||
(default), 19200 and 38400.</description>
|
||||
<default>9600</default>
|
||||
<options>
|
||||
<option value="600">600</option>
|
||||
<option value="1200">1200</option>
|
||||
<option value="2400">2400</option>
|
||||
<option value="4800">4800</option>
|
||||
<option value="9600">9600</option>
|
||||
<option value="19200">19200</option>
|
||||
<option value="38400">38400</option>
|
||||
<option value="76800">76800</option>
|
||||
</options>
|
||||
</parameter>
|
||||
|
||||
<parameter name="protocol" type="text" required="true">
|
||||
<context>protocol</context>
|
||||
<label>Caddx Bridge Protocol</label>
|
||||
<description>The configured panel protocol. Valid values
|
||||
are Binary and Ascii.</description>
|
||||
<default>Binary</default>
|
||||
<options>
|
||||
<option value="Ascii">Ascii</option>
|
||||
<option value="Binary">Binary</option>
|
||||
</options>
|
||||
</parameter>
|
||||
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="caddx"
|
||||
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 Command</description>
|
||||
</channel-type>
|
||||
|
||||
<!-- panel -->
|
||||
<channel-type id="panel_text">
|
||||
<item-type>String</item-type>
|
||||
<label>Panel Text</label>
|
||||
<description>Panel text</description>
|
||||
<state pattern="%s" readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="panel_flag">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Panel Flag</label>
|
||||
<description>Panel flag</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<!-- partition -->
|
||||
<channel-type id="partition_condition">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Partition Condition</label>
|
||||
<description>Partition Condition</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="partition_secondary">
|
||||
<item-type>Number</item-type>
|
||||
<label>Partition Secondary Command</label>
|
||||
<description>Partition secondary command</description>
|
||||
<state>
|
||||
<options>
|
||||
<option value="-1">None</option>
|
||||
<option value="0">Stay (1 button arm / toggle interiors)</option>
|
||||
<option value="1">Chime (toggle chime mode)</option>
|
||||
<option value="2">Exit (1 button arm / toggle instant)</option>
|
||||
<option value="3">Bypass interiors</option>
|
||||
<option value="4">Fire Panic</option>
|
||||
<option value="5">Medical Panic</option>
|
||||
<option value="6">Police Panic</option>
|
||||
<option value="7">Smoke detector reset</option>
|
||||
<option value="8">Auto callback download</option>
|
||||
<option value="9">Manual pickup download</option>
|
||||
<option value="10">Enable silent exit (for this arm cycle)</option>
|
||||
<option value="11">Perform test</option>
|
||||
<option value="12">Group Bypass</option>
|
||||
<option value="13">Auxiliary function 1</option>
|
||||
<option value="14">Auxiliary function 2</option>
|
||||
<option value="15">Start keypad sounder</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<!-- zone -->
|
||||
<channel-type id="zone_text">
|
||||
<item-type>String</item-type>
|
||||
<label>Zone Text</label>
|
||||
<description>Zone text</description>
|
||||
<state pattern="%s" readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="zone_partition">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Zone Partition</label>
|
||||
<description>Zone Partition</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="zone_type">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Zone Type</label>
|
||||
<description>Zone Type</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="zone_condition">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Zone Condition</label>
|
||||
<description>Zone Condition</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<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="zone_bypass">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Bypass Mode</label>
|
||||
<description>Bypass Mode (OFF=Armed, ON=Bypassed)</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>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="caddx"
|
||||
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="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Caddx Alarm Keypad</label>
|
||||
<description>Represents any of the keypads of the Caddx Alarm System.</description>
|
||||
|
||||
<representation-property>keypadAddress</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="keypadAddress" type="text" required="true">
|
||||
<label>Keypad Address</label>
|
||||
<description>The Keypad Address.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,206 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="caddx"
|
||||
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="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Caddx Alarm Panel</label>
|
||||
<description>The basic representation of the Caddx Alarm System.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="panel_firmware_version" typeId="panel_text">
|
||||
<label>Firmware Version</label>
|
||||
<description>Firmware version</description>
|
||||
</channel>
|
||||
|
||||
<channel id="panel_log_message_n_0" typeId="panel_text">
|
||||
<label>Log Message 10</label>
|
||||
<description>Log message 10</description>
|
||||
</channel>
|
||||
<channel id="panel_log_message_n_1" typeId="panel_text">
|
||||
<label>Log Message 9</label>
|
||||
<description>Log message 9</description>
|
||||
</channel>
|
||||
<channel id="panel_log_message_n_2" typeId="panel_text">
|
||||
<label>Log Message 8</label>
|
||||
<description>Log message 8</description>
|
||||
</channel>
|
||||
<channel id="panel_log_message_n_3" typeId="panel_text">
|
||||
<label>Log Message 7</label>
|
||||
<description>Log message 7</description>
|
||||
</channel>
|
||||
<channel id="panel_log_message_n_4" typeId="panel_text">
|
||||
<label>Log Message 6</label>
|
||||
<description>Log message 6</description>
|
||||
</channel>
|
||||
<channel id="panel_log_message_n_5" typeId="panel_text">
|
||||
<label>Log Message 5</label>
|
||||
<description>Log message 5</description>
|
||||
</channel>
|
||||
<channel id="panel_log_message_n_6" typeId="panel_text">
|
||||
<label>Log Message 4</label>
|
||||
<description>Log message 4</description>
|
||||
</channel>
|
||||
<channel id="panel_log_message_n_7" typeId="panel_text">
|
||||
<label>Log Message 3</label>
|
||||
<description>Log message 3</description>
|
||||
</channel>
|
||||
<channel id="panel_log_message_n_8" typeId="panel_text">
|
||||
<label>Log Message 2</label>
|
||||
<description>Log message 2</description>
|
||||
</channel>
|
||||
<channel id="panel_log_message_n_9" typeId="panel_text">
|
||||
<label>Log Message 1</label>
|
||||
<description>Log message 1</description>
|
||||
</channel>
|
||||
|
||||
<channel id="panel_interface_configuration_message" typeId="panel_flag">
|
||||
<label>Interface Configuration Message</label>
|
||||
<description>Interface Configuration Message</description>
|
||||
</channel>
|
||||
<channel id="panel_zone_status_message" typeId="panel_flag">
|
||||
<label>Zone Status Message</label>
|
||||
<description>Zone Status Message</description>
|
||||
</channel>
|
||||
<channel id="panel_zones_snapshot_message" typeId="panel_flag">
|
||||
<label>Zones Snapshot Message</label>
|
||||
<description>Zones Snapshot Message</description>
|
||||
</channel>
|
||||
<channel id="panel_partition_status_message" typeId="panel_flag">
|
||||
<label>Partition Status Message</label>
|
||||
<description>Partition Status Message</description>
|
||||
</channel>
|
||||
<channel id="panel_partitions_snapshot_message" typeId="panel_flag">
|
||||
<label>Partitions Snapshot Message</label>
|
||||
<description>Partitions Snapshot Message</description>
|
||||
</channel>
|
||||
|
||||
<channel id="panel_system_status_message" typeId="panel_flag">
|
||||
<label>System Status Message</label>
|
||||
<description>System Status Message</description>
|
||||
</channel>
|
||||
<channel id="panel_x10_message_received" typeId="panel_flag">
|
||||
<label>X-10 Message Received</label>
|
||||
<description>X-10 Message Received</description>
|
||||
</channel>
|
||||
<channel id="panel_log_event_message" typeId="panel_flag">
|
||||
<label>Log Event Message</label>
|
||||
<description>Log Event Message</description>
|
||||
</channel>
|
||||
<channel id="panel_keypad_message_received" typeId="panel_flag">
|
||||
<label>Keypad Message Received</label>
|
||||
<description>Keypad Message Received</description>
|
||||
</channel>
|
||||
|
||||
<channel id="panel_interface_configuration_request" typeId="panel_flag">
|
||||
<label>Interface Configuration Request</label>
|
||||
<description>Interface Configuration Request</description>
|
||||
</channel>
|
||||
<channel id="panel_zone_name_request" typeId="panel_flag">
|
||||
<label>Zone Name Request</label>
|
||||
<description>Zone Name Request</description>
|
||||
</channel>
|
||||
<channel id="panel_zone_status_request" typeId="panel_flag">
|
||||
<label>Zone Status Request</label>
|
||||
<description>Zone Status Request</description>
|
||||
</channel>
|
||||
<channel id="panel_zones_snapshot_request" typeId="panel_flag">
|
||||
<label>Zones Snapshot Request</label>
|
||||
<description>Zones Snapshot Request</description>
|
||||
</channel>
|
||||
<channel id="panel_partition_status_request" typeId="panel_flag">
|
||||
<label>Partition Status Request</label>
|
||||
<description>Partition Status Request</description>
|
||||
</channel>
|
||||
<channel id="panel_partitions_snapshot_request" typeId="panel_flag">
|
||||
<label>Partitions Snapshot Request</label>
|
||||
<description>Partitions Snapshot Request</description>
|
||||
</channel>
|
||||
|
||||
<channel id="panel_system_status_request" typeId="panel_flag">
|
||||
<label>System Status Request</label>
|
||||
<description>System Status Request</description>
|
||||
</channel>
|
||||
<channel id="panel_send_x10_message" typeId="panel_flag">
|
||||
<label>Send X-10 Message</label>
|
||||
<description>Send X-10 Message</description>
|
||||
</channel>
|
||||
<channel id="panel_log_event_request" typeId="panel_flag">
|
||||
<label>Log Event Request</label>
|
||||
<description>Log Event Request</description>
|
||||
</channel>
|
||||
<channel id="panel_send_keypad_text_message" typeId="panel_flag">
|
||||
<label>Send Keypad Text Message</label>
|
||||
<description>Send Keypad Text Message</description>
|
||||
</channel>
|
||||
<channel id="panel_keypad_terminal_mode_request" typeId="panel_flag">
|
||||
<label>Keypad Terminal Mode Request</label>
|
||||
<description>Keypad Terminal Mode Request</description>
|
||||
</channel>
|
||||
|
||||
<channel id="panel_program_data_request" typeId="panel_flag">
|
||||
<label>Program Data Request</label>
|
||||
<description>Program Data Request</description>
|
||||
</channel>
|
||||
<channel id="panel_program_data_command" typeId="panel_flag">
|
||||
<label>Program Data Command</label>
|
||||
<description>Program Data Command</description>
|
||||
</channel>
|
||||
<channel id="panel_user_information_request_with_pin" typeId="panel_flag">
|
||||
<label>User Information Request with PIN</label>
|
||||
<description>User Information Request with PIN</description>
|
||||
</channel>
|
||||
<channel id="panel_user_information_request_without_pin" typeId="panel_flag">
|
||||
<label>User Information Request without PIN</label>
|
||||
<description>User Information Request without PIN</description>
|
||||
</channel>
|
||||
<channel id="panel_set_user_code_command_with_pin" typeId="panel_flag">
|
||||
<label>Set User Code Command with PIN</label>
|
||||
<description>Set User Code Command with PIN</description>
|
||||
</channel>
|
||||
<channel id="panel_set_user_code_command_without_pin" typeId="panel_flag">
|
||||
<label>Set User Code Command without PIN</label>
|
||||
<description>Set User Code Command without PIN</description>
|
||||
</channel>
|
||||
<channel id="panel_set_user_authorization_command_with_pin" typeId="panel_flag">
|
||||
<label>Set User Authorization Command with PIN</label>
|
||||
<description>Set User Authorization Command with PIN</description>
|
||||
</channel>
|
||||
<channel id="panel_set_user_authorization_command_without_pin" typeId="panel_flag">
|
||||
<label>Set User Authorization Command without PIN</label>
|
||||
<description>Set User Authorization Command without PIN</description>
|
||||
</channel>
|
||||
|
||||
<channel id="panel_store_communication_event_command" typeId="panel_flag">
|
||||
<label>Store Communication Event Command</label>
|
||||
<description>Store Communication Event Command</description>
|
||||
</channel>
|
||||
<channel id="panel_set_clock_calendar_command" typeId="panel_flag">
|
||||
<label>Set Clock / Calendar Command</label>
|
||||
<description>Set Clock / Calendar Command</description>
|
||||
</channel>
|
||||
<channel id="panel_primary_keypad_function_with_pin" typeId="panel_flag">
|
||||
<label>Primary Keypad Function with PIN</label>
|
||||
<description>Primary Keypad Function with PIN</description>
|
||||
</channel>
|
||||
<channel id="panel_primary_keypad_function_without_pin" typeId="panel_flag">
|
||||
<label>Primary Keypad Function without PIN</label>
|
||||
<description>Primary Keypad Function without PIN</description>
|
||||
</channel>
|
||||
<channel id="panel_secondary_keypad_function" typeId="panel_flag">
|
||||
<label>Secondary Keypad Function</label>
|
||||
<description>Secondary Keypad Function</description>
|
||||
</channel>
|
||||
<channel id="panel_zone_bypass_toggle" typeId="panel_flag">
|
||||
<label>Zone Bypass Toggle</label>
|
||||
<description>Zone Bypass Toggle</description>
|
||||
</channel>
|
||||
</channels>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,224 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="caddx"
|
||||
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="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Caddx Alarm Partition</label>
|
||||
<description>Represents a controllable area within a Caddx Alarm System.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="partition_bypass_code_required" typeId="partition_condition">
|
||||
<label>Bypass Code Required</label>
|
||||
<description>Bypass code required</description>
|
||||
</channel>
|
||||
<channel id="partition_fire_trouble" typeId="partition_condition">
|
||||
<label>Fire Trouble</label>
|
||||
<description>Fire trouble</description>
|
||||
</channel>
|
||||
<channel id="partition_fire" typeId="partition_condition">
|
||||
<label>Fire</label>
|
||||
<description>Fire</description>
|
||||
</channel>
|
||||
<channel id="partition_pulsing_buzzer" typeId="partition_condition">
|
||||
<label>Pulsing Buzzer</label>
|
||||
<description>Pulsing Buzzer</description>
|
||||
</channel>
|
||||
<channel id="partition_tlm_fault_memory" typeId="partition_condition">
|
||||
<label>TLM Fault Memory</label>
|
||||
<description>TLM fault memory</description>
|
||||
</channel>
|
||||
<channel id="partition_armed" typeId="partition_condition">
|
||||
<label>Armed</label>
|
||||
<description>Armed</description>
|
||||
</channel>
|
||||
<channel id="partition_instant" typeId="partition_condition">
|
||||
<label>Instant</label>
|
||||
<description>Instant</description>
|
||||
</channel>
|
||||
|
||||
<channel id="partition_previous_alarm" typeId="partition_condition">
|
||||
<label>Previous Alarm</label>
|
||||
<description>Previous Alarm</description>
|
||||
</channel>
|
||||
<channel id="partition_siren_on" typeId="partition_condition">
|
||||
<label>Siren On</label>
|
||||
<description>Siren on</description>
|
||||
</channel>
|
||||
<channel id="partition_steady_siren_on" typeId="partition_condition">
|
||||
<label>Steady Siren On</label>
|
||||
<description>Steady siren on</description>
|
||||
</channel>
|
||||
<channel id="partition_alarm_memory" typeId="partition_condition">
|
||||
<label>Alarm Memory</label>
|
||||
<description>Alarm memory</description>
|
||||
</channel>
|
||||
<channel id="partition_tamper" typeId="partition_condition">
|
||||
<label>Tamper</label>
|
||||
<description>Tamper</description>
|
||||
</channel>
|
||||
<channel id="partition_cancel_command_entered" typeId="partition_condition">
|
||||
<label>Cancel Command Entered</label>
|
||||
<description>Cancel command entered</description>
|
||||
</channel>
|
||||
<channel id="partition_code_entered" typeId="partition_condition">
|
||||
<label>Code Entered</label>
|
||||
<description>Code entered</description>
|
||||
</channel>
|
||||
<channel id="partition_cancel_pending" typeId="partition_condition">
|
||||
<label>Cancel Pending</label>
|
||||
<description>Cancel pending</description>
|
||||
</channel>
|
||||
|
||||
<channel id="partition_silent_exit_enabled" typeId="partition_condition">
|
||||
<label>Silent Exit Enabled</label>
|
||||
<description>Silent exit enabled</description>
|
||||
</channel>
|
||||
<channel id="partition_entryguard" typeId="partition_condition">
|
||||
<label>Entryguard (Stay Mode)</label>
|
||||
<description>Entryguard (stay mode)</description>
|
||||
</channel>
|
||||
<channel id="partition_chime_mode_on" typeId="partition_condition">
|
||||
<label>Chime Mode On</label>
|
||||
<description>Chime mode on</description>
|
||||
</channel>
|
||||
<channel id="partition_entry" typeId="partition_condition">
|
||||
<label>Entry</label>
|
||||
<description>Entry</description>
|
||||
</channel>
|
||||
<channel id="partition_delay_expiration_warning" typeId="partition_condition">
|
||||
<label>Delay Expiration Warning</label>
|
||||
<description>Delay expiration warning</description>
|
||||
</channel>
|
||||
<channel id="partition_exit1" typeId="partition_condition">
|
||||
<label>Exit1</label>
|
||||
<description>Exit1</description>
|
||||
</channel>
|
||||
<channel id="partition_exit2" typeId="partition_condition">
|
||||
<label>Exit2</label>
|
||||
<description>Exit2</description>
|
||||
</channel>
|
||||
|
||||
<channel id="partition_led_extinguish" typeId="partition_condition">
|
||||
<label>Led Extinguish</label>
|
||||
<description>Led extinguish</description>
|
||||
</channel>
|
||||
<channel id="partition_cross_timing" typeId="partition_condition">
|
||||
<label>Cross Timing</label>
|
||||
<description>Cross timing</description>
|
||||
</channel>
|
||||
<channel id="partition_recent_closing_being_timed" typeId="partition_condition">
|
||||
<label>Recent Closing Being Timed</label>
|
||||
<description>Recent closing being timed</description>
|
||||
</channel>
|
||||
<channel id="partition_exit_error_triggered" typeId="partition_condition">
|
||||
<label>Exit Error Triggered</label>
|
||||
<description>Exit error triggered</description>
|
||||
</channel>
|
||||
<channel id="partition_auto_home_inhibited" typeId="partition_condition">
|
||||
<label>Auto Home Inhibited</label>
|
||||
<description>Auto home inhibited</description>
|
||||
</channel>
|
||||
<channel id="partition_sensor_low_battery" typeId="partition_condition">
|
||||
<label>Sensor Low Battery</label>
|
||||
<description>Sensor low battery</description>
|
||||
</channel>
|
||||
<channel id="partition_sensor_lost_supervision" typeId="partition_condition">
|
||||
<label>Sensor Lost Supervision</label>
|
||||
<description>Sensor lost supervision</description>
|
||||
</channel>
|
||||
|
||||
<channel id="partition_zone_bypassed" typeId="partition_condition">
|
||||
<label>Zone Bypassed</label>
|
||||
<description>Zone bypassed</description>
|
||||
</channel>
|
||||
<channel id="partition_force_arm_triggered_by_auto_arm" typeId="partition_condition">
|
||||
<label>Force Arm triggered by Auto Arm</label>
|
||||
<description>Force arm triggered by auto arm</description>
|
||||
</channel>
|
||||
<channel id="partition_ready_to_arm" typeId="partition_condition">
|
||||
<label>Ready to Arm</label>
|
||||
<description>Ready to arm</description>
|
||||
</channel>
|
||||
<channel id="partition_ready_to_force_arm" typeId="partition_condition">
|
||||
<label>Ready to Force Arm</label>
|
||||
<description>Ready to force arm</description>
|
||||
</channel>
|
||||
<channel id="partition_valid_pin_accepted" typeId="partition_condition">
|
||||
<label>Valid PIN Accepted</label>
|
||||
<description>Valid PIN accepted</description>
|
||||
</channel>
|
||||
<channel id="partition_chime_on" typeId="partition_condition">
|
||||
<label>Chime On (Sounding)</label>
|
||||
<description>Chime on (sounding)</description>
|
||||
</channel>
|
||||
<channel id="partition_error_beep" typeId="partition_condition">
|
||||
<label>Error Beep (Triple Beep)</label>
|
||||
<description>Error beep (triple beep)</description>
|
||||
</channel>
|
||||
<channel id="partition_tone_on" typeId="partition_condition">
|
||||
<label>Tone On (Activation Tone)</label>
|
||||
<description>Tone on (activation tone)</description>
|
||||
</channel>
|
||||
|
||||
<channel id="partition_entry1" typeId="partition_condition">
|
||||
<label>Entry 1</label>
|
||||
<description>Entry 1</description>
|
||||
</channel>
|
||||
<channel id="partition_open_period" typeId="partition_condition">
|
||||
<label>Open Period</label>
|
||||
<description>Open period</description>
|
||||
</channel>
|
||||
<channel id="partition_alarm_sent_using_phone_number_1" typeId="partition_condition">
|
||||
<label>Alarm Sent Using Phone 1</label>
|
||||
<description>Alarm sent using phone number 1</description>
|
||||
</channel>
|
||||
<channel id="partition_alarm_sent_using_phone_number_2" typeId="partition_condition">
|
||||
<label>Alarm Sent Using Phone 2</label>
|
||||
<description>Alarm sent using phone number 2</description>
|
||||
</channel>
|
||||
<channel id="partition_alarm_sent_using_phone_number_3" typeId="partition_condition">
|
||||
<label>Alarm Sent Using Phone 3</label>
|
||||
<description>Alarm sent using phone number 3</description>
|
||||
</channel>
|
||||
<channel id="partition_cancel_report_is_in_the_stack" typeId="partition_condition">
|
||||
<label>Cancel Report is in the Stack</label>
|
||||
<description>Cancel report is in the stack</description>
|
||||
</channel>
|
||||
<channel id="partition_keyswitch_armed" typeId="partition_condition">
|
||||
<label>Keyswitch Armed</label>
|
||||
<description>Keyswitch armed</description>
|
||||
</channel>
|
||||
<channel id="partition_delay_trip_in_progress" typeId="partition_condition">
|
||||
<label>Delay Trip in Progress</label>
|
||||
<description>Delay Trip in progress (common zone)</description>
|
||||
</channel>
|
||||
|
||||
<channel id="partition_secondary_command" typeId="partition_secondary">
|
||||
<label>Partition Secondary Command</label>
|
||||
<description>Partition Secondary Command</description>
|
||||
</channel>
|
||||
</channels>
|
||||
|
||||
<representation-property>partitionNumber</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="partitionNumber" type="integer" required="true" min="1" max="8">
|
||||
<label>Partition Number</label>
|
||||
<description>The Partition Number.</description>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
<parameter name="userNumber" type="integer" required="true" min="1" max="192">
|
||||
<label>User Number</label>
|
||||
<description>The User Number.</description>
|
||||
<default>1</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,206 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="caddx"
|
||||
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="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Caddx Alarm Zone</label>
|
||||
<description>Represents a physical device such as a door, window, or motion sensor.</description>
|
||||
|
||||
<channels>
|
||||
<!-- Zone partitions -->
|
||||
<channel id="zone_partition1" typeId="zone_partition">
|
||||
<label>Partition 1</label>
|
||||
<description>Partition 1</description>
|
||||
</channel>
|
||||
<channel id="zone_partition2" typeId="zone_partition">
|
||||
<label>Partition 2</label>
|
||||
<description>Partition 2</description>
|
||||
</channel>
|
||||
<channel id="zone_partition3" typeId="zone_partition">
|
||||
<label>Partition 3</label>
|
||||
<description>Partition 3</description>
|
||||
</channel>
|
||||
<channel id="zone_partition4" typeId="zone_partition">
|
||||
<label>Partition 4</label>
|
||||
<description>Partition 4</description>
|
||||
</channel>
|
||||
<channel id="zone_partition5" typeId="zone_partition">
|
||||
<label>Partition 5</label>
|
||||
<description>Partition 5</description>
|
||||
</channel>
|
||||
<channel id="zone_partition6" typeId="zone_partition">
|
||||
<label>Partition 6</label>
|
||||
<description>Partition 6</description>
|
||||
</channel>
|
||||
<channel id="zone_partition7" typeId="zone_partition">
|
||||
<label>Partition 7</label>
|
||||
<description>Partition 7</description>
|
||||
</channel>
|
||||
<channel id="zone_partition8" typeId="zone_partition">
|
||||
<label>Partition 8</label>
|
||||
<description>Partition 8</description>
|
||||
</channel>
|
||||
|
||||
<!-- Name -->
|
||||
<channel id="zone_name" typeId="zone_text">
|
||||
<label>Name</label>
|
||||
<description>Name</description>
|
||||
</channel>
|
||||
|
||||
<!-- Zone types -->
|
||||
<channel id="zone_fire" typeId="zone_type">
|
||||
<label>Fire</label>
|
||||
<description>Fire</description>
|
||||
</channel>
|
||||
<channel id="zone_24hour" typeId="zone_type">
|
||||
<label>24 Hour</label>
|
||||
<description>24 Hour</description>
|
||||
</channel>
|
||||
<channel id="zone_key_switch" typeId="zone_type">
|
||||
<label>Key-switch</label>
|
||||
<description>Key-switch</description>
|
||||
</channel>
|
||||
<channel id="zone_follower" typeId="zone_type">
|
||||
<label>Follower</label>
|
||||
<description>Follower</description>
|
||||
</channel>
|
||||
<channel id="zone_entry_exit_delay_1" typeId="zone_type">
|
||||
<label>Entry / Exit Delay 1</label>
|
||||
<description>Entry / exit delay 1</description>
|
||||
</channel>
|
||||
<channel id="zone_entry_exit_delay_2" typeId="zone_type">
|
||||
<label>Entry / Exit Delay 2</label>
|
||||
<description>Entry / exit delay 2</description>
|
||||
</channel>
|
||||
<channel id="zone_interior" typeId="zone_type">
|
||||
<label>Interior</label>
|
||||
<description>Interior</description>
|
||||
</channel>
|
||||
<channel id="zone_local_only" typeId="zone_type">
|
||||
<label>Local Only</label>
|
||||
<description>Local only</description>
|
||||
</channel>
|
||||
|
||||
<channel id="zone_keypad_sounder" typeId="zone_type">
|
||||
<label>Keypad Sounder</label>
|
||||
<description>Keypad Sounder</description>
|
||||
</channel>
|
||||
<channel id="zone_yelping_siren" typeId="zone_type">
|
||||
<label>Yelping Siren</label>
|
||||
<description>Yelping siren</description>
|
||||
</channel>
|
||||
<channel id="zone_steady_siren" typeId="zone_type">
|
||||
<label>Steady Siren</label>
|
||||
<description>Steady siren</description>
|
||||
</channel>
|
||||
<channel id="zone_chime" typeId="zone_type">
|
||||
<label>Chime</label>
|
||||
<description>Chime</description>
|
||||
</channel>
|
||||
<channel id="zone_bypassable" typeId="zone_type">
|
||||
<label>Bypassable</label>
|
||||
<description>Bypassable</description>
|
||||
</channel>
|
||||
<channel id="zone_group_bypassable" typeId="zone_type">
|
||||
<label>Group Bypassable</label>
|
||||
<description>Group bypassable</description>
|
||||
</channel>
|
||||
<channel id="zone_force_armable" typeId="zone_type">
|
||||
<label>Force Armable</label>
|
||||
<description>Force armable</description>
|
||||
</channel>
|
||||
<channel id="zone_entry_guard" typeId="zone_type">
|
||||
<label>Entry Guard</label>
|
||||
<description>Entry guard</description>
|
||||
</channel>
|
||||
|
||||
<channel id="zone_fast_loop_response" typeId="zone_type">
|
||||
<label>Fast Loop Response</label>
|
||||
<description>Fast loop response</description>
|
||||
</channel>
|
||||
<channel id="zone_double_eol_tamper" typeId="zone_type">
|
||||
<label>Double EOL Tamper</label>
|
||||
<description>Double EOL tamper</description>
|
||||
</channel>
|
||||
<channel id="zone_type_trouble" typeId="zone_type">
|
||||
<label>Trouble</label>
|
||||
<description>Trouble</description>
|
||||
</channel>
|
||||
<channel id="zone_cross_zone" typeId="zone_type">
|
||||
<label>Cross Zone</label>
|
||||
<description>Cross zone</description>
|
||||
</channel>
|
||||
<channel id="zone_dialer_delay" typeId="zone_type">
|
||||
<label>Dialer Delay</label>
|
||||
<description>Dialer delay</description>
|
||||
</channel>
|
||||
<channel id="zone_swinger_shutdown" typeId="zone_type">
|
||||
<label>Swinger Shutdown</label>
|
||||
<description>Swinger shutdown</description>
|
||||
</channel>
|
||||
<channel id="zone_restorable" typeId="zone_type">
|
||||
<label>Restorable</label>
|
||||
<description>Restorable</description>
|
||||
</channel>
|
||||
<channel id="zone_listen_in" typeId="zone_type">
|
||||
<label>Listen in</label>
|
||||
<description>Listen in</description>
|
||||
</channel>
|
||||
|
||||
<!-- Zone conditions -->
|
||||
<channel id="zone_faulted" typeId="zone_status">
|
||||
<label>Faulted</label>
|
||||
<description>Faulted (or delayed trip)</description>
|
||||
</channel>
|
||||
<channel id="zone_tampered" typeId="zone_condition">
|
||||
<label>Tampered</label>
|
||||
<description>Tampered</description>
|
||||
</channel>
|
||||
<channel id="zone_trouble" typeId="zone_condition">
|
||||
<label>Trouble</label>
|
||||
<description>Trouble</description>
|
||||
</channel>
|
||||
<channel id="zone_bypassed" typeId="zone_bypass">
|
||||
<label>Bypassed</label>
|
||||
<description>Bypassed</description>
|
||||
</channel>
|
||||
<channel id="zone_inhibited" typeId="zone_condition">
|
||||
<label>Inhibited (Force Armed)</label>
|
||||
<description>Inhibited (force armed)</description>
|
||||
</channel>
|
||||
<channel id="zone_low_battery" typeId="zone_condition">
|
||||
<label>Low Battery</label>
|
||||
<description>Low Battery</description>
|
||||
</channel>
|
||||
<channel id="zone_loss_of_supervision" typeId="zone_condition">
|
||||
<label>Loss of Supervision</label>
|
||||
<description>Loss of supervision</description>
|
||||
</channel>
|
||||
<channel id="zone_alarm_memory" typeId="zone_condition">
|
||||
<label>Alarm Memory</label>
|
||||
<description>Alarm memory</description>
|
||||
</channel>
|
||||
<channel id="zone_bypass_memory" typeId="zone_condition">
|
||||
<label>Bypass Memory</label>
|
||||
<description>Bypass memory</description>
|
||||
</channel>
|
||||
</channels>
|
||||
|
||||
<representation-property>zoneNumber</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="zoneNumber" type="integer" required="true" min="1" max="192">
|
||||
<label>Zone Number</label>
|
||||
<description>The Zone Number.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user