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