]> git.basschouten.com Git - openhab-addons.git/blob
53814ff95d79709c11de7bcfe1996d4c90efeebb
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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         if (newList.getDevices() != null) {
132             logger.debug("Device list {}", newList.getDevices());
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         } else {
176             logger.debug("updateDevices, rest API returned null");
177         }
178     }
179
180     private synchronized void updateSensors(TellstickNetSensors previouslist) throws TellstickException {
181         TellstickNetSensors newList = controller.callRestMethod(TelldusLiveDeviceController.HTTP_TELLDUS_SENSORS,
182                 TellstickNetSensors.class);
183         logger.debug("Updated sensors:{}", newList.getSensors());
184         if (newList.getSensors() != null) {
185             if (previouslist == null) {
186                 logger.debug("First update of sensors");
187                 this.sensorList = newList;
188                 for (TellstickNetSensor sensor : sensorList.getSensors()) {
189                     sensor.setUpdated(true);
190                     for (DeviceStatusListener listener : deviceStatusListeners) {
191                         listener.onDeviceAdded(getThing(), sensor);
192                     }
193                 }
194             } else {
195                 logger.debug("Update sensors, reset updated flag");
196                 for (TellstickNetSensor sensor : previouslist.getSensors()) {
197                     sensor.setUpdated(false);
198                 }
199                 logger.debug("Update sensors, reset updated flag1");
200
201                 for (TellstickNetSensor sensor : newList.getSensors()) {
202                     int index = this.sensorList.getSensors().indexOf(sensor);
203                     if (index >= 0) {
204                         TellstickNetSensor orgSensor = this.sensorList.getSensors().get(index);
205                         logger.debug("Update sensor {}, prev update {}, new update {}", sensor.getId(),
206                                 orgSensor.getLastUpdated(), sensor.getLastUpdated());
207                         if (sensor.getLastUpdated() > orgSensor.getLastUpdated()) {
208                             logger.debug("Update for sensor:{}", sensor);
209                             orgSensor.setData(sensor.getData());
210                             orgSensor.setLastUpdated(sensor.getLastUpdated());
211                             orgSensor.setUpdated(true);
212                             sensor.setUpdated(true);
213                         }
214                     } else {
215                         logger.debug("Adding sensor {}, new update {}", sensor.getId(), sensor.getLastUpdated());
216                         this.sensorList.getSensors().add(sensor);
217                         sensor.setUpdated(true);
218                         for (DeviceStatusListener listener : deviceStatusListeners) {
219                             listener.onDeviceAdded(getThing(), sensor);
220                         }
221                     }
222                 }
223             }
224             for (TellstickNetSensor sensor : sensorList.getSensors()) {
225                 if (sensor.getData() != null && sensor.isUpdated()) {
226                     for (DeviceStatusListener listener : deviceStatusListeners) {
227                         for (DataTypeValue type : sensor.getData()) {
228                             listener.onDeviceStateChanged(getThing(), sensor,
229                                     new TellstickNetSensorEvent(sensor.getId(), type.getValue(), type,
230                                             sensor.getProtocol(), sensor.getModel(), System.currentTimeMillis()));
231                         }
232                     }
233                     sensor.setUpdated(false);
234                 }
235             }
236         }
237     }
238
239     @Override
240     public void handleCommand(ChannelUID channelUID, Command command) {
241         if (command instanceof RefreshType) {
242             scheduleImmediateRefresh();
243         }
244     }
245
246     @Override
247     public void handleRemoval() {
248         super.handleRemoval();
249     }
250
251     @Override
252     public void thingUpdated(Thing thing) {
253         super.thingUpdated(thing);
254     }
255
256     @Override
257     public boolean registerDeviceStatusListener(DeviceStatusListener deviceStatusListener) {
258         if (deviceStatusListener == null) {
259             throw new IllegalArgumentException("It's not allowed to pass a null deviceStatusListener.");
260         }
261         return deviceStatusListeners.add(deviceStatusListener);
262     }
263
264     @Override
265     public boolean unregisterDeviceStatusListener(DeviceStatusListener deviceStatusListener) {
266         return deviceStatusListeners.remove(deviceStatusListener);
267     }
268
269     private Device getDevice(String id, List<TellstickNetDevice> devices) {
270         for (Device device : devices) {
271             if (device.getId() == Integer.valueOf(id)) {
272                 return device;
273             }
274         }
275         return null;
276     }
277
278     private Device getSensor(String id, List<TellstickNetSensor> sensors) {
279         for (Device sensor : sensors) {
280             if (sensor.getId() == Integer.valueOf(id)) {
281                 return sensor;
282             }
283         }
284         return null;
285     }
286
287     @Override
288     public Device getDevice(String serialNumber) {
289         return getDevice(serialNumber, getDevices());
290     }
291
292     private List<TellstickNetDevice> getDevices() {
293         if (deviceList == null) {
294             refreshDeviceList();
295         }
296         return deviceList.getDevices();
297     }
298
299     @Override
300     public Device getSensor(String deviceUUId) {
301         Device result = null;
302         if (sensorList != null) {
303             result = getSensor(deviceUUId, sensorList.getSensors());
304         }
305         return result;
306     }
307
308     @Override
309     public void rescanTelldusDevices() {
310         this.deviceList = null;
311         this.sensorList = null;
312         refreshDeviceList();
313     }
314
315     @Override
316     public TelldusDeviceController getController() {
317         return controller;
318     }
319 }