2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.caddx.internal.handler;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashMap;
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;
39 * This is a class for handling a Panel type Thing.
41 * @author Georgios Moutsos - Initial contribution
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;
50 public ThingHandlerPanel(Thing thing) {
51 super(thing, CaddxThingType.PANEL);
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));
60 // All Panel channels are OnOffType
63 onOffType = ("true".equals(data)) ? OnOffType.ON : OnOffType.OFF;
64 updateState(channelUID, onOffType);
69 public void handleCommand(ChannelUID channelUID, Command command) {
70 logger.trace("handleCommand(): Command Received - {} {}.", channelUID, command);
74 CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
75 if (bridgeHandler == null) {
79 if (command instanceof RefreshType) {
80 if (CaddxBindingConstants.PANEL_LOG_MESSAGE_N_0.equals(channelUID.getId())) {
81 cmd = CaddxBindingConstants.PANEL_SYSTEM_STATUS_REQUEST;
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;
91 bridgeHandler.sendCommand(cmd, data);
92 lastRefreshTime = System.currentTimeMillis();
94 logger.debug("Unknown command {}", command);
99 public void caddxEventReceived(CaddxEvent event, Thing thing) {
100 logger.trace("caddxEventReceived(): Event Received - {}.", event);
102 if (getThing().equals(thing)) {
103 CaddxMessage message = event.getCaddxMessage();
104 CaddxMessageType mt = message.getCaddxMessageType();
105 ChannelUID channelUID = null;
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);
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);
122 updateStatus(ThingStatus.ONLINE);
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
130 private void handleSystemStatusMessage(CaddxMessage message) {
131 // Get the bridge handler
132 CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
133 if (bridgeHandler == null) {
137 String pointer = message.getPropertyById("panel_communicator_stack_pointer");
138 communicatorStackPointer = pointer;
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;
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
153 private void handleLogEventMessage(CaddxMessage message) {
154 // Get the bridge handler
155 CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
156 if (bridgeHandler == null) {
160 String eventNumberString = message.getPropertyById("panel_log_event_number");
161 String eventSizeString = message.getPropertyById("panel_log_event_size");
164 LogEventMessage logEventMessage = new LogEventMessage(message);
166 logger.trace("Log_event: {}", logEventMessage);
168 // get the channel id from the map
169 HashMap<String, String> logMap = panelLogMessagesMap;
170 String id = logMap.get(eventNumberString);
171 if (logMap != null && id != null) {
172 ChannelUID channelUID = new ChannelUID(getThing().getUID(), id);
173 updateChannel(channelUID, logEventMessage.toString());
176 if (communicatorStackPointer != null && eventNumberString.equals(communicatorStackPointer)) {
177 HashMap<String, String> map = new HashMap<String, String>();
179 int eventNumber = Integer.parseInt(eventNumberString);
180 int eventSize = Integer.parseInt(eventSizeString);
182 // Retrieve at maximum the 10 last log messages from the panel
183 int messagesToRetrieve = Math.min(eventSize, 10);
184 for (int i = 1; i < messagesToRetrieve; i++) {
186 if (eventNumber < 0) {
187 eventNumber = eventSize;
190 map.put(Integer.toString(eventNumber), "panel_log_message_n_" + i);
191 bridgeHandler.sendCommand(CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, Integer.toString(eventNumber));
194 communicatorStackPointer = null;
195 panelLogMessagesMap = map;
200 public Collection<Class<? extends ThingHandlerService>> getServices() {
201 return Collections.singleton(CaddxPanelActions.class);
204 private void sendPrimaryCommand(String pin, String function) {
205 String cmd = CaddxBindingConstants.PARTITION_PRIMARY_COMMAND_WITH_PIN;
208 StringBuilder sb = new StringBuilder();
209 sb.append("0x").append(pin.charAt(1)).append(pin.charAt(0)).append(",0x").append(pin.charAt(3))
210 .append(pin.charAt(2)).append(",0x").append(pin.charAt(5)).append(pin.charAt(4)).append(",")
211 .append(function).append(",").append("255");
213 CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
214 if (bridgeHandler == null) {
217 bridgeHandler.sendCommand(cmd, sb.toString());
220 private void sendSecondaryCommand(String function) {
221 String cmd = CaddxBindingConstants.PARTITION_SECONDARY_COMMAND;
224 StringBuilder sb = new StringBuilder();
225 sb.append(function).append(",").append("255");
227 CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
228 if (bridgeHandler == null) {
231 bridgeHandler.sendCommand(cmd, sb.toString());
234 public void turnOffAnySounderOrAlarm(String pin) {
235 sendPrimaryCommand(pin, "0");
238 public void disarm(String pin) {
239 sendPrimaryCommand(pin, "1");
242 public void armInAwayMode(String pin) {
243 sendPrimaryCommand(pin, "2");
246 public void armInStayMode(String pin) {
247 sendPrimaryCommand(pin, "3");
250 public void cancel(String pin) {
251 sendPrimaryCommand(pin, "4");
254 public void initiateAutoArm(String pin) {
255 sendPrimaryCommand(pin, "5");
258 public void startWalkTestMode(String pin) {
259 sendPrimaryCommand(pin, "6");
262 public void stopWalkTestMode(String pin) {
263 sendPrimaryCommand(pin, "7");
267 sendSecondaryCommand("0");
270 public void chime() {
271 sendSecondaryCommand("1");
275 sendSecondaryCommand("2");
278 public void bypassInteriors() {
279 sendSecondaryCommand("3");
282 public void firePanic() {
283 sendSecondaryCommand("4");
286 public void medicalPanic() {
287 sendSecondaryCommand("5");
290 public void policePanic() {
291 sendSecondaryCommand("6");
294 public void smokeDetectorReset() {
295 sendSecondaryCommand("7");
298 public void autoCallbackDownload() {
299 sendSecondaryCommand("8");
302 public void manualPickupDownload() {
303 sendSecondaryCommand("9");
306 public void enableSilentExit() {
307 sendSecondaryCommand("10");
310 public void performTest() {
311 sendSecondaryCommand("11");
314 public void groupBypass() {
315 sendSecondaryCommand("12");
318 public void auxiliaryFunction1() {
319 sendSecondaryCommand("13");
322 public void auxiliaryFunction2() {
323 sendSecondaryCommand("14");
326 public void startKeypadSounder() {
327 sendSecondaryCommand("15");