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.melcloud.internal.discovery;
15 import static org.openhab.binding.melcloud.internal.MelCloudBindingConstants.*;
17 import java.util.HashMap;
18 import java.util.List;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.melcloud.internal.MelCloudBindingConstants;
25 import org.openhab.binding.melcloud.internal.api.json.Device;
26 import org.openhab.binding.melcloud.internal.exceptions.MelCloudCommException;
27 import org.openhab.binding.melcloud.internal.exceptions.MelCloudLoginException;
28 import org.openhab.binding.melcloud.internal.handler.MelCloudAccountHandler;
29 import org.openhab.core.config.discovery.AbstractDiscoveryService;
30 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
31 import org.openhab.core.config.discovery.DiscoveryService;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.thing.ThingTypeUID;
34 import org.openhab.core.thing.ThingUID;
35 import org.openhab.core.thing.binding.ThingHandler;
36 import org.openhab.core.thing.binding.ThingHandlerService;
37 import org.osgi.service.component.annotations.Modified;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 * The {@link MelCloudDiscoveryService} creates things based on the configured location.
44 * @author Luca Calcaterra - Initial Contribution
45 * @author Pauli Anttila - Refactoring
46 * @author Wietse van Buitenen - Check device type, added heatpump device
48 public class MelCloudDiscoveryService extends AbstractDiscoveryService
49 implements DiscoveryService, ThingHandlerService {
51 private final Logger logger = LoggerFactory.getLogger(MelCloudDiscoveryService.class);
53 private static final String PROPERTY_DEVICE_ID = "deviceID";
54 private static final int DISCOVER_TIMEOUT_SECONDS = 10;
56 private MelCloudAccountHandler melCloudHandler;
57 private ScheduledFuture<?> scanTask;
60 * Creates a MelCloudDiscoveryService with enabled autostart.
62 public MelCloudDiscoveryService() {
63 super(MelCloudBindingConstants.DISCOVERABLE_THING_TYPE_UIDS, DISCOVER_TIMEOUT_SECONDS, true);
67 protected void activate(Map<String, Object> configProperties) {
68 super.activate(configProperties);
72 public void deactivate() {
78 protected void modified(Map<String, Object> configProperties) {
79 super.modified(configProperties);
83 protected void startBackgroundDiscovery() {
88 protected void startScan() {
89 if (this.scanTask != null) {
90 scanTask.cancel(true);
92 this.scanTask = scheduler.schedule(() -> discoverDevices(), 0, TimeUnit.SECONDS);
96 protected void stopScan() {
99 if (this.scanTask != null) {
100 this.scanTask.cancel(true);
101 this.scanTask = null;
105 private void discoverDevices() {
106 logger.debug("Discover devices");
108 if (melCloudHandler != null) {
110 List<Device> deviceList = melCloudHandler.getDeviceList();
112 if (deviceList == null) {
113 logger.debug("No devices found");
115 ThingUID bridgeUID = melCloudHandler.getThing().getUID();
117 deviceList.forEach(device -> {
118 ThingTypeUID thingTypeUid = null;
119 if (device.getType() == 0) {
120 thingTypeUid = THING_TYPE_ACDEVICE;
121 } else if (device.getType() == 1) {
122 thingTypeUid = THING_TYPE_HEATPUMPDEVICE;
124 logger.debug("Unsupported device found: name {} : type: {}", device.getDeviceName(),
128 ThingUID deviceThing = new ThingUID(thingTypeUid, melCloudHandler.getThing().getUID(),
129 device.getDeviceID().toString());
131 Map<String, Object> deviceProperties = new HashMap<>();
132 deviceProperties.put(PROPERTY_DEVICE_ID, device.getDeviceID().toString());
133 deviceProperties.put(Thing.PROPERTY_SERIAL_NUMBER, device.getSerialNumber());
134 deviceProperties.put(Thing.PROPERTY_MAC_ADDRESS, device.getMacAddress());
135 deviceProperties.put("deviceName", device.getDeviceName());
136 deviceProperties.put("buildingID", device.getBuildingID().toString());
138 String label = createLabel(device);
139 logger.debug("Found device: {} : {}", label, deviceProperties);
141 thingDiscovered(DiscoveryResultBuilder.create(deviceThing).withLabel(label)
142 .withProperties(deviceProperties).withRepresentationProperty(PROPERTY_DEVICE_ID)
143 .withBridge(bridgeUID).build());
146 } catch (MelCloudLoginException e) {
147 logger.debug("Login error occurred during device list fetch, reason {}. ", e.getMessage(), e);
148 } catch (MelCloudCommException e) {
149 logger.debug("Error occurred during device list fetch, reason {}. ", e.getMessage(), e);
154 private String createLabel(Device device) {
155 StringBuilder sb = new StringBuilder();
156 if (device.getType() == 0) {
157 sb.append("A.C. Device - ");
158 } else if (device.getType() == 1) {
159 sb.append("Heatpump Device - ");
161 if (device.getBuildingName() instanceof String) {
162 sb.append(device.getBuildingName()).append(" - ");
164 sb.append(device.getDeviceName());
165 return sb.toString();
169 public void setThingHandler(@Nullable ThingHandler handler) {
170 if (handler instanceof MelCloudAccountHandler accountHandler) {
171 melCloudHandler = accountHandler;
176 public @Nullable ThingHandler getThingHandler() {
177 return melCloudHandler;