2 * Copyright (c) 2010-2024 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;
19 import java.util.Optional;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.mielecloud.internal.handler.MieleBridgeHandler;
24 import org.openhab.binding.mielecloud.internal.webservice.api.DeviceState;
25 import org.openhab.binding.mielecloud.internal.webservice.api.json.DeviceType;
26 import org.openhab.core.config.discovery.AbstractThingHandlerDiscoveryService;
27 import org.openhab.core.config.discovery.DiscoveryResult;
28 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
29 import org.openhab.core.config.discovery.DiscoveryService;
30 import org.openhab.core.thing.Thing;
31 import org.openhab.core.thing.ThingTypeUID;
32 import org.openhab.core.thing.ThingUID;
33 import org.osgi.service.component.annotations.Component;
34 import org.osgi.service.component.annotations.ServiceScope;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * Discovery service for things linked to a Miele cloud account.
41 * @author Roland Edelhoff - Initial contribution
42 * @author Björn Lange - Do not directly listen to webservice events
44 @Component(scope = ServiceScope.PROTOTYPE, service = ThingDiscoveryService.class)
46 public class ThingDiscoveryService extends AbstractThingHandlerDiscoveryService<MieleBridgeHandler> {
47 private static final int BACKGROUND_DISCOVERY_TIMEOUT_IN_SECONDS = 5;
49 private final Logger logger = LoggerFactory.getLogger(this.getClass());
51 private boolean discoveringDevices = false;
54 * Creates a new {@link ThingDiscoveryService}.
56 public ThingDiscoveryService() {
57 super(MieleBridgeHandler.class, SUPPORTED_THING_TYPES, BACKGROUND_DISCOVERY_TIMEOUT_IN_SECONDS);
61 private ThingUID getBridgeUid() {
62 var bridgeHandler = this.thingHandler;
63 if (bridgeHandler == null) {
66 return bridgeHandler.getThing().getUID();
71 protected void startScan() {
75 public void activate() {
76 super.activate(Map.of(DiscoveryService.CONFIG_PROPERTY_BACKGROUND_DISCOVERY, true));
80 public void dispose() {
82 removeOlderResults(System.currentTimeMillis(), getBridgeUid());
86 * Invoked when a device state update is received from the Miele cloud.
88 public void onDeviceStateUpdated(DeviceState deviceState) {
89 if (!discoveringDevices) {
93 Optional<ThingTypeUID> thingTypeUid = getThingTypeUID(deviceState);
94 if (thingTypeUid.isPresent()) {
95 createDiscoveryResult(deviceState, thingTypeUid.get());
97 logger.debug("Unsupported Miele device type: {}", deviceState.getType().orElse("<Empty>"));
101 private void createDiscoveryResult(DeviceState deviceState, ThingTypeUID thingTypeUid) {
102 ThingUID thingUid = new ThingUID(thingTypeUid, thingHandler.getThing().getUID(),
103 deviceState.getDeviceIdentifier());
105 DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(thingUid)
106 .withBridge(thingHandler.getThing().getUID()).withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER)
107 .withLabel(getLabel(deviceState));
109 ThingInformationExtractor.extractProperties(thingTypeUid, deviceState).entrySet()
110 .forEach(entry -> discoveryResultBuilder.withProperty(entry.getKey(), entry.getValue()));
112 DiscoveryResult result = discoveryResultBuilder.build();
114 thingDiscovered(result);
117 private Optional<ThingTypeUID> getThingTypeUID(DeviceState deviceState) {
118 switch (deviceState.getRawType()) {
120 return Optional.of(THING_TYPE_COFFEE_SYSTEM);
122 return Optional.of(THING_TYPE_DRYER);
123 case WASHING_MACHINE:
124 return Optional.of(THING_TYPE_WASHING_MACHINE);
126 return Optional.of(THING_TYPE_WASHER_DRYER);
128 return Optional.of(THING_TYPE_FREEZER);
130 return Optional.of(THING_TYPE_FRIDGE);
131 case FRIDGE_FREEZER_COMBINATION:
132 return Optional.of(THING_TYPE_FRIDGE_FREEZER);
135 return Optional.of(THING_TYPE_HOB);
137 return Optional.of(THING_TYPE_DISHWASHER);
141 case STEAM_OVEN_COMBINATION:
142 case STEAM_OVEN_MICROWAVE_COMBINATION:
144 return Optional.of(THING_TYPE_OVEN);
146 case WINE_STORAGE_CONDITIONING_UNIT:
147 case WINE_CONDITIONING_UNIT:
148 case WINE_CABINET_FREEZER_COMBINATION:
149 return Optional.of(THING_TYPE_WINE_STORAGE);
151 return Optional.of(THING_TYPE_HOOD);
153 return Optional.of(THING_TYPE_DISH_WARMER);
155 return Optional.of(THING_TYPE_ROBOTIC_VACUUM_CLEANER);
158 if (deviceState.getRawType() != DeviceType.UNKNOWN) {
159 logger.warn("Found no matching thing type for device type {}", deviceState.getRawType());
161 return Optional.empty();
166 protected void startBackgroundDiscovery() {
167 logger.debug("Starting background discovery");
169 removeOlderResults(System.currentTimeMillis(), getBridgeUid());
170 discoveringDevices = true;
174 protected void stopBackgroundDiscovery() {
175 logger.debug("Stopping background discovery");
176 discoveringDevices = false;
180 * Invoked when a device is removed from the Miele cloud.
182 public void onDeviceRemoved(String deviceIdentifier) {
183 removeOlderResults(System.currentTimeMillis(), getBridgeUid());
186 private String getLabel(DeviceState deviceState) {
187 Optional<String> deviceName = deviceState.getDeviceName();
188 if (deviceName.isPresent()) {
189 return deviceName.get();
192 return ThingInformationExtractor.getDeviceAndTechType(deviceState).orElse("Miele Device");
196 public void initialize() {
197 thingHandler.setDiscoveryService(this);