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.mielecloud.internal.discovery;
15 import static org.openhab.binding.mielecloud.internal.MieleCloudBindingConstants.*;
16 import static org.openhab.binding.mielecloud.internal.handler.MieleHandlerFactory.SUPPORTED_THING_TYPES;
18 import java.util.Optional;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.mielecloud.internal.handler.MieleBridgeHandler;
23 import org.openhab.binding.mielecloud.internal.webservice.api.DeviceState;
24 import org.openhab.binding.mielecloud.internal.webservice.api.json.DeviceType;
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.config.discovery.DiscoveryService;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingTypeUID;
31 import org.openhab.core.thing.ThingUID;
32 import org.openhab.core.thing.binding.ThingHandler;
33 import org.openhab.core.thing.binding.ThingHandlerService;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * Discovery service for things linked to a Miele cloud account.
40 * @author Roland Edelhoff - Initial contribution
41 * @author Björn Lange - Do not directly listen to webservice events
44 public class ThingDiscoveryService extends AbstractDiscoveryService implements DiscoveryService, ThingHandlerService {
45 private static final int BACKGROUND_DISCOVERY_TIMEOUT_IN_SECONDS = 5;
48 private MieleBridgeHandler bridgeHandler;
50 private final Logger logger = LoggerFactory.getLogger(this.getClass());
52 private boolean discoveringDevices = false;
55 * Creates a new {@link ThingDiscoveryService}.
57 public ThingDiscoveryService() {
58 super(SUPPORTED_THING_TYPES, BACKGROUND_DISCOVERY_TIMEOUT_IN_SECONDS);
62 private ThingUID getBridgeUid() {
63 var bridgeHandler = this.bridgeHandler;
64 if (bridgeHandler == null) {
67 return bridgeHandler.getThing().getUID();
72 protected void startScan() {
76 public void activate() {
77 startBackgroundDiscovery();
81 public void deactivate() {
82 stopBackgroundDiscovery();
83 removeOlderResults(System.currentTimeMillis(), getBridgeUid());
87 * Invoked when a device state update is received from the Miele cloud.
89 public void onDeviceStateUpdated(DeviceState deviceState) {
90 if (!discoveringDevices) {
94 Optional<ThingTypeUID> thingTypeUid = getThingTypeUID(deviceState);
95 if (thingTypeUid.isPresent()) {
96 createDiscoveryResult(deviceState, thingTypeUid.get());
98 logger.debug("Unsupported Miele device type: {}", deviceState.getType().orElse("<Empty>"));
102 private void createDiscoveryResult(DeviceState deviceState, ThingTypeUID thingTypeUid) {
103 MieleBridgeHandler bridgeHandler = this.bridgeHandler;
104 if (bridgeHandler == null) {
108 ThingUID thingUid = new ThingUID(thingTypeUid, bridgeHandler.getThing().getUID(),
109 deviceState.getDeviceIdentifier());
111 DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(thingUid)
112 .withBridge(bridgeHandler.getThing().getUID()).withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER)
113 .withLabel(getLabel(deviceState));
115 ThingInformationExtractor.extractProperties(thingTypeUid, deviceState).entrySet()
116 .forEach(entry -> discoveryResultBuilder.withProperty(entry.getKey(), entry.getValue()));
118 DiscoveryResult result = discoveryResultBuilder.build();
120 thingDiscovered(result);
123 private Optional<ThingTypeUID> getThingTypeUID(DeviceState deviceState) {
124 switch (deviceState.getRawType()) {
126 return Optional.of(THING_TYPE_COFFEE_SYSTEM);
128 return Optional.of(THING_TYPE_DRYER);
129 case WASHING_MACHINE:
130 return Optional.of(THING_TYPE_WASHING_MACHINE);
132 return Optional.of(THING_TYPE_WASHER_DRYER);
134 return Optional.of(THING_TYPE_FREEZER);
136 return Optional.of(THING_TYPE_FRIDGE);
137 case FRIDGE_FREEZER_COMBINATION:
138 return Optional.of(THING_TYPE_FRIDGE_FREEZER);
141 return Optional.of(THING_TYPE_HOB);
143 return Optional.of(THING_TYPE_DISHWASHER);
147 case STEAM_OVEN_COMBINATION:
148 case STEAM_OVEN_MICROWAVE_COMBINATION:
150 return Optional.of(THING_TYPE_OVEN);
152 case WINE_STORAGE_CONDITIONING_UNIT:
153 case WINE_CONDITIONING_UNIT:
154 case WINE_CABINET_FREEZER_COMBINATION:
155 return Optional.of(THING_TYPE_WINE_STORAGE);
157 return Optional.of(THING_TYPE_HOOD);
159 return Optional.of(THING_TYPE_DISH_WARMER);
161 return Optional.of(THING_TYPE_ROBOTIC_VACUUM_CLEANER);
164 if (deviceState.getRawType() != DeviceType.UNKNOWN) {
165 logger.warn("Found no matching thing type for device type {}", deviceState.getRawType());
167 return Optional.empty();
172 protected void startBackgroundDiscovery() {
173 logger.debug("Starting background discovery");
175 removeOlderResults(System.currentTimeMillis(), getBridgeUid());
176 discoveringDevices = true;
180 protected void stopBackgroundDiscovery() {
181 logger.debug("Stopping background discovery");
182 discoveringDevices = false;
186 * Invoked when a device is removed from the Miele cloud.
188 public void onDeviceRemoved(String deviceIdentifier) {
189 removeOlderResults(System.currentTimeMillis(), getBridgeUid());
192 private String getLabel(DeviceState deviceState) {
193 Optional<String> deviceName = deviceState.getDeviceName();
194 if (deviceName.isPresent()) {
195 return deviceName.get();
198 return ThingInformationExtractor.getDeviceAndTechType(deviceState).orElse("Miele Device");
202 public void setThingHandler(ThingHandler handler) {
203 if (handler instanceof MieleBridgeHandler) {
204 var bridgeHandler = (MieleBridgeHandler) handler;
205 bridgeHandler.setDiscoveryService(this);
206 this.bridgeHandler = bridgeHandler;
211 public @Nullable ThingHandler getThingHandler() {
212 return bridgeHandler;