]> git.basschouten.com Git - openhab-addons.git/blob
8c945200fdf5b7c63b4e5404626431b12c7ac78b
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.openwebnet.internal.handler;
14
15 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.*;
16
17 import java.util.HashSet;
18 import java.util.Set;
19
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;
40
41 /**
42  * The {@link OpenWebNetAlarmHandler} is responsible for handling
43  * commands/messages for Alarm system and zones. It extends the abstract
44  * {@link OpenWebNetThingHandler}.
45  *
46  * @author Massimo Valla - Initial contribution
47  * @author Giovanni Fabiani - Add zone alarm's tismestamp feature
48  */
49 @NonNullByDefault
50 public class OpenWebNetAlarmHandler extends OpenWebNetThingHandler {
51
52     private final Logger logger = LoggerFactory.getLogger(OpenWebNetAlarmHandler.class);
53
54     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.ALARM_SUPPORTED_THING_TYPES;
55
56     private static long lastAllDevicesRefreshTS = 0; // ts when last all device refresh was sent for this handler
57
58     private static Set<OpenWebNetAlarmHandler> zoneHandlers = new HashSet<OpenWebNetAlarmHandler>();
59
60     private static final String BATTERY_OK = "OK";
61     private static final String BATTERY_FAULT = "FAULT";
62     private static final String BATTERY_UNLOADED = "UNLOADED";
63
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";
71
72     public OpenWebNetAlarmHandler(Thing thing) {
73         super(thing);
74     }
75
76     @Override
77     public void initialize() {
78         super.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
82             // received)
83             updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_NONE));
84             // initializing timestamp
85             updateState(CHANNEL_ALARM_ZONE_ALARM_TIMESTAMP, new DateTimeType());
86         }
87     }
88
89     @Override
90     protected void handleChannelCommand(ChannelUID channel, Command command) {
91         logger.warn("Alarm.handleChannelCommand() Read only channel, unsupported command {}", command);
92     }
93
94     @Override
95     protected void requestChannelState(ChannelUID channel) {
96         super.requestChannelState(channel);
97         Where w = deviceWhere;
98         ThingTypeUID thingType = thing.getThingTypeUID();
99         try {
100             if (THING_TYPE_BUS_ALARM_SYSTEM.equals(thingType)) {
101                 send(Alarm.requestSystemStatus());
102                 lastAllDevicesRefreshTS = System.currentTimeMillis();
103             } else {
104                 if (w != null) {
105                     send(Alarm.requestZoneStatus("#" + w.value()));
106                 } else {
107                     logger.debug("null where while requesting state for channel {}", channel);
108                 }
109             }
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());
113         }
114     }
115
116     @Override
117     protected long getRefreshAllLastTS() {
118         return lastAllDevicesRefreshTS;
119     };
120
121     @Override
122     protected void refreshDevice(boolean refreshAll) {
123         if (refreshAll) {
124             logger.debug("--- refreshDevice() : refreshing all via ALARM CENTRAL UNIT... ({})", thing.getUID());
125             try {
126                 send(Alarm.requestSystemStatus());
127                 lastAllDevicesRefreshTS = System.currentTimeMillis();
128             } catch (OWNException e) {
129                 logger.warn("Exception while requesting alarm system status: {}", e.getMessage());
130             }
131         } else {
132             logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID());
133             requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_ALARM_SYSTEM_STATE));
134         }
135     }
136
137     @Override
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);
144         } else {
145             updateZone((Alarm) msg);
146         }
147     }
148
149     private void updateSystem(Alarm msg) {
150         WhatAlarm w = (WhatAlarm) msg.getWhat();
151         if (w == null) {
152             logger.debug("Alarm.updateSystem() WHAT is null. Frame={}", msg);
153             return;
154         }
155         switch (w) {
156             case SYSTEM_ACTIVE:
157             case SYSTEM_INACTIVE:
158             case SYSTEM_MAINTENANCE:
159                 updateAlarmSystemState(w);
160                 break;
161             case SYSTEM_DISENGAGED:
162             case SYSTEM_ENGAGED:
163                 updateAlarmSystemArmed(w);
164                 break;
165             case SYSTEM_BATTERY_OK:
166             case SYSTEM_BATTERY_UNLOADED:
167             case SYSTEM_BATTERY_FAULT:
168                 updateBatteryState(w);
169                 break;
170             case SYSTEM_NETWORK_ERROR:
171             case SYSTEM_NETWORK_OK:
172                 updateNetworkState(w);
173                 break;
174             case DELAY_END:
175                 resetAllZonesAlarmState();
176                 break;
177             case START_PROGRAMMING:
178             case STOP_PROGRAMMING:
179             case NO_CONNECTION_TO_DEVICE:
180             default:
181                 logger.debug("Alarm.updateSystem() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
182         }
183     }
184
185     private void updateAlarmSystemState(WhatAlarm w) {
186         updateState(CHANNEL_ALARM_SYSTEM_STATE, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_ACTIVE));
187     }
188
189     private void updateAlarmSystemArmed(WhatAlarm w) {
190         updateState(CHANNEL_ALARM_SYSTEM_ARMED, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_ENGAGED));
191     }
192
193     private void updateNetworkState(WhatAlarm w) {
194         updateState(CHANNEL_ALARM_SYSTEM_NETWORK, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_NETWORK_OK));
195     }
196
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));
202         } else {
203             updateState(CHANNEL_ALARM_SYSTEM_BATTERY, new StringType(BATTERY_FAULT));
204         }
205     }
206
207     private void updateZone(Alarm msg) {
208         WhatAlarm w = (WhatAlarm) msg.getWhat();
209         if (w == null) {
210             logger.debug("Alarm.updateZone() WHAT is null. Frame={}", msg);
211             return;
212         }
213         switch (w) {
214             case ZONE_DISENGAGED:
215             case ZONE_ENGAGED:
216                 updateZoneState(w);
217                 break;
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:
224                 updateZoneAlarm(w);
225                 updateState(CHANNEL_ALARM_ZONE_ALARM_TIMESTAMP, new DateTimeType());
226                 break;
227             default:
228                 logger.debug("Alarm.updateZone() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
229         }
230     }
231
232     private void updateZoneState(WhatAlarm w) {
233         updateState(CHANNEL_ALARM_ZONE_STATE, OnOffType.from(w == Alarm.WhatAlarm.ZONE_ENGAGED));
234     }
235
236     private void updateZoneAlarm(WhatAlarm w) {
237         switch (w) {
238             case ZONE_ALARM_INTRUSION:
239                 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_INTRUSION));
240                 break;
241             case ZONE_ALARM_TAMPERING:
242                 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_TAMPERING));
243                 break;
244             case ZONE_ALARM_ANTI_PANIC:
245                 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_ANTI_PANIC));
246                 break;
247             case ZONE_ALARM_SILENT:
248                 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_SILENT));
249                 break;
250             case ZONE_ALARM_TECHNICAL:
251                 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_TECHNICAL));
252                 break;
253             case ZONE_ALARM_TECHNICAL_RESET:
254                 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_TECHNICAL_RESET));
255                 break;
256             default:
257                 updateState(CHANNEL_ALARM_ZONE_ALARM, new StringType(ALARM_NONE));
258                 logger.warn("Alarm.updateZoneAlarm() Ignoring unsupported WHAT {} for  zone {}", w, this.deviceWhere);
259         }
260     }
261
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());
266         }
267     }
268
269     @Override
270     protected Where buildBusWhere(String wStr) throws IllegalArgumentException {
271         return new WhereAlarm(wStr);
272     }
273
274     @Override
275     protected String ownIdPrefix() {
276         return Who.BURGLAR_ALARM.value().toString();
277     }
278
279     @Override
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);
284         }
285         super.dispose();
286     }
287 }