2 * Copyright (c) 2010-2021 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.debug("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 if (logMap != null) {
171 String id = logMap.get(eventNumberString);
173 ChannelUID channelUID = new ChannelUID(getThing().getUID(), id);
174 updateChannel(channelUID, logEventMessage.toString());
178 if (communicatorStackPointer != null && eventNumberString.equals(communicatorStackPointer)) {
179 HashMap<String, String> map = new HashMap<String, String>();
181 int eventNumber = Integer.parseInt(eventNumberString);
182 int eventSize = Integer.parseInt(eventSizeString);
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++) {
188 if (eventNumber < 0) {
189 eventNumber = eventSize;
192 map.put(Integer.toString(eventNumber), "panel_log_message_n_" + i);
193 bridgeHandler.sendCommand(CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, Integer.toString(eventNumber));
196 communicatorStackPointer = null;
197 panelLogMessagesMap = map;
202 public Collection<Class<? extends ThingHandlerService>> getServices() {
203 return Collections.singleton(CaddxPanelActions.class);
206 private void sendPrimaryCommand(String pin, String function) {
207 String cmd = CaddxBindingConstants.PARTITION_PRIMARY_COMMAND_WITH_PIN;
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");
215 CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
216 if (bridgeHandler == null) {
219 bridgeHandler.sendCommand(cmd, sb.toString());
222 private void sendSecondaryCommand(String function) {
223 String cmd = CaddxBindingConstants.PARTITION_SECONDARY_COMMAND;
226 StringBuilder sb = new StringBuilder();
227 sb.append(function).append(",").append("255");
229 CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
230 if (bridgeHandler == null) {
233 bridgeHandler.sendCommand(cmd, sb.toString());
236 public void turnOffAnySounderOrAlarm(String pin) {
237 sendPrimaryCommand(pin, "0");
240 public void disarm(String pin) {
241 sendPrimaryCommand(pin, "1");
244 public void armInAwayMode(String pin) {
245 sendPrimaryCommand(pin, "2");
248 public void armInStayMode(String pin) {
249 sendPrimaryCommand(pin, "3");
252 public void cancel(String pin) {
253 sendPrimaryCommand(pin, "4");
256 public void initiateAutoArm(String pin) {
257 sendPrimaryCommand(pin, "5");
260 public void startWalkTestMode(String pin) {
261 sendPrimaryCommand(pin, "6");
264 public void stopWalkTestMode(String pin) {
265 sendPrimaryCommand(pin, "7");
269 sendSecondaryCommand("0");
272 public void chime() {
273 sendSecondaryCommand("1");
277 sendSecondaryCommand("2");
280 public void bypassInteriors() {
281 sendSecondaryCommand("3");
284 public void firePanic() {
285 sendSecondaryCommand("4");
288 public void medicalPanic() {
289 sendSecondaryCommand("5");
292 public void policePanic() {
293 sendSecondaryCommand("6");
296 public void smokeDetectorReset() {
297 sendSecondaryCommand("7");
300 public void autoCallbackDownload() {
301 sendSecondaryCommand("8");
304 public void manualPickupDownload() {
305 sendSecondaryCommand("9");
308 public void enableSilentExit() {
309 sendSecondaryCommand("10");
312 public void performTest() {
313 sendSecondaryCommand("11");
316 public void groupBypass() {
317 sendSecondaryCommand("12");
320 public void auxiliaryFunction1() {
321 sendSecondaryCommand("13");
324 public void auxiliaryFunction2() {
325 sendSecondaryCommand("14");
328 public void startKeypadSounder() {
329 sendSecondaryCommand("15");