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.vesync.internal.discovery;
15 import static org.openhab.binding.vesync.internal.VeSyncConstants.*;
17 import java.util.Collections;
18 import java.util.HashMap;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.vesync.internal.handlers.VeSyncBaseDeviceHandler;
25 import org.openhab.binding.vesync.internal.handlers.VeSyncBridgeHandler;
26 import org.openhab.binding.vesync.internal.handlers.VeSyncDeviceAirHumidifierHandler;
27 import org.openhab.binding.vesync.internal.handlers.VeSyncDeviceAirPurifierHandler;
28 import org.openhab.core.config.discovery.AbstractDiscoveryService;
29 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
30 import org.openhab.core.config.discovery.DiscoveryService;
31 import org.openhab.core.thing.ThingStatus;
32 import org.openhab.core.thing.ThingTypeUID;
33 import org.openhab.core.thing.ThingUID;
34 import org.openhab.core.thing.binding.ThingHandler;
35 import org.openhab.core.thing.binding.ThingHandlerService;
36 import org.osgi.service.component.annotations.Component;
39 * The {@link VeSyncDiscoveryService} is an implementation of a discovery service for VeSync devices. The meta-data is
40 * read by the bridge, and the discovery data updated via a callback implemented by the DeviceMetaDataUpdatedHandler.
42 * @author David Godyear - Initial contribution
45 @Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.vesync")
46 public class VeSyncDiscoveryService extends AbstractDiscoveryService
47 implements DiscoveryService, ThingHandlerService, DeviceMetaDataUpdatedHandler {
49 private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE);
51 private static final int DISCOVER_TIMEOUT_SECONDS = 5;
53 private @NonNullByDefault({}) VeSyncBridgeHandler bridgeHandler;
54 private @NonNullByDefault({}) ThingUID bridgeUID;
57 * Creates a VeSyncDiscoveryService with enabled autostart.
59 public VeSyncDiscoveryService() {
60 super(SUPPORTED_THING_TYPES, DISCOVER_TIMEOUT_SECONDS);
64 public Set<ThingTypeUID> getSupportedThingTypes() {
65 return SUPPORTED_THING_TYPES;
69 public void activate() {
70 final Map<String, Object> properties = new HashMap<>();
71 properties.put(DiscoveryService.CONFIG_PROPERTY_BACKGROUND_DISCOVERY, Boolean.TRUE);
72 super.activate(properties);
76 public void deactivate() {
81 public void setThingHandler(@Nullable ThingHandler handler) {
82 if (handler instanceof VeSyncBridgeHandler) {
83 bridgeHandler = (VeSyncBridgeHandler) handler;
84 bridgeUID = bridgeHandler.getUID();
89 public @Nullable ThingHandler getThingHandler() {
94 protected void startBackgroundDiscovery() {
95 if (bridgeHandler != null) {
96 bridgeHandler.registerMetaDataUpdatedHandler(this);
101 protected void stopBackgroundDiscovery() {
102 if (bridgeHandler != null) {
103 bridgeHandler.unregisterMetaDataUpdatedHandler(this);
108 protected void startScan() {
109 // If the bridge is not online no other thing devices can be found, so no reason to scan at this moment.
110 removeOlderResults(getTimestampOfLastScan());
111 if (ThingStatus.ONLINE.equals(bridgeHandler.getThing().getStatus())) {
112 bridgeHandler.runDeviceScanSequenceNoAuthErrors();
117 public void handleMetadataRetrieved(VeSyncBridgeHandler handler) {
118 bridgeHandler.getAirPurifiersMetadata().map(apMeta -> {
119 final Map<String, Object> properties = new HashMap<>(6);
120 final String deviceUUID = apMeta.getUuid();
121 properties.put(DEVICE_PROP_DEVICE_NAME, apMeta.getDeviceName());
122 properties.put(DEVICE_PROP_DEVICE_TYPE, apMeta.getDeviceType());
123 properties.put(DEVICE_PROP_DEVICE_FAMILY,
124 VeSyncBaseDeviceHandler.getDeviceFamilyMetadata(apMeta.getDeviceType(),
125 VeSyncDeviceAirHumidifierHandler.DEV_TYPE_FAMILY_AIR_HUMIDIFIER,
126 VeSyncDeviceAirHumidifierHandler.SUPPORTED_MODEL_FAMILIES));
127 properties.put(DEVICE_PROP_DEVICE_MAC_ID, apMeta.getMacId());
128 properties.put(DEVICE_PROP_DEVICE_UUID, deviceUUID);
129 properties.put(DEVICE_PROP_CONFIG_DEVICE_MAC, apMeta.getMacId());
130 properties.put(DEVICE_PROP_CONFIG_DEVICE_NAME, apMeta.getDeviceName());
131 return DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_AIR_PURIFIER, bridgeUID, deviceUUID))
132 .withLabel(apMeta.getDeviceName()).withBridge(bridgeUID).withProperties(properties)
133 .withRepresentationProperty(DEVICE_PROP_DEVICE_MAC_ID).build();
134 }).forEach(this::thingDiscovered);
136 bridgeHandler.getAirHumidifiersMetadata().map(apMeta -> {
137 final Map<String, Object> properties = new HashMap<>(6);
138 final String deviceUUID = apMeta.getUuid();
139 properties.put(DEVICE_PROP_DEVICE_NAME, apMeta.getDeviceName());
140 properties.put(DEVICE_PROP_DEVICE_TYPE, apMeta.getDeviceType());
141 properties.put(DEVICE_PROP_DEVICE_FAMILY,
142 VeSyncBaseDeviceHandler.getDeviceFamilyMetadata(apMeta.getDeviceType(),
143 VeSyncDeviceAirPurifierHandler.DEV_TYPE_FAMILY_AIR_PURIFIER,
144 VeSyncDeviceAirPurifierHandler.SUPPORTED_MODEL_FAMILIES));
145 properties.put(DEVICE_PROP_DEVICE_MAC_ID, apMeta.getMacId());
146 properties.put(DEVICE_PROP_DEVICE_UUID, deviceUUID);
147 properties.put(DEVICE_PROP_CONFIG_DEVICE_MAC, apMeta.getMacId());
148 properties.put(DEVICE_PROP_CONFIG_DEVICE_NAME, apMeta.getDeviceName());
149 return DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_AIR_HUMIDIFIER, bridgeUID, deviceUUID))
150 .withLabel(apMeta.getDeviceName()).withBridge(bridgeUID).withProperties(properties)
151 .withRepresentationProperty(DEVICE_PROP_DEVICE_MAC_ID).build();
152 }).forEach(this::thingDiscovered);