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