2 * Copyright (c) 2010-2022 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.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.miele.internal.FullyQualifiedApplianceIdentifier;
26 import org.openhab.binding.miele.internal.api.dto.DeviceClassObject;
27 import org.openhab.binding.miele.internal.api.dto.DeviceProperty;
28 import org.openhab.binding.miele.internal.api.dto.HomeDevice;
29 import org.openhab.binding.miele.internal.handler.ApplianceStatusListener;
30 import org.openhab.binding.miele.internal.handler.MieleApplianceHandler;
31 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler;
32 import org.openhab.core.config.discovery.AbstractDiscoveryService;
33 import org.openhab.core.config.discovery.DiscoveryResult;
34 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
35 import org.openhab.core.thing.Thing;
36 import org.openhab.core.thing.ThingTypeUID;
37 import org.openhab.core.thing.ThingUID;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 * The {@link MieleApplianceDiscoveryService} tracks appliances that are
43 * associated with the Miele@Home gateway
45 * @author Karel Goderis - Initial contribution
46 * @author Martin Lepsy - Added protocol information in order so support WiFi devices
47 * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
50 public class MieleApplianceDiscoveryService extends AbstractDiscoveryService implements ApplianceStatusListener {
52 private final Logger logger = LoggerFactory.getLogger(MieleApplianceDiscoveryService.class);
54 private static final int SEARCH_TIME = 60;
56 private MieleBridgeHandler mieleBridgeHandler;
58 public MieleApplianceDiscoveryService(MieleBridgeHandler mieleBridgeHandler) {
59 super(MieleApplianceHandler.SUPPORTED_THING_TYPES, SEARCH_TIME, false);
60 this.mieleBridgeHandler = mieleBridgeHandler;
63 public void activate() {
64 mieleBridgeHandler.registerApplianceStatusListener(this);
68 public void deactivate() {
69 removeOlderResults(new Date().getTime());
70 mieleBridgeHandler.unregisterApplianceStatusListener(this);
74 public Set<ThingTypeUID> getSupportedThingTypes() {
75 return MieleApplianceHandler.SUPPORTED_THING_TYPES;
79 public void startScan() {
80 List<HomeDevice> appliances = mieleBridgeHandler.getHomeDevices();
81 for (HomeDevice l : appliances) {
82 onApplianceAddedInternal(l);
87 protected synchronized void stopScan() {
89 removeOlderResults(getTimestampOfLastScan());
93 public void onApplianceAdded(HomeDevice appliance) {
94 onApplianceAddedInternal(appliance);
97 private void onApplianceAddedInternal(HomeDevice appliance) {
98 ThingUID thingUID = getThingUID(appliance);
99 if (thingUID != null) {
100 ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID();
101 Map<String, Object> properties = new HashMap<>(9);
103 FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier();
104 String vendor = appliance.Vendor;
105 if (vendor != null) {
106 properties.put(Thing.PROPERTY_VENDOR, vendor);
108 properties.put(Thing.PROPERTY_MODEL_ID, appliance.getApplianceModel());
109 properties.put(Thing.PROPERTY_SERIAL_NUMBER, appliance.getSerialNumber());
110 properties.put(Thing.PROPERTY_FIRMWARE_VERSION, appliance.getFirmwareVersion());
111 String protocolAdapterName = appliance.ProtocolAdapterName;
112 if (protocolAdapterName != null) {
113 properties.put(PROPERTY_PROTOCOL_ADAPTER, protocolAdapterName);
115 properties.put(APPLIANCE_ID, applianceIdentifier.getApplianceId());
116 String deviceClass = appliance.getDeviceClass();
117 if (deviceClass != null) {
118 properties.put(PROPERTY_DEVICE_CLASS, deviceClass);
120 String connectionType = appliance.getConnectionType();
121 if (connectionType != null) {
122 properties.put(PROPERTY_CONNECTION_TYPE, connectionType);
124 String connectionBaudRate = appliance.getConnectionBaudRate();
125 if (connectionBaudRate != null) {
126 properties.put(PROPERTY_CONNECTION_BAUD_RATE, connectionBaudRate);
129 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
130 .withBridge(bridgeUID).withLabel(deviceClass != null ? deviceClass : appliance.getApplianceModel())
131 .withRepresentationProperty(APPLIANCE_ID).build();
133 thingDiscovered(discoveryResult);
135 logger.debug("Discovered an unsupported appliance of vendor '{}' with id {}", appliance.Vendor,
141 public void onApplianceRemoved(HomeDevice appliance) {
142 ThingUID thingUID = getThingUID(appliance);
144 if (thingUID != null) {
145 thingRemoved(thingUID);
150 public void onApplianceStateChanged(FullyQualifiedApplianceIdentifier applianceIdentifier, DeviceClassObject dco) {
155 public void onAppliancePropertyChanged(FullyQualifiedApplianceIdentifier applianceIdentifier, DeviceProperty dp) {
159 private @Nullable ThingUID getThingUID(HomeDevice appliance) {
160 ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID();
161 String modelId = appliance.getDeviceClass();
163 if (modelId != null) {
164 ThingTypeUID thingTypeUID = getThingTypeUidFromModelId(modelId);
166 if (getSupportedThingTypes().contains(thingTypeUID)) {
167 ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, appliance.getApplianceIdentifier().getId());
177 private ThingTypeUID getThingTypeUidFromModelId(String modelId) {
179 * Coffee machine CVA 6805 is reported as CoffeeSystem, but thing type is
180 * coffeemachine. At least until it is known if any models are actually reported
181 * as CoffeeMachine, we need this special mapping.
183 if (MIELE_DEVICE_CLASS_COFFEE_SYSTEM.equals(modelId)) {
184 return THING_TYPE_COFFEEMACHINE;
187 String thingTypeId = modelId.replaceAll("[^a-zA-Z0-9_]", "_").toLowerCase();
189 return new ThingTypeUID(BINDING_ID, thingTypeId);