2 * Copyright (c) 2010-2020 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.velux.internal.discovery;
15 import static org.openhab.binding.velux.internal.VeluxBindingConstants.*;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.openhab.core.config.discovery.AbstractDiscoveryService;
20 import org.openhab.core.config.discovery.DiscoveryResult;
21 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
22 import org.openhab.core.config.discovery.DiscoveryService;
23 import org.openhab.core.i18n.LocaleProvider;
24 import org.openhab.core.i18n.LocationProvider;
25 import org.openhab.core.i18n.TranslationProvider;
26 import org.openhab.core.thing.ThingTypeUID;
27 import org.openhab.core.thing.ThingUID;
28 import org.openhab.binding.velux.internal.VeluxBindingConstants;
29 import org.openhab.binding.velux.internal.VeluxBindingProperties;
30 import org.openhab.binding.velux.internal.handler.VeluxBridgeHandler;
31 import org.openhab.binding.velux.internal.things.VeluxProduct;
32 import org.openhab.binding.velux.internal.things.VeluxProductSerialNo;
33 import org.openhab.binding.velux.internal.things.VeluxScene;
34 import org.openhab.binding.velux.internal.utils.Localization;
35 import org.openhab.binding.velux.internal.utils.ManifestInformation;
36 import org.osgi.service.component.annotations.Component;
37 import org.osgi.service.component.annotations.Reference;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
42 * The {@link VeluxDiscoveryService} is responsible for discovering actuators and scenes on the current Velux Bridge.
44 * @author Guenther Schreiner - Initial contribution.
47 // To-be-discussed: check whether an immediate activation is preferable.
48 // Might be activated by:
49 // @Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.velux")
52 @Component(service = DiscoveryService.class, configurationPid = "discovery.velux")
53 public class VeluxDiscoveryService extends AbstractDiscoveryService implements Runnable {
54 private final Logger logger = LoggerFactory.getLogger(VeluxDiscoveryService.class);
58 private static final int DISCOVER_TIMEOUT_SECONDS = 300;
60 private @NonNullByDefault({}) LocaleProvider localeProvider;
61 private @NonNullByDefault({}) TranslationProvider i18nProvider;
62 private Localization localization = Localization.UNKNOWN;
63 private static @Nullable VeluxBridgeHandler bridgeHandler = null;
67 private void updateLocalization() {
68 if (localization == Localization.UNKNOWN && localeProvider != null && i18nProvider != null) {
69 logger.trace("updateLocalization(): creating Localization based on locale={},translation={}).",
70 localeProvider, i18nProvider);
71 localization = new Localization(localeProvider, i18nProvider);
78 * Initializes the {@link VeluxDiscoveryService} without any further information.
80 public VeluxDiscoveryService() {
81 super(VeluxBindingConstants.SUPPORTED_THINGS_ITEMS, DISCOVER_TIMEOUT_SECONDS);
82 logger.trace("VeluxDiscoveryService(without Bridge) just initialized.");
86 protected void setLocaleProvider(final LocaleProvider givenLocaleProvider) {
87 logger.trace("setLocaleProvider(): provided locale={}.", givenLocaleProvider);
88 localeProvider = givenLocaleProvider;
93 protected void setTranslationProvider(TranslationProvider givenI18nProvider) {
94 logger.trace("setTranslationProvider(): provided translation={}.", givenI18nProvider);
95 i18nProvider = givenI18nProvider;
102 * Initializes the {@link VeluxDiscoveryService} with a reference to the well-prepared environment with a
103 * {@link VeluxBridgeHandler}.
105 * @param bridge Initialized Velux bridge handler.
106 * @param localizationHandler Initialized localization handler.
108 public VeluxDiscoveryService(VeluxBridgeHandler bridge, Localization localizationHandler) {
109 super(VeluxBindingConstants.SUPPORTED_THINGS_ITEMS, DISCOVER_TIMEOUT_SECONDS);
110 logger.trace("VeluxDiscoveryService(bridge={},locale={},i18n={}) just initialized.", bridge, localeProvider,
113 if (bridgeHandler == null) {
114 logger.trace("VeluxDiscoveryService(): registering bridge {} for lateron use for Discovery.", bridge);
115 } else if (!bridge.equals(bridgeHandler)) {
116 logger.trace("VeluxDiscoveryService(): replacing already registered bridge {} by {}.", bridgeHandler,
119 bridgeHandler = bridge;
120 localization = localizationHandler;
126 * Initializes the {@link VeluxDiscoveryService} with a reference to the well-prepared environment with a
127 * {@link VeluxBridgeHandler}.
129 * @param bridge Initialized Velux bridge handler.
130 * @param locationProvider Provider for a location.
131 * @param localeProvider Provider for a locale.
132 * @param i18nProvider Provider for the internationalization.
134 public VeluxDiscoveryService(VeluxBridgeHandler bridge, LocationProvider locationProvider,
135 LocaleProvider localeProvider, TranslationProvider i18nProvider) {
136 this(bridge, new Localization(localeProvider, i18nProvider));
137 logger.trace("VeluxDiscoveryService(bridge={},locale={},i18n={}) finished.", bridge, localeProvider,
142 public void deactivate() {
143 logger.trace("deactivate() called.");
148 protected synchronized void startScan() {
149 logger.trace("startScan() called.");
151 logger.debug("startScan(): creating a thing of type binding.");
152 ThingUID thingUID = new ThingUID(THING_TYPE_BINDING, "org_openhab_binding_velux");
153 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID)
154 .withProperty(VeluxBindingProperties.PROPERTY_BINDING_BUNDLEVERSION,
155 ManifestInformation.getBundleVersion())
156 .withLabel(localization.getText("discovery.velux.binding...label")).build();
157 logger.debug("startScan(): registering new thing {}.", discoveryResult);
158 thingDiscovered(discoveryResult);
160 if (bridgeHandler == null) {
161 logger.debug("startScan(): VeluxDiscoveryService cannot proceed due to missing Velux bridge.");
163 logger.debug("startScan(): Starting Velux discovery scan for scenes and actuators.");
167 logger.trace("startScan() done.");
171 public synchronized void stopScan() {
172 logger.trace("stopScan() called.");
174 removeOlderResults(getTimestampOfLastScan());
175 logger.trace("stopScan() done.");
180 logger.trace("run() called.");
184 * Discover the gateway-defined scenes.
186 private void discoverScenes() {
187 logger.trace("discoverScenes() called.");
188 // Just for avoidance of Potential null pointer access
189 VeluxBridgeHandler bridgeHandlerX = bridgeHandler;
190 if (bridgeHandlerX == null) {
191 logger.debug("discoverScenes(): VeluxDiscoveryService.bridgeHandler not initialized, aborting discovery.");
194 ThingUID bridgeUID = bridgeHandlerX.getThing().getUID();
195 logger.debug("discoverScenes(): discovering all scenes.");
196 for (VeluxScene scene : bridgeHandlerX.existingScenes().values()) {
197 String sceneName = scene.getName().toString();
198 logger.trace("discoverScenes(): found scene {}.", sceneName);
200 String label = sceneName.replaceAll("\\P{Alnum}", "_");
201 logger.trace("discoverScenes(): using label {}.", label);
203 ThingTypeUID thingTypeUID = THING_TYPE_VELUX_SCENE;
204 ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
205 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
206 .withProperty(VeluxBindingProperties.PROPERTY_SCENE_NAME, sceneName)
207 .withRepresentationProperty(VeluxBindingProperties.PROPERTY_SCENE_NAME).withBridge(bridgeUID)
208 .withLabel(label).build();
209 logger.debug("discoverScenes(): registering new thing {}.", discoveryResult);
210 thingDiscovered(discoveryResult);
212 logger.trace("discoverScenes() finished.");
216 * Discover the gateway-defined products/actuators.
218 private void discoverProducts() {
219 logger.trace("discoverProducts() called.");
220 // Just for avoidance of Potential null pointer access
221 VeluxBridgeHandler bridgeHandlerX = bridgeHandler;
222 if (bridgeHandlerX == null) {
223 logger.debug("discoverScenes() VeluxDiscoveryService.bridgeHandlerR not initialized, aborting discovery.");
226 ThingUID bridgeUID = bridgeHandlerX.getThing().getUID();
227 logger.debug("discoverProducts(): discovering all actuators.");
228 for (VeluxProduct product : bridgeHandlerX.existingProducts().values()) {
229 String serialNumber = product.getSerialNumber();
230 String actuatorName = product.getProductName().toString();
231 logger.trace("discoverProducts() found actuator {} (name {}).", serialNumber, actuatorName);
233 if (serialNumber.equals(VeluxProductSerialNo.UNKNOWN)) {
234 identifier = actuatorName;
236 identifier = serialNumber;
238 String label = actuatorName.replaceAll("\\P{Alnum}", "_");
239 logger.trace("discoverProducts(): using label {}.", label);
240 ThingTypeUID thingTypeUID;
241 boolean isInverted = false;
242 logger.trace("discoverProducts() dealing with {} (type {}).", product, product.getProductType());
243 switch (product.getProductType()) {
245 logger.trace("discoverProducts(): creating window.");
246 thingTypeUID = THING_TYPE_VELUX_WINDOW;
251 logger.trace("discoverProducts(): creating rollershutter.");
252 thingTypeUID = THING_TYPE_VELUX_ROLLERSHUTTER;
256 logger.trace("discoverProducts(): creating actuator.");
257 thingTypeUID = THING_TYPE_VELUX_ACTUATOR;
259 ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
261 DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
262 .withProperty(VeluxBindingProperties.CONFIG_ACTUATOR_SERIALNUMBER, identifier)
263 .withProperty(VeluxBindingProperties.PROPERTY_ACTUATOR_NAME, actuatorName)
264 .withProperty(VeluxBindingProperties.PROPERTY_ACTUATOR_INVERTED, isInverted)
265 .withRepresentationProperty(VeluxBindingProperties.CONFIG_ACTUATOR_SERIALNUMBER)
266 .withBridge(bridgeUID).withLabel(actuatorName).build();
267 logger.debug("discoverProducts(): registering new thing {}.", discoveryResult);
268 thingDiscovered(discoveryResult);
270 logger.trace("discoverProducts() finished.");