]> git.basschouten.com Git - openhab-addons.git/blob
9739152d210afcf9c2b492377c025c26b0719dca
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.powermax.internal.message;
14
15 import org.openhab.binding.powermax.internal.state.PowermaxArmMode;
16 import org.openhab.binding.powermax.internal.state.PowermaxPanelSettings;
17 import org.openhab.binding.powermax.internal.state.PowermaxState;
18 import org.openhab.binding.powermax.internal.state.PowermaxZoneSettings;
19
20 /**
21  * A class for STATUS message handling
22  *
23  * @author Laurent Garnier - Initial contribution
24  */
25 public class PowermaxStatusMessage extends PowermaxBaseMessage {
26
27     private static final String[] EVENT_TYPE_TABLE = new String[] { "None", "Tamper Alarm", "Tamper Restore", "Open",
28             "Closed", "Violated (Motion)", "Panic Alarm", "RF Jamming", "Tamper Open", "Communication Failure",
29             "Line Failure", "Fuse", "Not Active", "Low Battery", "AC Failure", "Fire Alarm", "Emergency",
30             "Siren Tamper", "Siren Tamper Restore", "Siren Low Battery", "Siren AC Fail" };
31
32     /**
33      * Constructor
34      *
35      * @param message
36      *            the received message as a buffer of bytes
37      */
38     public PowermaxStatusMessage(byte[] message) {
39         super(message);
40     }
41
42     @Override
43     public PowermaxState handleMessage(PowermaxCommManager commManager) {
44         super.handleMessage(commManager);
45
46         if (commManager == null) {
47             return null;
48         }
49
50         PowermaxPanelSettings panelSettings = commManager.getPanelSettings();
51         PowermaxState updatedState = commManager.createNewState();
52
53         byte[] message = getRawData();
54         byte eventType = message[3];
55
56         if (eventType == 0x02) {
57             int zoneStatus = (message[4] & 0x000000FF) | ((message[5] << 8) & 0x0000FF00)
58                     | ((message[6] << 16) & 0x00FF0000) | ((message[7] << 24) & 0xFF000000);
59             int batteryStatus = (message[8] & 0x000000FF) | ((message[9] << 8) & 0x0000FF00)
60                     | ((message[10] << 16) & 0x00FF0000) | ((message[11] << 24) & 0xFF000000);
61
62             for (int i = 1; i <= panelSettings.getNbZones(); i++) {
63                 updatedState.setSensorTripped(i, ((zoneStatus >> (i - 1)) & 0x1) > 0);
64                 updatedState.setSensorLowBattery(i, ((batteryStatus >> (i - 1)) & 0x1) > 0);
65             }
66         } else if (eventType == 0x04) {
67             byte sysStatus = message[4];
68             byte sysFlags = message[5];
69             byte eventZone = message[6];
70             byte zoneEType = message[7];
71             int x10Status = (message[10] & 0x000000FF) | ((message[11] << 8) & 0x0000FF00);
72
73             String zoneETypeStr = ((zoneEType & 0x000000FF) < EVENT_TYPE_TABLE.length)
74                     ? EVENT_TYPE_TABLE[zoneEType & 0x000000FF]
75                     : "UNKNOWN";
76
77             if (zoneEType == 0x03) {
78                 updatedState.setSensorTripped(eventZone, Boolean.TRUE);
79                 updatedState.setSensorLastTripped(eventZone, System.currentTimeMillis());
80             } else if (zoneEType == 0x04) {
81                 updatedState.setSensorTripped(eventZone, Boolean.FALSE);
82             } else if (zoneEType == 0x05) {
83                 PowermaxZoneSettings zone = panelSettings.getZoneSettings(eventZone);
84                 if ((zone != null) && zone.getSensorType().equalsIgnoreCase("unknown")) {
85                     zone.setSensorType("Motion");
86                 }
87                 updatedState.setSensorTripped(eventZone, Boolean.TRUE);
88                 updatedState.setSensorLastTripped(eventZone, System.currentTimeMillis());
89             }
90
91             // PGM & X10 devices
92             for (int i = 0; i < panelSettings.getNbPGMX10Devices(); i++) {
93                 updatedState.setPGMX10DeviceStatus(i, ((x10Status >> i) & 0x1) > 0);
94             }
95
96             String sysStatusStr = "";
97             if ((sysFlags & 0x1) == 1) {
98                 sysStatusStr = sysStatusStr + "Ready, ";
99                 updatedState.setReady(true);
100             } else {
101                 sysStatusStr = sysStatusStr + "Not ready, ";
102                 updatedState.setReady(false);
103             }
104             if (((sysFlags >> 1) & 0x1) == 1) {
105                 sysStatusStr = sysStatusStr + "Alert in memory, ";
106                 updatedState.setAlertInMemory(true);
107             } else {
108                 updatedState.setAlertInMemory(false);
109             }
110             if (((sysFlags >> 2) & 0x1) == 1) {
111                 sysStatusStr = sysStatusStr + "Trouble, ";
112                 updatedState.setTrouble(true);
113             } else {
114                 updatedState.setTrouble(false);
115             }
116             if (((sysFlags >> 3) & 0x1) == 1) {
117                 sysStatusStr = sysStatusStr + "Bypass on, ";
118                 updatedState.setBypass(true);
119             } else {
120                 updatedState.setBypass(false);
121                 for (int i = 1; i <= panelSettings.getNbZones(); i++) {
122                     updatedState.setSensorBypassed(i, false);
123                 }
124             }
125             if (((sysFlags >> 4) & 0x1) == 1) {
126                 sysStatusStr = sysStatusStr + "Last 10 seconds, ";
127             }
128             if (((sysFlags >> 5) & 0x1) == 1) {
129                 sysStatusStr = sysStatusStr + zoneETypeStr;
130                 if (eventZone == 0xFF) {
131                     sysStatusStr = sysStatusStr + " from Panel, ";
132                 } else if (eventZone > 0) {
133                     sysStatusStr = sysStatusStr + String.format(" in Zone %d, ", eventZone);
134                 } else {
135                     sysStatusStr = sysStatusStr + ", ";
136                 }
137             }
138             if (((sysFlags >> 6) & 0x1) == 1) {
139                 sysStatusStr = sysStatusStr + "Status changed, ";
140             }
141             if (((sysFlags >> 7) & 0x1) == 1) {
142                 sysStatusStr = sysStatusStr + "Alarm event, ";
143                 updatedState.setAlarmActive(true);
144             } else {
145                 updatedState.setAlarmActive(false);
146             }
147             sysStatusStr = sysStatusStr.substring(0, sysStatusStr.length() - 2);
148             String statusStr;
149             try {
150                 PowermaxArmMode armMode = PowermaxArmMode.fromCode(sysStatus & 0x000000FF);
151                 statusStr = armMode.getName();
152             } catch (IllegalArgumentException e) {
153                 statusStr = "UNKNOWN";
154             }
155             updatedState.setArmMode(statusStr);
156             updatedState.setStatusStr(statusStr + ", " + sysStatusStr);
157
158             for (int i = 1; i <= panelSettings.getNbZones(); i++) {
159                 PowermaxZoneSettings zone = panelSettings.getZoneSettings(i);
160                 if (zone != null) {
161                     // mode: armed or not: 4=armed home; 5=armed away
162                     int mode = sysStatus & 0x0000000F;
163                     // Zone is shown as armed if
164                     // the sensor type always triggers an alarm
165                     // or the system is armed away (mode = 5)
166                     // or the system is armed home (mode = 4) and the zone is not interior(-follow)
167                     boolean armed = (!zone.getType().equalsIgnoreCase("Non-Alarm") && (zone.isAlwaysInAlarm()
168                             || (mode == 0x5) || ((mode == 0x4) && !zone.getType().equalsIgnoreCase("Interior-Follow")
169                                     && !zone.getType().equalsIgnoreCase("Interior"))));
170                     updatedState.setSensorArmed(i, armed);
171                 }
172             }
173         } else if (eventType == 0x06) {
174             int zoneBypass = (message[8] & 0x000000FF) | ((message[9] << 8) & 0x0000FF00)
175                     | ((message[10] << 16) & 0x00FF0000) | ((message[11] << 24) & 0xFF000000);
176
177             for (int i = 1; i <= panelSettings.getNbZones(); i++) {
178                 updatedState.setSensorBypassed(i, ((zoneBypass >> (i - 1)) & 0x1) > 0);
179             }
180         }
181
182         return updatedState;
183     }
184
185     @Override
186     public String toString() {
187         String str = super.toString();
188
189         byte[] message = getRawData();
190         byte eventType = message[3];
191
192         str += "\n - event type = " + String.format("%02X", eventType);
193         if (eventType == 0x02) {
194             int zoneStatus = (message[4] & 0x000000FF) | ((message[5] << 8) & 0x0000FF00)
195                     | ((message[6] << 16) & 0x00FF0000) | ((message[7] << 24) & 0xFF000000);
196             int batteryStatus = (message[8] & 0x000000FF) | ((message[9] << 8) & 0x0000FF00)
197                     | ((message[10] << 16) & 0x00FF0000) | ((message[11] << 24) & 0xFF000000);
198
199             str += "\n - zone status = " + String.format("%08X", zoneStatus);
200             str += "\n - battery status = " + String.format("%08X", batteryStatus);
201         } else if (eventType == 0x04) {
202             byte sysStatus = message[4];
203             byte sysFlags = message[5];
204             byte eventZone = message[6];
205             byte zoneEType = message[7];
206             int x10Status = (message[10] & 0x000000FF) | ((message[11] << 8) & 0x0000FF00);
207
208             String zoneETypeStr = ((zoneEType & 0x000000FF) < EVENT_TYPE_TABLE.length)
209                     ? EVENT_TYPE_TABLE[zoneEType & 0x000000FF]
210                     : "UNKNOWN";
211
212             str += "\n - system status = " + String.format("%02X", sysStatus);
213             str += "\n - system flags = " + String.format("%02X", sysFlags);
214             str += "\n - event zone = " + eventZone;
215             str += String.format("\n - zone event type = %02X (%s)", zoneEType, zoneETypeStr);
216             str += "\n - X10 status = " + String.format("%04X", x10Status);
217         } else if (eventType == 0x06) {
218             int zoneBypass = (message[8] & 0x000000FF) | ((message[9] << 8) & 0x0000FF00)
219                     | ((message[10] << 16) & 0x00FF0000) | ((message[11] << 24) & 0xFF000000);
220
221             str += "\n - zone bypass = " + String.format("%08X", zoneBypass);
222         }
223
224         return str;
225     }
226 }