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