2 * Copyright (c) 2010-2023 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.handler;
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.openhab.binding.velux.internal.VeluxBindingConstants;
17 import org.openhab.binding.velux.internal.VeluxBindingProperties;
18 import org.openhab.binding.velux.internal.VeluxItemType;
19 import org.openhab.binding.velux.internal.handler.utils.ExtendedBaseThingHandler;
20 import org.openhab.binding.velux.internal.handler.utils.StateUtils;
21 import org.openhab.binding.velux.internal.handler.utils.ThingProperty;
22 import org.openhab.binding.velux.internal.utils.Localization;
23 import org.openhab.binding.velux.internal.utils.ManifestInformation;
24 import org.openhab.core.common.AbstractUID;
25 import org.openhab.core.thing.Channel;
26 import org.openhab.core.thing.ChannelUID;
27 import org.openhab.core.thing.Thing;
28 import org.openhab.core.thing.ThingStatus;
29 import org.openhab.core.thing.ThingStatusDetail;
30 import org.openhab.core.thing.ThingTypeUID;
31 import org.openhab.core.types.Command;
32 import org.openhab.core.types.RefreshType;
33 import org.openhab.core.types.State;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * The class is responsible for representing the overall status of the Velux binding.
40 * Beside the normal thing handling introduced by {@link ExtendedBaseThingHandler}, it provides a method:
42 * <li>{@link #updateBindingState} to enable other classes to modify the number of activated Velux bridges and
46 * @author Guenther Schreiner - Initial contribution
49 public class VeluxBindingHandler extends ExtendedBaseThingHandler {
50 private final Logger logger = LoggerFactory.getLogger(VeluxBindingHandler.class);
53 * ***************************
54 * ***** Private Objects *****
57 private Localization localization;
58 private Integer currentNumberOfBridges = 0;
59 private Integer currentNumberOfThings = 0;
62 * ************************
63 * ***** Constructors *****
66 public VeluxBindingHandler(Thing thing, final Localization localization) {
69 this.localization = localization;
70 logger.trace("VeluxBindingHandler(constructor) called.");
74 * ***************************
75 * ***** Private Methods *****
79 * Provide the ThingType for a given Channel.
81 * Separated into this private method to deal with the deprecated method.
84 * @param channelUID for type {@link ChannelUID}.
85 * @return thingTypeUID of type {@link ThingTypeUID}.
87 private ThingTypeUID thingTypeUIDOf(ChannelUID channelUID) {
88 String[] segments = channelUID.getAsString().split(AbstractUID.SEPARATOR);
89 if (segments.length > 1) {
90 return new ThingTypeUID(segments[0], segments[1]);
92 logger.warn("thingTypeUIDOf({}) failed.", channelUID);
93 return new ThingTypeUID(VeluxBindingConstants.BINDING_ID, VeluxBindingConstants.UNKNOWN_THING_TYPE_ID);
97 * Returns a human-readable representation of the binding state. This should help especially unexperienced user to
98 * blossom up the introduction of the Velux binding.
100 * @return bindingInformation of type {@link String}.
102 private String bridgeCountToString() {
104 switch (currentNumberOfBridges) {
106 information = localization.getText("runtime.no-bridge");
109 information = localization.getText("runtime.one-bridge");
112 information = localization.getText("runtime.multiple-bridges");
119 * Modifies all informations within openHAB to inform the user about the current state of this binding. That is:
121 * <LI>Update the properties about bundle version, number of bridges and things,</LI>
122 * <LI>Usability of the binding in respect to defined bridges within the ThingStatus, and</LI>
123 * <LI>Information of the binding state as channel value.</LI>
126 private void updateVisibleInformation() {
127 logger.trace("updateVisibleInformation(): updating properties.");
128 ThingProperty.setValue(thing, VeluxBindingProperties.PROPERTY_BINDING_BUNDLEVERSION,
129 ManifestInformation.getBundleVersion());
130 ThingProperty.setValue(thing, VeluxBindingProperties.PROPERTY_BINDING_NOOFBRIDGES,
131 currentNumberOfBridges.toString());
132 ThingProperty.setValue(thing, VeluxBindingProperties.PROPERTY_BINDING_NOOFTHINGS,
133 currentNumberOfThings.toString());
135 // BaseThingHandler is sensitive during initialization phase. Therefore, to avoid (wrong) warnings about:
136 // "tried updating the thing status although the handler was already disposed."
137 if (this.isInitialized()) {
138 logger.trace("updateVisibleInformation(): updating thing status.");
139 if (currentNumberOfBridges < 1) {
140 updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING, bridgeCountToString());
142 updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE, bridgeCountToString());
144 logger.trace("updateVisibleInformation(): updating all channels.");
145 for (Channel channel : thing.getChannels()) {
146 handleCommand(channel.getUID(), RefreshType.REFRESH);
152 * *******************************************************************
153 * ***** Objects and Methods for abstract class BaseThingHandler *****
157 public void initialize() {
158 logger.debug("initialize() called.");
159 // The framework requires you to return from this method quickly.
160 // Setting the thing status to UNKNOWN temporarily and let the background task decide for the real status.
161 updateStatus(ThingStatus.UNKNOWN);
162 // Take care of unusual situations...
163 if (scheduler.isShutdown()) {
164 logger.warn("initialize(): scheduler is shutdown, aborting the initialization of this bridge.");
167 logger.trace("initialize(): preparing background initialization task.");
168 // Background initialization...
169 scheduler.execute(() -> {
170 logger.trace("initialize.scheduled(): Setting ThingStatus to ONLINE.");
171 updateStatus(ThingStatus.ONLINE);
172 updateVisibleInformation();
173 logger.debug("Velux Binding Info Element '{}' is initialized.", getThing().getUID());
175 logger.trace("initialize() done.");
179 public void handleCommand(ChannelUID channelUID, Command command) {
180 logger.trace("handleCommand({},{}) called.", channelUID.getAsString(), command);
182 * ===========================================================
185 String channelId = channelUID.getId();
186 State newState = null;
187 String itemName = channelUID.getAsString();
188 VeluxItemType itemType = VeluxItemType.getByThingAndChannel(thingTypeUIDOf(channelUID), channelUID.getId());
190 if (command instanceof RefreshType) {
192 * ===========================================================
195 logger.trace("handleCommand(): refreshing item {}.", itemName);
197 case BINDING_INFORMATION:
198 newState = StateUtils.createState(bridgeCountToString());
201 logger.trace("handleCommand(): cannot handle REFRESH on channel {} as it is of type {}.", itemName,
204 if (newState != null) {
205 logger.debug("handleCommand(): updating {} ({}) to {}.", itemName, channelUID, newState);
206 updateState(channelUID, newState);
208 logger.info("handleCommand({},{}): updating of item {} failed.", channelUID.getAsString(), command,
213 * ===========================================================
218 logger.warn("handleCommand() cannot handle command {} on channel {} (type {}).", command, itemName,
222 logger.trace("handleCommand() done.");
226 * **********************************
227 * ***** (Other) Public Methods *****
231 * Update the information about bridges and things.
233 * Provided for instrumentation of factory class to update this set of information.
236 * @param veluxBridgeCount describing the number of initialized bridges.
237 * @param veluxThingCount describing the number of initialized things (in addition to Thing of type
238 * BindingInformation).
240 public void updateBindingState(Integer veluxBridgeCount, Integer veluxThingCount) {
241 currentNumberOfBridges = veluxBridgeCount;
242 currentNumberOfThings = veluxThingCount;
243 updateVisibleInformation();