]> git.basschouten.com Git - openhab-addons.git/blob
500d0a4d970ac3f25f1ea3c065fc25ca067e5472
[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.draytonwiser.internal.discovery;
14
15 import static org.openhab.binding.draytonwiser.internal.DraytonWiserBindingConstants.*;
16
17 import java.util.HashMap;
18 import java.util.Map;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.draytonwiser.internal.DraytonWiserRefreshListener;
23 import org.openhab.binding.draytonwiser.internal.handler.DraytonWiserPropertyHelper;
24 import org.openhab.binding.draytonwiser.internal.handler.HeatHubHandler;
25 import org.openhab.binding.draytonwiser.internal.model.DeviceDTO;
26 import org.openhab.binding.draytonwiser.internal.model.DraytonWiserDTO;
27 import org.openhab.binding.draytonwiser.internal.model.HotWaterDTO;
28 import org.openhab.binding.draytonwiser.internal.model.RoomDTO;
29 import org.openhab.binding.draytonwiser.internal.model.RoomStatDTO;
30 import org.openhab.binding.draytonwiser.internal.model.SmartPlugDTO;
31 import org.openhab.binding.draytonwiser.internal.model.SmartValveDTO;
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.config.discovery.DiscoveryService;
36 import org.openhab.core.thing.ThingTypeUID;
37 import org.openhab.core.thing.ThingUID;
38 import org.openhab.core.thing.binding.ThingHandler;
39 import org.openhab.core.thing.binding.ThingHandlerService;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * The {@link DraytonWiserDiscoveryService} is used to discover devices that are connected to a Heat Hub.
45  *
46  * @author Andrew Schofield - Initial contribution
47  */
48 @NonNullByDefault
49 public class DraytonWiserDiscoveryService extends AbstractDiscoveryService
50         implements DiscoveryService, ThingHandlerService, DraytonWiserRefreshListener {
51
52     private final Logger logger = LoggerFactory.getLogger(DraytonWiserDiscoveryService.class);
53
54     private @Nullable HeatHubHandler bridgeHandler;
55     private @Nullable ThingUID bridgeUID;
56
57     public DraytonWiserDiscoveryService() {
58         super(SUPPORTED_THING_TYPES_UIDS, 30, false);
59     }
60
61     @Override
62     public void activate() {
63         super.activate(null);
64     }
65
66     @Override
67     public void deactivate() {
68         super.deactivate();
69     }
70
71     @Override
72     protected void startScan() {
73         final HeatHubHandler handler = bridgeHandler;
74         if (handler != null) {
75             removeOlderResults(getTimestampOfLastScan());
76             handler.setDiscoveryService(this);
77         }
78     }
79
80     @Override
81     public void onRefresh(final DraytonWiserDTO domainDTOProxy) {
82         logger.debug("Received data from Drayton Wiser device. Parsing to discover devices.");
83         onControllerAdded(domainDTOProxy);
84         domainDTOProxy.getRooms().forEach(this::onRoomAdded);
85         domainDTOProxy.getRoomStats().forEach(r -> onRoomStatAdded(domainDTOProxy, r));
86         domainDTOProxy.getSmartValves().forEach(sv -> onSmartValveAdded(domainDTOProxy, sv));
87         domainDTOProxy.getHotWater().forEach(hw -> onHotWaterAdded(domainDTOProxy, hw));
88         domainDTOProxy.getSmartPlugs().forEach(sp -> onSmartPlugAdded(domainDTOProxy, sp));
89     }
90
91     private void onControllerAdded(final DraytonWiserDTO domainDTOProxy) {
92         final DeviceDTO device = domainDTOProxy.getExtendedDeviceProperties(0);
93
94         if (device != null) {
95             logger.debug("Controller discovered, model: {}", device.getModelIdentifier());
96             onThingWithId(THING_TYPE_CONTROLLER, "controller", device, "Controller");
97         }
98     }
99
100     private void onHotWaterAdded(final DraytonWiserDTO domainDTOProxy, final HotWaterDTO hotWater) {
101         final Integer hotWaterId = hotWater.getId();
102         final String roomName = getRoomName(domainDTOProxy, hotWaterId);
103
104         onThingWithId(THING_TYPE_HOTWATER, "hotwater" + hotWaterId, null,
105                 (roomName.isEmpty() ? "" : (roomName + " - ")) + "Hot Water");
106     }
107
108     private void onThingWithId(final ThingTypeUID deviceType, final String deviceTypeId,
109             @Nullable final DeviceDTO device, final String name) {
110         logger.debug("{} discovered: {}", deviceTypeId, name);
111         ThingUID localBridgeUID = this.bridgeUID;
112         if (localBridgeUID != null) {
113             final Map<String, Object> properties = new HashMap<>();
114
115             properties.put(PROP_ID, deviceTypeId);
116             if (device != null) {
117                 DraytonWiserPropertyHelper.setGeneralDeviceProperties(device, properties);
118             }
119             final DiscoveryResult discoveryResult = DiscoveryResultBuilder
120                     .create(new ThingUID(deviceType, localBridgeUID, deviceTypeId)).withBridge(localBridgeUID)
121                     .withProperties(properties).withRepresentationProperty(PROP_ID).withLabel(name).build();
122
123             thingDiscovered(discoveryResult);
124         }
125     }
126
127     private void onRoomStatAdded(final DraytonWiserDTO domainDTOProxy, final RoomStatDTO roomStat) {
128         final Integer roomStatId = roomStat.getId();
129         final DeviceDTO device = domainDTOProxy.getExtendedDeviceProperties(roomStatId);
130
131         if (device != null) {
132             onThingWithSerialNumber(THING_TYPE_ROOMSTAT, "Thermostat", device, getRoomName(domainDTOProxy, roomStatId));
133         }
134     }
135
136     private void onRoomAdded(final RoomDTO room) {
137         ThingUID localBridgeUID = this.bridgeUID;
138         if (localBridgeUID != null) {
139             final Map<String, Object> properties = new HashMap<>();
140
141             logger.debug("Room discovered: {}", room.getName());
142             properties.put(PROP_NAME, room.getName());
143             final DiscoveryResult discoveryResult = DiscoveryResultBuilder
144                     .create(new ThingUID(THING_TYPE_ROOM, localBridgeUID,
145                             room.getName().replaceAll("[^A-Za-z0-9]", "").toLowerCase()))
146                     .withBridge(localBridgeUID).withProperties(properties).withRepresentationProperty(PROP_NAME)
147                     .withLabel(room.getName()).build();
148
149             thingDiscovered(discoveryResult);
150         }
151     }
152
153     private void onSmartValveAdded(final DraytonWiserDTO domainDTOProxy, final SmartValveDTO smartValve) {
154         final Integer smartValueId = smartValve.getId();
155         final DeviceDTO device = domainDTOProxy.getExtendedDeviceProperties(smartValueId);
156
157         if (device != null) {
158             onThingWithSerialNumber(THING_TYPE_ITRV, "TRV", device, getRoomName(domainDTOProxy, smartValueId));
159         }
160     }
161
162     private void onSmartPlugAdded(final DraytonWiserDTO domainDTOProxy, final SmartPlugDTO smartPlug) {
163         final DeviceDTO device = domainDTOProxy.getExtendedDeviceProperties(smartPlug.getId());
164
165         if (device != null) {
166             onThingWithSerialNumber(THING_TYPE_SMARTPLUG, "Smart Plug", device, smartPlug.getName());
167         }
168     }
169
170     private String getRoomName(final DraytonWiserDTO domainDTOProxy, final Integer roomId) {
171         final RoomDTO assignedRoom = domainDTOProxy.getRoomForDeviceId(roomId);
172         return assignedRoom == null ? "" : assignedRoom.getName();
173     }
174
175     private void onThingWithSerialNumber(final ThingTypeUID deviceType, final String deviceTypeName,
176             final DeviceDTO device, final String name) {
177         final String serialNumber = device.getSerialNumber();
178         logger.debug("{} discovered, serialnumber: {}", deviceTypeName, serialNumber);
179         ThingUID localBridgeUID = this.bridgeUID;
180         if (localBridgeUID != null) {
181             final Map<String, Object> properties = new HashMap<>();
182
183             DraytonWiserPropertyHelper.setPropertiesWithSerialNumber(device, properties);
184             final DiscoveryResult discoveryResult = DiscoveryResultBuilder
185                     .create(new ThingUID(deviceType, localBridgeUID, serialNumber)).withBridge(localBridgeUID)
186                     .withProperties(properties).withRepresentationProperty(PROP_SERIAL_NUMBER)
187                     .withLabel((name.isEmpty() ? "" : (name + " - ")) + deviceTypeName).build();
188
189             thingDiscovered(discoveryResult);
190         }
191     }
192
193     @Override
194     public synchronized void stopScan() {
195         final HeatHubHandler handler = bridgeHandler;
196
197         if (handler != null) {
198             handler.unsetDiscoveryService();
199         }
200         super.stopScan();
201     }
202
203     @Override
204     public void setThingHandler(@Nullable final ThingHandler handler) {
205         if (handler instanceof HeatHubHandler hubHandler) {
206             bridgeHandler = hubHandler;
207             bridgeUID = handler.getThing().getUID();
208         } else {
209             bridgeHandler = null;
210             bridgeUID = null;
211         }
212     }
213
214     @Override
215     public @Nullable ThingHandler getThingHandler() {
216         return bridgeHandler;
217     }
218 }