2 * Copyright (c) 2010-2023 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.openwebnet.internal.handler;
15 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.*;
17 import java.util.HashSet;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants;
22 import org.openhab.core.library.types.OnOffType;
23 import org.openhab.core.library.types.StringType;
24 import org.openhab.core.thing.ChannelUID;
25 import org.openhab.core.thing.Thing;
26 import org.openhab.core.thing.ThingStatus;
27 import org.openhab.core.thing.ThingStatusDetail;
28 import org.openhab.core.thing.ThingTypeUID;
29 import org.openhab.core.types.Command;
30 import org.openwebnet4j.communication.OWNException;
31 import org.openwebnet4j.message.Alarm;
32 import org.openwebnet4j.message.Alarm.WhatAlarm;
33 import org.openwebnet4j.message.BaseOpenMessage;
34 import org.openwebnet4j.message.Where;
35 import org.openwebnet4j.message.WhereAlarm;
36 import org.openwebnet4j.message.Who;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
41 * The {@link OpenWebNetAlarmHandler} is responsible for handling
42 * commands/messages for Alarm system and zones. It extends the abstract
43 * {@link OpenWebNetThingHandler}.
45 * @author Massimo Valla - Initial contribution
48 public class OpenWebNetAlarmHandler extends OpenWebNetThingHandler {
50 private final Logger logger = LoggerFactory.getLogger(OpenWebNetAlarmHandler.class);
52 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.ALARM_SUPPORTED_THING_TYPES;
54 private static long lastAllDevicesRefreshTS = 0; // ts when last all device refresh was sent for this handler
56 private static Set<OpenWebNetAlarmHandler> zoneHandlers = new HashSet<OpenWebNetAlarmHandler>();
58 private static final String BATTERY_OK = "OK";
59 private static final String BATTERY_FAULT = "FAULT";
60 private static final String BATTERY_UNLOADED = "UNLOADED";
62 private static final String ALARM_INTRUSION = "INTRUSION";
63 private static final String ALARM_TAMPERING = "TAMPERING";
64 private static final String ALARM_ANTI_PANIC = "ANTI_PANIC";
65 private static final String ALARM_SILENT = "SILENT";
66 private static final String ALARM_TECHNICAL = "TECHNICAL";
67 private static final String ALARM_TECHNICAL_RESET = "TECHNICAL_RESET";
68 private static final String ALARM_NONE = "NONE";
70 public OpenWebNetAlarmHandler(Thing thing) {
75 public void initialize() {
77 if (OpenWebNetBindingConstants.THING_TYPE_BUS_ALARM_ZONE.equals(thing.getThingTypeUID())) {
78 zoneHandlers.add(this);
79 // initially set zone alarm to NONE (it will be set if specific alarm message is
81 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_NONE));
86 protected void handleChannelCommand(ChannelUID channel, Command command) {
87 logger.warn("Alarm.handleChannelCommand() Read only channel, unsupported command {}", command);
91 protected void requestChannelState(ChannelUID channel) {
92 super.requestChannelState(channel);
93 Where w = deviceWhere;
94 ThingTypeUID thingType = thing.getThingTypeUID();
96 if (THING_TYPE_BUS_ALARM_SYSTEM.equals(thingType)) {
97 send(Alarm.requestSystemStatus());
98 lastAllDevicesRefreshTS = System.currentTimeMillis();
101 send(Alarm.requestZoneStatus("#" + w.value()));
103 logger.debug("null where while requesting state for channel {}", channel);
106 } catch (OWNException e) {
107 logger.debug("Exception while requesting state for channel {}: {} ", channel, e.getMessage());
108 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
113 protected long getRefreshAllLastTS() {
114 return lastAllDevicesRefreshTS;
118 protected void refreshDevice(boolean refreshAll) {
120 logger.debug("--- refreshDevice() : refreshing all via ALARM CENTRAL UNIT... ({})", thing.getUID());
122 send(Alarm.requestSystemStatus());
123 lastAllDevicesRefreshTS = System.currentTimeMillis();
124 } catch (OWNException e) {
125 logger.warn("Excpetion while requesting alarm system status: {}", e.getMessage());
128 logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID());
129 requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_ALARM_SYSTEM_STATE));
134 protected void handleMessage(BaseOpenMessage msg) {
135 logger.debug("handleMessage({}) for: {} {}", msg, thing.getUID(), msg.getWhat());
136 super.handleMessage(msg);
137 ThingTypeUID thingType = thing.getThingTypeUID();
138 if (THING_TYPE_BUS_ALARM_SYSTEM.equals(thingType)) {
139 updateSystem((Alarm) msg);
141 updateZone((Alarm) msg);
145 private void updateSystem(Alarm msg) {
146 WhatAlarm w = (WhatAlarm) msg.getWhat();
148 logger.debug("Alarm.updateSystem() WHAT is null. Frame={}", msg);
153 case SYSTEM_INACTIVE:
154 case SYSTEM_MAINTENANCE:
155 updateAlarmSystemState(w);
157 case SYSTEM_DISENGAGED:
159 updateAlarmSystemArmed(w);
161 case SYSTEM_BATTERY_OK:
162 case SYSTEM_BATTERY_UNLOADED:
163 case SYSTEM_BATTERY_FAULT:
164 updateBatteryState(w);
166 case SYSTEM_NETWORK_ERROR:
167 case SYSTEM_NETWORK_OK:
168 updateNetworkState(w);
171 resetAllZonesAlarmState();
173 case START_PROGRAMMING:
174 case STOP_PROGRAMMING:
175 case NO_CONNECTION_TO_DEVICE:
177 logger.debug("Alarm.updateSystem() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
181 private void updateAlarmSystemState(WhatAlarm w) {
182 updateState(CHANNEL_ALARM_SYSTEM_STATE, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_ACTIVE));
185 private void updateAlarmSystemArmed(WhatAlarm w) {
186 updateState(CHANNEL_ALARM_SYSTEM_ARMED, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_ENGAGED));
189 private void updateNetworkState(WhatAlarm w) {
190 updateState(CHANNEL_ALARM_SYSTEM_NETWORK, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_NETWORK_OK));
193 private void updateBatteryState(WhatAlarm w) {
194 if (w == Alarm.WhatAlarm.SYSTEM_BATTERY_OK) {
195 updateState(CHANNEL_ALARM_SYSTEM_BATTERY, new StringType(BATTERY_OK));
196 } else if (w == Alarm.WhatAlarm.SYSTEM_BATTERY_UNLOADED) {
197 updateState(CHANNEL_ALARM_SYSTEM_BATTERY, new StringType(BATTERY_UNLOADED));
199 updateState(CHANNEL_ALARM_SYSTEM_BATTERY, new StringType(BATTERY_FAULT));
203 private void updateZone(Alarm msg) {
204 WhatAlarm w = (WhatAlarm) msg.getWhat();
206 logger.debug("Alarm.updateZone() WHAT is null. Frame={}", msg);
210 case ZONE_DISENGAGED:
214 case ZONE_ALARM_INTRUSION:
215 case ZONE_ALARM_TAMPERING:
216 case ZONE_ALARM_ANTI_PANIC:
217 case ZONE_ALARM_SILENT:
218 case ZONE_ALARM_TECHNICAL:
219 case ZONE_ALARM_TECHNICAL_RESET:
223 logger.debug("Alarm.updateZone() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
227 private void updateZoneState(WhatAlarm w) {
228 updateState(CHANNEL_ALARM_ZONE_STATE, OnOffType.from(w == Alarm.WhatAlarm.ZONE_ENGAGED));
231 private void updateZoneAlarm(WhatAlarm w) {
233 case ZONE_ALARM_INTRUSION:
234 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_INTRUSION));
236 case ZONE_ALARM_TAMPERING:
237 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_TAMPERING));
239 case ZONE_ALARM_ANTI_PANIC:
240 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_ANTI_PANIC));
242 case ZONE_ALARM_SILENT:
243 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_SILENT));
245 case ZONE_ALARM_TECHNICAL:
246 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_TECHNICAL));
248 case ZONE_ALARM_TECHNICAL_RESET:
249 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_TECHNICAL_RESET));
252 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_NONE));
253 logger.warn("Alarm.updateZoneAlarm() Ignoring unsupported WHAT {} for zone {}", w, this.deviceWhere);
257 private void resetAllZonesAlarmState() {
258 for (OpenWebNetAlarmHandler h : zoneHandlers) {
259 h.updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_NONE));
264 protected Where buildBusWhere(String wStr) throws IllegalArgumentException {
265 return new WhereAlarm(wStr);
269 protected String ownIdPrefix() {
270 return Who.BURGLAR_ALARM.value().toString();
274 public void dispose() {
275 if (OpenWebNetBindingConstants.THING_TYPE_BUS_ALARM_ZONE.equals(thing.getThingTypeUID())) {
276 zoneHandlers.remove(this);
277 logger.debug("Alarm.dispose() - removed zone {}", this.deviceWhere);