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