]> git.basschouten.com Git - openhab-addons.git/blob
444ad4ca1d60becde57e34eb80526c74b7a12fd1
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.velux.internal.discovery;
14
15 import static org.openhab.binding.velux.internal.VeluxBindingConstants.*;
16
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;
40
41 /**
42  * The {@link VeluxDiscoveryService} is responsible for discovering actuators and scenes on the current Velux Bridge.
43  *
44  * @author Guenther Schreiner - Initial contribution.
45  */
46 //
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")
50 //
51 @NonNullByDefault
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);
55
56     // Class internal
57
58     private static final int DISCOVER_TIMEOUT_SECONDS = 300;
59
60     private @NonNullByDefault({}) LocaleProvider localeProvider;
61     private @NonNullByDefault({}) TranslationProvider i18nProvider;
62     private Localization localization = Localization.UNKNOWN;
63     private static @Nullable VeluxBridgeHandler bridgeHandler = null;
64
65     // Private
66
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);
72         }
73     }
74
75     /**
76      * Constructor
77      * <P>
78      * Initializes the {@link VeluxDiscoveryService} without any further information.
79      */
80     public VeluxDiscoveryService() {
81         super(VeluxBindingConstants.SUPPORTED_THINGS_ITEMS, DISCOVER_TIMEOUT_SECONDS);
82         logger.trace("VeluxDiscoveryService(without Bridge) just initialized.");
83     }
84
85     @Reference
86     protected void setLocaleProvider(final LocaleProvider givenLocaleProvider) {
87         logger.trace("setLocaleProvider(): provided locale={}.", givenLocaleProvider);
88         localeProvider = givenLocaleProvider;
89         updateLocalization();
90     }
91
92     @Reference
93     protected void setTranslationProvider(TranslationProvider givenI18nProvider) {
94         logger.trace("setTranslationProvider(): provided translation={}.", givenI18nProvider);
95         i18nProvider = givenI18nProvider;
96         updateLocalization();
97     }
98
99     /**
100      * Constructor
101      * <P>
102      * Initializes the {@link VeluxDiscoveryService} with a reference to the well-prepared environment with a
103      * {@link VeluxBridgeHandler}.
104      *
105      * @param bridge Initialized Velux bridge handler.
106      * @param localizationHandler Initialized localization handler.
107      */
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,
111                 i18nProvider);
112
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,
117                     bridge);
118         }
119         bridgeHandler = bridge;
120         localization = localizationHandler;
121     }
122
123     /**
124      * Constructor
125      * <P>
126      * Initializes the {@link VeluxDiscoveryService} with a reference to the well-prepared environment with a
127      * {@link VeluxBridgeHandler}.
128      *
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.
133      */
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,
138                 i18nProvider);
139     }
140
141     @Override
142     public void deactivate() {
143         logger.trace("deactivate() called.");
144         super.deactivate();
145     }
146
147     @Override
148     protected synchronized void startScan() {
149         logger.trace("startScan() called.");
150
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);
159
160         if (bridgeHandler == null) {
161             logger.debug("startScan(): VeluxDiscoveryService cannot proceed due to missing Velux bridge.");
162         } else {
163             logger.debug("startScan(): Starting Velux discovery scan for scenes and actuators.");
164             discoverScenes();
165             discoverProducts();
166         }
167         logger.trace("startScan() done.");
168     }
169
170     @Override
171     public synchronized void stopScan() {
172         logger.trace("stopScan() called.");
173         super.stopScan();
174         removeOlderResults(getTimestampOfLastScan());
175         logger.trace("stopScan() done.");
176     }
177
178     @Override
179     public void run() {
180         logger.trace("run() called.");
181     }
182
183     /**
184      * Discover the gateway-defined scenes.
185      */
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.");
192             return;
193         }
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);
199
200             String label = sceneName.replaceAll("\\P{Alnum}", "_");
201             logger.trace("discoverScenes(): using label {}.", label);
202
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);
211         }
212         logger.trace("discoverScenes() finished.");
213     }
214
215     /**
216      * Discover the gateway-defined products/actuators.
217      */
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.");
224             return;
225         }
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);
232             String identifier;
233             if (serialNumber.equals(VeluxProductSerialNo.UNKNOWN)) {
234                 identifier = actuatorName;
235             } else {
236                 identifier = serialNumber;
237             }
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()) {
244                 case SLIDER_WINDOW:
245                     logger.trace("discoverProducts(): creating window.");
246                     thingTypeUID = THING_TYPE_VELUX_WINDOW;
247                     isInverted = true;
248                     break;
249
250                 case SLIDER_SHUTTER:
251                     logger.trace("discoverProducts(): creating rollershutter.");
252                     thingTypeUID = THING_TYPE_VELUX_ROLLERSHUTTER;
253                     break;
254
255                 default:
256                     logger.trace("discoverProducts(): creating actuator.");
257                     thingTypeUID = THING_TYPE_VELUX_ACTUATOR;
258             }
259             ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
260
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);
269         }
270         logger.trace("discoverProducts() finished.");
271     }
272 }