]> git.basschouten.com Git - openhab-addons.git/blob
828b30c5484eb3a6a7c66fdadbfeed8a9efd5e5e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.jablotron.internal.handler;
14
15 import static org.openhab.binding.jablotron.JablotronBindingConstants.*;
16
17 import java.time.Instant;
18 import java.time.ZoneId;
19 import java.time.ZonedDateTime;
20 import java.time.format.DateTimeFormatter;
21 import java.util.List;
22 import java.util.concurrent.ScheduledFuture;
23 import java.util.concurrent.TimeUnit;
24
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.openhab.binding.jablotron.internal.config.JablotronDeviceConfig;
28 import org.openhab.binding.jablotron.internal.model.*;
29 import org.openhab.core.cache.ExpiringCache;
30 import org.openhab.core.library.types.DateTimeType;
31 import org.openhab.core.library.types.StringType;
32 import org.openhab.core.thing.*;
33 import org.openhab.core.thing.binding.BaseThingHandler;
34 import org.openhab.core.types.State;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import com.google.gson.Gson;
39
40 /**
41  * The {@link JablotronAlarmHandler} is responsible for handling commands, which are
42  * sent to one of the channels.
43  *
44  * @author Ondrej Pecta - Initial contribution
45  */
46 @NonNullByDefault
47 public abstract class JablotronAlarmHandler extends BaseThingHandler {
48
49     private final Logger logger = LoggerFactory.getLogger(getClass());
50
51     protected final Gson gson = new Gson();
52
53     protected JablotronDeviceConfig thingConfig = new JablotronDeviceConfig();
54
55     private String lastWarningTime = "";
56
57     protected String alarmName = "";
58
59     private boolean inService = false;
60
61     protected @Nullable ScheduledFuture<?> future = null;
62
63     protected @Nullable ExpiringCache<JablotronDataUpdateResponse> dataCache;
64     protected ExpiringCache<List<JablotronHistoryDataEvent>> eventCache;
65
66     public JablotronAlarmHandler(Thing thing, String alarmName) {
67         super(thing);
68         this.alarmName = alarmName;
69         eventCache = new ExpiringCache<>(CACHE_TIMEOUT_MS, this::sendGetEventHistory);
70     }
71
72     @Override
73     public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
74         super.bridgeStatusChanged(bridgeStatusInfo);
75         if (ThingStatus.OFFLINE == bridgeStatusInfo.getStatus()
76                 || ThingStatus.UNINITIALIZED == bridgeStatusInfo.getStatus()) {
77             cleanup();
78         }
79         if (ThingStatus.ONLINE == bridgeStatusInfo.getStatus()) {
80             initialize();
81         }
82     }
83
84     @Override
85     public void dispose() {
86         super.dispose();
87         cleanup();
88     }
89
90     @Override
91     public void initialize() {
92         logger.debug("Initializing the alarm: {}", getThing().getUID());
93         thingConfig = getConfigAs(JablotronDeviceConfig.class);
94         future = scheduler.scheduleWithFixedDelay(this::updateAlarmStatus, 1, thingConfig.getRefresh(),
95                 TimeUnit.SECONDS);
96         updateStatus(ThingStatus.ONLINE);
97     }
98
99     public boolean isInService() {
100         return inService;
101     }
102
103     public String getAlarmName() {
104         return alarmName;
105     }
106
107     protected abstract void updateSegmentStatus(JablotronServiceDetailSegment segment);
108
109     protected void updateSegmentStatus(String segmentName, @Nullable JablotronDataUpdateResponse dataUpdate) {
110         if (dataUpdate == null || !dataUpdate.isStatus()) {
111             return;
112         }
113         List<JablotronServiceData> serviceData = dataUpdate.getData().getServiceData();
114         for (JablotronServiceData data : serviceData) {
115             if (!thingConfig.getServiceId().equals(data.getServiceId())) {
116                 continue;
117             }
118             List<JablotronService> services = data.getData();
119             for (JablotronService service : services) {
120                 JablotronServiceDetail detail = service.getData();
121                 for (JablotronServiceDetailSegment segment : detail.getSegments()) {
122                     if (segmentName.toUpperCase().equals(segment.getSegmentId())) {
123                         updateSegmentStatus(segment);
124                     }
125                 }
126             }
127         }
128     }
129
130     private void cleanup() {
131         logger.debug("doing cleanup...");
132         ScheduledFuture<?> localFuture = future;
133         if (localFuture != null) {
134             localFuture.cancel(true);
135         }
136     }
137
138     protected State getCheckTime() {
139         ZonedDateTime zdt = ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
140         return new DateTimeType(zdt);
141     }
142
143     protected synchronized @Nullable JablotronDataUpdateResponse sendGetStatusRequest() {
144         JablotronBridgeHandler handler = getBridgeHandler();
145         if (handler != null) {
146             return handler.sendGetStatusRequest(getThing());
147         }
148         return null;
149     }
150
151     protected synchronized boolean updateAlarmStatus() {
152         logger.debug("Updating status of alarm: {}", getThing().getUID());
153         JablotronDataUpdateResponse dataUpdate = sendGetStatusRequest();
154         if (dataUpdate == null) {
155             return false;
156         }
157
158         if (dataUpdate.isStatus()) {
159             updateState(CHANNEL_LAST_CHECK_TIME, getCheckTime());
160             List<JablotronServiceData> serviceData = dataUpdate.getData().getServiceData();
161             for (JablotronServiceData data : serviceData) {
162                 if (!thingConfig.getServiceId().equals(data.getServiceId())) {
163                     continue;
164                 }
165                 List<JablotronService> services = data.getData();
166                 for (JablotronService service : services) {
167                     JablotronServiceDetail detail = service.getData();
168                     for (JablotronServiceDetailSegment segment : detail.getSegments()) {
169                         updateSegmentStatus(segment);
170                     }
171                 }
172
173             }
174         } else {
175             logger.debug("Error during alarm status update: {}", dataUpdate.getErrorMessage());
176         }
177
178         List<JablotronHistoryDataEvent> events = sendGetEventHistory();
179         if (events != null && events.size() > 0) {
180             JablotronHistoryDataEvent event = events.get(0);
181             updateLastEvent(event);
182         }
183
184         return true;
185     }
186
187     protected @Nullable List<JablotronHistoryDataEvent> sendGetEventHistory() {
188         return sendGetEventHistory(alarmName);
189     }
190
191     private @Nullable List<JablotronHistoryDataEvent> sendGetEventHistory(String alarm) {
192         JablotronBridgeHandler handler = getBridgeHandler();
193         if (handler != null) {
194             return handler.sendGetEventHistory(getThing(), alarm);
195         }
196         return null;
197     }
198
199     protected void updateLastEvent(JablotronHistoryDataEvent event) {
200         updateState(CHANNEL_LAST_EVENT_TIME, new DateTimeType(getZonedDateTime(event.getDate())));
201         updateState(CHANNEL_LAST_EVENT, new StringType(event.getEventText()));
202         updateState(CHANNEL_LAST_EVENT_CLASS, new StringType(event.getIconType()));
203         updateState(CHANNEL_LAST_EVENT_INVOKER, new StringType(event.getInvokerName()));
204
205         // oasis does not have sections
206         if (getThing().getChannel(CHANNEL_LAST_EVENT_SECTION) != null) {
207             updateState(CHANNEL_LAST_EVENT_SECTION, new StringType(event.getSectionName()));
208         }
209     }
210
211     protected void updateEventChannel(String channel) {
212         List<JablotronHistoryDataEvent> events = eventCache.getValue();
213         if (events != null && events.size() > 0) {
214             JablotronHistoryDataEvent event = events.get(0);
215             switch (channel) {
216                 case CHANNEL_LAST_EVENT_TIME:
217                     updateState(CHANNEL_LAST_EVENT_TIME, new DateTimeType(getZonedDateTime(event.getDate())));
218                     break;
219                 case CHANNEL_LAST_EVENT:
220                     updateState(CHANNEL_LAST_EVENT, new StringType(event.getEventText()));
221                     break;
222                 case CHANNEL_LAST_EVENT_CLASS:
223                     updateState(CHANNEL_LAST_EVENT_CLASS, new StringType(event.getIconType()));
224                     break;
225                 case CHANNEL_LAST_EVENT_INVOKER:
226                     updateState(CHANNEL_LAST_EVENT_INVOKER, new StringType(event.getInvokerName()));
227                     break;
228                 case CHANNEL_LAST_EVENT_SECTION:
229                     updateState(CHANNEL_LAST_EVENT_SECTION, new StringType(event.getSectionName()));
230                     break;
231             }
232         }
233     }
234
235     public ZonedDateTime getZonedDateTime(String date) {
236         return ZonedDateTime.parse(date.substring(0, 22) + ":" + date.substring(22, 24),
237                 DateTimeFormatter.ISO_DATE_TIME);
238     }
239
240     protected @Nullable JablotronControlResponse sendUserCode(String section, String key, String status, String code) {
241         JablotronBridgeHandler handler = getBridgeHandler();
242         if (handler != null) {
243             return handler.sendUserCode(getThing(), section, key, status, code);
244         }
245         return null;
246     }
247
248     protected @Nullable JablotronBridgeHandler getBridgeHandler() {
249         Bridge br = getBridge();
250         if (br != null && br.getHandler() != null) {
251             return (JablotronBridgeHandler) br.getHandler();
252         }
253         return null;
254     }
255
256     public void setStatus(ThingStatus status, ThingStatusDetail detail, String message) {
257         updateStatus(status, detail, message);
258     }
259
260     public void triggerAlarm(JablotronDiscoveredService service) {
261         if (!service.getWarningTime().equals(lastWarningTime)) {
262             logger.debug("Service id: {} is triggering an alarm: {}", thing.getUID().getId(), service.getWarning());
263             lastWarningTime = service.getWarningTime();
264             triggerChannel(CHANNEL_ALARM, service.getWarning());
265         }
266     }
267
268     public void setInService(boolean inService) {
269         this.inService = inService;
270     }
271 }