]> git.basschouten.com Git - openhab-addons.git/blob
29f99de388630b95bb402470b545c6d696fa22c7
[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.handler;
14
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.openhab.binding.velux.internal.VeluxBindingProperties;
17 import org.openhab.binding.velux.internal.VeluxItemType;
18 import org.openhab.binding.velux.internal.handler.utils.ExtendedBaseThingHandler;
19 import org.openhab.binding.velux.internal.handler.utils.StateUtils;
20 import org.openhab.binding.velux.internal.handler.utils.ThingProperty;
21 import org.openhab.binding.velux.internal.utils.Localization;
22 import org.openhab.binding.velux.internal.utils.ManifestInformation;
23 import org.openhab.core.thing.Channel;
24 import org.openhab.core.thing.ChannelUID;
25 import org.openhab.core.thing.Thing;
26 import org.openhab.core.thing.ThingStatus;
27 import org.openhab.core.thing.ThingStatusDetail;
28 import org.openhab.core.thing.ThingTypeUID;
29 import org.openhab.core.types.Command;
30 import org.openhab.core.types.RefreshType;
31 import org.openhab.core.types.State;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /***
36  * The class is responsible for representing the overall status of the Velux binding.
37  * <P>
38  * Beside the normal thing handling introduced by {@link ExtendedBaseThingHandler}, it provides a method:
39  * <ul>
40  * <li>{@link #updateBindingState} to enable other classes to modify the number of activated Velux bridges and
41  * Things.</LI>
42  * </UL>
43  *
44  * @author Guenther Schreiner - Initial contribution
45  */
46 @NonNullByDefault
47 public class VeluxBindingHandler extends ExtendedBaseThingHandler {
48     private final Logger logger = LoggerFactory.getLogger(VeluxBindingHandler.class);
49
50     /*
51      * ***************************
52      * ***** Private Objects *****
53      */
54     private Thing thing;
55     private Localization localization;
56     private Integer currentNumberOfBridges = 0;
57     private Integer currentNumberOfThings = 0;
58
59     /*
60      * ************************
61      * ***** Constructors *****
62      */
63
64     public VeluxBindingHandler(Thing thing, final Localization localization) {
65         super(thing);
66         this.thing = thing;
67         this.localization = localization;
68         logger.trace("VeluxBindingHandler(constructor) called.");
69     }
70
71     /*
72      * ***************************
73      * ***** Private Methods *****
74      */
75
76     /**
77      * Provide the ThingType for a given Channel.
78      * <P>
79      * Separated into this private method to deal with the deprecated method.
80      * </P>
81      *
82      * @param channelUID for type {@link ChannelUID}.
83      * @return thingTypeUID of type {@link ThingTypeUID}.
84      */
85     @SuppressWarnings("deprecation")
86     private ThingTypeUID thingTypeUIDOf(ChannelUID channelUID) {
87         return channelUID.getThingUID().getThingTypeUID();
88     }
89
90     /**
91      * Returns a human-readable representation of the binding state. This should help especially unexperienced user to
92      * blossom up the introduction of the Velux binding.
93      *
94      * @return bindingInformation of type {@link String}.
95      */
96     private String bridgeCountToString() {
97         String information;
98         switch (currentNumberOfBridges) {
99             case 0:
100                 information = localization.getText("runtime.no-bridge");
101                 break;
102             case 1:
103                 information = localization.getText("runtime.one-bridge");
104                 break;
105             default:
106                 information = localization.getText("runtime.multiple-bridges");
107                 break;
108         }
109         return information;
110     }
111
112     /**
113      * Modifies all informations within openHAB to inform the user about the current state of this binding. That is:
114      * <UL>
115      * <LI>Update the properties about bundle version, number of bridges and things,</LI>
116      * <LI>Usability of the binding in respect to defined bridges within the ThingStatus, and</LI>
117      * <LI>Information of the binding state as channel value.</LI>
118      * </UL>
119      */
120     private void updateVisibleInformation() {
121         logger.trace("updateVisibleInformation(): updating properties.");
122         ThingProperty.setValue(thing, VeluxBindingProperties.PROPERTY_BINDING_BUNDLEVERSION,
123                 ManifestInformation.getBundleVersion());
124         ThingProperty.setValue(thing, VeluxBindingProperties.PROPERTY_BINDING_NOOFBRIDGES,
125                 currentNumberOfBridges.toString());
126         ThingProperty.setValue(thing, VeluxBindingProperties.PROPERTY_BINDING_NOOFTHINGS,
127                 currentNumberOfThings.toString());
128
129         // BaseThingHandler is sensitive during initialization phase. Therefore, to avoid (wrong) warnings about:
130         // "tried updating the thing status although the handler was already disposed."
131         if (this.isInitialized()) {
132             logger.trace("updateVisibleInformation(): updating thing status.");
133             if (currentNumberOfBridges < 1) {
134                 updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING, bridgeCountToString());
135             } else {
136                 updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE, bridgeCountToString());
137             }
138             logger.trace("updateVisibleInformation(): updating all channels.");
139             for (Channel channel : thing.getChannels()) {
140                 handleCommand(channel.getUID(), RefreshType.REFRESH);
141             }
142         }
143     }
144
145     /*
146      * *******************************************************************
147      * ***** Objects and Methods for abstract class BaseThingHandler *****
148      */
149
150     @Override
151     public void initialize() {
152         logger.debug("initialize() called.");
153         logger.info("Initializing VeluxBindingHandler for '{}'.", getThing().getUID());
154         // The framework requires you to return from this method quickly.
155         // Setting the thing status to UNKNOWN temporarily and let the background task decide for the real status.
156         updateStatus(ThingStatus.UNKNOWN);
157         // Take care of unusual situations...
158         if (scheduler.isShutdown()) {
159             logger.warn("initialize(): scheduler is shutdown, aborting the initialization of this bridge.");
160             return;
161         }
162         logger.trace("initialize(): preparing background initialization task.");
163         // Background initialization...
164         scheduler.execute(() -> {
165             logger.trace("initialize.scheduled(): Setting ThingStatus to ONLINE.");
166             updateStatus(ThingStatus.ONLINE);
167             updateVisibleInformation();
168             logger.trace("initialize.scheduled(): done.");
169         });
170         logger.trace("initialize() done.");
171     }
172
173     @Override
174     public void handleCommand(ChannelUID channelUID, Command command) {
175         logger.trace("handleCommand({},{}) called.", channelUID.getAsString(), command);
176         /*
177          * ===========================================================
178          * Common part
179          */
180         String channelId = channelUID.getId();
181         State newState = null;
182         String itemName = channelUID.getAsString();
183         VeluxItemType itemType = VeluxItemType.getByThingAndChannel(thingTypeUIDOf(channelUID), channelUID.getId());
184
185         if (command instanceof RefreshType) {
186             /*
187              * ===========================================================
188              * Refresh part
189              */
190             logger.trace("handleCommand(): refreshing item {}.", itemName);
191             switch (itemType) {
192                 case BINDING_INFORMATION:
193                     newState = StateUtils.createState(bridgeCountToString());
194                     break;
195                 default:
196                     logger.trace("handleCommand(): cannot handle REFRESH on channel {} as it is of type {}.", itemName,
197                             channelId);
198             }
199             if (newState != null) {
200                 logger.debug("handleCommand(): updating {} ({}) to {}.", itemName, channelUID, newState);
201                 updateState(channelUID, newState);
202             } else {
203                 logger.info("handleCommand({},{}): updating of item {} failed.", channelUID.getAsString(), command,
204                         itemName);
205             }
206         } else {
207             /*
208              * ===========================================================
209              * Modification part
210              */
211             switch (channelId) {
212                 default:
213                     logger.warn("handleCommand() cannot handle command {} on channel {} (type {}).", command, itemName,
214                             itemType);
215             }
216         }
217         logger.trace("handleCommand() done.");
218     }
219
220     /*
221      * **********************************
222      * ***** (Other) Public Methods *****
223      */
224
225     /**
226      * Update the information about bridges and things.
227      * <P>
228      * Provided for instrumentation of factory class to update this set of information.
229      * </P>
230      *
231      * @param veluxBridgeCount describing the number of initialized bridges.
232      * @param veluxThingCount describing the number of initialized things (in addition to Thing of type
233      *            BindingInformation).
234      */
235     public void updateBindingState(Integer veluxBridgeCount, Integer veluxThingCount) {
236         currentNumberOfBridges = veluxBridgeCount;
237         currentNumberOfThings = veluxThingCount;
238         updateVisibleInformation();
239     }
240 }