]> git.basschouten.com Git - openhab-addons.git/blob
ce6264c0fcb52575300dc31ce7b542c132b9f0b8
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.openwebnet.internal.discovery;
14
15 import java.util.HashMap;
16 import java.util.Map;
17 import java.util.Set;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants;
22 import org.openhab.binding.openwebnet.internal.handler.OpenWebNetBridgeHandler;
23 import org.openhab.core.config.discovery.AbstractDiscoveryService;
24 import org.openhab.core.config.discovery.DiscoveryResult;
25 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
26 import org.openhab.core.config.discovery.DiscoveryService;
27 import org.openhab.core.thing.ThingTypeUID;
28 import org.openhab.core.thing.ThingUID;
29 import org.openhab.core.thing.binding.ThingHandler;
30 import org.openhab.core.thing.binding.ThingHandlerService;
31 import org.openwebnet4j.OpenDeviceType;
32 import org.openwebnet4j.message.BaseOpenMessage;
33 import org.openwebnet4j.message.Where;
34 import org.openwebnet4j.message.WhereThermo;
35 import org.openwebnet4j.message.WhereZigBee;
36 import org.openwebnet4j.message.Who;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 /**
41  * The {@link OpenWebNetDeviceDiscoveryService} is responsible for discovering
42  * OpenWebNet devices connected to a bridge/gateway
43  *
44  * @author Massimo Valla - Initial contribution
45  * @author Andrea Conte - Energy management, Thermoregulation
46  * @author Gilberto Cocchi - Thermoregulation
47  * @author Giovanni Fabiani - Aux support
48  */
49 @NonNullByDefault
50 public class OpenWebNetDeviceDiscoveryService extends AbstractDiscoveryService
51         implements DiscoveryService, ThingHandlerService {
52
53     private final Logger logger = LoggerFactory.getLogger(OpenWebNetDeviceDiscoveryService.class);
54
55     private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.DEVICE_SUPPORTED_THING_TYPES;
56     private static final int SEARCH_TIME_SEC = 60;
57
58     private @NonNullByDefault({}) OpenWebNetBridgeHandler bridgeHandler;
59     private @NonNullByDefault({}) ThingUID bridgeUID;
60
61     public OpenWebNetDeviceDiscoveryService() {
62         super(SUPPORTED_THING_TYPES, SEARCH_TIME_SEC);
63     }
64
65     @Override
66     public Set<ThingTypeUID> getSupportedThingTypes() {
67         return SUPPORTED_THING_TYPES;
68     }
69
70     @Override
71     protected void startScan() {
72         logger.info("------ SEARCHING for DEVICES on bridge '{}' ({}) ...", bridgeHandler.getThing().getLabel(),
73                 bridgeUID);
74         bridgeHandler.searchDevices();
75     }
76
77     @Override
78     protected void stopScan() {
79         logger.debug("------ stopScan() on bridge '{}'", bridgeUID);
80         bridgeHandler.scanStopped();
81     }
82
83     @Override
84     public void abortScan() {
85         logger.debug("------ abortScan() on bridge '{}'", bridgeUID);
86         bridgeHandler.scanStopped();
87     }
88
89     /**
90      * Create and notify to Inbox a new DiscoveryResult based on WHERE,
91      * OpenDeviceType and BaseOpenMessage
92      *
93      * @param where the discovered device's address (WHERE)
94      * @param deviceType {@link OpenDeviceType} of the discovered device
95      * @param message the OWN message received that identified the device
96      *            (optional)
97      */
98     public void newDiscoveryResult(Where where, OpenDeviceType deviceType, @Nullable BaseOpenMessage baseMsg) {
99         logger.debug("newDiscoveryResult() WHERE={}, deviceType={}", where, deviceType);
100         ThingTypeUID thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_GENERIC_DEVICE; // generic device
101         String thingLabel = OpenWebNetBindingConstants.THING_LABEL_GENERIC_DEVICE;
102         Who deviceWho = Who.UNKNOWN;
103         switch (deviceType) {
104             case ZIGBEE_ON_OFF_SWITCH:
105                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_ZB_ON_OFF_SWITCH;
106                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_ZB_ON_OFF_SWITCH;
107                 deviceWho = Who.LIGHTING;
108                 break;
109             case ZIGBEE_DIMMER_SWITCH:
110                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_ZB_DIMMER;
111                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_ZB_DIMMER;
112                 deviceWho = Who.LIGHTING;
113                 break;
114             case SCS_ON_OFF_SWITCH:
115                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_ON_OFF_SWITCH;
116                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_ON_OFF_SWITCH;
117                 deviceWho = Who.LIGHTING;
118                 break;
119             case SCS_DIMMER_SWITCH:
120                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_DIMMER;
121                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_DIMMER;
122                 deviceWho = Who.LIGHTING;
123                 break;
124             case SCS_SHUTTER_SWITCH:
125             case SCS_SHUTTER_CONTROL: {
126                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_AUTOMATION;
127                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_AUTOMATION;
128                 deviceWho = Who.AUTOMATION;
129                 break;
130             }
131             case ZIGBEE_SHUTTER_SWITCH:
132             case ZIGBEE_SHUTTER_CONTROL: {
133                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_ZB_AUTOMATION;
134                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_ZB_AUTOMATION;
135                 deviceWho = Who.AUTOMATION;
136                 break;
137             }
138             case SCS_THERMO_SENSOR: {
139                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_SENSOR;
140                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_THERMO_SENSOR;
141                 deviceWho = Who.THERMOREGULATION;
142                 break;
143             }
144             case SCS_THERMO_ZONE: {
145                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_ZONE;
146                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_THERMO_ZONE;
147                 deviceWho = Who.THERMOREGULATION;
148                 break;
149             }
150             case SCS_THERMO_CENTRAL_UNIT: {
151                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_CU;
152                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_THERMO_CU;
153                 deviceWho = Who.THERMOREGULATION;
154                 break;
155             }
156             case SCS_ENERGY_METER: {
157                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_ENERGY_METER;
158                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_ENERGY_METER;
159                 deviceWho = Who.ENERGY_MANAGEMENT;
160                 break;
161             }
162             case BASIC_SCENARIO: {
163                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_SCENARIO;
164                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_SCENARIO;
165                 deviceWho = Who.SCENARIO;
166                 break;
167             }
168             case SCENARIO_CONTROL: {
169                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_CEN_SCENARIO_CONTROL;
170                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_CEN_SCENARIO_CONTROL;
171                 deviceWho = Who.CEN_SCENARIO_SCHEDULER;
172                 break;
173             }
174             case SCS_DRY_CONTACT_IR: {
175                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_DRY_CONTACT_IR;
176                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_DRY_CONTACT_IR;
177                 deviceWho = Who.CEN_PLUS_SCENARIO_SCHEDULER;
178                 break;
179             }
180             case MULTIFUNCTION_SCENARIO_CONTROL: {
181                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_CENPLUS_SCENARIO_CONTROL;
182                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_CENPLUS_SCENARIO_CONTROL;
183                 deviceWho = Who.CEN_PLUS_SCENARIO_SCHEDULER;
184                 break;
185             }
186             case SCS_AUXILIARY_TOGGLE_CONTROL: {
187                 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_AUX;
188                 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_AUX;
189                 deviceWho = Who.AUX;
190                 break;
191             }
192             default:
193                 logger.warn("Device type {} is not supported, default to GENERIC device (WHERE={})", deviceType, where);
194                 if (where instanceof WhereZigBee) {
195                     thingLabel = "ZigBee " + thingLabel;
196                 }
197                 if (baseMsg != null) {
198                     deviceWho = baseMsg.getWho();
199                 }
200         }
201
202         String ownId = bridgeHandler.ownIdFromWhoWhere(deviceWho, where);
203         if (OpenWebNetBindingConstants.THING_TYPE_BUS_ON_OFF_SWITCH.equals(thingTypeUID)) {
204             if (bridgeHandler.getRegisteredDevice(ownId) != null) {
205                 logger.debug("dimmer/switch with WHERE={} already registered, skipping this discovery result", where);
206                 return;
207             }
208         }
209
210         String tId = bridgeHandler.thingIdFromWhere(where);
211         ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, tId);
212
213         DiscoveryResult discoveryResult = null;
214
215         String whereConfig = where.value();
216
217         // remove # from discovered thermo zone or central unit
218         if (OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_ZONE.equals(thingTypeUID)
219                 || OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_CU.equals(thingTypeUID)) {
220             whereConfig = "" + ((WhereThermo) where).getZone();
221         }
222         if (where instanceof WhereZigBee && WhereZigBee.UNIT_02.equals(((WhereZigBee) where).getUnit())) {
223             logger.debug("UNIT=02 found (WHERE={}) -> will remove previous result if exists", where);
224             thingRemoved(thingUID); // remove previously discovered thing
225             // re-create thingUID with new type
226             thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_ZB_ON_OFF_SWITCH_2UNITS;
227             thingLabel = OpenWebNetBindingConstants.THING_LABEL_ZB_ON_OFF_SWITCH_2UNITS;
228             thingUID = new ThingUID(thingTypeUID, bridgeUID, tId);
229             whereConfig = ((WhereZigBee) where).valueWithUnit(WhereZigBee.UNIT_ALL); // replace unit '02' with '00'
230             logger.debug("UNIT=02, switching type from {} to {}",
231                     OpenWebNetBindingConstants.THING_TYPE_ZB_ON_OFF_SWITCH,
232                     OpenWebNetBindingConstants.THING_TYPE_ZB_ON_OFF_SWITCH_2UNITS);
233         }
234         Map<String, Object> properties = new HashMap<>(2);
235         properties.put(OpenWebNetBindingConstants.CONFIG_PROPERTY_WHERE, whereConfig);
236         properties.put(OpenWebNetBindingConstants.PROPERTY_OWNID, ownId);
237         if (OpenWebNetBindingConstants.THING_TYPE_GENERIC_DEVICE.equals(thingTypeUID)) {
238             thingLabel = thingLabel + " (WHO=" + deviceWho + ", WHERE=" + whereConfig + ")";
239         } else {
240             thingLabel = thingLabel + " (WHERE=" + whereConfig + ")";
241         }
242         discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID).withProperties(properties)
243                 .withRepresentationProperty(OpenWebNetBindingConstants.PROPERTY_OWNID).withBridge(bridgeUID)
244                 .withLabel(thingLabel).build();
245         thingDiscovered(discoveryResult);
246     }
247
248     @Override
249     public void deactivate() {
250         super.deactivate();
251     }
252
253     @Override
254     public void setThingHandler(@Nullable ThingHandler handler) {
255         if (handler instanceof OpenWebNetBridgeHandler) {
256             logger.debug("attaching {} to handler {} ", this, handler);
257             bridgeHandler = (OpenWebNetBridgeHandler) handler;
258             bridgeHandler.deviceDiscoveryService = this;
259             bridgeUID = bridgeHandler.getThing().getUID();
260         }
261     }
262
263     @Override
264     public @Nullable ThingHandler getThingHandler() {
265         return bridgeHandler;
266     }
267 }