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.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.HomeDevice;
27 import org.openhab.binding.miele.internal.handler.DiscoveryListener;
28 import org.openhab.binding.miele.internal.handler.MieleApplianceHandler;
29 import org.openhab.binding.miele.internal.handler.MieleBridgeHandler;
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.Thing;
34 import org.openhab.core.thing.ThingTypeUID;
35 import org.openhab.core.thing.ThingUID;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
40 * The {@link MieleApplianceDiscoveryService} tracks appliances that are
41 * associated with the Miele@Home gateway
43 * @author Karel Goderis - Initial contribution
44 * @author Martin Lepsy - Added protocol information in order so support WiFi devices
45 * @author Jacob Laursen - Fixed multicast and protocol support (ZigBee/LAN)
48 public class MieleApplianceDiscoveryService extends AbstractDiscoveryService implements DiscoveryListener {
50 private final Logger logger = LoggerFactory.getLogger(MieleApplianceDiscoveryService.class);
52 private static final int SEARCH_TIME = 60;
54 private MieleBridgeHandler mieleBridgeHandler;
56 public MieleApplianceDiscoveryService(MieleBridgeHandler mieleBridgeHandler) {
57 super(MieleApplianceHandler.SUPPORTED_THING_TYPES, SEARCH_TIME, false);
58 this.mieleBridgeHandler = mieleBridgeHandler;
61 public void activate() {
62 mieleBridgeHandler.registerDiscoveryListener(this);
66 public void deactivate() {
67 removeOlderResults(new Date().getTime());
68 mieleBridgeHandler.unregisterDiscoveryListener(this);
72 public Set<ThingTypeUID> getSupportedThingTypes() {
73 return MieleApplianceHandler.SUPPORTED_THING_TYPES;
77 public void startScan() {
78 List<HomeDevice> appliances = mieleBridgeHandler.getHomeDevicesEmptyOnFailure();
79 for (HomeDevice l : appliances) {
80 onApplianceAddedInternal(l);
85 protected synchronized void stopScan() {
87 removeOlderResults(getTimestampOfLastScan());
91 public void onApplianceAdded(HomeDevice appliance) {
92 onApplianceAddedInternal(appliance);
95 private void onApplianceAddedInternal(HomeDevice appliance) {
96 ThingUID thingUID = getThingUID(appliance);
97 if (thingUID != null) {
98 ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID();
99 Map<String, Object> properties = new HashMap<>(9);
101 FullyQualifiedApplianceIdentifier applianceIdentifier = appliance.getApplianceIdentifier();
102 String vendor = appliance.Vendor;
103 if (vendor != null) {
104 properties.put(Thing.PROPERTY_VENDOR, vendor);
106 properties.put(Thing.PROPERTY_MODEL_ID, appliance.getApplianceModel());
107 properties.put(Thing.PROPERTY_SERIAL_NUMBER, appliance.getSerialNumber());
108 properties.put(Thing.PROPERTY_FIRMWARE_VERSION, appliance.getFirmwareVersion());
109 String protocolAdapterName = appliance.ProtocolAdapterName;
110 if (protocolAdapterName != null) {
111 properties.put(PROPERTY_PROTOCOL_ADAPTER, protocolAdapterName);
113 properties.put(APPLIANCE_ID, applianceIdentifier.getApplianceId());
114 String deviceClass = appliance.getDeviceClass();
115 if (deviceClass != null) {
116 properties.put(PROPERTY_DEVICE_CLASS, deviceClass);
118 String connectionType = appliance.getConnectionType();
119 if (connectionType != null) {
120 properties.put(PROPERTY_CONNECTION_TYPE, connectionType);
122 String connectionBaudRate = appliance.getConnectionBaudRate();
123 if (connectionBaudRate != null) {
124 properties.put(PROPERTY_CONNECTION_BAUD_RATE, connectionBaudRate);
127 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
128 .withBridge(bridgeUID).withLabel(deviceClass != null ? deviceClass : appliance.getApplianceModel())
129 .withRepresentationProperty(APPLIANCE_ID).build();
131 thingDiscovered(discoveryResult);
133 logger.debug("Discovered an unsupported appliance of vendor '{}' with id {}", appliance.Vendor,
139 public void onApplianceRemoved(HomeDevice appliance) {
140 ThingUID thingUID = getThingUID(appliance);
142 if (thingUID != null) {
143 thingRemoved(thingUID);
147 private @Nullable ThingUID getThingUID(HomeDevice appliance) {
148 ThingUID bridgeUID = mieleBridgeHandler.getThing().getUID();
149 String modelId = appliance.getDeviceClass();
151 if (modelId != null) {
152 ThingTypeUID thingTypeUID = getThingTypeUidFromModelId(modelId);
154 if (getSupportedThingTypes().contains(thingTypeUID)) {
155 ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, appliance.getApplianceIdentifier().getId());
165 private ThingTypeUID getThingTypeUidFromModelId(String modelId) {
167 * Coffee machine CVA 6805 is reported as CoffeeSystem, but thing type is
168 * coffeemachine. At least until it is known if any models are actually reported
169 * as CoffeeMachine, we need this special mapping.
171 if (MIELE_DEVICE_CLASS_COFFEE_SYSTEM.equals(modelId)) {
172 return THING_TYPE_COFFEEMACHINE;
175 String thingTypeId = modelId.replaceAll("[^a-zA-Z0-9_]", "_").toLowerCase();
177 return new ThingTypeUID(BINDING_ID, thingTypeId);