2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.jeelink.internal.discovery;
15 import static org.openhab.binding.jeelink.internal.JeeLinkBindingConstants.*;
17 import java.util.List;
18 import java.util.concurrent.atomic.AtomicBoolean;
20 import org.openhab.binding.jeelink.internal.JeeLinkHandler;
21 import org.openhab.binding.jeelink.internal.Reading;
22 import org.openhab.binding.jeelink.internal.ReadingHandler;
23 import org.openhab.binding.jeelink.internal.SensorDefinition;
24 import org.openhab.binding.jeelink.internal.config.JeeLinkSensorConfig;
25 import org.openhab.core.config.discovery.AbstractDiscoveryService;
26 import org.openhab.core.config.discovery.DiscoveryResult;
27 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
28 import org.openhab.core.thing.Thing;
29 import org.openhab.core.thing.ThingUID;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
34 * Discovery service for sensors connected to a JeeLink USB Receiver.
36 * @author Volker Bier - Initial contribution
38 public class SensorDiscoveryService extends AbstractDiscoveryService implements ReadingHandler<Reading> {
39 private static final int DISCOVER_TIMEOUT_SECONDS = 30;
41 private final Logger logger = LoggerFactory.getLogger(SensorDiscoveryService.class);
43 JeeLinkHandler bridge;
44 AtomicBoolean capture = new AtomicBoolean();
47 * Creates the discovery service for the given handler and converter.
49 public SensorDiscoveryService(JeeLinkHandler jeeLinkHandler) {
50 super(SUPPORTED_SENSOR_THING_TYPES_UIDS, DISCOVER_TIMEOUT_SECONDS, true);
52 bridge = jeeLinkHandler;
56 protected synchronized void startScan() {
57 if (!capture.getAndSet(true)) {
58 logger.debug("discovery started for bridge {}", bridge.getThing().getUID());
60 // start listening for new sensor values
61 bridge.addReadingHandler(this);
67 protected void startBackgroundDiscovery() {
72 protected synchronized void stopScan() {
73 if (capture.getAndSet(false)) {
74 bridge.removeReadingHandler(this);
75 logger.debug("discovery stopped for bridge {}", bridge.getThing().getUID());
80 protected void stopBackgroundDiscovery() {
84 private boolean idExistsAtBridge(String id) {
85 List<Thing> existingThings = bridge.getThing().getThings();
86 boolean idExists = false;
87 for (Thing t : existingThings) {
88 idExists = idExists || t.getUID().getId().equals(id);
94 public void handleReading(Reading reading) {
95 final String id = reading.getSensorId();
97 List<Thing> existingThings = bridge.getThing().getThings();
98 boolean sensorThingExists = false;
100 for (Thing t : existingThings) {
101 sensorThingExists = sensorThingExists
102 || id.equals(t.getConfiguration().as(JeeLinkSensorConfig.class).sensorId);
105 ThingUID bridgeUID = bridge.getThing().getUID();
107 if (!sensorThingExists) {
108 SensorDefinition<?> def = SensorDefinition.getSensorDefinition(reading);
109 logger.debug("discovery for bridge {} found unknown sensor of type {} with id {}", bridgeUID,
110 def.getThingTypeUID(), id);
112 boolean idExists = idExistsAtBridge(id);
116 logger.debug("bridge {} already has a connected sensor with thing id {}", bridgeUID, id);
120 newId = id + "-" + idx++;
121 idExists = idExistsAtBridge(newId);
124 logger.debug("Bridge {} uses thing id {} instead of {}", bridgeUID, newId, id);
127 ThingUID sensorThing = new ThingUID(def.getThingTypeUID(), bridgeUID, newId);
129 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(sensorThing).withLabel(def.getName())
130 .withBridge(bridgeUID).withRepresentationProperty("id").withProperty(PROPERTY_SENSOR_ID, id)
132 thingDiscovered(discoveryResult);
134 logger.debug("discovery for bridge {} found already known sensor id {}", bridgeUID, id);
139 public Class<Reading> getReadingClass() {
140 return Reading.class;
144 public String getSensorType() {
145 return SensorDefinition.ALL_TYPE;