]> git.basschouten.com Git - openhab-addons.git/blob
c6d461fbba3e3b3ed5811aefd12ba62049a6322a
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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 java.util.Map;
16 import java.util.Map.Entry;
17
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.openhab.binding.velux.internal.VeluxBindingConstants;
20 import org.openhab.binding.velux.internal.handler.utils.ExtendedBaseThingHandler;
21 import org.openhab.binding.velux.internal.handler.utils.Thing2VeluxActuator;
22 import org.openhab.binding.velux.internal.things.VeluxProduct;
23 import org.openhab.binding.velux.internal.utils.Localization;
24 import org.openhab.core.config.core.Configuration;
25 import org.openhab.core.thing.Bridge;
26 import org.openhab.core.thing.Channel;
27 import org.openhab.core.thing.ChannelUID;
28 import org.openhab.core.thing.Thing;
29 import org.openhab.core.thing.ThingStatus;
30 import org.openhab.core.thing.ThingStatusDetail;
31 import org.openhab.core.thing.binding.BridgeHandler;
32 import org.openhab.core.types.Command;
33 import org.openhab.core.types.RefreshType;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /***
38  * The{@link VeluxHandler} is responsible for handling commands, which are
39  * sent via {@link VeluxBridgeHandler} to one of the channels.
40  *
41  * @author Guenther Schreiner - Initial contribution
42  */
43 @NonNullByDefault
44 public class VeluxHandler extends ExtendedBaseThingHandler {
45     private final Logger logger = LoggerFactory.getLogger(VeluxHandler.class);
46
47     public VeluxHandler(Thing thing, Localization localization) {
48         super(thing);
49         logger.trace("VeluxHandler(thing={},localization={}) constructor called.", thing, localization);
50     }
51
52     @Override
53     public void initialize() {
54         logger.trace("initialize() called.");
55         Bridge thisBridge = getBridge();
56         logger.debug("initialize(): Initializing thing {} in combination with bridge {}.", getThing().getUID(),
57                 thisBridge);
58         if (thisBridge == null) {
59             logger.trace("initialize() updating ThingStatus to OFFLINE/CONFIGURATION_PENDING.");
60             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING);
61
62         } else if (thisBridge.getStatus() == ThingStatus.ONLINE) {
63             logger.trace("initialize() updating ThingStatus to ONLINE.");
64             updateStatus(ThingStatus.ONLINE);
65             initializeProperties();
66         } else {
67             logger.trace("initialize() updating ThingStatus to OFFLINE/BRIDGE_OFFLINE.");
68             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
69         }
70         logger.trace("initialize() done.");
71     }
72
73     private synchronized void initializeProperties() {
74         logger.trace("initializeProperties() done.");
75     }
76
77     @Override
78     public void dispose() {
79         logger.trace("dispose() called.");
80         super.dispose();
81     }
82
83     @Override
84     public void channelLinked(ChannelUID channelUID) {
85         logger.trace("channelLinked({}) called.", channelUID.getAsString());
86
87         if (thing.getStatus() == ThingStatus.ONLINE) {
88             handleCommand(channelUID, RefreshType.REFRESH);
89         }
90     }
91
92     @Override
93     public void handleCommand(ChannelUID channelUID, Command command) {
94         logger.trace("handleCommand({},{}) initiated by {}.", channelUID.getAsString(), command,
95                 Thread.currentThread());
96         Bridge bridge = getBridge();
97         if (bridge == null) {
98             logger.trace("handleCommand() nothing yet to do as there is no bridge available.");
99         } else {
100             BridgeHandler handler = bridge.getHandler();
101             if (handler == null) {
102                 logger.trace("handleCommand() nothing yet to do as thing is not initialized.");
103             } else {
104                 handler.handleCommand(channelUID, command);
105             }
106         }
107         logger.trace("handleCommand() done.");
108     }
109
110     @Override
111     public void handleConfigurationUpdate(Map<String, Object> configurationParameters) {
112         if (isInitialized()) { // prevents change of address
113             validateConfigurationParameters(configurationParameters);
114             Configuration configuration = editConfiguration();
115             for (Entry<String, Object> configurationParameter : configurationParameters.entrySet()) {
116                 logger.trace("handleConfigurationUpdate(): found modified config entry {}.",
117                         configurationParameter.getKey());
118                 configuration.put(configurationParameter.getKey(), configurationParameter.getValue());
119             }
120             // persist new configuration and reinitialize handler
121             dispose();
122             updateConfiguration(configuration);
123             initialize();
124         } else {
125             super.handleConfigurationUpdate(configurationParameters);
126         }
127     }
128
129     /**
130      * Remove previously statically created vane channel if the device does not support it. Or log a warning if it does
131      * support a vane and the respective channel is missing.
132      *
133      * @param bridgeHandler the calling bridge handler.
134      * @throws IllegalStateException if something went wrong.
135      */
136     public void updateDynamicChannels(VeluxBridgeHandler bridgeHandler) throws IllegalStateException {
137         // roller shutters are the only things with a previously statically created vane channel
138         if (!VeluxBindingConstants.THING_TYPE_VELUX_ROLLERSHUTTER.equals(thing.getThingTypeUID())) {
139             return;
140         }
141
142         String id = VeluxBindingConstants.CHANNEL_VANE_POSITION;
143         ChannelUID uid = new ChannelUID(thing.getUID(), id);
144         Thing2VeluxActuator actuator = new Thing2VeluxActuator(bridgeHandler, uid);
145         VeluxProduct product = bridgeHandler.existingProducts().get(actuator.getProductBridgeIndex());
146
147         if (product.equals(VeluxProduct.UNKNOWN)) {
148             throw new IllegalStateException("updateDynamicChannels(): Product unknown in the bridge");
149         }
150
151         Channel channel = thing.getChannel(id);
152         boolean required = product.supportsVanePosition();
153
154         if (!required && channel != null) {
155             logger.debug("Removing unsupported channel for {}: {}", thing.getUID(), id);
156             updateThing(editThing().withoutChannels(channel).build());
157         } else if (required && channel == null) {
158             logger.warn("Thing {} does not have a '{}' channel => please re-create it", thing.getUID(), id);
159         }
160     }
161 }