]> git.basschouten.com Git - openhab-addons.git/blob
b3af9b20fa34825272e0476fa6e8f6b2ab78de4c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.insteon.internal.discovery;
14
15 import static org.openhab.binding.insteon.internal.InsteonBindingConstants.*;
16
17 import java.time.Instant;
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.Optional;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.insteon.internal.device.InsteonAddress;
25 import org.openhab.binding.insteon.internal.device.InsteonModem;
26 import org.openhab.binding.insteon.internal.device.ProductData;
27 import org.openhab.binding.insteon.internal.handler.InsteonBridgeHandler;
28 import org.openhab.core.config.discovery.AbstractDiscoveryService;
29 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
30 import org.openhab.core.thing.ThingUID;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 /**
35  * The {@link InsteonDiscoveryService} is responsible for insteon devices & scenes discovery.
36  *
37  * @author Jeremy Setton - Initial contribution
38  */
39 @NonNullByDefault
40 public class InsteonDiscoveryService extends AbstractDiscoveryService {
41     private static final int SCAN_TIMEOUT = 2; // in seconds
42
43     private final Logger logger = LoggerFactory.getLogger(InsteonDiscoveryService.class);
44
45     private final InsteonBridgeHandler handler;
46
47     public InsteonDiscoveryService(InsteonBridgeHandler handler) {
48         super(DISCOVERABLE_THING_TYPES_UIDS, SCAN_TIMEOUT, false);
49         this.handler = handler;
50
51         logger.debug("initializing discovery service for bridge {}", handler.getThing().getUID());
52
53         handler.setDiscoveryService(this);
54     }
55
56     @Override
57     protected void startScan() {
58         logger.debug("starting manual scan on bridge {}", handler.getThing().getUID());
59
60         discoverMissingThings();
61     }
62
63     public void discoverInsteonDevice(InsteonAddress address, @Nullable ProductData productData) {
64         InsteonModem modem = handler.getModem();
65         if (handler.isDeviceDiscoveryEnabled() && modem != null && modem.getDB().hasEntry(address)
66                 && !modem.hasDevice(address)) {
67             addInsteonDevice(address, productData);
68         } else {
69             removeInsteonDevice(address);
70         }
71     }
72
73     public void discoverInsteonScene(int group) {
74         InsteonModem modem = handler.getModem();
75         if (handler.isSceneDiscoveryEnabled() && modem != null && modem.getDB().hasBroadcastGroup(group)
76                 && !modem.hasScene(group)) {
77             addInsteonScene(group);
78         } else {
79             removeInsteonScene(group);
80         }
81     }
82
83     public void discoverMissingThings() {
84         InsteonModem modem = handler.getModem();
85         if (modem == null) {
86             logger.debug("modem not initialized, scanning aborted.");
87         } else if (!modem.getDB().isComplete()) {
88             logger.debug("modem database not complete, scanning aborted.");
89         } else {
90             long startTime = Instant.now().toEpochMilli();
91
92             if (handler.isDeviceDiscoveryEnabled()) {
93                 modem.getDB().getDevices().stream().filter(address -> !modem.hasDevice(address)).forEach(address -> {
94                     logger.debug("device {} in the modem database, but not configured", address);
95                     addInsteonDevice(address, handler.getProductData(address));
96                 });
97             } else {
98                 logger.debug("device discovery is disabled, no device will be discovered.");
99             }
100
101             if (handler.isSceneDiscoveryEnabled()) {
102                 modem.getDB().getBroadcastGroups().stream().filter(group -> !modem.hasScene(group)).forEach(group -> {
103                     logger.debug("scene {} in the modem database, but not configured", group);
104                     addInsteonScene(group);
105                 });
106             } else {
107                 logger.debug("scene discovery is disabled, no scene will be discovered.");
108             }
109
110             removeOlderResults(startTime, handler.getThing().getUID());
111         }
112     }
113
114     private void addInsteonDevice(InsteonAddress address, @Nullable ProductData productData) {
115         ThingUID bridgeUID = handler.getThing().getUID();
116         String id = address.toString().replace(".", "").toLowerCase();
117         ThingUID thingUID = new ThingUID(THING_TYPE_DEVICE, bridgeUID, id);
118         String label = Optional.ofNullable(productData).map(ProductData::getLabel).orElse("Insteon Device " + address);
119         Map<String, Object> properties = new HashMap<>();
120         properties.put(PROPERTY_DEVICE_ADDRESS, address.toString());
121
122         thingDiscovered(DiscoveryResultBuilder.create(thingUID).withBridge(bridgeUID).withLabel(label)
123                 .withProperties(properties).withRepresentationProperty(PROPERTY_DEVICE_ADDRESS).build());
124
125         logger.debug("added Insteon device {} to inbox", address);
126     }
127
128     private void addInsteonScene(int group) {
129         ThingUID bridgeUID = handler.getThing().getUID();
130         String id = Integer.toString(group);
131         ThingUID thingUID = new ThingUID(THING_TYPE_SCENE, bridgeUID, id);
132         String label = "Insteon Scene " + group;
133         Map<String, Object> properties = new HashMap<>();
134         properties.put(PROPERTY_SCENE_GROUP, group);
135
136         thingDiscovered(DiscoveryResultBuilder.create(thingUID).withBridge(bridgeUID).withLabel(label)
137                 .withProperties(properties).withRepresentationProperty(PROPERTY_SCENE_GROUP).build());
138
139         logger.debug("added Insteon scene {} to inbox", group);
140     }
141
142     private void removeInsteonDevice(InsteonAddress address) {
143         ThingUID bridgeUID = handler.getThing().getUID();
144         String id = address.toString().replace(".", "").toLowerCase();
145         ThingUID thingUID = new ThingUID(THING_TYPE_DEVICE, bridgeUID, id);
146
147         thingRemoved(thingUID);
148     }
149
150     private void removeInsteonScene(int group) {
151         ThingUID bridgeUID = handler.getThing().getUID();
152         String id = Integer.toString(group);
153         ThingUID thingUID = new ThingUID(THING_TYPE_SCENE, bridgeUID, id);
154
155         thingRemoved(thingUID);
156     }
157 }