]> git.basschouten.com Git - openhab-addons.git/blob
bd6fd30c85699ebbb0e7b999e3bf652f3d1f477e
[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.mielecloud.internal.discovery;
14
15 import static org.openhab.binding.mielecloud.internal.MieleCloudBindingConstants.*;
16 import static org.openhab.binding.mielecloud.internal.handler.MieleHandlerFactory.SUPPORTED_THING_TYPES;
17
18 import java.util.Optional;
19
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;
36
37 /**
38  * Discovery service for things linked to a Miele cloud account.
39  *
40  * @author Roland Edelhoff - Initial contribution
41  * @author Björn Lange - Do not directly listen to webservice events
42  */
43 @NonNullByDefault
44 public class ThingDiscoveryService extends AbstractDiscoveryService implements DiscoveryService, ThingHandlerService {
45     private static final int BACKGROUND_DISCOVERY_TIMEOUT_IN_SECONDS = 5;
46
47     @Nullable
48     private MieleBridgeHandler bridgeHandler;
49
50     private final Logger logger = LoggerFactory.getLogger(this.getClass());
51
52     private boolean discoveringDevices = false;
53
54     /**
55      * Creates a new {@link ThingDiscoveryService}.
56      */
57     public ThingDiscoveryService() {
58         super(SUPPORTED_THING_TYPES, BACKGROUND_DISCOVERY_TIMEOUT_IN_SECONDS);
59     }
60
61     @Nullable
62     private ThingUID getBridgeUid() {
63         var bridgeHandler = this.bridgeHandler;
64         if (bridgeHandler == null) {
65             return null;
66         } else {
67             return bridgeHandler.getThing().getUID();
68         }
69     }
70
71     @Override
72     protected void startScan() {
73     }
74
75     @Override
76     public void activate() {
77         startBackgroundDiscovery();
78     }
79
80     @Override
81     public void deactivate() {
82         stopBackgroundDiscovery();
83         removeOlderResults(System.currentTimeMillis(), getBridgeUid());
84     }
85
86     /**
87      * Invoked when a device state update is received from the Miele cloud.
88      */
89     public void onDeviceStateUpdated(DeviceState deviceState) {
90         if (!discoveringDevices) {
91             return;
92         }
93
94         Optional<ThingTypeUID> thingTypeUid = getThingTypeUID(deviceState);
95         if (thingTypeUid.isPresent()) {
96             createDiscoveryResult(deviceState, thingTypeUid.get());
97         } else {
98             logger.debug("Unsupported Miele device type: {}", deviceState.getType().orElse("<Empty>"));
99         }
100     }
101
102     private void createDiscoveryResult(DeviceState deviceState, ThingTypeUID thingTypeUid) {
103         MieleBridgeHandler bridgeHandler = this.bridgeHandler;
104         if (bridgeHandler == null) {
105             return;
106         }
107
108         ThingUID thingUid = new ThingUID(thingTypeUid, bridgeHandler.getThing().getUID(),
109                 deviceState.getDeviceIdentifier());
110
111         DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(thingUid)
112                 .withBridge(bridgeHandler.getThing().getUID()).withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER)
113                 .withLabel(getLabel(deviceState));
114
115         ThingInformationExtractor.extractProperties(thingTypeUid, deviceState).entrySet()
116                 .forEach(entry -> discoveryResultBuilder.withProperty(entry.getKey(), entry.getValue()));
117
118         DiscoveryResult result = discoveryResultBuilder.build();
119
120         thingDiscovered(result);
121     }
122
123     private Optional<ThingTypeUID> getThingTypeUID(DeviceState deviceState) {
124         switch (deviceState.getRawType()) {
125             case COFFEE_SYSTEM:
126                 return Optional.of(THING_TYPE_COFFEE_SYSTEM);
127             case TUMBLE_DRYER:
128                 return Optional.of(THING_TYPE_DRYER);
129             case WASHING_MACHINE:
130                 return Optional.of(THING_TYPE_WASHING_MACHINE);
131             case WASHER_DRYER:
132                 return Optional.of(THING_TYPE_WASHER_DRYER);
133             case FREEZER:
134                 return Optional.of(THING_TYPE_FREEZER);
135             case FRIDGE:
136                 return Optional.of(THING_TYPE_FRIDGE);
137             case FRIDGE_FREEZER_COMBINATION:
138                 return Optional.of(THING_TYPE_FRIDGE_FREEZER);
139             case HOB_INDUCTION:
140             case HOB_HIGHLIGHT:
141                 return Optional.of(THING_TYPE_HOB);
142             case DISHWASHER:
143                 return Optional.of(THING_TYPE_DISHWASHER);
144             case OVEN:
145             case OVEN_MICROWAVE:
146             case STEAM_OVEN:
147             case STEAM_OVEN_COMBINATION:
148             case STEAM_OVEN_MICROWAVE_COMBINATION:
149             case DIALOGOVEN:
150                 return Optional.of(THING_TYPE_OVEN);
151             case WINE_CABINET:
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);
156             case HOOD:
157                 return Optional.of(THING_TYPE_HOOD);
158             case DISH_WARMER:
159                 return Optional.of(THING_TYPE_DISH_WARMER);
160             case VACUUM_CLEANER:
161                 return Optional.of(THING_TYPE_ROBOTIC_VACUUM_CLEANER);
162
163             default:
164                 if (deviceState.getRawType() != DeviceType.UNKNOWN) {
165                     logger.warn("Found no matching thing type for device type {}", deviceState.getRawType());
166                 }
167                 return Optional.empty();
168         }
169     }
170
171     @Override
172     protected void startBackgroundDiscovery() {
173         logger.debug("Starting background discovery");
174
175         removeOlderResults(System.currentTimeMillis(), getBridgeUid());
176         discoveringDevices = true;
177     }
178
179     @Override
180     protected void stopBackgroundDiscovery() {
181         logger.debug("Stopping background discovery");
182         discoveringDevices = false;
183     }
184
185     /**
186      * Invoked when a device is removed from the Miele cloud.
187      */
188     public void onDeviceRemoved(String deviceIdentifier) {
189         removeOlderResults(System.currentTimeMillis(), getBridgeUid());
190     }
191
192     private String getLabel(DeviceState deviceState) {
193         Optional<String> deviceName = deviceState.getDeviceName();
194         if (deviceName.isPresent()) {
195             return deviceName.get();
196         }
197
198         return ThingInformationExtractor.getDeviceAndTechType(deviceState).orElse("Miele Device");
199     }
200
201     @Override
202     public void setThingHandler(ThingHandler handler) {
203         if (handler instanceof MieleBridgeHandler bridgeHandler) {
204             bridgeHandler.setDiscoveryService(this);
205             this.bridgeHandler = bridgeHandler;
206         }
207     }
208
209     @Override
210     public @Nullable ThingHandler getThingHandler() {
211         return bridgeHandler;
212     }
213 }