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.openwebnet.internal.discovery;
15 import java.util.HashMap;
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;
41 * The {@link OpenWebNetDeviceDiscoveryService} is responsible for discovering
42 * OpenWebNet devices connected to a bridge/gateway
44 * @author Massimo Valla - Initial contribution
45 * @author Andrea Conte - Energy management, Thermoregulation
46 * @author Gilberto Cocchi - Thermoregulation
47 * @author Giovanni Fabiani - Aux support
50 public class OpenWebNetDeviceDiscoveryService extends AbstractDiscoveryService
51 implements DiscoveryService, ThingHandlerService {
53 private final Logger logger = LoggerFactory.getLogger(OpenWebNetDeviceDiscoveryService.class);
55 private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.DEVICE_SUPPORTED_THING_TYPES;
56 private static final int SEARCH_TIME_SEC = 60;
58 private @NonNullByDefault({}) OpenWebNetBridgeHandler bridgeHandler;
59 private @NonNullByDefault({}) ThingUID bridgeUID;
61 public OpenWebNetDeviceDiscoveryService() {
62 super(SUPPORTED_THING_TYPES, SEARCH_TIME_SEC);
66 public Set<ThingTypeUID> getSupportedThingTypes() {
67 return SUPPORTED_THING_TYPES;
71 protected void startScan() {
72 logger.info("------ SEARCHING for DEVICES on bridge '{}' ({}) ...", bridgeHandler.getThing().getLabel(),
74 bridgeHandler.searchDevices();
78 protected void stopScan() {
79 logger.debug("------ stopScan() on bridge '{}'", bridgeUID);
80 bridgeHandler.scanStopped();
84 public void abortScan() {
85 logger.debug("------ abortScan() on bridge '{}'", bridgeUID);
86 bridgeHandler.scanStopped();
90 * Create and notify to Inbox a new DiscoveryResult based on WHERE,
91 * OpenDeviceType and BaseOpenMessage
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
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;
109 case ZIGBEE_DIMMER_SWITCH:
110 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_ZB_DIMMER;
111 thingLabel = OpenWebNetBindingConstants.THING_LABEL_ZB_DIMMER;
112 deviceWho = Who.LIGHTING;
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;
119 case SCS_DIMMER_SWITCH:
120 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_DIMMER;
121 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_DIMMER;
122 deviceWho = Who.LIGHTING;
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;
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;
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;
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;
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;
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;
162 case BASIC_SCENARIO: {
163 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_SCENARIO;
164 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_SCENARIO;
165 deviceWho = Who.SCENARIO;
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;
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;
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;
186 case SCS_AUXILIARY_TOGGLE_CONTROL: {
187 thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_AUX;
188 thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_AUX;
193 logger.warn("Device type {} is not supported, default to GENERIC device (WHERE={})", deviceType, where);
194 if (where instanceof WhereZigBee) {
195 thingLabel = "ZigBee " + thingLabel;
197 if (baseMsg != null) {
198 deviceWho = baseMsg.getWho();
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);
210 String tId = bridgeHandler.thingIdFromWhere(where);
211 ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, tId);
213 DiscoveryResult discoveryResult = null;
215 String whereConfig = where.value();
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();
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);
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 + ")";
240 thingLabel = thingLabel + " (WHERE=" + whereConfig + ")";
242 discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID).withProperties(properties)
243 .withRepresentationProperty(OpenWebNetBindingConstants.PROPERTY_OWNID).withBridge(bridgeUID)
244 .withLabel(thingLabel).build();
245 thingDiscovered(discoveryResult);
249 public void deactivate() {
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();
264 public @Nullable ThingHandler getThingHandler() {
265 return bridgeHandler;