]> git.basschouten.com Git - openhab-addons.git/blob
7e4a96615aa6bcb3dfa80f13f8b6c23013766a29
[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.tellstick.internal.live;
14
15 import java.util.List;
16 import java.util.Vector;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
19
20 import org.openhab.binding.tellstick.internal.conf.TelldusLiveConfiguration;
21 import org.openhab.binding.tellstick.internal.handler.DeviceStatusListener;
22 import org.openhab.binding.tellstick.internal.handler.TelldusBridgeHandler;
23 import org.openhab.binding.tellstick.internal.handler.TelldusDeviceController;
24 import org.openhab.binding.tellstick.internal.handler.TelldusDevicesHandler;
25 import org.openhab.binding.tellstick.internal.live.xml.DataTypeValue;
26 import org.openhab.binding.tellstick.internal.live.xml.TellstickNetDevice;
27 import org.openhab.binding.tellstick.internal.live.xml.TellstickNetDevices;
28 import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensor;
29 import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensorEvent;
30 import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensors;
31 import org.openhab.core.thing.Bridge;
32 import org.openhab.core.thing.ChannelUID;
33 import org.openhab.core.thing.Thing;
34 import org.openhab.core.thing.ThingStatus;
35 import org.openhab.core.thing.ThingStatusDetail;
36 import org.openhab.core.thing.binding.BaseBridgeHandler;
37 import org.openhab.core.types.Command;
38 import org.openhab.core.types.RefreshType;
39 import org.openhab.core.types.State;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42 import org.tellstick.device.TellstickDeviceEvent;
43 import org.tellstick.device.TellstickException;
44 import org.tellstick.device.iface.Device;
45
46 /**
47  * {@link TelldusLiveBridgeHandler} is the handler for Telldus Live service (Tellstick.NET and ZNET) and connects it
48  * to the framework. All {@link TelldusDevicesHandler}s use the
49  * {@link TelldusLiveDeviceController} to execute the actual commands.
50  *
51  * @author Jarle Hjortland - Initial contribution
52  */
53 public class TelldusLiveBridgeHandler extends BaseBridgeHandler implements TelldusBridgeHandler {
54
55     private final Logger logger = LoggerFactory.getLogger(TelldusLiveBridgeHandler.class);
56
57     private TellstickNetDevices deviceList = null;
58     private TellstickNetSensors sensorList = null;
59     private TelldusLiveDeviceController controller = new TelldusLiveDeviceController();
60     private List<DeviceStatusListener> deviceStatusListeners = new Vector<>();
61
62     private static final int REFRESH_DELAY = 10;
63
64     public TelldusLiveBridgeHandler(Bridge bridge) {
65         super(bridge);
66     }
67
68     private ScheduledFuture<?> pollingJob;
69     private ScheduledFuture<?> immediateRefreshJob;
70
71     @Override
72     public void dispose() {
73         logger.debug("Live Handler disposed.");
74         if (pollingJob != null) {
75             pollingJob.cancel(true);
76         }
77         if (this.controller != null) {
78             this.controller.dispose();
79         }
80         deviceList = null;
81         sensorList = null;
82         super.dispose();
83     }
84
85     @Override
86     public void initialize() {
87         logger.debug("Initializing TelldusLive bridge handler.");
88         TelldusLiveConfiguration configuration = getConfigAs(TelldusLiveConfiguration.class);
89         this.controller = new TelldusLiveDeviceController();
90         this.controller.connectHttpClient(configuration.publicKey, configuration.privateKey, configuration.token,
91                 configuration.tokenSecret);
92         startAutomaticRefresh(configuration.refreshInterval);
93         refreshDeviceList();
94         updateStatus(ThingStatus.ONLINE);
95     }
96
97     private synchronized void startAutomaticRefresh(long refreshInterval) {
98         if (pollingJob != null && !pollingJob.isCancelled()) {
99             pollingJob.cancel(true);
100         }
101         pollingJob = scheduler.scheduleWithFixedDelay(this::refreshDeviceList, 0, refreshInterval,
102                 TimeUnit.MILLISECONDS);
103     }
104
105     private void scheduleImmediateRefresh() {
106         // We schedule in 10 sec, to avoid multiple updates
107         logger.debug("Current remaining delay {}", pollingJob.getDelay(TimeUnit.SECONDS));
108         if (pollingJob.getDelay(TimeUnit.SECONDS) > REFRESH_DELAY) {
109             if (immediateRefreshJob == null || immediateRefreshJob.isDone()) {
110                 immediateRefreshJob = scheduler.schedule(this::refreshDeviceList, REFRESH_DELAY, TimeUnit.SECONDS);
111             }
112         }
113     }
114
115     synchronized void refreshDeviceList() {
116         try {
117             updateDevices(deviceList);
118             updateSensors(sensorList);
119             updateStatus(ThingStatus.ONLINE);
120         } catch (TellstickException e) {
121             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
122             logger.error("Failed to update", e);
123         } catch (Exception e) {
124             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
125             logger.error("Failed to update", e);
126         }
127     }
128
129     private synchronized void updateDevices(TellstickNetDevices previouslist) throws TellstickException {
130         TellstickNetDevices newList = controller.callRestMethod(TelldusLiveDeviceController.HTTP_TELLDUS_DEVICES,
131                 TellstickNetDevices.class);
132         logger.debug("Device list {}", newList.getDevices());
133         if (newList.getDevices() != null) {
134             if (previouslist == null) {
135                 logger.debug("updateDevices, Creating devices.");
136                 for (TellstickNetDevice device : newList.getDevices()) {
137                     device.setUpdated(true);
138                     for (DeviceStatusListener listener : deviceStatusListeners) {
139                         listener.onDeviceAdded(getThing(), device);
140                     }
141                 }
142                 this.deviceList = newList;
143             } else {
144                 logger.debug("updateDevices, Updating devices.");
145                 for (TellstickNetDevice device : newList.getDevices()) {
146                     int index = previouslist.getDevices().indexOf(device);
147                     logger.debug("Device:{} found at {}", device, index);
148                     if (index >= 0) {
149                         TellstickNetDevice orgDevice = previouslist.getDevices().get(index);
150                         if (device.getState() != orgDevice.getState()) {
151                             orgDevice.setState(device.getState());
152                             orgDevice.setStatevalue(device.getStatevalue());
153                             orgDevice.setUpdated(true);
154                         }
155                     } else {
156                         logger.debug("New Device - Adding:{}", device);
157                         previouslist.getDevices().add(device);
158                         device.setUpdated(true);
159                         for (DeviceStatusListener listener : deviceStatusListeners) {
160                             listener.onDeviceAdded(getThing(), device);
161                         }
162                     }
163                 }
164             }
165
166             for (TellstickNetDevice device : deviceList.getDevices()) {
167                 if (device.isUpdated()) {
168                     logger.debug("Updated device:{}", device);
169                     for (DeviceStatusListener listener : deviceStatusListeners) {
170                         listener.onDeviceStateChanged(getThing(), device,
171                                 new TellstickDeviceEvent(device, null, null, null, System.currentTimeMillis()));
172                     }
173                     device.setUpdated(false);
174                 }
175             }
176         }
177     }
178
179     private synchronized void updateSensors(TellstickNetSensors previouslist) throws TellstickException {
180         TellstickNetSensors newList = controller.callRestMethod(TelldusLiveDeviceController.HTTP_TELLDUS_SENSORS,
181                 TellstickNetSensors.class);
182         logger.debug("Updated sensors:{}", newList.getSensors());
183         if (newList.getSensors() != null) {
184             if (previouslist == null) {
185                 logger.debug("First update of sensors");
186                 this.sensorList = newList;
187                 for (TellstickNetSensor sensor : sensorList.getSensors()) {
188                     sensor.setUpdated(true);
189                     for (DeviceStatusListener listener : deviceStatusListeners) {
190                         listener.onDeviceAdded(getThing(), sensor);
191                     }
192                 }
193             } else {
194                 logger.debug("Update sensors, reset updated flag");
195                 for (TellstickNetSensor sensor : previouslist.getSensors()) {
196                     sensor.setUpdated(false);
197                 }
198                 logger.debug("Update sensors, reset updated flag1");
199
200                 for (TellstickNetSensor sensor : newList.getSensors()) {
201                     int index = this.sensorList.getSensors().indexOf(sensor);
202                     if (index >= 0) {
203                         TellstickNetSensor orgSensor = this.sensorList.getSensors().get(index);
204                         logger.debug("Update sensor {}, prev update {}, new update {}", sensor.getId(),
205                                 orgSensor.getLastUpdated(), sensor.getLastUpdated());
206                         if (sensor.getLastUpdated() > orgSensor.getLastUpdated()) {
207                             logger.debug("Update for sensor:{}", sensor);
208                             orgSensor.setData(sensor.getData());
209                             orgSensor.setLastUpdated(sensor.getLastUpdated());
210                             orgSensor.setUpdated(true);
211                             sensor.setUpdated(true);
212                         }
213                     } else {
214                         logger.debug("Adding sensor {}, new update {}", sensor.getId(), sensor.getLastUpdated());
215                         this.sensorList.getSensors().add(sensor);
216                         sensor.setUpdated(true);
217                         for (DeviceStatusListener listener : deviceStatusListeners) {
218                             listener.onDeviceAdded(getThing(), sensor);
219                         }
220                     }
221                 }
222             }
223             for (TellstickNetSensor sensor : sensorList.getSensors()) {
224                 if (sensor.getData() != null && sensor.isUpdated()) {
225                     for (DeviceStatusListener listener : deviceStatusListeners) {
226                         for (DataTypeValue type : sensor.getData()) {
227                             listener.onDeviceStateChanged(getThing(), sensor,
228                                     new TellstickNetSensorEvent(sensor.getId(), type.getValue(), type,
229                                             sensor.getProtocol(), sensor.getModel(), System.currentTimeMillis()));
230                         }
231                     }
232                     sensor.setUpdated(false);
233                 }
234             }
235         }
236     }
237
238     @Override
239     public void handleCommand(ChannelUID channelUID, Command command) {
240         if (command instanceof RefreshType) {
241             scheduleImmediateRefresh();
242         }
243     }
244
245     @Override
246     public void handleRemoval() {
247         super.handleRemoval();
248     }
249
250     @Override
251     public void handleUpdate(ChannelUID channelUID, State newState) {
252         super.handleUpdate(channelUID, newState);
253     }
254
255     @Override
256     public void thingUpdated(Thing thing) {
257         super.thingUpdated(thing);
258     }
259
260     @Override
261     public boolean registerDeviceStatusListener(DeviceStatusListener deviceStatusListener) {
262         if (deviceStatusListener == null) {
263             throw new IllegalArgumentException("It's not allowed to pass a null deviceStatusListener.");
264         }
265         return deviceStatusListeners.add(deviceStatusListener);
266     }
267
268     @Override
269     public boolean unregisterDeviceStatusListener(DeviceStatusListener deviceStatusListener) {
270         return deviceStatusListeners.remove(deviceStatusListener);
271     }
272
273     private Device getDevice(String id, List<TellstickNetDevice> devices) {
274         for (Device device : devices) {
275             if (device.getId() == Integer.valueOf(id)) {
276                 return device;
277             }
278         }
279         return null;
280     }
281
282     private Device getSensor(String id, List<TellstickNetSensor> sensors) {
283         for (Device sensor : sensors) {
284             if (sensor.getId() == Integer.valueOf(id)) {
285                 return sensor;
286             }
287         }
288         return null;
289     }
290
291     @Override
292     public Device getDevice(String serialNumber) {
293         return getDevice(serialNumber, getDevices());
294     }
295
296     private List<TellstickNetDevice> getDevices() {
297         if (deviceList == null) {
298             refreshDeviceList();
299         }
300         return deviceList.getDevices();
301     }
302
303     @Override
304     public Device getSensor(String deviceUUId) {
305         Device result = null;
306         if (sensorList != null) {
307             result = getSensor(deviceUUId, sensorList.getSensors());
308         }
309         return result;
310     }
311
312     @Override
313     public void rescanTelldusDevices() {
314         this.deviceList = null;
315         this.sensorList = null;
316         refreshDeviceList();
317     }
318
319     @Override
320     public TelldusDeviceController getController() {
321         return controller;
322     }
323 }