]> git.basschouten.com Git - openhab-addons.git/blob
bd6838e2ba9636511689a1bda854fb25e69f62ab
[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.zway.internal.discovery;
14
15 import java.util.List;
16 import java.util.Map;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
19
20 import org.openhab.binding.zway.internal.ZWayBindingConstants;
21 import org.openhab.binding.zway.internal.handler.ZWayBridgeHandler;
22 import org.openhab.core.config.discovery.AbstractDiscoveryService;
23 import org.openhab.core.config.discovery.DiscoveryResult;
24 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
25 import org.openhab.core.thing.Thing;
26 import org.openhab.core.thing.ThingStatus;
27 import org.openhab.core.thing.ThingUID;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import de.fh_zwickau.informatik.sensor.model.devices.Device;
32 import de.fh_zwickau.informatik.sensor.model.devices.DeviceList;
33 import de.fh_zwickau.informatik.sensor.model.devices.types.Camera;
34 import de.fh_zwickau.informatik.sensor.model.devices.types.SensorMultiline;
35 import de.fh_zwickau.informatik.sensor.model.devices.types.Text;
36 import de.fh_zwickau.informatik.sensor.model.locations.LocationList;
37 import de.fh_zwickau.informatik.sensor.model.zwaveapi.devices.ZWaveDevice;
38
39 /**
40  * The {@link ZWayDeviceDiscoveryService} is responsible for device discovery.
41  *
42  * @author Patrick Hecker - Initial contribution
43  */
44 public class ZWayDeviceDiscoveryService extends AbstractDiscoveryService {
45
46     private final Logger logger = LoggerFactory.getLogger(getClass());
47
48     private static final int SEARCH_TIME = 60;
49     private static final int INITIAL_DELAY = 15;
50     private static final int SCAN_INTERVAL = 240;
51
52     private ZWayBridgeHandler mBridgeHandler;
53     private ZWayDeviceScan mZWayDeviceScanningRunnable;
54     private ScheduledFuture<?> mZWayDeviceScanningJob;
55
56     public ZWayDeviceDiscoveryService(ZWayBridgeHandler bridgeHandler) {
57         super(ZWayBindingConstants.SUPPORTED_DEVICE_THING_TYPES_UIDS, SEARCH_TIME);
58         logger.debug("Initializing ZWayBridgeDiscoveryService");
59         mBridgeHandler = bridgeHandler;
60         mZWayDeviceScanningRunnable = new ZWayDeviceScan();
61         activate(null);
62     }
63
64     private void scan() {
65         logger.debug("Starting scan on Z-Way Server {}", mBridgeHandler.getThing().getUID());
66
67         // Z-Way bridge have to be ONLINE because configuration is needed
68         if (mBridgeHandler == null || !mBridgeHandler.getThing().getStatus().equals(ThingStatus.ONLINE)) {
69             logger.debug("Z-Way bridge handler not found or not ONLINE.");
70             return;
71         }
72
73         LocationList locationList = mBridgeHandler.getZWayApi().getLocations();
74
75         DeviceList deviceList = mBridgeHandler.getZWayApi().getDevices();
76         if (deviceList != null) {
77             Map<Integer, List<Device>> physicalDevices = deviceList.getDevicesGroupByNodeId();
78             for (Map.Entry<Integer, List<Device>> entry : physicalDevices.entrySet()) {
79                 final Integer nodeId = entry.getKey();
80                 List<Device> devices = entry.getValue();
81
82                 final ThingUID bridgeUID = mBridgeHandler.getThing().getUID();
83
84                 String location = "";
85
86                 String deviceTypes = "";
87                 Integer index = 0;
88                 for (Device device : devices) {
89                     if (index != 0 && index != devices.size()) {
90                         deviceTypes += ", ";
91                     }
92                     deviceTypes += device.getDeviceType();
93                     index++;
94
95                     // Add location, assuming that each (virtual) device is assigned to the same room
96                     if (locationList != null) {
97                         // Add only the location if this differs from globalRoom (with id 0)
98                         if (device.getLocation() != -1 && device.getLocation() != 0) {
99                             try {
100                                 location = locationList.getLocationById(device.getLocation()).getTitle();
101                             } catch (NullPointerException npe) {
102                                 location = "";
103                             }
104                         }
105                     }
106                 }
107                 logger.debug("Z-Way device found with {} virtual devices - device types: {}", devices.size(),
108                         deviceTypes);
109
110                 ZWaveDevice zwaveDevice = mBridgeHandler.getZWayApi().getZWaveDevice(nodeId);
111                 if (zwaveDevice != null) {
112                     String givenName = "Device " + nodeId;
113                     if (!zwaveDevice.getData().getGivenName().getValue().equals("")) {
114                         givenName = zwaveDevice.getData().getGivenName().getValue();
115                     } else if (!zwaveDevice.getData().getDeviceTypeString().getValue().equals("")) {
116                         givenName += " - " + zwaveDevice.getData().getDeviceTypeString().getValue();
117                     }
118                     // Add additional information as properties
119                     String vendorString = zwaveDevice.getData().getVendorString().getValue();
120                     if (!zwaveDevice.getData().getVendorString().getValue().equals("")) {
121                         givenName += " (" + vendorString + ")";
122                     }
123                     String manufacturerId = zwaveDevice.getData().getManufacturerId().getValue();
124                     String deviceType = zwaveDevice.getData().getDeviceTypeString().getValue();
125                     String zddxmlfile = zwaveDevice.getData().getZDDXMLFile().getValue();
126                     String sdk = zwaveDevice.getData().getSDK().getValue();
127
128                     ThingUID thingUID = new ThingUID(ZWayBindingConstants.THING_TYPE_DEVICE,
129                             mBridgeHandler.getThing().getUID(), nodeId.toString());
130
131                     /*
132                      * Properties
133                      * - Configuration: DEVICE_CONFIG_NODE_ID
134                      * - System properties:
135                      * --- PROPERTY_VENDOR
136                      * --- other default properties not available
137                      * - Custom properties:
138                      * --- DEVICE_LOCATION
139                      * --- DEVICE_MANUFACTURER_ID
140                      * --- DEVICE_DEVICE_TYPE
141                      * --- DEVICE_ZDDXMLFILE
142                      * --- DEVICE_SDK
143                      */
144                     DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withLabel(givenName)
145                             .withBridge(bridgeUID).withProperty(ZWayBindingConstants.DEVICE_CONFIG_NODE_ID, nodeId)
146                             .withProperty(Thing.PROPERTY_VENDOR, vendorString)
147                             .withProperty(ZWayBindingConstants.DEVICE_PROP_LOCATION, location)
148                             .withProperty(ZWayBindingConstants.DEVICE_PROP_MANUFACTURER_ID, manufacturerId)
149                             .withProperty(ZWayBindingConstants.DEVICE_PROP_DEVICE_TYPE, deviceType)
150                             .withProperty(ZWayBindingConstants.DEVICE_PROP_ZDDXMLFILE, zddxmlfile)
151                             .withProperty(ZWayBindingConstants.DEVICE_PROP_SDK, sdk).build();
152                     thingDiscovered(discoveryResult);
153                 } else {
154                     logger.warn("Z-Wave device not loaded");
155                 }
156             }
157
158             for (Device device : deviceList.getDevices()) {
159                 if (device.getVisibility() && !device.getPermanentlyHidden()) {
160                     if (ZWayBindingConstants.DISCOVERY_IGNORED_DEVICES.contains(device.getDeviceId().split("_")[0])) {
161                         logger.debug("Skip device: {}", device.getMetrics().getTitle());
162                         continue;
163                     }
164
165                     if (device instanceof SensorMultiline || device instanceof Camera || device instanceof Text) {
166                         logger.debug("Skip device because the device type is not supported: {}",
167                                 device.getMetrics().getTitle());
168                         continue;
169                     }
170
171                     ThingUID bridgeUID = mBridgeHandler.getThing().getUID();
172
173                     String location = "";
174                     // Add location, assuming that each (virtual) device is assigned to the same room
175                     if (locationList != null) {
176                         // Add only the location if this differs from globalRoom (with id 0)
177                         if (device.getLocation() != -1 && device.getLocation() != 0) {
178                             try {
179                                 location = locationList.getLocationById(device.getLocation()).getTitle();
180                             } catch (NullPointerException npe) {
181                                 location = "";
182                             }
183                         }
184                     }
185
186                     logger.debug("Z-Way virtual device found with device type: {} - {} - {}", device.getDeviceType(),
187                             device.getMetrics().getProbeTitle(), device.getNodeId());
188
189                     ThingUID thingUID = new ThingUID(ZWayBindingConstants.THING_TYPE_VIRTUAL_DEVICE,
190                             mBridgeHandler.getThing().getUID(), device.getDeviceId());
191                     DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID)
192                             .withLabel(device.getMetrics().getTitle()).withBridge(bridgeUID)
193                             .withProperty(ZWayBindingConstants.DEVICE_CONFIG_VIRTUAL_DEVICE_ID, device.getDeviceId())
194                             .withProperty(ZWayBindingConstants.DEVICE_PROP_LOCATION, location).build();
195                     thingDiscovered(discoveryResult);
196                 }
197             }
198         } else {
199             logger.warn("Devices not loaded");
200         }
201     }
202
203     @Override
204     protected void startScan() {
205         scan();
206     }
207
208     @Override
209     protected synchronized void stopScan() {
210         super.stopScan();
211         removeOlderResults(getTimestampOfLastScan());
212     }
213
214     @Override
215     protected void startBackgroundDiscovery() {
216         if (mZWayDeviceScanningJob == null || mZWayDeviceScanningJob.isCancelled()) {
217             logger.debug("Starting background scanning job");
218             mZWayDeviceScanningJob = scheduler.scheduleWithFixedDelay(mZWayDeviceScanningRunnable, INITIAL_DELAY,
219                     SCAN_INTERVAL, TimeUnit.SECONDS);
220         } else {
221             logger.debug("Scanning job is allready active");
222         }
223     }
224
225     @Override
226     protected void stopBackgroundDiscovery() {
227         if (mZWayDeviceScanningJob != null && !mZWayDeviceScanningJob.isCancelled()) {
228             mZWayDeviceScanningJob.cancel(false);
229             mZWayDeviceScanningJob = null;
230         }
231     }
232
233     public class ZWayDeviceScan implements Runnable {
234         @Override
235         public void run() {
236             scan();
237         }
238     }
239 }