From a0a9bc11287c165c1681ad1eba52854b7144a407 Mon Sep 17 00:00:00 2001 From: Georgios Moutsos <50378548+jossuar@users.noreply.github.com> Date: Fri, 16 Jul 2021 15:43:37 +0300 Subject: [PATCH] [caddx] Add new channels and support for ignoring zone status transitions (#10923) * Cleanup of binding configuration classes * Added context to CaddxMessage * Logging enhancements * Added support for ignoring Zone Status Transitions Signed-off-by: Georgios Moutsos Signed-off-by: dw-8 --- bundles/org.openhab.binding.caddx/README.md | 3 + .../caddx/internal/CaddxCommunicator.java | 20 ++- .../binding/caddx/internal/CaddxEvent.java | 14 ++ .../binding/caddx/internal/CaddxMessage.java | 18 ++- .../caddx/internal/CaddxMessageContext.java | 27 ++++ .../caddx/internal/CaddxMessageType.java | 137 +++++++++++------- .../caddx/internal/CaddxPanelListener.java | 2 +- .../config/CaddxBridgeConfiguration.java | 6 + .../config/CaddxPartitionConfiguration.java | 9 -- .../handler/CaddxBaseThingHandler.java | 27 +--- .../internal/handler/CaddxBridgeHandler.java | 77 +++++----- .../internal/handler/ThingHandlerKeypad.java | 18 ++- .../internal/handler/ThingHandlerPanel.java | 86 +++++++++-- .../handler/ThingHandlerPartition.java | 22 ++- .../internal/handler/ThingHandlerZone.java | 27 +++- .../main/resources/OH-INF/thing/bridge.xml | 5 + .../src/main/resources/OH-INF/thing/panel.xml | 14 ++ .../internal/CaddxMessageReaderUtil.java | 2 +- .../message/CaddxMessageParseTest.java | 72 ++++++++- .../caddx/internal/zones_snapshot_message.msg | 1 + 20 files changed, 434 insertions(+), 153 deletions(-) create mode 100644 bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageContext.java create mode 100644 bundles/org.openhab.binding.caddx/src/test/resources/org/openhab/binding/caddx/internal/zones_snapshot_message.msg diff --git a/bundles/org.openhab.binding.caddx/README.md b/bundles/org.openhab.binding.caddx/README.md index df46713c9e72..e59408a1df30 100644 --- a/bundles/org.openhab.binding.caddx/README.md +++ b/bundles/org.openhab.binding.caddx/README.md @@ -125,6 +125,9 @@ Caddx Alarm things support a variety of channels as seen below in the following | 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 | +| panel_ac_fail | Switch | Configuration | AC fail | +| panel_ac_power_on | Switch | Configuration | AC Power on | +| panel_low_battery_memory | Switch | Configuration | Low Battery Memory | | partition_bypass_code_required | Switch | Partition Condition | Bypass code required | | partition_fire_trouble | Switch | Partition Condition | Fire trouble | | partition_fire | Switch | Partition Condition | Fire | diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxCommunicator.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxCommunicator.java index c06204c20f51..b5c3ed33d649 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxCommunicator.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxCommunicator.java @@ -179,17 +179,17 @@ public void stop() { @SuppressWarnings("null") private void messageDispatchLoop() { - int @Nullable [] expectedMessageNumbers = null; - - @Nullable + int[] expectedMessageNumbers = null; CaddxMessage outgoingMessage = null; boolean skipTransmit = true; + CaddxMessageContext context = null; try { // loop until the thread is interrupted, sending out messages while (!Thread.currentThread().isInterrupted()) { // Initialize the state outgoingMessage = null; + context = null; expectedMessageNumbers = null; if (!skipTransmit) { @@ -203,6 +203,7 @@ private void messageDispatchLoop() { out.flush(); expectedMessageNumbers = outgoingMessage.getReplyMessageNumbers(); + context = outgoingMessage.getContext(); // Log message if (logger.isDebugEnabled()) { @@ -248,10 +249,12 @@ private void messageDispatchLoop() { if (incomingMessage.hasAcknowledgementFlag()) { if (incomingMessage.isChecksumCorrect()) { // send ACK - transmitFirst(new CaddxMessage(CaddxMessageType.POSITIVE_ACKNOWLEDGE, "")); + transmitFirst(new CaddxMessage(CaddxMessageContext.NONE, + CaddxMessageType.POSITIVE_ACKNOWLEDGE, "")); } else { // Send NAK - transmitFirst(new CaddxMessage(CaddxMessageType.NEGATIVE_ACKNOWLEDGE, "")); + transmitFirst(new CaddxMessage(CaddxMessageContext.NONE, + CaddxMessageType.NEGATIVE_ACKNOWLEDGE, "")); } } } @@ -289,7 +292,10 @@ private void messageDispatchLoop() { if (incomingMessage != null) { if (incomingMessage.isChecksumCorrect()) { for (CaddxPanelListener listener : listenerQueue) { - listener.caddxMessage(this, incomingMessage); + if (context != null) { + incomingMessage.setContext(context); + } + listener.caddxMessage(incomingMessage); } } else { logger.warn( @@ -367,7 +373,7 @@ private void offerCaddxMessage() throws InterruptedException { logger.trace("Offering received message"); // Full message received in data byte array - CaddxMessage caddxMessage = new CaddxMessage(message, true); + CaddxMessage caddxMessage = new CaddxMessage(CaddxMessageContext.NONE, message, true); if (!exchanger.offer(caddxMessage, 3, TimeUnit.SECONDS)) { logger.debug("Offered message was not received"); } diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxEvent.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxEvent.java index ce33fd92b34f..2a1170ff1603 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxEvent.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxEvent.java @@ -60,4 +60,18 @@ public CaddxMessage getCaddxMessage() { public @Nullable Integer getKeypad() { return keypad; } + + /** + * Returns a string representation of a CaddxEvent. + * + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append(String.format("partition: %d, zone: %d, keypad: %d\r\n", partition, zone, keypad)); + sb.append(caddxMessage.toString()); + + return sb.toString(); + } } diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessage.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessage.java index 150d4b223ae7..a0b3486a02fa 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessage.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessage.java @@ -40,8 +40,9 @@ public class CaddxMessage { private final byte checksum2In; private final byte checksum1Calc; private final byte checksum2Calc; + private CaddxMessageContext context; - public CaddxMessage(byte[] message, boolean withChecksum) { + public CaddxMessage(CaddxMessageContext context, 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"); @@ -52,6 +53,7 @@ public CaddxMessage(byte[] message, boolean withChecksum) { } // Received data + this.context = context; byte[] msg = message; // Fill in the checksum @@ -94,7 +96,7 @@ public CaddxMessage(byte[] message, boolean withChecksum) { processCaddxMessage(); } - public CaddxMessage(CaddxMessageType type, String data) { + public CaddxMessage(CaddxMessageContext context, CaddxMessageType type, String data) { int length = type.length; String[] tokens = data.split("\\,"); if (length != 1 && tokens.length != length - 1) { @@ -102,6 +104,7 @@ public CaddxMessage(CaddxMessageType type, String data) { throw new IllegalArgumentException("CaddxMessage: data has not the correct format."); } + this.context = context; byte[] msg = new byte[length]; msg[0] = (byte) type.number; for (int i = 0; i < length - 1; i++) { @@ -133,6 +136,14 @@ public CaddxMessage(CaddxMessageType type, String data) { processCaddxMessage(); } + public CaddxMessageContext getContext() { + return context; + } + + public void setContext(CaddxMessageContext context) { + this.context = context; + } + public byte getChecksum1In() { return checksum1In; } @@ -259,6 +270,9 @@ public String toString() { return "Unknown message type"; } + sb.append(String.format("Context: %s", context.toString())); + sb.append(System.lineSeparator()); + sb.append("Message: "); sb.append(String.format("%2s", Integer.toHexString(message[0]))); sb.append(" "); diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageContext.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageContext.java new file mode 100644 index 000000000000..dc02be03349a --- /dev/null +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageContext.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2010-2021 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; + +/** + * Used to map thing types from the binding string to a ENUM value. + * + * @author Georgios Moutsos - Initial contribution + */ +@NonNullByDefault +public enum CaddxMessageContext { + NONE, + DISCOVERY, + COMMAND; +} diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageType.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageType.java index 94f37e8d6063..ad357576fc2c 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageType.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageType.java @@ -197,100 +197,134 @@ public enum CaddxMessageType { false), // Byte 3 Zone 1 & 2 (+offset) status flags - new CaddxProperty("", 3, 1, 0, 1, CaddxPropertyType.BIT, "Zone 1 faulted (or delayed trip)", false), - new CaddxProperty("", 3, 1, 1, 1, CaddxPropertyType.BIT, "Zone 1 bypass (or inhibited)", false), + new CaddxProperty("zone_1_faulted", 3, 1, 0, 1, CaddxPropertyType.BIT, "Zone 1 faulted (or delayed trip)", + false), + new CaddxProperty("zone_1_bypassed", 3, 1, 1, 1, CaddxPropertyType.BIT, "Zone 1 bypass (or inhibited)", + false), new CaddxProperty("zone_1_trouble", 3, 1, 2, 1, CaddxPropertyType.BIT, "Zone 1 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 3, 1, 3, 1, CaddxPropertyType.BIT, "Zone 1 alarm memory", false), - new CaddxProperty("", 3, 1, 4, 1, CaddxPropertyType.BIT, "Zone 2 faulted (or delayed trip)", false), - new CaddxProperty("", 3, 1, 5, 1, CaddxPropertyType.BIT, "Zone 2 bypass (or inhibited)", false), + new CaddxProperty("zone_1_alarm_memory", 3, 1, 3, 1, CaddxPropertyType.BIT, "Zone 1 alarm memory", false), + new CaddxProperty("zone_2_faulted", 3, 1, 4, 1, CaddxPropertyType.BIT, "Zone 2 faulted (or delayed trip)", + false), + new CaddxProperty("zone_2_bypassed", 3, 1, 5, 1, CaddxPropertyType.BIT, "Zone 2 bypass (or inhibited)", + false), new CaddxProperty("zone_2_trouble", 3, 1, 6, 1, CaddxPropertyType.BIT, "Zone 2 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 3, 1, 7, 1, CaddxPropertyType.BIT, "Zone 2 alarm memory", false), + new CaddxProperty("zone_2_alarm_memory", 3, 1, 7, 1, CaddxPropertyType.BIT, "Zone 2 alarm memory", false), // Byte 4 Zone 3 & 4 status flags (see byte 3) - new CaddxProperty("", 4, 1, 0, 1, CaddxPropertyType.BIT, "Zone 3 faulted (or delayed trip)", false), - new CaddxProperty("", 4, 1, 1, 1, CaddxPropertyType.BIT, "Zone 3 bypass (or inhibited)", false), + new CaddxProperty("zone_3_faulted", 4, 1, 0, 1, CaddxPropertyType.BIT, "Zone 3 faulted (or delayed trip)", + false), + new CaddxProperty("zone_3_bypassed", 4, 1, 1, 1, CaddxPropertyType.BIT, "Zone 3 bypass (or inhibited)", + false), new CaddxProperty("zone_3_trouble", 4, 1, 2, 1, CaddxPropertyType.BIT, "Zone 3 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 4, 1, 3, 1, CaddxPropertyType.BIT, "Zone 3 alarm memory", false), - new CaddxProperty("", 4, 1, 4, 1, CaddxPropertyType.BIT, "Zone 4 faulted (or delayed trip)", false), - new CaddxProperty("", 4, 1, 5, 1, CaddxPropertyType.BIT, "Zone 4 bypass (or inhibited)", false), + new CaddxProperty("zone_3_alarm_memory", 4, 1, 3, 1, CaddxPropertyType.BIT, "Zone 3 alarm memory", false), + new CaddxProperty("zone_4_faulted", 4, 1, 4, 1, CaddxPropertyType.BIT, "Zone 4 faulted (or delayed trip)", + false), + new CaddxProperty("zone_4_bypassed", 4, 1, 5, 1, CaddxPropertyType.BIT, "Zone 4 bypass (or inhibited)", + false), new CaddxProperty("zone_4_trouble", 4, 1, 6, 1, CaddxPropertyType.BIT, "Zone 4 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 4, 1, 7, 1, CaddxPropertyType.BIT, "Zone 4 alarm memory", false), + new CaddxProperty("zone_4_alarm_memory", 4, 1, 7, 1, CaddxPropertyType.BIT, "Zone 4 alarm memory", false), // Byte 5 Zone 5 & 6 status flags (see byte 3) - new CaddxProperty("", 5, 1, 0, 1, CaddxPropertyType.BIT, "Zone 5 faulted (or delayed trip)", false), - new CaddxProperty("", 5, 1, 1, 1, CaddxPropertyType.BIT, "Zone 5 bypass (or inhibited)", false), + new CaddxProperty("zone_5_faulted", 5, 1, 0, 1, CaddxPropertyType.BIT, "Zone 5 faulted (or delayed trip)", + false), + new CaddxProperty("zone_5_bypassed", 5, 1, 1, 1, CaddxPropertyType.BIT, "Zone 5 bypass (or inhibited)", + false), new CaddxProperty("zone_5_trouble", 5, 1, 2, 1, CaddxPropertyType.BIT, "Zone 5 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 5, 1, 3, 1, CaddxPropertyType.BIT, "Zone 5 alarm memory", false), - new CaddxProperty("", 5, 1, 4, 1, CaddxPropertyType.BIT, "Zone 6 faulted (or delayed trip)", false), - new CaddxProperty("", 5, 1, 5, 1, CaddxPropertyType.BIT, "Zone 6 bypass (or inhibited)", false), + new CaddxProperty("zone_5_alarm_memory", 5, 1, 3, 1, CaddxPropertyType.BIT, "Zone 5 alarm memory", false), + new CaddxProperty("zone_6_faulted", 5, 1, 4, 1, CaddxPropertyType.BIT, "Zone 6 faulted (or delayed trip)", + false), + new CaddxProperty("zone_6_bypassed", 5, 1, 5, 1, CaddxPropertyType.BIT, "Zone 6 bypass (or inhibited)", + false), new CaddxProperty("zone_6_trouble", 5, 1, 6, 1, CaddxPropertyType.BIT, "Zone 6 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 5, 1, 7, 1, CaddxPropertyType.BIT, "Zone 6 alarm memory", false), + new CaddxProperty("zone_6_alarm_memory", 5, 1, 7, 1, CaddxPropertyType.BIT, "Zone 6 alarm memory", false), // Byte 6 Zone 7 & 8 status flags (see byte 3) - new CaddxProperty("", 6, 1, 0, 1, CaddxPropertyType.BIT, "Zone 7 faulted (or delayed trip)", false), - new CaddxProperty("", 6, 1, 1, 1, CaddxPropertyType.BIT, "Zone 7 bypass (or inhibited)", false), + new CaddxProperty("zone_7_faulted", 6, 1, 0, 1, CaddxPropertyType.BIT, "Zone 7 faulted (or delayed trip)", + false), + new CaddxProperty("zone_7_bypassed", 6, 1, 1, 1, CaddxPropertyType.BIT, "Zone 7 bypass (or inhibited)", + false), new CaddxProperty("zone_7_trouble", 6, 1, 2, 1, CaddxPropertyType.BIT, "Zone 7 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 6, 1, 3, 1, CaddxPropertyType.BIT, "Zone 7 alarm memory", false), - new CaddxProperty("", 6, 1, 4, 1, CaddxPropertyType.BIT, "Zone 8 faulted (or delayed trip)", false), - new CaddxProperty("", 6, 1, 5, 1, CaddxPropertyType.BIT, "Zone 8 bypass (or inhibited)", false), + new CaddxProperty("zone_7_alarm_memory", 6, 1, 3, 1, CaddxPropertyType.BIT, "Zone 7 alarm memory", false), + new CaddxProperty("zone_8_faulted", 6, 1, 4, 1, CaddxPropertyType.BIT, "Zone 8 faulted (or delayed trip)", + false), + new CaddxProperty("zone_8_bypassed", 6, 1, 5, 1, CaddxPropertyType.BIT, "Zone 8 bypass (or inhibited)", + false), new CaddxProperty("zone_8_trouble", 6, 1, 6, 1, CaddxPropertyType.BIT, "Zone 8 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 6, 1, 7, 1, CaddxPropertyType.BIT, "Zone 8 alarm memory", false), + new CaddxProperty("zone_8_alarm_memory", 6, 1, 7, 1, CaddxPropertyType.BIT, "Zone 8 alarm memory", false), // Byte 7 Zone 9 & 10 status flags (see byte 3) - new CaddxProperty("", 7, 1, 0, 1, CaddxPropertyType.BIT, "Zone 9 faulted (or delayed trip)", false), - new CaddxProperty("", 7, 1, 1, 1, CaddxPropertyType.BIT, "Zone 9 bypass (or inhibited)", false), + new CaddxProperty("zone_9_faulted", 7, 1, 0, 1, CaddxPropertyType.BIT, "Zone 9 faulted (or delayed trip)", + false), + new CaddxProperty("zone_9_bypassed", 7, 1, 1, 1, CaddxPropertyType.BIT, "Zone 9 bypass (or inhibited)", + false), new CaddxProperty("zone_9_trouble", 7, 1, 2, 1, CaddxPropertyType.BIT, "Zone 9 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 7, 1, 3, 1, CaddxPropertyType.BIT, "Zone 9 alarm memory", false), - new CaddxProperty("", 7, 1, 4, 1, CaddxPropertyType.BIT, "Zone 10 faulted (or delayed trip)", false), - new CaddxProperty("", 7, 1, 5, 1, CaddxPropertyType.BIT, "Zone 10 bypass (or inhibited)", false), + new CaddxProperty("zone_9_alarm_memory", 7, 1, 3, 1, CaddxPropertyType.BIT, "Zone 9 alarm memory", false), + new CaddxProperty("zone_10_faulted", 7, 1, 4, 1, CaddxPropertyType.BIT, "Zone 10 faulted (or delayed trip)", + false), + new CaddxProperty("zone_10_bypassed", 7, 1, 5, 1, CaddxPropertyType.BIT, "Zone 10 bypass (or inhibited)", + false), new CaddxProperty("zone_10_trouble", 7, 1, 6, 1, CaddxPropertyType.BIT, "Zone 10 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 7, 1, 7, 1, CaddxPropertyType.BIT, "Zone 10 alarm memory", false), + new CaddxProperty("zone_10_alarm_memory", 7, 1, 7, 1, CaddxPropertyType.BIT, "Zone 10 alarm memory", false), // Byte 8 Zone 11 & 12 status flags (see byte 3) - new CaddxProperty("", 8, 1, 0, 1, CaddxPropertyType.BIT, "Zone 11 faulted (or delayed trip)", false), - new CaddxProperty("", 8, 1, 1, 1, CaddxPropertyType.BIT, "Zone 11 bypass (or inhibited)", false), + new CaddxProperty("zone_11_faulted", 8, 1, 0, 1, CaddxPropertyType.BIT, "Zone 11 faulted (or delayed trip)", + false), + new CaddxProperty("zone_11_bypassed", 8, 1, 1, 1, CaddxPropertyType.BIT, "Zone 11 bypass (or inhibited)", + false), new CaddxProperty("zone_11_trouble", 8, 1, 2, 1, CaddxPropertyType.BIT, "Zone 11 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 8, 1, 3, 1, CaddxPropertyType.BIT, "Zone 11 alarm memory", false), - new CaddxProperty("", 8, 1, 4, 1, CaddxPropertyType.BIT, "Zone 12 faulted (or delayed trip)", false), - new CaddxProperty("", 8, 1, 5, 1, CaddxPropertyType.BIT, "Zone 12 bypass (or inhibited)", false), + new CaddxProperty("zone_11_alarm_memory", 8, 1, 3, 1, CaddxPropertyType.BIT, "Zone 11 alarm memory", false), + new CaddxProperty("zone_12_faulted", 8, 1, 4, 1, CaddxPropertyType.BIT, "Zone 12 faulted (or delayed trip)", + false), + new CaddxProperty("zone_12_bypassed", 8, 1, 5, 1, CaddxPropertyType.BIT, "Zone 12 bypass (or inhibited)", + false), new CaddxProperty("zone_12_trouble", 8, 1, 6, 1, CaddxPropertyType.BIT, "Zone 12 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 8, 1, 7, 1, CaddxPropertyType.BIT, "Zone 12 alarm memory", false), + new CaddxProperty("zone_12_alarm_memory", 8, 1, 7, 1, CaddxPropertyType.BIT, "Zone 12 alarm memory", false), // Byte 9 Zone 13 & 14 status flags (see byte 3) - new CaddxProperty("", 9, 1, 0, 1, CaddxPropertyType.BIT, "Zone 13 faulted (or delayed trip)", false), - new CaddxProperty("", 9, 1, 1, 1, CaddxPropertyType.BIT, "Zone 13 bypass (or inhibited)", false), + new CaddxProperty("zone_13_faulted", 9, 1, 0, 1, CaddxPropertyType.BIT, "Zone 13 faulted (or delayed trip)", + false), + new CaddxProperty("zone_13_bypassed", 9, 1, 1, 1, CaddxPropertyType.BIT, "Zone 13 bypass (or inhibited)", + false), new CaddxProperty("zone_13_trouble", 9, 1, 2, 1, CaddxPropertyType.BIT, "Zone 13 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 9, 1, 3, 1, CaddxPropertyType.BIT, "Zone 13 alarm memory", false), - new CaddxProperty("", 9, 1, 4, 1, CaddxPropertyType.BIT, "Zone 14 faulted (or delayed trip)", false), - new CaddxProperty("", 9, 1, 5, 1, CaddxPropertyType.BIT, "Zone 14 bypass (or inhibited)", false), + new CaddxProperty("zone_13_alarm_memory", 9, 1, 3, 1, CaddxPropertyType.BIT, "Zone 13 alarm memory", false), + new CaddxProperty("zone_14_faulted", 9, 1, 4, 1, CaddxPropertyType.BIT, "Zone 14 faulted (or delayed trip)", + false), + new CaddxProperty("zone_14_bypassed", 9, 1, 5, 1, CaddxPropertyType.BIT, "Zone 14 bypass (or inhibited)", + false), new CaddxProperty("zone_14_trouble", 9, 1, 6, 1, CaddxPropertyType.BIT, "Zone 14 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 9, 1, 7, 1, CaddxPropertyType.BIT, "Zone 14 alarm memory", false), + new CaddxProperty("zone_14_alarm_memory", 9, 1, 7, 1, CaddxPropertyType.BIT, "Zone 14 alarm memory", false), // Byte 10 Zone 15 & 16 status flags (see byte 3) - new CaddxProperty("", 10, 1, 0, 1, CaddxPropertyType.BIT, "Zone 15 faulted (or delayed trip)", false), - new CaddxProperty("", 10, 1, 1, 1, CaddxPropertyType.BIT, "Zone 15 bypass (or inhibited)", false), + new CaddxProperty("zone_15_faulted", 10, 1, 0, 1, CaddxPropertyType.BIT, + "Zone 15 faulted (or delayed trip)", false), + new CaddxProperty("zone_15_bypassed", 10, 1, 1, 1, CaddxPropertyType.BIT, "Zone 15 bypass (or inhibited)", + false), new CaddxProperty("zone_15_trouble", 10, 1, 2, 1, CaddxPropertyType.BIT, "Zone 15 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 10, 1, 3, 1, CaddxPropertyType.BIT, "Zone 15 alarm memory", false), - new CaddxProperty("", 10, 1, 4, 1, CaddxPropertyType.BIT, "Zone 16 faulted (or delayed trip)", false), - new CaddxProperty("", 10, 1, 5, 1, CaddxPropertyType.BIT, "Zone 16 bypass (or inhibited)", false), + new CaddxProperty("zone_15_alarm_memory", 10, 1, 3, 1, CaddxPropertyType.BIT, "Zone 15 alarm memory", + false), + new CaddxProperty("zone_16_faulted", 10, 1, 4, 1, CaddxPropertyType.BIT, + "Zone 16 faulted (or delayed trip)", false), + new CaddxProperty("zone_16_bypassed", 10, 1, 5, 1, CaddxPropertyType.BIT, "Zone 16 bypass (or inhibited)", + false), new CaddxProperty("zone_16_trouble", 10, 1, 6, 1, CaddxPropertyType.BIT, "Zone 16 trouble (tamper, low battery, or lost)", false), - new CaddxProperty("", 10, 1, 7, 1, CaddxPropertyType.BIT, "Zone 16 alarm memory", false)), + new CaddxProperty("zone_16_alarm_memory", 10, 1, 7, 1, CaddxPropertyType.BIT, "Zone 16 alarm memory", + false)), PARTITION_STATUS_MESSAGE(0x06, null, 9, "Partition Status Message", "This message will contain all information relevant to a single partition in the system.", @@ -508,7 +542,7 @@ public enum CaddxMessageType { new CaddxProperty("", 4, 1, 4, 1, CaddxPropertyType.BIT, "Box tamper", false), new CaddxProperty("", 4, 1, 5, 1, CaddxPropertyType.BIT, "Siren tamper / trouble", false), new CaddxProperty("", 4, 1, 6, 1, CaddxPropertyType.BIT, "Low Battery", false), - new CaddxProperty("", 4, 1, 7, 1, CaddxPropertyType.BIT, "AC fail", false), + new CaddxProperty("panel_ac_fail", 4, 1, 7, 1, CaddxPropertyType.BIT, "AC fail", false), // Byte 5 new CaddxProperty("", 5, 1, 0, 1, CaddxPropertyType.BIT, "Expander box tamper", false), @@ -531,8 +565,9 @@ public enum CaddxMessageType { // Byte 7 new CaddxProperty("", 7, 1, 0, 1, CaddxPropertyType.BIT, "Dynamic battery test", false), - new CaddxProperty("", 7, 1, 1, 1, CaddxPropertyType.BIT, "AC power on", false), - new CaddxProperty("", 7, 1, 2, 1, CaddxPropertyType.BIT, "Low battery memory", false), + new CaddxProperty("panel_ac_power_on", 7, 1, 1, 1, CaddxPropertyType.BIT, "AC power on", false), + new CaddxProperty("panel_low_battery_memory", 7, 1, 2, 1, CaddxPropertyType.BIT, "Low battery memory", + false), new CaddxProperty("", 7, 1, 3, 1, CaddxPropertyType.BIT, "Ground fault memory", false), new CaddxProperty("", 7, 1, 4, 1, CaddxPropertyType.BIT, "Fire alarm verification being timed", false), new CaddxProperty("", 7, 1, 5, 1, CaddxPropertyType.BIT, "Smoke power reset", false), diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxPanelListener.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxPanelListener.java index a0459aab7f0b..7d904494348f 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxPanelListener.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxPanelListener.java @@ -21,5 +21,5 @@ */ @NonNullByDefault public interface CaddxPanelListener { - public void caddxMessage(CaddxCommunicator communicator, CaddxMessage message); + public void caddxMessage(CaddxMessage message); } diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxBridgeConfiguration.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxBridgeConfiguration.java index 96d485827cfb..0cc18f485f53 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxBridgeConfiguration.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxBridgeConfiguration.java @@ -30,11 +30,13 @@ public class CaddxBridgeConfiguration { public static final String SERIAL_PORT = "serialPort"; public static final String BAUD = "baud"; public static final String MAX_ZONE_NUMBER = "maxZoneNumber"; + public static final String IGNORE_ZONE_STATUS_TRANSITIONS = "ignoreZoneStatusTransitions"; private CaddxProtocol protocol = CaddxProtocol.Binary; private @Nullable String serialPort; private int baudrate = 9600; private int maxZoneNumber = 16; + private boolean ignoreZoneStatusTransitions = false; public CaddxProtocol getProtocol() { return protocol; @@ -51,4 +53,8 @@ public int getBaudrate() { public int getMaxZoneNumber() { return maxZoneNumber; } + + public boolean isIgnoreZoneStatusTransitions() { + return ignoreZoneStatusTransitions; + } } diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxPartitionConfiguration.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxPartitionConfiguration.java index 673e5b2db5d8..b346ab1564b6 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxPartitionConfiguration.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxPartitionConfiguration.java @@ -30,16 +30,7 @@ public class CaddxPartitionConfiguration { */ 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; - } } diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBaseThingHandler.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBaseThingHandler.java index 98625104d721..ef1bcd09d127 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBaseThingHandler.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBaseThingHandler.java @@ -49,7 +49,6 @@ public abstract class CaddxBaseThingHandler extends BaseThingHandler { /** Partition */ private int partitionNumber; - private int userNumber; /** Zone */ private int zoneNumber; @@ -130,7 +129,6 @@ private void getConfiguration(CaddxThingType caddxThingType) { case PARTITION: CaddxPartitionConfiguration partitionConfiguration = getConfigAs(CaddxPartitionConfiguration.class); setPartitionNumber(partitionConfiguration.getPartitionNumber()); - setUserNumber(partitionConfiguration.getUserNumber()); break; case ZONE: CaddxZoneConfiguration zoneConfiguration = getConfigAs(CaddxZoneConfiguration.class); @@ -139,6 +137,7 @@ private void getConfiguration(CaddxThingType caddxThingType) { case KEYPAD: CaddxKeypadConfiguration keypadConfiguration = getConfigAs(CaddxKeypadConfiguration.class); setKeypadAddress(keypadConfiguration.getKeypadAddress()); + setTerminalModeSeconds(keypadConfiguration.getTerminalModeSeconds()); default: break; } @@ -171,24 +170,6 @@ 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. * @@ -228,16 +209,16 @@ public void setKeypadAddress(int keypadAddress) { /** * Get Keypad Terminal Mode Seconds. * - * @return keypadAddress + * @return terminalModeSeconds */ public int getTerminalModeSeconds() { return terminalModeSeconds; } /** - * Set Keypad Address. + * Set Keypad Terminal Mode Seconds. * - * @param keypadAddress + * @param terminalModeSeconds */ public void setTerminalModeSeconds(int terminalModeSeconds) { this.terminalModeSeconds = terminalModeSeconds; diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBridgeHandler.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBridgeHandler.java index 73a6657e75c5..d086b0b2d33b 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBridgeHandler.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBridgeHandler.java @@ -29,6 +29,7 @@ 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.CaddxMessageContext; import org.openhab.binding.caddx.internal.CaddxMessageType; import org.openhab.binding.caddx.internal.CaddxPanelListener; import org.openhab.binding.caddx.internal.CaddxProtocol; @@ -85,6 +86,7 @@ public class CaddxBridgeHandler extends BaseBridgeHandler implements CaddxPanelL private String serialPortName = ""; private int baudRate; private int maxZoneNumber; + private boolean isIgnoreZoneStatusTransitions; private @Nullable CaddxCommunicator communicator = null; // Things served by the bridge @@ -120,6 +122,7 @@ public void initialize() { protocol = configuration.getProtocol(); baudRate = configuration.getBaudrate(); maxZoneNumber = configuration.getMaxZoneNumber(); + isIgnoreZoneStatusTransitions = configuration.isIgnoreZoneStatusTransitions(); updateStatus(ThingStatus.OFFLINE); // create & start panel interface @@ -141,27 +144,28 @@ public void initialize() { comm.addListener(this); // Send discovery commands for the zones - 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_ZONES_SNAPSHOT_REQUEST_30, false)); - comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_40, false)); - comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_50, false)); - comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_60, false)); - comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_70, false)); - comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_80, false)); - comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_90, false)); - comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_A0, false)); - comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_B0, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_00, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_10, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_20, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_30, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_40, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_50, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_60, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_70, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_80, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_90, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_A0, false)); + comm.transmit(new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_ZONES_SNAPSHOT_REQUEST_B0, false)); // Send discovery commands for the partitions - comm.transmit(new CaddxMessage(DISCOVERY_PARTITIONS_SNAPSHOT_REQUEST, false)); + comm.transmit( + new CaddxMessage(CaddxMessageContext.DISCOVERY, DISCOVERY_PARTITIONS_SNAPSHOT_REQUEST, false)); // Send status commands to the zones and partitions - thingZonesMap.forEach((k, v) -> sendCommand(CaddxBindingConstants.ZONE_STATUS_REQUEST, - k.subtract(BigDecimal.ONE).toString())); - thingPartitionsMap.forEach((k, v) -> sendCommand(CaddxBindingConstants.PARTITION_STATUS_REQUEST, - k.subtract(BigDecimal.ONE).toString())); + thingZonesMap.forEach((k, v) -> sendCommand(CaddxMessageContext.COMMAND, + CaddxBindingConstants.ZONE_STATUS_REQUEST, k.subtract(BigDecimal.ONE).toString())); + thingPartitionsMap.forEach((k, v) -> sendCommand(CaddxMessageContext.COMMAND, + CaddxBindingConstants.PARTITION_STATUS_REQUEST, k.subtract(BigDecimal.ONE).toString())); } // list all channels @@ -224,7 +228,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { data = tokens[1]; } - sendCommand(cmd, data); + sendCommand(CaddxMessageContext.COMMAND, cmd, data); updateState(channelUID, new StringType("")); } @@ -241,44 +245,44 @@ public void handleCommand(ChannelUID channelUID, Command command) { * @param command The command to be send * @param data The associated command data */ - public boolean sendCommand(String command, String data) { + public boolean sendCommand(CaddxMessageContext context, 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); + msg = new CaddxMessage(context, CaddxMessageType.ZONE_BYPASS_TOGGLE, data); break; case CaddxBindingConstants.ZONE_STATUS_REQUEST: - msg = new CaddxMessage(CaddxMessageType.ZONE_STATUS_REQUEST, data); + msg = new CaddxMessage(context, CaddxMessageType.ZONE_STATUS_REQUEST, data); break; case CaddxBindingConstants.ZONE_NAME_REQUEST: - msg = new CaddxMessage(CaddxMessageType.ZONE_NAME_REQUEST, data); + msg = new CaddxMessage(context, CaddxMessageType.ZONE_NAME_REQUEST, data); break; case CaddxBindingConstants.PARTITION_STATUS_REQUEST: - msg = new CaddxMessage(CaddxMessageType.PARTITION_STATUS_REQUEST, data); + msg = new CaddxMessage(context, CaddxMessageType.PARTITION_STATUS_REQUEST, data); break; case CaddxBindingConstants.PARTITION_PRIMARY_COMMAND_WITH_PIN: - msg = new CaddxMessage(CaddxMessageType.PRIMARY_KEYPAD_FUNCTION_WITH_PIN, data); + msg = new CaddxMessage(context, CaddxMessageType.PRIMARY_KEYPAD_FUNCTION_WITH_PIN, data); break; case CaddxBindingConstants.PARTITION_SECONDARY_COMMAND: - msg = new CaddxMessage(CaddxMessageType.SECONDARY_KEYPAD_FUNCTION, data); + msg = new CaddxMessage(context, CaddxMessageType.SECONDARY_KEYPAD_FUNCTION, data); break; case CaddxBindingConstants.PANEL_SYSTEM_STATUS_REQUEST: - msg = new CaddxMessage(CaddxMessageType.SYSTEM_STATUS_REQUEST, data); + msg = new CaddxMessage(context, CaddxMessageType.SYSTEM_STATUS_REQUEST, data); break; case CaddxBindingConstants.PANEL_INTERFACE_CONFIGURATION_REQUEST: - msg = new CaddxMessage(CaddxMessageType.INTERFACE_CONFIGURATION_REQUEST, data); + msg = new CaddxMessage(context, CaddxMessageType.INTERFACE_CONFIGURATION_REQUEST, data); break; case CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST: - msg = new CaddxMessage(CaddxMessageType.LOG_EVENT_REQUEST, data); + msg = new CaddxMessage(context, CaddxMessageType.LOG_EVENT_REQUEST, data); break; case CaddxBindingConstants.KEYPAD_TERMINAL_MODE_REQUEST: - msg = new CaddxMessage(CaddxMessageType.KEYPAD_TERMINAL_MODE_REQUEST, data); + msg = new CaddxMessage(context, CaddxMessageType.KEYPAD_TERMINAL_MODE_REQUEST, data); break; case CaddxBindingConstants.KEYPAD_SEND_KEYPAD_TEXT_MESSAGE: - msg = new CaddxMessage(CaddxMessageType.SEND_KEYPAD_TEXT_MESSAGE, data); + msg = new CaddxMessage(context, CaddxMessageType.SEND_KEYPAD_TEXT_MESSAGE, data); break; default: logger.debug("Unknown command {}", command); @@ -312,16 +316,13 @@ public void unregisterDiscoveryService() { } @Override - public void caddxMessage(CaddxCommunicator communicator, CaddxMessage caddxMessage) { + public void caddxMessage(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) { @@ -347,6 +348,14 @@ public void caddxMessage(CaddxCommunicator communicator, CaddxMessage caddxMessa CaddxEvent event = new CaddxEvent(caddxMessage, partition, zone, keypad); + // Ignore Zone Status messages according to the configuration + if (isIgnoreZoneStatusTransitions + && caddxMessage.getCaddxMessageType() == CaddxMessageType.ZONE_STATUS_MESSAGE + && caddxMessage.getContext() == CaddxMessageContext.NONE) { + logger.debug("Zone {} Transition ignored.", zone); + return; + } + // Find the thing Thing thing = findThing(caddxThingType, partition, zone, keypad); CaddxDiscoveryService discoveryService = getDiscoveryService(); diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerKeypad.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerKeypad.java index 69f93cfd8f34..19da26eedcce 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerKeypad.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerKeypad.java @@ -19,6 +19,7 @@ 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.CaddxMessageContext; import org.openhab.binding.caddx.internal.CaddxMessageType; import org.openhab.binding.caddx.internal.CaddxProperty; import org.openhab.binding.caddx.internal.action.CaddxKeypadActions; @@ -44,6 +45,19 @@ public ThingHandlerKeypad(Thing thing) { super(thing, CaddxThingType.KEYPAD); } + @Override + public void initialize() { + super.initialize(); + + CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler(); + if (bridgeHandler == null) { + return; + } + + // Follow the bridge status + updateStatus(bridgeHandler.getThing().getStatus()); + } + @Override public void updateChannel(ChannelUID channelUID, String data) { if (channelUID.getId().equals(CaddxBindingConstants.KEYPAD_KEY_PRESSED)) { @@ -97,7 +111,7 @@ public void enterTerminalMode() { if (bridgeHandler == null) { return; } - bridgeHandler.sendCommand(cmd, data); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, data); } public void sendKeypadTextMessage(String displayLocation, String text) { @@ -114,6 +128,6 @@ public void sendKeypadTextMessage(String displayLocation, String text) { if (bridgeHandler == null) { return; } - bridgeHandler.sendCommand(cmd, data); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, data); } } diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPanel.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPanel.java index 3c3053f41843..4103b8fad47b 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPanel.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPanel.java @@ -21,6 +21,7 @@ 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.CaddxMessageContext; import org.openhab.binding.caddx.internal.CaddxMessageType; import org.openhab.binding.caddx.internal.CaddxProperty; import org.openhab.binding.caddx.internal.action.CaddxPanelActions; @@ -51,6 +52,20 @@ public ThingHandlerPanel(Thing thing) { super(thing, CaddxThingType.PANEL); } + @Override + public void initialize() { + super.initialize(); + + CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler(); + if (bridgeHandler == null) { + return; + } + + String cmd = CaddxBindingConstants.PANEL_SYSTEM_STATUS_REQUEST; + String data = ""; + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, data); + } + @Override public void updateChannel(ChannelUID channelUID, String data) { if (channelUID.getId().equals(CaddxBindingConstants.PANEL_FIRMWARE_VERSION) @@ -82,13 +97,13 @@ public void handleCommand(ChannelUID channelUID, Command command) { data = ""; } else if (System.currentTimeMillis() - lastRefreshTime > 2000) { // Refresh only if 2 seconds have passed from the last refresh - cmd = CaddxBindingConstants.PANEL_INTERFACE_CONFIGURATION_REQUEST; + cmd = CaddxBindingConstants.PANEL_SYSTEM_STATUS_REQUEST; data = ""; } else { return; } - bridgeHandler.sendCommand(cmd, data); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, data); lastRefreshTime = System.currentTimeMillis(); } else { logger.debug("Unknown command {}", command); @@ -104,19 +119,22 @@ public void caddxEventReceived(CaddxEvent event, Thing thing) { 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); + logger.trace("Updating panel channel: {}", channelUID.getAsString()); + } + } + // 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); - } - } + } else if (CaddxMessageType.ZONES_SNAPSHOT_MESSAGE.equals(mt)) { + handleZonesSnapshotMessage(message); } updateStatus(ThingStatus.ONLINE); @@ -140,7 +158,7 @@ private void handleSystemStatusMessage(CaddxMessage message) { // build map of log message channels to event numbers HashMap map = new HashMap(); map.put(pointer, CaddxBindingConstants.PANEL_LOG_MESSAGE_N_0); - bridgeHandler.sendCommand(CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, pointer); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, pointer); panelLogMessagesMap = map; } @@ -190,7 +208,8 @@ private void handleLogEventMessage(CaddxMessage message) { } map.put(Integer.toString(eventNumber), "panel_log_message_n_" + i); - bridgeHandler.sendCommand(CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, Integer.toString(eventNumber)); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, + Integer.toString(eventNumber)); } communicatorStackPointer = null; @@ -198,6 +217,45 @@ private void handleLogEventMessage(CaddxMessage message) { } } + private void handleZonesSnapshotMessage(CaddxMessage message) { + // Get the bridge handler + CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler(); + if (bridgeHandler == null) { + return; + } + + int zoneOffset = Integer.parseInt(message.getPropertyById("zone_offset")); + + for (int i = 1; i <= 16; i++) { + int zoneNumber = zoneOffset * 16 + i; + + String zoneFaulted = message.getPropertyById("zone_" + i + "_faulted"); + String zoneBypassed = message.getPropertyById("zone_" + i + "_bypassed"); + String zoneTrouble = message.getPropertyById("zone_" + i + "_trouble"); + String zoneAlarmMemory = message.getPropertyById("zone_" + i + "_alarm_memory"); + + logger.debug("Flags for zone {}. faulted:{}, bypassed:{}, trouble:{}, alarm_memory:{}", zoneNumber, + zoneFaulted, zoneBypassed, zoneTrouble, zoneAlarmMemory); + + // Get thing + Thing thing = bridgeHandler.findThing(CaddxThingType.ZONE, null, zoneNumber, null); + if (thing != null) { + ChannelUID channelUID; + + logger.debug("Thing found for zone {}.", zoneNumber); + + channelUID = new ChannelUID(thing.getUID(), "zone_faulted"); + updateChannel(channelUID, zoneFaulted); + channelUID = new ChannelUID(thing.getUID(), "zone_bypassed"); + updateChannel(channelUID, zoneBypassed); + channelUID = new ChannelUID(thing.getUID(), "zone_trouble"); + updateChannel(channelUID, zoneTrouble); + channelUID = new ChannelUID(thing.getUID(), "zone_alarm_memory"); + updateChannel(channelUID, zoneAlarmMemory); + } + } + } + @Override public Collection> getServices() { return Collections.singleton(CaddxPanelActions.class); @@ -216,7 +274,7 @@ private void sendPrimaryCommand(String pin, String function) { if (bridgeHandler == null) { return; } - bridgeHandler.sendCommand(cmd, sb.toString()); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, sb.toString()); } private void sendSecondaryCommand(String function) { @@ -230,7 +288,7 @@ private void sendSecondaryCommand(String function) { if (bridgeHandler == null) { return; } - bridgeHandler.sendCommand(cmd, sb.toString()); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, sb.toString()); } public void turnOffAnySounderOrAlarm(String pin) { diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPartition.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPartition.java index b7ddffbede34..c308b5bd553b 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPartition.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPartition.java @@ -19,6 +19,7 @@ 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.CaddxMessageContext; import org.openhab.binding.caddx.internal.CaddxMessageType; import org.openhab.binding.caddx.internal.CaddxProperty; import org.openhab.binding.caddx.internal.action.CaddxPartitionActions; @@ -48,6 +49,20 @@ public ThingHandlerPartition(Thing thing) { super(thing, CaddxThingType.PARTITION); } + @Override + public void initialize() { + super.initialize(); + + CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler(); + if (bridgeHandler == null) { + return; + } + + String cmd = CaddxBindingConstants.PARTITION_STATUS_REQUEST; + String data = String.format("%d", getPartitionNumber() - 1); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, data); + } + @Override public void updateChannel(ChannelUID channelUID, String data) { if (CaddxBindingConstants.PARTITION_SECONDARY_COMMAND.equals(channelUID.getId())) { @@ -87,7 +102,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { } if (!data.startsWith("-")) { - bridgeHandler.sendCommand(cmd, data); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, data); } } @@ -105,6 +120,7 @@ public void caddxEventReceived(CaddxEvent event, Thing thing) { String value = message.getPropertyById(p.getId()); channelUID = new ChannelUID(getThing().getUID(), p.getId()); updateChannel(channelUID, value); + logger.trace("Updating partition channel: {}", channelUID.getAsString()); } } @@ -135,7 +151,7 @@ private void sendPrimaryCommand(String pin, String function) { if (bridgeHandler == null) { return; } - bridgeHandler.sendCommand(cmd, sb.toString()); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, sb.toString()); } private void sendSecondaryCommand(String function) { @@ -149,7 +165,7 @@ private void sendSecondaryCommand(String function) { if (bridgeHandler == null) { return; } - bridgeHandler.sendCommand(cmd, sb.toString()); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, sb.toString()); } public void turnOffAnySounderOrAlarm(String pin) { diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerZone.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerZone.java index b8bff044e8f8..7200d320e4a1 100644 --- a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerZone.java +++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerZone.java @@ -19,6 +19,7 @@ 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.CaddxMessageContext; import org.openhab.binding.caddx.internal.CaddxMessageType; import org.openhab.binding.caddx.internal.CaddxProperty; import org.openhab.binding.caddx.internal.action.CaddxZoneActions; @@ -49,6 +50,23 @@ public ThingHandlerZone(Thing thing) { super(thing, CaddxThingType.ZONE); } + @Override + public void initialize() { + super.initialize(); + + CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler(); + if (bridgeHandler == null) { + return; + } + + String cmd1 = CaddxBindingConstants.ZONE_STATUS_REQUEST; + String cmd2 = CaddxBindingConstants.ZONE_NAME_REQUEST; + String data = String.format("%d", getZoneNumber() - 1); + + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd1, data); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd2, data); + } + @Override public void updateChannel(ChannelUID channelUID, String data) { if (channelUID.getId().equals(CaddxBindingConstants.ZONE_NAME)) { @@ -99,8 +117,8 @@ public void handleCommand(ChannelUID channelUID, Command command) { if (bridgeHandler == null) { return; } - bridgeHandler.sendCommand(cmd1, data); - bridgeHandler.sendCommand(cmd2, data); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd1, data); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd2, data); } @Override @@ -119,8 +137,7 @@ public void caddxEventReceived(CaddxEvent event, Thing thing) { String value = message.getPropertyById(p.getId()); channelUID = new ChannelUID(getThing().getUID(), p.getId()); updateChannel(channelUID, value); - - logger.trace(" updateChannel: {} = {}", channelUID, value); + logger.trace("Updating zone channel: {}", channelUID.getAsString()); } } } @@ -141,6 +158,6 @@ public void bypass() { if (bridgeHandler == null) { return; } - bridgeHandler.sendCommand(cmd, data); + bridgeHandler.sendCommand(CaddxMessageContext.COMMAND, cmd, data); } } diff --git a/bundles/org.openhab.binding.caddx/src/main/resources/OH-INF/thing/bridge.xml b/bundles/org.openhab.binding.caddx/src/main/resources/OH-INF/thing/bridge.xml index e0458b34ee57..663cb0b532a8 100644 --- a/bundles/org.openhab.binding.caddx/src/main/resources/OH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.caddx/src/main/resources/OH-INF/thing/bridge.xml @@ -60,6 +60,11 @@ 16 + + + Flag specifying if the Zone Status Transitions should be ignored + false + diff --git a/bundles/org.openhab.binding.caddx/src/main/resources/OH-INF/thing/panel.xml b/bundles/org.openhab.binding.caddx/src/main/resources/OH-INF/thing/panel.xml index 4cce0123e59a..7cf962634c9b 100644 --- a/bundles/org.openhab.binding.caddx/src/main/resources/OH-INF/thing/panel.xml +++ b/bundles/org.openhab.binding.caddx/src/main/resources/OH-INF/thing/panel.xml @@ -200,6 +200,20 @@ Zone Bypass Toggle + + + + AC fail + + + + AC Power On + + + + Low Battery Memory + + diff --git a/bundles/org.openhab.binding.caddx/src/test/java/org/openhab/binding/caddx/internal/CaddxMessageReaderUtil.java b/bundles/org.openhab.binding.caddx/src/test/java/org/openhab/binding/caddx/internal/CaddxMessageReaderUtil.java index 72f799c000ab..edf10de20a27 100644 --- a/bundles/org.openhab.binding.caddx/src/test/java/org/openhab/binding/caddx/internal/CaddxMessageReaderUtil.java +++ b/bundles/org.openhab.binding.caddx/src/test/java/org/openhab/binding/caddx/internal/CaddxMessageReaderUtil.java @@ -60,6 +60,6 @@ public static byte[] readRawMessage(String messageName) { */ public static CaddxMessage readCaddxMessage(String messageName) { byte[] bytes = readRawMessage(messageName); - return new CaddxMessage(bytes, true); + return new CaddxMessage(CaddxMessageContext.NONE, bytes, true); } } diff --git a/bundles/org.openhab.binding.caddx/src/test/java/org/openhab/binding/caddx/internal/message/CaddxMessageParseTest.java b/bundles/org.openhab.binding.caddx/src/test/java/org/openhab/binding/caddx/internal/message/CaddxMessageParseTest.java index 3eccc4e201a8..519b492f685a 100644 --- a/bundles/org.openhab.binding.caddx/src/test/java/org/openhab/binding/caddx/internal/message/CaddxMessageParseTest.java +++ b/bundles/org.openhab.binding.caddx/src/test/java/org/openhab/binding/caddx/internal/message/CaddxMessageParseTest.java @@ -34,10 +34,80 @@ public class CaddxMessageParseTest { // @formatter:off public static final List data() { return Arrays.asList(new Object[][] { - { "zone_status_message", "zone_number", "4", }, { "interface_configuration_message", "panel_firmware_version", "5.37", }, { "interface_configuration_message", "panel_interface_configuration_message", "true", }, + { "zone_status_message", "zone_number", "4", }, + { "zone_status_message", "zone_partition1", "true", }, + { "zone_status_message", "zone_partition2", "false", }, + { "zone_status_message", "zone_partition3", "false", }, + { "zone_status_message", "zone_partition4", "false", }, + { "zone_status_message", "zone_partition5", "false", }, + { "zone_status_message", "zone_partition6", "false", }, + { "zone_status_message", "zone_partition7", "false", }, + { "zone_status_message", "zone_partition8", "false", }, + { "zone_status_message", "zone_fire", "true", }, + { "zone_status_message", "zone_24hour", "false", }, + { "zone_status_message", "zone_key_switch", "false", }, + { "zone_status_message", "zone_follower", "false", }, + { "zone_status_message", "zone_entry_exit_delay_1", "false", }, + { "zone_status_message", "zone_entry_exit_delay_2", "false", }, + { "zone_status_message", "zone_interior", "false", }, + { "zone_status_message", "zone_local_only", "false", }, + { "zone_status_message", "zone_keypad_sounder", "true", }, + { "zone_status_message", "zone_yelping_siren", "false", }, + { "zone_status_message", "zone_steady_siren", "true", }, + { "zone_status_message", "zone_chime", "false", }, + { "zone_status_message", "zone_bypassable", "false", }, + { "zone_status_message", "zone_group_bypassable", "false", }, + { "zone_status_message", "zone_force_armable", "false", }, + { "zone_status_message", "zone_entry_guard", "false", }, + { "zone_status_message", "zone_fast_loop_response", "false", }, + { "zone_status_message", "zone_double_eol_tamper", "false", }, + { "zone_status_message", "zone_type_trouble", "true", }, + { "zone_status_message", "zone_cross_zone", "false", }, + { "zone_status_message", "zone_dialer_delay", "false", }, + { "zone_status_message", "zone_swinger_shutdown", "false", }, + { "zone_status_message", "zone_restorable", "true", }, + { "zone_status_message", "zone_listen_in", "true", }, + { "zone_status_message", "zone_faulted", "false", }, + { "zone_status_message", "zone_tampered", "false", }, + { "zone_status_message", "zone_trouble", "false", }, + { "zone_status_message", "zone_bypassed", "false", }, + { "zone_status_message", "zone_inhibited", "false", }, + { "zone_status_message", "zone_low_battery", "false", }, + { "zone_status_message", "zone_loss_of_supervision", "false", }, + { "zone_status_message", "zone_alarm_memory", "false", }, + { "zone_status_message", "zone_bypass_memory", "false", }, + + { "zones_snapshot_message", "zone_offset", "1", }, + { "zones_snapshot_message", "zone_1_faulted", "false", }, + { "zones_snapshot_message", "zone_1_bypassed", "false", }, + { "zones_snapshot_message", "zone_1_trouble", "false", }, + { "zones_snapshot_message", "zone_1_alarm_memory", "false", }, + { "zones_snapshot_message", "zone_2_faulted", "false", }, + { "zones_snapshot_message", "zone_2_bypassed", "false", }, + { "zones_snapshot_message", "zone_2_trouble", "false", }, + { "zones_snapshot_message", "zone_2_alarm_memory", "false", }, + { "zones_snapshot_message", "zone_3_faulted", "false", }, + { "zones_snapshot_message", "zone_3_bypassed", "false", }, + { "zones_snapshot_message", "zone_3_trouble", "false", }, + { "zones_snapshot_message", "zone_3_alarm_memory", "false", }, + { "zones_snapshot_message", "zone_4_faulted", "true", }, + { "zones_snapshot_message", "zone_4_bypassed", "false", }, + { "zones_snapshot_message", "zone_4_trouble", "false", }, + { "zones_snapshot_message", "zone_4_alarm_memory", "false", }, + { "zones_snapshot_message", "zone_5_faulted", "false", }, + { "zones_snapshot_message", "zone_6_faulted", "false", }, + { "zones_snapshot_message", "zone_7_faulted", "false", }, + { "zones_snapshot_message", "zone_8_faulted", "false", }, + { "zones_snapshot_message", "zone_9_faulted", "false", }, + { "zones_snapshot_message", "zone_10_faulted", "true", }, + { "zones_snapshot_message", "zone_11_faulted", "false", }, + { "zones_snapshot_message", "zone_12_faulted", "false", }, + { "zones_snapshot_message", "zone_13_faulted", "false", }, + { "zones_snapshot_message", "zone_14_faulted", "true", }, + }); } // @formatter:on diff --git a/bundles/org.openhab.binding.caddx/src/test/resources/org/openhab/binding/caddx/internal/zones_snapshot_message.msg b/bundles/org.openhab.binding.caddx/src/test/resources/org/openhab/binding/caddx/internal/zones_snapshot_message.msg new file mode 100644 index 000000000000..a8b041d486ee --- /dev/null +++ b/bundles/org.openhab.binding.caddx/src/test/resources/org/openhab/binding/caddx/internal/zones_snapshot_message.msg @@ -0,0 +1 @@ +85 01 00 10 00 00 10 00 10 00 C0 7F \ No newline at end of file