diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxBridgeHandler.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxBridgeHandler.java index 978babc86..bb69478c3 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxBridgeHandler.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/handler/PowermaxBridgeHandler.java @@ -134,7 +134,7 @@ public class PowermaxBridgeHandler extends BaseBridgeHandler implements Powermax // Delay the startup in case the handler is restarted immediately globalJob = scheduler.scheduleWithFixedDelay(() -> { try { - logger.debug("Powermax job..."); + logger.trace("Powermax job..."); updateMotionSensorState(); if (isConnected()) { checkKeepAlive(); diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxAckMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxAckMessage.java index 7718f47b3..e51690d01 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxAckMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxAckMessage.java @@ -32,9 +32,7 @@ public class PowermaxAckMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxBaseMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxBaseMessage.java index 154348e5b..bc4df5d1d 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxBaseMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxBaseMessage.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.powermax.internal.message; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.powermax.internal.state.PowermaxState; import org.openhab.core.util.HexUtils; import org.slf4j.Logger; @@ -30,6 +31,7 @@ public class PowermaxBaseMessage { private int code; private PowermaxSendType sendType; private PowermaxReceiveType receiveType; + private Object messageType; /** * Constructor. @@ -38,6 +40,7 @@ public class PowermaxBaseMessage { */ public PowermaxBaseMessage(byte[] message) { this.sendType = null; + this.messageType = "UNKNOWN"; decodeMessage(message); } @@ -58,6 +61,7 @@ public class PowermaxBaseMessage { */ public PowermaxBaseMessage(PowermaxSendType sendType, byte[] param) { this.sendType = sendType; + this.messageType = "UNKNOWN"; byte[] message = new byte[sendType.getMessage().length + 3]; int index = 0; message[index++] = 0x0D; @@ -87,6 +91,8 @@ public class PowermaxBaseMessage { } catch (IllegalArgumentException e) { receiveType = null; } + + messageType = sendType != null ? sendType : receiveType != null ? receiveType : "UNKNOWN"; } /** @@ -94,17 +100,26 @@ public class PowermaxBaseMessage { * * @return a new state containing all changes driven by the message */ - public PowermaxState handleMessage(PowermaxCommManager commManager) { + public final PowermaxState handleMessage(PowermaxCommManager commManager) { // Send an ACK if needed if (isAckRequired() && commManager != null) { commManager.sendAck(this, (byte) 0x02); } if (logger.isDebugEnabled()) { - logger.debug("{}message handled by class {}: {}", (receiveType == null) ? "Unsupported " : "", - this.getClass().getSimpleName(), this); + logger.debug("{}message will be handled by class {}:", (receiveType == null) ? "Unsupported " : "", + this.getClass().getSimpleName()); + + debug("Raw data", rawData); + debug("Message type", code, messageType.toString()); } + PowermaxState newState = handleMessageInternal(commManager); + + return newState; + } + + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { return null; } @@ -147,17 +162,42 @@ public class PowermaxBaseMessage { return receiveType == null || receiveType.isAckRequired(); } - @Override - public String toString() { - String str = "\n - Raw data = " + HexUtils.bytesToHex(rawData); - str += "\n - type = " + String.format("%02X", code); - if (sendType != null) { - str += " ( " + sendType.toString() + " )"; - } else if (receiveType != null) { - str += " ( " + receiveType.toString() + " )"; + // Debugging helpers + + public void debug(String name, String info, @Nullable String decoded) { + if (!logger.isDebugEnabled()) { + return; } - return str; + String decodedStr = ""; + + if (decoded != null && !decoded.isBlank()) { + decodedStr = " - " + decoded; + } + + logger.debug("| {} = {}{}", name, info, decodedStr); + } + + public void debug(String name, String info) { + debug(name, info, null); + } + + public void debug(String name, byte[] data, @Nullable String decoded) { + String hex = "0x" + HexUtils.bytesToHex(data); + debug(name, hex, decoded); + } + + public void debug(String name, byte[] data) { + debug(name, data, null); + } + + public void debug(String name, int data, @Nullable String decoded) { + String hex = String.format("0x%02X", data); + debug(name, hex, decoded); + } + + public void debug(String name, int data) { + debug(name, data, null); } /** diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxCommManager.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxCommManager.java index 4fc57ff49..1e6a9da6b 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxCommManager.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxCommManager.java @@ -239,7 +239,8 @@ public class PowermaxCommManager implements PowermaxMessageEventListener { PowermaxBaseMessage message = messageEvent.getMessage(); if (logger.isDebugEnabled()) { - logger.debug("onNewMessageReceived(): received message {}", + logger.debug("onNewMessageReceived(): received message 0x{} ({})", + HexUtils.bytesToHex(message.getRawData()), (message.getReceiveType() != null) ? message.getReceiveType() : String.format("%02X", message.getCode())); } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDeniedMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDeniedMessage.java index ca1662dcc..1fd7bd7ed 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDeniedMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDeniedMessage.java @@ -36,9 +36,7 @@ public class PowermaxDeniedMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDownloadRetryMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDownloadRetryMessage.java index 417125cc7..4a6d828ad 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDownloadRetryMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxDownloadRetryMessage.java @@ -32,9 +32,7 @@ public class PowermaxDownloadRetryMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } @@ -42,20 +40,10 @@ public class PowermaxDownloadRetryMessage extends PowermaxBaseMessage { byte[] message = getRawData(); int waitTime = message[4] & 0x000000FF; + debug("Wait time", waitTime + " seconds"); + commManager.sendMessageLater(PowermaxSendType.DOWNLOAD, waitTime); return null; } - - @Override - public String toString() { - String str = super.toString(); - - byte[] message = getRawData(); - int waitTime = message[4] & 0x000000FF; - - str += "\n - wait time = " + waitTime + " seconds"; - - return str; - } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxEventLogMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxEventLogMessage.java index bd17cc91e..26b023c35 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxEventLogMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxEventLogMessage.java @@ -22,44 +22,6 @@ import org.openhab.binding.powermax.internal.state.PowermaxState; */ public class PowermaxEventLogMessage extends PowermaxBaseMessage { - public static final String[] LOG_EVENT_TABLE = new String[] { "None", "Interior Alarm", "Perimeter Alarm", - "Delay Alarm", "24h Silent Alarm", "24h Audible Alarm", "Tamper", "Control Panel Tamper", "Tamper Alarm", - "Tamper Alarm", "Communication Loss", "Panic From Keyfob", "Panic From Control Panel", "Duress", - "Confirm Alarm", "General Trouble", "General Trouble Restore", "Interior Restore", "Perimeter Restore", - "Delay Restore", "24h Silent Restore", "24h Audible Restore", "Tamper Restore", - "Control Panel Tamper Restore", "Tamper Restore", "Tamper Restore", "Communication Restore", "Cancel Alarm", - "General Restore", "Trouble Restore", "Not used", "Recent Close", "Fire", "Fire Restore", "No Active", - "Emergency", "No used", "Disarm Latchkey", "Panic Restore", "Supervision (Inactive)", - "Supervision Restore (Active)", "Low Battery", "Low Battery Restore", "AC Fail", "AC Restore", - "Control Panel Low Battery", "Control Panel Low Battery Restore", "RF Jamming", "RF Jamming Restore", - "Communications Failure", "Communications Restore", "Telephone Line Failure", "Telephone Line Restore", - "Auto Test", "Fuse Failure", "Fuse Restore", "Keyfob Low Battery", "Keyfob Low Battery Restore", - "Engineer Reset", "Battery Disconnect", "1-Way Keypad Low Battery", "1-Way Keypad Low Battery Restore", - "1-Way Keypad Inactive", "1-Way Keypad Restore Active", "Low Battery", "Clean Me", "Fire Trouble", - "Low Battery", "Battery Restore", "AC Fail", "AC Restore", "Supervision (Inactive)", - "Supervision Restore (Active)", "Gas Alert", "Gas Alert Restore", "Gas Trouble", "Gas Trouble Restore", - "Flood Alert", "Flood Alert Restore", "X-10 Trouble", "X-10 Trouble Restore", "Arm Home", "Arm Away", - "Quick Arm Home", "Quick Arm Away", "Disarm", "Fail To Auto-Arm", "Enter To Test Mode", - "Exit From Test Mode", "Force Arm", "Auto Arm", "Instant Arm", "Bypass", "Fail To Arm", "Door Open", - "Communication Established By Control Panel", "System Reset", "Installer Programming", "Wrong Password", - "Not Sys Event", "Not Sys Event", "Extreme Hot Alert", "Extreme Hot Alert Restore", "Freeze Alert", - "Freeze Alert Restore", "Human Cold Alert", "Human Cold Alert Restore", "Human Hot Alert", - "Human Hot Alert Restore", "Temperature Sensor Trouble", "Temperature Sensor Trouble Restore", - // new values partition models - "PIR Mask", "PIR Mask Restore", "", "", "", "", "", "", "", "", "", "", "Alarmed", "Restore", "Alarmed", - "Restore", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Exit Installer", "Enter Installer", - "", "", "", "", "" }; - - public static final String[] LOG_USER_TABLE = new String[] { "System", "Zone 1", "Zone 2", "Zone 3", "Zone 4", - "Zone 5", "Zone 6", "Zone 7", "Zone 8", "Zone 9", "Zone 10", "Zone 11", "Zone 12", "Zone 13", "Zone 14", - "Zone 15", "Zone 16", "Zone 17", "Zone 18", "Zone 19", "Zone 20", "Zone 21", "Zone 22", "Zone 23", - "Zone 24", "Zone 25", "Zone 26", "Zone 27", "Zone 28", "Zone 29", "Zone 30", "Fob 1", "Fob 2", "Fob 3", - "Fob 4", "Fob 5", "Fob 6", "Fob 7", "Fob 8", "User 1", "User 2", "User 3", "User 4", "User 5", "User 6", - "User 7", "User 8", "Pad 1", "Pad 2", "Pad 3", "Pad 4", "Pad 5", "Pad 6", "Pad 7", "Pad 8", "Siren 1", - "Siren 2", "2Pad 1", "2Pad 2", "2Pad 3", "2Pad 4", "X10 1", "X10 2", "X10 3", "X10 4", "X10 5", "X10 6", - "X10 7", "X10 8", "X10 9", "X10 10", "X10 11", "X10 12", "X10 13", "X10 14", "X10 15", "PGM", "GSM", - "P-LINK", "PTag 1", "PTag 2", "PTag 3", "PTag 4", "PTag 5", "PTag 6", "PTag 7", "PTag 8" }; - /** * Constructor * @@ -71,9 +33,7 @@ public class PowermaxEventLogMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } @@ -83,11 +43,14 @@ public class PowermaxEventLogMessage extends PowermaxBaseMessage { byte[] message = getRawData(); int eventNum = message[3] & 0x000000FF; - eventNum--; - if (eventNum == 0) { + debug("Event number", eventNum); + + if (eventNum == 1) { int eventCnt = message[2] & 0x000000FF; updatedState.setEventLogSize(eventCnt - 1); + + debug("Event count", eventCnt); } else { int second = message[4] & 0x000000FF; int minute = message[5] & 0x000000FF; @@ -95,14 +58,11 @@ public class PowermaxEventLogMessage extends PowermaxBaseMessage { int day = message[7] & 0x000000FF; int month = message[8] & 0x000000FF; int year = (message[9] & 0x000000FF) + 2000; + String timestamp = String.format("%02d/%02d/%04d %02d:%02d:%02d", day, month, year, hour, minute, second); byte eventZone = message[10]; byte logEvent = message[11]; - String logEventStr = ((logEvent & 0x000000FF) < LOG_EVENT_TABLE.length) - ? LOG_EVENT_TABLE[logEvent & 0x000000FF] - : "UNKNOWN"; - String logUserStr = ((eventZone & 0x000000FF) < LOG_USER_TABLE.length) - ? LOG_USER_TABLE[eventZone & 0x000000FF] - : "UNKNOWN"; + String logEventStr = PowermaxMessageConstants.getSystemEventString(logEvent & 0x000000FF); + String logUserStr = PowermaxMessageConstants.getZoneOrUserString(eventZone & 0x000000FF); String eventStr; if (panelSettings.getPanelType().getPartitions() > 1) { @@ -116,55 +76,18 @@ public class PowermaxEventLogMessage extends PowermaxBaseMessage { } else { part = "Panel"; } - eventStr = String.format("%02d/%02d/%04d %02d:%02d / %s: %s (%s)", day, month, year, hour, minute, part, - logEventStr, logUserStr); + eventStr = String.format("%s / %s: %s (%s)", timestamp, part, logEventStr, logUserStr); } else { - eventStr = String.format("%02d/%02d/%04d %02d:%02d:%02d: %s (%s)", day, month, year, hour, minute, - second, logEventStr, logUserStr); + eventStr = String.format("%s: %s (%s)", timestamp, logEventStr, logUserStr); } - updatedState.setEventLogSize(eventNum); - updatedState.setEventLog(eventNum, eventStr); + updatedState.setEventLogSize(eventNum - 1); + updatedState.setEventLog(eventNum - 1, eventStr); + + debug("Event " + eventNum + " date/time", timestamp); + debug("Event " + eventNum + " zone code", eventZone, logUserStr); + debug("Event " + eventNum + " event code", logEvent, logEventStr); } return updatedState; } - - @Override - public String toString() { - String str = super.toString(); - - byte[] message = getRawData(); - int eventNum = message[3] & 0x000000FF; - - str += "\n - event number = " + eventNum; - - if (eventNum == 1) { - int eventCnt = message[2] & 0x000000FF; - - str += "\n - event count = " + eventCnt; - } else { - int second = message[4] & 0x000000FF; - int minute = message[5] & 0x000000FF; - int hour = message[6] & 0x000000FF; - int day = message[7] & 0x000000FF; - int month = message[8] & 0x000000FF; - int year = (message[9] & 0x000000FF) + 2000; - byte eventZone = message[10]; - byte logEvent = message[11]; - - String logEventStr = ((logEvent & 0x000000FF) < LOG_EVENT_TABLE.length) - ? LOG_EVENT_TABLE[logEvent & 0x000000FF] - : "UNKNOWN"; - String logUserStr = ((eventZone & 0x000000FF) < LOG_USER_TABLE.length) - ? LOG_USER_TABLE[eventZone & 0x000000FF] - : "UNKNOWN"; - - str += "\n - event " + eventNum + " date & time = " - + String.format("%02d/%02d/%04d %02d:%02d:%02d", day, month, year, hour, minute, second); - str += "\n - event " + eventNum + " zone code = " + String.format("%08X - %s", eventZone, logUserStr); - str += "\n - event " + eventNum + " event code = " + String.format("%08X - %s", logEvent, logEventStr); - } - - return str; - } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxInfoMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxInfoMessage.java index 2fb089d15..74f25d58f 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxInfoMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxInfoMessage.java @@ -37,9 +37,7 @@ public class PowermaxInfoMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } @@ -47,15 +45,20 @@ public class PowermaxInfoMessage extends PowermaxBaseMessage { PowermaxState updatedState = commManager.createNewState(); byte[] message = getRawData(); + byte panelTypeNr = message[7]; + String panelTypeStr; PowermaxPanelType panelType = null; try { - panelType = PowermaxPanelType.fromCode(message[7]); + panelType = PowermaxPanelType.fromCode(panelTypeNr); + panelTypeStr = panelType.toString(); } catch (IllegalArgumentException e) { - logger.debug("Powermax alarm binding: unknwon panel type for code {}", message[7] & 0x000000FF); panelType = null; + panelTypeStr = "UNKNOWN"; } + debug("Panel type", panelTypeNr, panelTypeStr); + logger.debug("Reading panel settings"); updatedState.setDownloadMode(true); commManager.sendMessage(PowermaxSendType.DL_PANELFW); @@ -70,16 +73,4 @@ public class PowermaxInfoMessage extends PowermaxBaseMessage { return updatedState; } - - @Override - public String toString() { - String str = super.toString(); - - byte[] message = getRawData(); - byte panelTypeNr = message[7]; - - str += "\n - panel type number = " + String.format("%02X", panelTypeNr); - - return str; - } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageConstants.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageConstants.java new file mode 100644 index 000000000..f4209c9fa --- /dev/null +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxMessageConstants.java @@ -0,0 +1,102 @@ +/** + * 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.powermax.internal.message; + +/** + * Constants used in Powermax messages + * + * @author Ron Isaacson - Initial contribution + */ +public class PowermaxMessageConstants { + + private PowermaxMessageConstants() { + } + + private static String getValue(String[] table, int index) { + return (((index >= 0) && (index < table.length)) ? table[index] : "UNKNOWN"); + } + + /** + * System event lookup + */ + public static String getSystemEventString(int code) { + return getValue(SYSTEM_EVENT_TABLE, code); + } + + private static final String[] SYSTEM_EVENT_TABLE = new String[] { "None", "Interior Alarm", "Perimeter Alarm", + "Delay Alarm", "24h Silent Alarm", "24h Audible Alarm", "Tamper", "Control Panel Tamper", "Tamper Alarm", + "Tamper Alarm", "Communication Loss", "Panic From Keyfob", "Panic From Control Panel", "Duress", + "Confirm Alarm", "General Trouble", "General Trouble Restore", "Interior Restore", "Perimeter Restore", + "Delay Restore", "24h Silent Restore", "24h Audible Restore", "Tamper Restore", + "Control Panel Tamper Restore", "Tamper Restore", "Tamper Restore", "Communication Restore", "Cancel Alarm", + "General Restore", "Trouble Restore", "Not used", "Recent Close", "Fire", "Fire Restore", "No Active", + "Emergency", "No used", "Disarm Latchkey", "Panic Restore", "Supervision (Inactive)", + "Supervision Restore (Active)", "Low Battery", "Low Battery Restore", "AC Fail", "AC Restore", + "Control Panel Low Battery", "Control Panel Low Battery Restore", "RF Jamming", "RF Jamming Restore", + "Communications Failure", "Communications Restore", "Telephone Line Failure", "Telephone Line Restore", + "Auto Test", "Fuse Failure", "Fuse Restore", "Keyfob Low Battery", "Keyfob Low Battery Restore", + "Engineer Reset", "Battery Disconnect", "1-Way Keypad Low Battery", "1-Way Keypad Low Battery Restore", + "1-Way Keypad Inactive", "1-Way Keypad Restore Active", "Low Battery", "Clean Me", "Fire Trouble", + "Low Battery", "Battery Restore", "AC Fail", "AC Restore", "Supervision (Inactive)", + "Supervision Restore (Active)", "Gas Alert", "Gas Alert Restore", "Gas Trouble", "Gas Trouble Restore", + "Flood Alert", "Flood Alert Restore", "X-10 Trouble", "X-10 Trouble Restore", "Arm Home", "Arm Away", + "Quick Arm Home", "Quick Arm Away", "Disarm", "Fail To Auto-Arm", "Enter To Test Mode", + "Exit From Test Mode", "Force Arm", "Auto Arm", "Instant Arm", "Bypass", "Fail To Arm", "Door Open", + "Communication Established By Control Panel", "System Reset", "Installer Programming", "Wrong Password", + "Not Sys Event", "Not Sys Event", "Extreme Hot Alert", "Extreme Hot Alert Restore", "Freeze Alert", + "Freeze Alert Restore", "Human Cold Alert", "Human Cold Alert Restore", "Human Hot Alert", + "Human Hot Alert Restore", "Temperature Sensor Trouble", "Temperature Sensor Trouble Restore", + // new values partition models + "PIR Mask", "PIR Mask Restore", "", "", "", "", "", "", "", "", "", "", "Alarmed", "Restore", "Alarmed", + "Restore", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Exit Installer", "Enter Installer", + "", "", "", "", "" }; + + /** + * Zone/User lookup + */ + public static String getZoneOrUserString(int code) { + return getValue(ZONE_OR_USER_TABLE, code); + } + + private static final String[] ZONE_OR_USER_TABLE = new String[] { "System", "Zone 1", "Zone 2", "Zone 3", "Zone 4", + "Zone 5", "Zone 6", "Zone 7", "Zone 8", "Zone 9", "Zone 10", "Zone 11", "Zone 12", "Zone 13", "Zone 14", + "Zone 15", "Zone 16", "Zone 17", "Zone 18", "Zone 19", "Zone 20", "Zone 21", "Zone 22", "Zone 23", + "Zone 24", "Zone 25", "Zone 26", "Zone 27", "Zone 28", "Zone 29", "Zone 30", "Fob 1", "Fob 2", "Fob 3", + "Fob 4", "Fob 5", "Fob 6", "Fob 7", "Fob 8", "User 1", "User 2", "User 3", "User 4", "User 5", "User 6", + "User 7", "User 8", "Pad 1", "Pad 2", "Pad 3", "Pad 4", "Pad 5", "Pad 6", "Pad 7", "Pad 8", "Siren 1", + "Siren 2", "2Pad 1", "2Pad 2", "2Pad 3", "2Pad 4", "X10 1", "X10 2", "X10 3", "X10 4", "X10 5", "X10 6", + "X10 7", "X10 8", "X10 9", "X10 10", "X10 11", "X10 12", "X10 13", "X10 14", "X10 15", "PGM", "GSM", + "P-LINK", "PTag 1", "PTag 2", "PTag 3", "PTag 4", "PTag 5", "PTag 6", "PTag 7", "PTag 8" }; + + /** + * Zone event lookup + */ + public static String getZoneEventString(int code) { + return getValue(ZONE_EVENT_TABLE, code); + } + + private static final String[] ZONE_EVENT_TABLE = new String[] { "None", "Tamper Alarm", "Tamper Restore", "Open", + "Closed", "Violated (Motion)", "Panic Alarm", "RF Jamming", "Tamper Open", "Communication Failure", + "Line Failure", "Fuse", "Not Active", "Low Battery", "AC Failure", "Fire Alarm", "Emergency", + "Siren Tamper", "Siren Tamper Restore", "Siren Low Battery", "Siren AC Fail" }; + + /** + * Message type lookup + */ + public static String getMessageTypeString(int code) { + return getValue(MESSAGE_TYPE_TABLE, code); + } + + private static final String[] MESSAGE_TYPE_TABLE = new String[] { "None", "Log Message", "Status Message", + "Tamper Message", "Zone Message", "Unknown", "Enroll/Bypass Message" }; +} diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPanelMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPanelMessage.java index 14d16208d..55dd0b4a4 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPanelMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPanelMessage.java @@ -32,9 +32,7 @@ public class PowermaxPanelMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } @@ -44,18 +42,19 @@ public class PowermaxPanelMessage extends PowermaxBaseMessage { byte[] message = getRawData(); int msgCnt = message[2] & 0x000000FF; + debug("Event count", msgCnt); + for (int i = 1; i <= msgCnt; i++) { byte eventZone = message[2 + 2 * i]; byte logEvent = message[3 + 2 * i]; int eventType = logEvent & 0x0000007F; - String logEventStr = (eventType < PowermaxEventLogMessage.LOG_EVENT_TABLE.length) - ? PowermaxEventLogMessage.LOG_EVENT_TABLE[eventType] - : "UNKNOWN"; - String logUserStr = ((eventZone & 0x000000FF) < PowermaxEventLogMessage.LOG_USER_TABLE.length) - ? PowermaxEventLogMessage.LOG_USER_TABLE[eventZone & 0x000000FF] - : "UNKNOWN"; + String logEventStr = PowermaxMessageConstants.getSystemEventString(eventType); + String logUserStr = PowermaxMessageConstants.getZoneOrUserString(eventZone & 0x000000FF); updatedState.setPanelStatus(logEventStr + " (" + logUserStr + ")"); + debug("Event " + i + " zone code", eventZone, logUserStr); + debug("Event " + i + " event code", eventType, logEventStr); + String alarmStatus; try { PowermaxAlarmType alarmType = PowermaxAlarmType.fromCode(eventType); @@ -82,23 +81,4 @@ public class PowermaxPanelMessage extends PowermaxBaseMessage { return updatedState; } - - @Override - public String toString() { - String str = super.toString(); - - byte[] message = getRawData(); - int msgCnt = message[2] & 0x000000FF; - - str += "\n - event count = " + msgCnt; - for (int i = 1; i <= msgCnt; i++) { - byte eventZone = message[2 + 2 * i]; - byte logEvent = message[3 + 2 * i]; - - str += "\n - event " + i + " zone code = " + String.format("%08X", eventZone); - str += "\n - event " + i + " event code = " + String.format("%08X", logEvent); - } - - return str; - } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerMasterMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerMasterMessage.java index d8b047d22..1545c7298 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerMasterMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerMasterMessage.java @@ -32,9 +32,7 @@ public class PowermaxPowerMasterMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } @@ -42,6 +40,11 @@ public class PowermaxPowerMasterMessage extends PowermaxBaseMessage { byte[] message = getRawData(); byte msgType = message[2]; byte subType = message[3]; + byte msgLen = message[4]; + + debug("Type", msgType); + debug("Subtype", subType); + debug("Message length", msgLen); if ((msgType == 0x03) && (subType == 0x39)) { commManager.sendMessage(PowermaxSendType.POWERMASTER_ZONE_STAT1); @@ -50,20 +53,4 @@ public class PowermaxPowerMasterMessage extends PowermaxBaseMessage { return null; } - - @Override - public String toString() { - String str = super.toString(); - - byte[] message = getRawData(); - byte msgType = message[2]; - byte subType = message[3]; - byte msgLen = message[4]; - - str += "\n - type = " + String.format("%02X", msgType); - str += "\n - subtype = " + String.format("%02X", subType); - str += "\n - msgLen = " + String.format("%02X", msgLen); - - return str; - } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerlinkMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerlinkMessage.java index f79f385d8..59bd9a9d2 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerlinkMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxPowerlinkMessage.java @@ -36,9 +36,7 @@ public class PowermaxPowerlinkMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } @@ -50,37 +48,31 @@ public class PowermaxPowerlinkMessage extends PowermaxBaseMessage { if (subType == 0x03) { // keep alive message + + debug("Subtype", subType, "Keep Alive"); + commManager.sendAck(this, (byte) 0x02); updatedState = commManager.createNewState(); updatedState.setLastKeepAlive(System.currentTimeMillis()); - } else if (subType == 0x0A && message[4] == 0x01) { - logger.debug("Powermax alarm binding: Enrolling Powerlink"); - commManager.enrollPowerlink(); - updatedState = commManager.createNewState(); - updatedState.setDownloadSetupRequired(true); + } else if (subType == 0x0A) { + byte enroll = message[4]; + + debug("Subtype", subType, "Enroll"); + debug("Enroll", enroll); + + if (enroll == 0x01) { + logger.debug("Powermax alarm binding: Enrolling Powerlink"); + commManager.enrollPowerlink(); + updatedState = commManager.createNewState(); + updatedState.setDownloadSetupRequired(true); + } else { + commManager.sendAck(this, (byte) 0x02); + } } else { + debug("Subtype", subType, "UNKNOWN"); commManager.sendAck(this, (byte) 0x02); } return updatedState; } - - @Override - public String toString() { - String str = super.toString(); - - byte[] message = getRawData(); - byte subType = message[2]; - - if (subType == 0x03) { - str += "\n - sub type = keep alive"; - } else if (subType == 0x0A) { - str += "\n - sub type = enroll"; - str += "\n - enroll = " + String.format("%02X", message[4]); - } else { - str += "\n - sub type = " + String.format("%02X", subType); - } - - return str; - } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSettingsMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSettingsMessage.java index ed36f04c8..3d85dc8bd 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSettingsMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxSettingsMessage.java @@ -38,9 +38,7 @@ public class PowermaxSettingsMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } @@ -52,6 +50,9 @@ public class PowermaxSettingsMessage extends PowermaxBaseMessage { int page = message[3] & 0x000000FF; int length = 0; + debug("Page", page, Integer.toString(page)); + debug("Index", index, Integer.toString(index)); + if (getReceiveType() == PowermaxReceiveType.SETTINGS) { length = message.length - 6; updatedState.setUpdateSettings(Arrays.copyOfRange(message, 2, 2 + 2 + length)); @@ -74,18 +75,4 @@ public class PowermaxSettingsMessage extends PowermaxBaseMessage { return updatedState; } - - @Override - public String toString() { - String str = super.toString(); - - byte[] message = getRawData(); - int index = message[2] & 0x000000FF; - int page = message[3] & 0x000000FF; - - str += "\n - page = " + String.format("%02X (%d)", page, page); - str += "\n - index = " + String.format("%02X (%d)", index, index); - - return str; - } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxStatusMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxStatusMessage.java index 9739152d2..009957b00 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxStatusMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxStatusMessage.java @@ -12,6 +12,10 @@ */ package org.openhab.binding.powermax.internal.message; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + import org.openhab.binding.powermax.internal.state.PowermaxArmMode; import org.openhab.binding.powermax.internal.state.PowermaxPanelSettings; import org.openhab.binding.powermax.internal.state.PowermaxState; @@ -24,10 +28,34 @@ import org.openhab.binding.powermax.internal.state.PowermaxZoneSettings; */ public class PowermaxStatusMessage extends PowermaxBaseMessage { - private static final String[] EVENT_TYPE_TABLE = new String[] { "None", "Tamper Alarm", "Tamper Restore", "Open", - "Closed", "Violated (Motion)", "Panic Alarm", "RF Jamming", "Tamper Open", "Communication Failure", - "Line Failure", "Fuse", "Not Active", "Low Battery", "AC Failure", "Fire Alarm", "Emergency", - "Siren Tamper", "Siren Tamper Restore", "Siren Low Battery", "Siren AC Fail" }; + private static byte[] zoneBytes(byte zones1, byte zones9, byte zones17, byte zones25) { + return new byte[] { zones25, zones17, zones9, zones1 }; + } + + private static boolean[] zoneBits(byte[] zoneBytes) { + boolean[] zones = new boolean[32]; + char[] binary = new BigInteger(zoneBytes).toString(2).toCharArray(); + int len = binary.length - 1; + + for (int i = len; i >= 0; i--) { + zones[len - i + 1] = (binary[i] == '1'); + } + + return zones; + } + + private static String zoneList(byte[] zoneBytes) { + boolean[] zones = zoneBits(zoneBytes); + List names = new ArrayList<>(); + + for (int i = 1; i < zones.length; i++) { + if (zones[i]) { + names.add(String.format("Zone %d", i)); + } + } + + return String.join(", ", names); + } /** * Constructor @@ -40,9 +68,7 @@ public class PowermaxStatusMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } @@ -52,17 +78,27 @@ public class PowermaxStatusMessage extends PowermaxBaseMessage { byte[] message = getRawData(); byte eventType = message[3]; + String eventTypeStr = PowermaxMessageConstants.getMessageTypeString(eventType & 0x000000FF); + + debug("Event type", eventType, eventTypeStr); if (eventType == 0x02) { - int zoneStatus = (message[4] & 0x000000FF) | ((message[5] << 8) & 0x0000FF00) - | ((message[6] << 16) & 0x00FF0000) | ((message[7] << 24) & 0xFF000000); - int batteryStatus = (message[8] & 0x000000FF) | ((message[9] << 8) & 0x0000FF00) - | ((message[10] << 16) & 0x00FF0000) | ((message[11] << 24) & 0xFF000000); + byte[] zoneStatusBytes = zoneBytes(message[4], message[5], message[6], message[7]); + byte[] batteryStatusBytes = zoneBytes(message[8], message[9], message[10], message[11]); + + boolean[] zoneStatus = zoneBits(zoneStatusBytes); + boolean[] batteryStatus = zoneBits(batteryStatusBytes); + + String zoneStatusStr = zoneList(zoneStatusBytes); + String batteryStatusStr = zoneList(batteryStatusBytes); for (int i = 1; i <= panelSettings.getNbZones(); i++) { - updatedState.setSensorTripped(i, ((zoneStatus >> (i - 1)) & 0x1) > 0); - updatedState.setSensorLowBattery(i, ((batteryStatus >> (i - 1)) & 0x1) > 0); + updatedState.setSensorTripped(i, zoneStatus[i]); + updatedState.setSensorLowBattery(i, batteryStatus[i]); } + + debug("Zone status", zoneStatusBytes, zoneStatusStr); + debug("Battery status", batteryStatusBytes, batteryStatusStr); } else if (eventType == 0x04) { byte sysStatus = message[4]; byte sysFlags = message[5]; @@ -70,9 +106,8 @@ public class PowermaxStatusMessage extends PowermaxBaseMessage { byte zoneEType = message[7]; int x10Status = (message[10] & 0x000000FF) | ((message[11] << 8) & 0x0000FF00); - String zoneETypeStr = ((zoneEType & 0x000000FF) < EVENT_TYPE_TABLE.length) - ? EVENT_TYPE_TABLE[zoneEType & 0x000000FF] - : "UNKNOWN"; + String eventZoneStr = PowermaxMessageConstants.getZoneOrUserString(eventZone & 0x000000FF); + String zoneETypeStr = PowermaxMessageConstants.getZoneEventString(zoneEType & 0x000000FF); if (zoneEType == 0x03) { updatedState.setSensorTripped(eventZone, Boolean.TRUE); @@ -155,6 +190,12 @@ public class PowermaxStatusMessage extends PowermaxBaseMessage { updatedState.setArmMode(statusStr); updatedState.setStatusStr(statusStr + ", " + sysStatusStr); + debug("System status", sysStatus, statusStr); + debug("System flags", sysFlags, sysStatusStr); + debug("Event zone", eventZone, eventZoneStr); + debug("Zone event type", zoneEType, zoneETypeStr); + debug("X10 status", x10Status); + for (int i = 1; i <= panelSettings.getNbZones(); i++) { PowermaxZoneSettings zone = panelSettings.getZoneSettings(i); if (zone != null) { @@ -171,56 +212,17 @@ public class PowermaxStatusMessage extends PowermaxBaseMessage { } } } else if (eventType == 0x06) { - int zoneBypass = (message[8] & 0x000000FF) | ((message[9] << 8) & 0x0000FF00) - | ((message[10] << 16) & 0x00FF0000) | ((message[11] << 24) & 0xFF000000); + byte[] zoneBypassBytes = zoneBytes(message[8], message[9], message[10], message[11]); + boolean[] zoneBypass = zoneBits(zoneBypassBytes); + String zoneBypassStr = zoneList(zoneBypassBytes); for (int i = 1; i <= panelSettings.getNbZones(); i++) { - updatedState.setSensorBypassed(i, ((zoneBypass >> (i - 1)) & 0x1) > 0); + updatedState.setSensorBypassed(i, zoneBypass[i]); } + + debug("Zone bypass", zoneBypassBytes, zoneBypassStr); } return updatedState; } - - @Override - public String toString() { - String str = super.toString(); - - byte[] message = getRawData(); - byte eventType = message[3]; - - str += "\n - event type = " + String.format("%02X", eventType); - if (eventType == 0x02) { - int zoneStatus = (message[4] & 0x000000FF) | ((message[5] << 8) & 0x0000FF00) - | ((message[6] << 16) & 0x00FF0000) | ((message[7] << 24) & 0xFF000000); - int batteryStatus = (message[8] & 0x000000FF) | ((message[9] << 8) & 0x0000FF00) - | ((message[10] << 16) & 0x00FF0000) | ((message[11] << 24) & 0xFF000000); - - str += "\n - zone status = " + String.format("%08X", zoneStatus); - str += "\n - battery status = " + String.format("%08X", batteryStatus); - } else if (eventType == 0x04) { - byte sysStatus = message[4]; - byte sysFlags = message[5]; - byte eventZone = message[6]; - byte zoneEType = message[7]; - int x10Status = (message[10] & 0x000000FF) | ((message[11] << 8) & 0x0000FF00); - - String zoneETypeStr = ((zoneEType & 0x000000FF) < EVENT_TYPE_TABLE.length) - ? EVENT_TYPE_TABLE[zoneEType & 0x000000FF] - : "UNKNOWN"; - - str += "\n - system status = " + String.format("%02X", sysStatus); - str += "\n - system flags = " + String.format("%02X", sysFlags); - str += "\n - event zone = " + eventZone; - str += String.format("\n - zone event type = %02X (%s)", zoneEType, zoneETypeStr); - str += "\n - X10 status = " + String.format("%04X", x10Status); - } else if (eventType == 0x06) { - int zoneBypass = (message[8] & 0x000000FF) | ((message[9] << 8) & 0x0000FF00) - | ((message[10] << 16) & 0x00FF0000) | ((message[11] << 24) & 0xFF000000); - - str += "\n - zone bypass = " + String.format("%08X", zoneBypass); - } - - return str; - } } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxTimeoutMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxTimeoutMessage.java index a3d6679e5..54d092a62 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxTimeoutMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxTimeoutMessage.java @@ -32,9 +32,7 @@ public class PowermaxTimeoutMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager != null) { commManager.sendMessage(PowermaxSendType.EXIT); } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesNameMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesNameMessage.java index 488eb6e4d..dbe454327 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesNameMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesNameMessage.java @@ -32,9 +32,7 @@ public class PowermaxZonesNameMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; } diff --git a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesTypeMessage.java b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesTypeMessage.java index 2d1358765..55378d434 100644 --- a/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesTypeMessage.java +++ b/bundles/org.openhab.binding.powermax/src/main/java/org/openhab/binding/powermax/internal/message/PowermaxZonesTypeMessage.java @@ -32,9 +32,7 @@ public class PowermaxZonesTypeMessage extends PowermaxBaseMessage { } @Override - public PowermaxState handleMessage(PowermaxCommManager commManager) { - super.handleMessage(commManager); - + protected PowermaxState handleMessageInternal(PowermaxCommManager commManager) { if (commManager == null) { return null; }