]> git.basschouten.com Git - openhab-addons.git/blob
614eeb50e41c2e1270d5ce2340c8070e64813506
[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.airgradient.internal.discovery;
14
15 import static org.openhab.binding.airgradient.internal.AirGradientBindingConstants.BACKGROUND_DISCOVERY;
16 import static org.openhab.binding.airgradient.internal.AirGradientBindingConstants.CONFIG_LOCATION;
17 import static org.openhab.binding.airgradient.internal.AirGradientBindingConstants.PROPERTY_NAME;
18 import static org.openhab.binding.airgradient.internal.AirGradientBindingConstants.SEARCH_TIME;
19 import static org.openhab.binding.airgradient.internal.AirGradientBindingConstants.THING_TYPE_LOCATION;
20
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Set;
26
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.openhab.binding.airgradient.internal.communication.AirGradientCommunicationException;
30 import org.openhab.binding.airgradient.internal.handler.AirGradientAPIHandler;
31 import org.openhab.binding.airgradient.internal.handler.PollEventListener;
32 import org.openhab.binding.airgradient.internal.model.Measure;
33 import org.openhab.core.config.discovery.AbstractDiscoveryService;
34 import org.openhab.core.config.discovery.DiscoveryResult;
35 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingUID;
38 import org.openhab.core.thing.binding.BridgeHandler;
39 import org.openhab.core.thing.binding.ThingHandler;
40 import org.openhab.core.thing.binding.ThingHandlerService;
41 import org.osgi.service.component.annotations.Component;
42 import org.osgi.service.component.annotations.ServiceScope;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * The {@link AirGradientLocationDiscoveryService} is responsible for discovering new locations
48  * that are not bound to any items.
49  *
50  * @author Jørgen Austvik - Initial contribution
51  */
52 @Component(scope = ServiceScope.PROTOTYPE, service = AirGradientLocationDiscoveryService.class)
53 @NonNullByDefault
54 public class AirGradientLocationDiscoveryService extends AbstractDiscoveryService
55         implements ThingHandlerService, PollEventListener {
56
57     private final Logger logger = LoggerFactory.getLogger(AirGradientLocationDiscoveryService.class);
58
59     private @NonNullByDefault({}) AirGradientAPIHandler apiHandler;
60
61     public AirGradientLocationDiscoveryService() {
62         super(Set.of(THING_TYPE_LOCATION), (int) SEARCH_TIME.getSeconds(), BACKGROUND_DISCOVERY);
63     }
64
65     @Override
66     protected void startBackgroundDiscovery() {
67         logger.debug("Start AirGradient background discovery");
68         apiHandler.addPollEventListener(this);
69     }
70
71     @Override
72     protected void stopBackgroundDiscovery() {
73         logger.debug("Stopping AirGradient background discovery");
74         apiHandler.removePollEventListener(this);
75     }
76
77     @Override
78     public void pollEvent(List<Measure> measures) {
79         BridgeHandler bridge = apiHandler.getThing().getHandler();
80         if (bridge == null) {
81             logger.debug("Missing bridge, can't discover sensors for unknown bridge.");
82             return;
83         }
84
85         ThingUID bridgeUid = bridge.getThing().getUID();
86
87         Set<String> registeredLocationIds = new HashSet<>(apiHandler.getRegisteredLocationIds());
88         for (Measure measure : measures) {
89             String id = measure.getLocationId();
90             if (id.isEmpty()) {
91                 // Local devices don't have location ID.
92                 id = measure.getSerialNo();
93             }
94
95             String name = measure.getLocationName();
96             if (name.isEmpty()) {
97                 name = "Sensor_" + measure.getSerialNo();
98             }
99
100             if (!registeredLocationIds.contains(id)) {
101                 Map<String, Object> properties = new HashMap<>(5);
102                 properties.put(PROPERTY_NAME, name);
103                 properties.put(Thing.PROPERTY_FIRMWARE_VERSION, measure.getFirmwareVersion());
104                 properties.put(Thing.PROPERTY_SERIAL_NUMBER, measure.getSerialNo());
105                 String model = measure.getModel();
106                 if (model != null) {
107                     properties.put(Thing.PROPERTY_MODEL_ID, model);
108                 }
109                 properties.put(CONFIG_LOCATION, id);
110
111                 ThingUID thingUID = new ThingUID(THING_TYPE_LOCATION, bridgeUid, id);
112
113                 logger.debug("Adding location {} with id {} to bridge {} with location id {}", name, thingUID,
114                         bridgeUid, measure.getLocationId());
115                 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
116                         .withBridge(bridgeUid).withLabel(name).withRepresentationProperty(CONFIG_LOCATION).build();
117
118                 thingDiscovered(discoveryResult);
119             }
120         }
121     }
122
123     @Override
124     protected void startScan() {
125         try {
126             List<Measure> measures = apiHandler.getApiController().getMeasures();
127             pollEvent(measures);
128         } catch (AirGradientCommunicationException agce) {
129             logger.warn("Failed discovery due to communication exception: {}", agce.getMessage());
130         }
131     }
132
133     @Override
134     public void setThingHandler(ThingHandler handler) {
135         if (handler instanceof AirGradientAPIHandler airGradientAPIHandler) {
136             this.apiHandler = airGradientAPIHandler;
137         }
138     }
139
140     @Override
141     public @Nullable ThingHandler getThingHandler() {
142         return apiHandler;
143     }
144
145     @Override
146     public void activate() {
147         super.activate(null);
148     }
149
150     @Override
151     public void deactivate() {
152         super.deactivate();
153     }
154 }