2 * Copyright (c) 2010-2021 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.miele.internal.discovery;
15 import static org.openhab.binding.miele.internal.MieleBindingConstants.*;
17 import java.util.Date;
18 import java.util.HashMap;
19 import java.util.List;
23 import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
24 import org.openhab.binding.miele.internal.handler.ApplianceStatusListener;
25 import org.openhab.binding.miele.internal.handler.MieleApplianceHandler;
26 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler;
27 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceClassObject;
28 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.DeviceProperty;
29 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler.HomeDevice;
30 import org.openhab.core.config.discovery.AbstractDiscoveryService;
31 import org.openhab.core.config.discovery.DiscoveryResult;
32 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
33 import org.openhab.core.thing.ThingTypeUID;
34 import org.openhab.core.thing.ThingUID;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 import com.google.gson.JsonElement;
41 * The {@link MieleApplianceDiscoveryService} tracks appliances that are
42 * associated with the Miele@Home gateway
44 * @author Karel Goderis - Initial contribution
45 * @author Martin Lepsy - Added protocol information in order so support WiFi devices
46 * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
48 public class MieleApplianceDiscoveryService extends AbstractDiscoveryService implements ApplianceStatusListener {
50 private static final String MIELE_APPLIANCE_CLASS = "com.miele.xgw3000.gateway.hdm.deviceclasses.MieleAppliance";
51 private static final String MIELE_CLASS = "com.miele.xgw3000.gateway.hdm.deviceclasses.Miele";
53 private final Logger logger = LoggerFactory.getLogger(MieleApplianceDiscoveryService.class);
55 private static final int SEARCH_TIME = 60;
57 private MieleBridgeHandler mieleBridgeHandler;
59 public MieleApplianceDiscoveryService(MieleBridgeHandler mieleBridgeHandler) {
60 super(MieleApplianceHandler.SUPPORTED_THING_TYPES, SEARCH_TIME, false);
61 this.mieleBridgeHandler = mieleBridgeHandler;
64 public void activate() {
65 mieleBridgeHandler.registerApplianceStatusListener(this);
69 public void deactivate() {
70 removeOlderResults(new Date().getTime());
71 mieleBridgeHandler.unregisterApplianceStatusListener(this);
75 public Set<ThingTypeUID> getSupportedThingTypes() {
76 return MieleApplianceHandler.SUPPORTED_THING_TYPES;
80 public void startScan() {
81 List<HomeDevice> appliances = mieleBridgeHandler.getHomeDevices();
82 if (appliances != null) {
83 for (HomeDevice l : appliances) {
84 onApplianceAddedInternal(l);
90 protected synchronized void stopScan() {
92 removeOlderResults(getTimestampOfLastScan());
96 public void onApplianceAdded(HomeDevice appliance) {
97 onApplianceAddedInternal(appliance);
100 private void onApplianceAddedInternal(HomeDevice appliance) {
101 ThingUID thingUID = getThingUID(appliance);
102 if (thingUID != null) {
103 ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID();
104 Map<String, Object> properties = new HashMap<>(2);
106 FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier();
107 properties.put(PROTOCOL_PROPERTY_NAME, applianceIdentifier.getProtocol());
108 properties.put(APPLIANCE_ID, applianceIdentifier.getApplianceId());
109 properties.put(SERIAL_NUMBER_PROPERTY_NAME, appliance.getSerialNumber());
111 for (JsonElement dc : appliance.DeviceClasses) {
112 String dcStr = dc.getAsString();
113 if (dcStr.contains(MIELE_CLASS) && !dcStr.equals(MIELE_APPLIANCE_CLASS)) {
114 properties.put(DEVICE_CLASS, dcStr.substring(MIELE_CLASS.length()));
119 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
120 .withBridge(bridgeUID).withLabel((String) properties.get(DEVICE_CLASS))
121 .withRepresentationProperty(APPLIANCE_ID).build();
123 thingDiscovered(discoveryResult);
125 logger.debug("Discovered an unsupported appliance of vendor '{}' with id {}", appliance.Vendor,
131 public void onApplianceRemoved(HomeDevice appliance) {
132 ThingUID thingUID = getThingUID(appliance);
134 if (thingUID != null) {
135 thingRemoved(thingUID);
140 public void onApplianceStateChanged(FullyQualifiedApplianceIdentifier applianceIdentifier, DeviceClassObject dco) {
145 public void onAppliancePropertyChanged(FullyQualifiedApplianceIdentifier applianceIdentifier, DeviceProperty dp) {
150 public void onAppliancePropertyChanged(String serialNumber, DeviceProperty dp) {
154 private ThingUID getThingUID(HomeDevice appliance) {
155 ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID();
156 String modelID = null;
158 for (JsonElement dc : appliance.DeviceClasses) {
159 String dcStr = dc.getAsString();
160 if (dcStr.contains(MIELE_CLASS) && !dcStr.equals(MIELE_APPLIANCE_CLASS)) {
161 modelID = dcStr.substring(MIELE_CLASS.length());
166 if (modelID != null) {
167 ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID,
168 modelID.replaceAll("[^a-zA-Z0-9_]", "_").toLowerCase());
170 if (getSupportedThingTypes().contains(thingTypeUID)) {
171 ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, appliance.getApplianceIdentifier().getId());