]> git.basschouten.com Git - openhab-addons.git/blob
3c3053f418437877b83a19e6f059e70b9dc4a582
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.caddx.internal.handler;
14
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashMap;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.caddx.internal.CaddxBindingConstants;
22 import org.openhab.binding.caddx.internal.CaddxEvent;
23 import org.openhab.binding.caddx.internal.CaddxMessage;
24 import org.openhab.binding.caddx.internal.CaddxMessageType;
25 import org.openhab.binding.caddx.internal.CaddxProperty;
26 import org.openhab.binding.caddx.internal.action.CaddxPanelActions;
27 import org.openhab.core.library.types.OnOffType;
28 import org.openhab.core.library.types.StringType;
29 import org.openhab.core.thing.ChannelUID;
30 import org.openhab.core.thing.Thing;
31 import org.openhab.core.thing.ThingStatus;
32 import org.openhab.core.thing.binding.ThingHandlerService;
33 import org.openhab.core.types.Command;
34 import org.openhab.core.types.RefreshType;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * This is a class for handling a Panel type Thing.
40  *
41  * @author Georgios Moutsos - Initial contribution
42  */
43 @NonNullByDefault
44 public class ThingHandlerPanel extends CaddxBaseThingHandler {
45     private final Logger logger = LoggerFactory.getLogger(ThingHandlerPanel.class);
46     private @Nullable HashMap<String, String> panelLogMessagesMap = null;
47     private @Nullable String communicatorStackPointer = null;
48     private long lastRefreshTime = 0;
49
50     public ThingHandlerPanel(Thing thing) {
51         super(thing, CaddxThingType.PANEL);
52     }
53
54     @Override
55     public void updateChannel(ChannelUID channelUID, String data) {
56         if (channelUID.getId().equals(CaddxBindingConstants.PANEL_FIRMWARE_VERSION)
57                 || channelUID.getId().startsWith("panel_log_message_")) {
58             updateState(channelUID, new StringType(data));
59         } else {
60             // All Panel channels are OnOffType
61             OnOffType onOffType;
62
63             onOffType = ("true".equals(data)) ? OnOffType.ON : OnOffType.OFF;
64             updateState(channelUID, onOffType);
65         }
66     }
67
68     @Override
69     public void handleCommand(ChannelUID channelUID, Command command) {
70         logger.debug("handleCommand(): Command Received - {} {}.", channelUID, command);
71
72         String cmd = null;
73         String data = null;
74         CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
75         if (bridgeHandler == null) {
76             return;
77         }
78
79         if (command instanceof RefreshType) {
80             if (CaddxBindingConstants.PANEL_LOG_MESSAGE_N_0.equals(channelUID.getId())) {
81                 cmd = CaddxBindingConstants.PANEL_SYSTEM_STATUS_REQUEST;
82                 data = "";
83             } else if (System.currentTimeMillis() - lastRefreshTime > 2000) {
84                 // Refresh only if 2 seconds have passed from the last refresh
85                 cmd = CaddxBindingConstants.PANEL_INTERFACE_CONFIGURATION_REQUEST;
86                 data = "";
87             } else {
88                 return;
89             }
90
91             bridgeHandler.sendCommand(cmd, data);
92             lastRefreshTime = System.currentTimeMillis();
93         } else {
94             logger.debug("Unknown command {}", command);
95         }
96     }
97
98     @Override
99     public void caddxEventReceived(CaddxEvent event, Thing thing) {
100         logger.trace("caddxEventReceived(): Event Received - {}.", event);
101
102         if (getThing().equals(thing)) {
103             CaddxMessage message = event.getCaddxMessage();
104             CaddxMessageType mt = message.getCaddxMessageType();
105             ChannelUID channelUID = null;
106
107             // Log event messages have special handling
108             if (CaddxMessageType.SYSTEM_STATUS_MESSAGE.equals(mt)) {
109                 handleSystemStatusMessage(message);
110             } else if (CaddxMessageType.LOG_EVENT_MESSAGE.equals(mt)) {
111                 handleLogEventMessage(message);
112             } else {
113                 for (CaddxProperty p : mt.properties) {
114                     if (!p.getId().isEmpty()) {
115                         String value = message.getPropertyById(p.getId());
116                         channelUID = new ChannelUID(getThing().getUID(), p.getId());
117                         updateChannel(channelUID, value);
118                     }
119                 }
120             }
121
122             updateStatus(ThingStatus.ONLINE);
123         }
124     }
125
126     /*
127      * Gets the pointer into the panel's log messages ring buffer
128      * and sends the command for the retrieval of the last event_message
129      */
130     private void handleSystemStatusMessage(CaddxMessage message) {
131         // Get the bridge handler
132         CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
133         if (bridgeHandler == null) {
134             return;
135         }
136
137         String pointer = message.getPropertyById("panel_communicator_stack_pointer");
138         communicatorStackPointer = pointer;
139
140         // build map of log message channels to event numbers
141         HashMap<String, String> map = new HashMap<String, String>();
142         map.put(pointer, CaddxBindingConstants.PANEL_LOG_MESSAGE_N_0);
143         bridgeHandler.sendCommand(CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, pointer);
144         panelLogMessagesMap = map;
145     }
146
147     /*
148      * This function handles the panel log messages.
149      * If the received event_number matches our communication stack pointer then this is the last panel message. The
150      * channel gets updated and the required log message requests are generated for the update of the other log message
151      * channels
152      */
153     private void handleLogEventMessage(CaddxMessage message) {
154         // Get the bridge handler
155         CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
156         if (bridgeHandler == null) {
157             return;
158         }
159
160         String eventNumberString = message.getPropertyById("panel_log_event_number");
161         String eventSizeString = message.getPropertyById("panel_log_event_size");
162
163         // build the message
164         LogEventMessage logEventMessage = new LogEventMessage(message);
165
166         logger.trace("Log_event: {}", logEventMessage);
167
168         // get the channel id from the map
169         HashMap<String, String> logMap = panelLogMessagesMap;
170         if (logMap != null) {
171             String id = logMap.get(eventNumberString);
172             if (id != null) {
173                 ChannelUID channelUID = new ChannelUID(getThing().getUID(), id);
174                 updateChannel(channelUID, logEventMessage.toString());
175             }
176         }
177
178         if (communicatorStackPointer != null && eventNumberString.equals(communicatorStackPointer)) {
179             HashMap<String, String> map = new HashMap<String, String>();
180
181             int eventNumber = Integer.parseInt(eventNumberString);
182             int eventSize = Integer.parseInt(eventSizeString);
183
184             // Retrieve at maximum the 10 last log messages from the panel
185             int messagesToRetrieve = Math.min(eventSize, 10);
186             for (int i = 1; i < messagesToRetrieve; i++) {
187                 eventNumber--;
188                 if (eventNumber < 0) {
189                     eventNumber = eventSize;
190                 }
191
192                 map.put(Integer.toString(eventNumber), "panel_log_message_n_" + i);
193                 bridgeHandler.sendCommand(CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, Integer.toString(eventNumber));
194             }
195
196             communicatorStackPointer = null;
197             panelLogMessagesMap = map;
198         }
199     }
200
201     @Override
202     public Collection<Class<? extends ThingHandlerService>> getServices() {
203         return Collections.singleton(CaddxPanelActions.class);
204     }
205
206     private void sendPrimaryCommand(String pin, String function) {
207         String cmd = CaddxBindingConstants.PARTITION_PRIMARY_COMMAND_WITH_PIN;
208
209         // Build the data
210         StringBuilder sb = new StringBuilder();
211         sb.append("0x").append(pin.charAt(1)).append(pin.charAt(0)).append(",0x").append(pin.charAt(3))
212                 .append(pin.charAt(2)).append(",0x").append(pin.charAt(5)).append(pin.charAt(4)).append(",")
213                 .append(function).append(",").append("255");
214
215         CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
216         if (bridgeHandler == null) {
217             return;
218         }
219         bridgeHandler.sendCommand(cmd, sb.toString());
220     }
221
222     private void sendSecondaryCommand(String function) {
223         String cmd = CaddxBindingConstants.PARTITION_SECONDARY_COMMAND;
224
225         // Build the data
226         StringBuilder sb = new StringBuilder();
227         sb.append(function).append(",").append("255");
228
229         CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
230         if (bridgeHandler == null) {
231             return;
232         }
233         bridgeHandler.sendCommand(cmd, sb.toString());
234     }
235
236     public void turnOffAnySounderOrAlarm(String pin) {
237         sendPrimaryCommand(pin, "0");
238     }
239
240     public void disarm(String pin) {
241         sendPrimaryCommand(pin, "1");
242     }
243
244     public void armInAwayMode(String pin) {
245         sendPrimaryCommand(pin, "2");
246     }
247
248     public void armInStayMode(String pin) {
249         sendPrimaryCommand(pin, "3");
250     }
251
252     public void cancel(String pin) {
253         sendPrimaryCommand(pin, "4");
254     }
255
256     public void initiateAutoArm(String pin) {
257         sendPrimaryCommand(pin, "5");
258     }
259
260     public void startWalkTestMode(String pin) {
261         sendPrimaryCommand(pin, "6");
262     }
263
264     public void stopWalkTestMode(String pin) {
265         sendPrimaryCommand(pin, "7");
266     }
267
268     public void stay() {
269         sendSecondaryCommand("0");
270     }
271
272     public void chime() {
273         sendSecondaryCommand("1");
274     }
275
276     public void exit() {
277         sendSecondaryCommand("2");
278     }
279
280     public void bypassInteriors() {
281         sendSecondaryCommand("3");
282     }
283
284     public void firePanic() {
285         sendSecondaryCommand("4");
286     }
287
288     public void medicalPanic() {
289         sendSecondaryCommand("5");
290     }
291
292     public void policePanic() {
293         sendSecondaryCommand("6");
294     }
295
296     public void smokeDetectorReset() {
297         sendSecondaryCommand("7");
298     }
299
300     public void autoCallbackDownload() {
301         sendSecondaryCommand("8");
302     }
303
304     public void manualPickupDownload() {
305         sendSecondaryCommand("9");
306     }
307
308     public void enableSilentExit() {
309         sendSecondaryCommand("10");
310     }
311
312     public void performTest() {
313         sendSecondaryCommand("11");
314     }
315
316     public void groupBypass() {
317         sendSecondaryCommand("12");
318     }
319
320     public void auxiliaryFunction1() {
321         sendSecondaryCommand("13");
322     }
323
324     public void auxiliaryFunction2() {
325         sendSecondaryCommand("14");
326     }
327
328     public void startKeypadSounder() {
329         sendSecondaryCommand("15");
330     }
331 }