2 * Copyright (c) 2010-2024 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.DateTimeType;
23 import org.openhab.core.library.types.OnOffType;
24 import org.openhab.core.library.types.StringType;
25 import org.openhab.core.thing.ChannelUID;
26 import org.openhab.core.thing.Thing;
27 import org.openhab.core.thing.ThingStatus;
28 import org.openhab.core.thing.ThingStatusDetail;
29 import org.openhab.core.thing.ThingTypeUID;
30 import org.openhab.core.types.Command;
31 import org.openwebnet4j.communication.OWNException;
32 import org.openwebnet4j.message.Alarm;
33 import org.openwebnet4j.message.Alarm.WhatAlarm;
34 import org.openwebnet4j.message.BaseOpenMessage;
35 import org.openwebnet4j.message.Where;
36 import org.openwebnet4j.message.WhereAlarm;
37 import org.openwebnet4j.message.Who;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 * The {@link OpenWebNetAlarmHandler} is responsible for handling
43 * commands/messages for Alarm system and zones. It extends the abstract
44 * {@link OpenWebNetThingHandler}.
46 * @author Massimo Valla - Initial contribution
47 * @author Giovanni Fabiani - Add zone alarm's tismestamp feature
50 public class OpenWebNetAlarmHandler extends OpenWebNetThingHandler {
52 private final Logger logger = LoggerFactory.getLogger(OpenWebNetAlarmHandler.class);
54 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.ALARM_SUPPORTED_THING_TYPES;
56 private static long lastAllDevicesRefreshTS = 0; // ts when last all device refresh was sent for this handler
58 private static Set<OpenWebNetAlarmHandler> zoneHandlers = new HashSet<OpenWebNetAlarmHandler>();
60 private static final String BATTERY_OK = "OK";
61 private static final String BATTERY_FAULT = "FAULT";
62 private static final String BATTERY_UNLOADED = "UNLOADED";
64 private static final String ALARM_INTRUSION = "INTRUSION";
65 private static final String ALARM_TAMPERING = "TAMPERING";
66 private static final String ALARM_ANTI_PANIC = "ANTI_PANIC";
67 private static final String ALARM_SILENT = "SILENT";
68 private static final String ALARM_TECHNICAL = "TECHNICAL";
69 private static final String ALARM_TECHNICAL_RESET = "TECHNICAL_RESET";
70 private static final String ALARM_NONE = "NONE";
72 public OpenWebNetAlarmHandler(Thing thing) {
77 public void initialize() {
79 if (OpenWebNetBindingConstants.THING_TYPE_BUS_ALARM_ZONE.equals(thing.getThingTypeUID())) {
80 zoneHandlers.add(this);
81 // initially set zone alarm to NONE (it will be set if specific alarm message is
83 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_NONE));
84 // initializing timestamp
85 updateState(CHANNEL_ALARM_ZONE_ALARM_TIMESTAMP, new DateTimeType());
90 protected void handleChannelCommand(ChannelUID channel, Command command) {
91 logger.warn("Alarm.handleChannelCommand() Read only channel, unsupported command {}", command);
95 protected void requestChannelState(ChannelUID channel) {
96 super.requestChannelState(channel);
97 Where w = deviceWhere;
98 ThingTypeUID thingType = thing.getThingTypeUID();
100 if (THING_TYPE_BUS_ALARM_SYSTEM.equals(thingType)) {
101 send(Alarm.requestSystemStatus());
102 lastAllDevicesRefreshTS = System.currentTimeMillis();
105 send(Alarm.requestZoneStatus("#" + w.value()));
107 logger.debug("null where while requesting state for channel {}", channel);
110 } catch (OWNException e) {
111 logger.debug("Exception while requesting state for channel {}: {} ", channel, e.getMessage());
112 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
117 protected long getRefreshAllLastTS() {
118 return lastAllDevicesRefreshTS;
122 protected void refreshDevice(boolean refreshAll) {
124 logger.debug("--- refreshDevice() : refreshing all via ALARM CENTRAL UNIT... ({})", thing.getUID());
126 send(Alarm.requestSystemStatus());
127 lastAllDevicesRefreshTS = System.currentTimeMillis();
128 } catch (OWNException e) {
129 logger.warn("Exception while requesting alarm system status: {}", e.getMessage());
132 logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID());
133 requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_ALARM_SYSTEM_STATE));
138 protected void handleMessage(BaseOpenMessage msg) {
139 logger.debug("handleMessage({}) for: {} {}", msg, thing.getUID(), msg.getWhat());
140 super.handleMessage(msg);
141 ThingTypeUID thingType = thing.getThingTypeUID();
142 if (THING_TYPE_BUS_ALARM_SYSTEM.equals(thingType)) {
143 updateSystem((Alarm) msg);
145 updateZone((Alarm) msg);
149 private void updateSystem(Alarm msg) {
150 WhatAlarm w = (WhatAlarm) msg.getWhat();
152 logger.debug("Alarm.updateSystem() WHAT is null. Frame={}", msg);
157 case SYSTEM_INACTIVE:
158 case SYSTEM_MAINTENANCE:
159 updateAlarmSystemState(w);
161 case SYSTEM_DISENGAGED:
163 updateAlarmSystemArmed(w);
165 case SYSTEM_BATTERY_OK:
166 case SYSTEM_BATTERY_UNLOADED:
167 case SYSTEM_BATTERY_FAULT:
168 updateBatteryState(w);
170 case SYSTEM_NETWORK_ERROR:
171 case SYSTEM_NETWORK_OK:
172 updateNetworkState(w);
175 resetAllZonesAlarmState();
177 case START_PROGRAMMING:
178 case STOP_PROGRAMMING:
179 case NO_CONNECTION_TO_DEVICE:
181 logger.debug("Alarm.updateSystem() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
185 private void updateAlarmSystemState(WhatAlarm w) {
186 updateState(CHANNEL_ALARM_SYSTEM_STATE, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_ACTIVE));
189 private void updateAlarmSystemArmed(WhatAlarm w) {
190 updateState(CHANNEL_ALARM_SYSTEM_ARMED, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_ENGAGED));
193 private void updateNetworkState(WhatAlarm w) {
194 updateState(CHANNEL_ALARM_SYSTEM_NETWORK, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_NETWORK_OK));
197 private void updateBatteryState(WhatAlarm w) {
198 if (w == Alarm.WhatAlarm.SYSTEM_BATTERY_OK) {
199 updateState(CHANNEL_ALARM_SYSTEM_BATTERY, new StringType(BATTERY_OK));
200 } else if (w == Alarm.WhatAlarm.SYSTEM_BATTERY_UNLOADED) {
201 updateState(CHANNEL_ALARM_SYSTEM_BATTERY, new StringType(BATTERY_UNLOADED));
203 updateState(CHANNEL_ALARM_SYSTEM_BATTERY, new StringType(BATTERY_FAULT));
207 private void updateZone(Alarm msg) {
208 WhatAlarm w = (WhatAlarm) msg.getWhat();
210 logger.debug("Alarm.updateZone() WHAT is null. Frame={}", msg);
214 case ZONE_DISENGAGED:
218 case ZONE_ALARM_INTRUSION:
219 case ZONE_ALARM_TAMPERING:
220 case ZONE_ALARM_ANTI_PANIC:
221 case ZONE_ALARM_SILENT:
222 case ZONE_ALARM_TECHNICAL:
223 case ZONE_ALARM_TECHNICAL_RESET:
225 updateState(CHANNEL_ALARM_ZONE_ALARM_TIMESTAMP, new DateTimeType());
228 logger.debug("Alarm.updateZone() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
232 private void updateZoneState(WhatAlarm w) {
233 updateState(CHANNEL_ALARM_ZONE_STATE, OnOffType.from(w == Alarm.WhatAlarm.ZONE_ENGAGED));
236 private void updateZoneAlarm(WhatAlarm w) {
238 case ZONE_ALARM_INTRUSION:
239 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_INTRUSION));
241 case ZONE_ALARM_TAMPERING:
242 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_TAMPERING));
244 case ZONE_ALARM_ANTI_PANIC:
245 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_ANTI_PANIC));
247 case ZONE_ALARM_SILENT:
248 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_SILENT));
250 case ZONE_ALARM_TECHNICAL:
251 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_TECHNICAL));
253 case ZONE_ALARM_TECHNICAL_RESET:
254 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_TECHNICAL_RESET));
257 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_NONE));
258 logger.warn("Alarm.updateZoneAlarm() Ignoring unsupported WHAT {} for zone {}", w, this.deviceWhere);
262 private void resetAllZonesAlarmState() {
263 for (OpenWebNetAlarmHandler h : zoneHandlers) {
264 h.updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_NONE));
265 h.updateState(CHANNEL_ALARM_ZONE_ALARM_TIMESTAMP, new DateTimeType());
270 protected Where buildBusWhere(String wStr) throws IllegalArgumentException {
271 return new WhereAlarm(wStr);
275 protected String ownIdPrefix() {
276 return Who.BURGLAR_ALARM.value().toString();
280 public void dispose() {
281 if (OpenWebNetBindingConstants.THING_TYPE_BUS_ALARM_ZONE.equals(thing.getThingTypeUID())) {
282 zoneHandlers.remove(this);
283 logger.debug("Alarm.dispose() - removed zone {}", this.deviceWhere);