]> git.basschouten.com Git - openhab-addons.git/blob
bf13aa727ecca2471346d4cf67cfee1119784fdd
[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.modbus.discovery.internal;
14
15 import java.util.Set;
16 import java.util.concurrent.CopyOnWriteArraySet;
17
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.openhab.binding.modbus.discovery.ModbusDiscoveryParticipant;
20 import org.openhab.core.config.discovery.AbstractDiscoveryService;
21 import org.openhab.core.config.discovery.DiscoveryResult;
22 import org.openhab.core.config.discovery.DiscoveryService;
23 import org.openhab.core.thing.ThingTypeUID;
24 import org.osgi.service.component.annotations.Component;
25 import org.osgi.service.component.annotations.Reference;
26 import org.osgi.service.component.annotations.ReferenceCardinality;
27 import org.osgi.service.component.annotations.ReferencePolicy;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  *
33  * Discovery service for Modbus bridges.
34  *
35  * This service acts as a rendezvous point between the different Modbus endpoints and any
36  * bundles that implement auto discovery through an endpoint.
37  *
38  * New bridges (TCP or Serial Modbus endpoint) should register with this service. This is
39  * handled automatically by the ModbusEndpointDiscoveryService.
40  * Also any bundles that perform auto discovery should register a ModbusDiscoveryParticipant.
41  * This ModbusDiscoveryParticipants will be called by the service when
42  * a discovery scan is requested.
43  *
44  * @author Nagy Attila Gabor - initial contribution
45  *
46  */
47 @Component(service = DiscoveryService.class, configurationPid = "discovery.modbus")
48 @NonNullByDefault
49 public class ModbusDiscoveryService extends AbstractDiscoveryService {
50
51     private final Logger logger = LoggerFactory.getLogger(ModbusDiscoveryService.class);
52
53     // Set of services that support Modbus discovery
54     private final Set<ModbusThingHandlerDiscoveryService> services = new CopyOnWriteArraySet<>();
55
56     // Set of the registered participants
57     private final Set<ModbusDiscoveryParticipant> participants = new CopyOnWriteArraySet<>();
58
59     // Set of the supported thing types. This is a union of all the thing types
60     // supported by the registered discovery services.
61     private final Set<ThingTypeUID> supportedThingTypes = new CopyOnWriteArraySet<>();
62
63     private static final int SEARCH_TIME_SECS = 5;
64
65     /**
66      * Constructor for the discovery service.
67      * Set up default parameters
68      */
69     public ModbusDiscoveryService() {
70         // No supported thing types by default
71         // Search time is for the visual reference
72         // Background discovery disabled by default
73         super(null, SEARCH_TIME_SECS, false);
74     }
75
76     /**
77      * ThingHandlerService
78      * Begin a discovery scan over each endpoint
79      */
80     @Override
81     protected void startScan() {
82         logger.trace("ModbusDiscoveryService starting scan");
83
84         if (participants.isEmpty()) {
85             // There's no point on continuing if there are no participants at the moment
86             stopScan();
87             return;
88         }
89
90         boolean scanStarted = false;
91         for (ModbusThingHandlerDiscoveryService service : services) {
92             scanStarted |= service.startScan(this);
93         }
94         if (!scanStarted) {
95             stopScan();
96         }
97     }
98
99     /**
100      * Interface to notify us when a handler has finished it's discovery process
101      */
102     protected void scanFinished() {
103         for (ModbusThingHandlerDiscoveryService service : services) {
104             if (service.scanInProgress()) {
105                 return;
106             }
107         }
108         logger.trace("All endpoints finished scanning, stopping scan");
109         stopScan();
110     }
111
112     /**
113      * Real discovery is done by the ModbusDiscoveryParticipants
114      * They are executed in series for each Modbus endpoint by ModbusDiscoveryProcess
115      * instances. They call back this method when a thing has been discovered
116      */
117     @Override
118     protected void thingDiscovered(DiscoveryResult discoveryResult) {
119         super.thingDiscovered(discoveryResult);
120     }
121
122     /**
123      * Returns the list of {@code Thing} types which are supported by the {@link DiscoveryService}.
124      *
125      * @return the list of Thing types which are supported by the discovery service
126      *         (not null, could be empty)
127      */
128     @Override
129     public Set<ThingTypeUID> getSupportedThingTypes() {
130         return this.supportedThingTypes;
131     }
132
133     /**
134      * This reference is used to register any new Modbus bridge with the discovery service
135      * Running bridges have a ModbusThingHandlerDiscoveryService connected
136      * which will be responsible for the discovery
137      *
138      * @param handler the Modbus bridge handler
139      */
140     @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
141     protected void addModbusEndpoint(ModbusThingHandlerDiscoveryService service) {
142         logger.trace("Received new handler: {}", service);
143         services.add(service);
144     }
145
146     /**
147      * Remove an already registered thing handler discovery component
148      *
149      * @param handler the handler that has been removed
150      */
151     protected void removeModbusEndpoint(ModbusThingHandlerDiscoveryService service) {
152         logger.trace("Removed handler: {}", service);
153         services.remove(service);
154     }
155
156     /**
157      * Register a discovery participant. This participant will be called
158      * with any new Modbus bridges that allow discovery
159      *
160      * @param participant
161      */
162     @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
163     protected void addModbusDiscoveryParticipant(ModbusDiscoveryParticipant participant) {
164         logger.trace("Received new participant: {}", participant);
165         participants.add(participant);
166         supportedThingTypes.addAll(participant.getSupportedThingTypeUIDs());
167     }
168
169     /**
170      * Remove an already registered discovery participant
171      *
172      * @param participant
173      */
174     protected void removeModbusDiscoveryParticipant(ModbusDiscoveryParticipant participant) {
175         logger.trace("Removing participant: {}", participant);
176         supportedThingTypes.removeAll(participant.getSupportedThingTypeUIDs());
177         participants.remove(participant);
178     }
179
180     /**
181      * Return the set of participants
182      *
183      * @return a set of the participants. Note: this is a copy of the original set
184      */
185     public Set<ModbusDiscoveryParticipant> getDiscoveryParticipants() {
186         return new CopyOnWriteArraySet<>(participants);
187     }
188 }