]> git.basschouten.com Git - openhab-addons.git/blob
be4794559e469d68cc18fa759f4cc925fc453198
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.plugwiseha.internal.handler;
14
15 import static org.openhab.core.thing.ThingStatus.*;
16
17 import java.lang.reflect.ParameterizedType;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.plugwiseha.internal.api.exception.PlugwiseHAException;
22 import org.openhab.binding.plugwiseha.internal.api.model.PlugwiseHAController;
23 import org.openhab.binding.plugwiseha.internal.config.PlugwiseHAThingConfig;
24 import org.openhab.core.thing.Bridge;
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.ThingStatusInfo;
31 import org.openhab.core.thing.binding.BaseThingHandler;
32 import org.openhab.core.types.Command;
33 import org.openhab.core.types.RefreshType;
34 import org.openhab.core.types.UnDefType;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * The {@link PlugwiseHABaseHandler} abstract class provides common methods and
40  * properties for the ThingHandlers of this binding. Extends @{link
41  * BaseThingHandler}
42  *
43  * @author Bas van Wetten - Initial contribution
44  * @author Leo Siepel - finish initial contribution
45  *
46  * @param <E> entity - the Plugwise Home Automation entity class used by this
47  *            thing handler
48  * @param <C> config - the Plugwise Home Automation config class used by this
49  *            thing handler
50  */
51
52 @NonNullByDefault
53 public abstract class PlugwiseHABaseHandler<E, C extends PlugwiseHAThingConfig> extends BaseThingHandler {
54
55     protected static final String STATUS_DESCRIPTION_COMMUNICATION_ERROR = "Error communicating with the Plugwise Home Automation controller";
56
57     protected final Logger logger = LoggerFactory.getLogger(PlugwiseHABaseHandler.class);
58
59     private Class<?> clazz;
60
61     // Constructor
62     @SuppressWarnings("null")
63     public PlugwiseHABaseHandler(Thing thing) {
64         super(thing);
65         clazz = (Class<?>) (((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1]);
66     }
67
68     // Abstract methods
69
70     /**
71      * Initializes the Plugwise Entity that this class handles.
72      *
73      * @param config the thing configuration
74      * @param bridge the bridge that this thing is part of
75      */
76     protected abstract void initialize(C config, PlugwiseHABridgeHandler bridge);
77
78     /**
79      * Get the Plugwise Entity that belongs to this ThingHandler
80      *
81      * @param controller the controller for this ThingHandler
82      * @param forceRefresh indicated if the entity should be refreshed from the Plugwise API
83      */
84     protected abstract @Nullable E getEntity(PlugwiseHAController controller, Boolean forceRefresh)
85             throws PlugwiseHAException;
86
87     /**
88      * Handles a {@link RefreshType} command for a given channel.
89      *
90      * @param entity the Plugwise Entity
91      * @param channelUID the channel uid the command is for
92      */
93     protected abstract void refreshChannel(E entity, ChannelUID channelUID);
94
95     /**
96      * Handles a command for a given channel.
97      * 
98      * @param entity the Plugwise Entity
99      * @param channelUID the channel uid the command is for
100      * @param command the command
101      */
102     protected abstract void handleCommand(E entity, ChannelUID channelUID, Command command) throws PlugwiseHAException;
103
104     // Overrides
105
106     @Override
107     public void initialize() {
108         C config = getPlugwiseThingConfig();
109
110         if (checkConfig(config)) {
111             Bridge bridge = getBridge();
112             if (bridge == null || bridge.getHandler() == null
113                     || !(bridge.getHandler() instanceof PlugwiseHABridgeHandler)) {
114                 updateStatus(OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
115                         "You must choose a Plugwise Home Automation bridge for this thing.");
116                 return;
117             }
118
119             if (bridge.getStatus() == OFFLINE) {
120                 updateStatus(OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE,
121                         "The Plugwise Home Automation bridge is currently offline.");
122             }
123
124             PlugwiseHABridgeHandler bridgeHandler = (PlugwiseHABridgeHandler) bridge.getHandler();
125             if (bridgeHandler != null) {
126                 initialize(config, bridgeHandler);
127             }
128         } else {
129             logger.debug("Invalid config for Plugwise Home Automation thing handler with config = {}", config);
130         }
131     }
132
133     @Override
134     public final void handleCommand(ChannelUID channelUID, Command command) {
135         logger.debug("Handling command = {} for channel = {}", command, channelUID);
136
137         if (getThing().getStatus() == ONLINE) {
138             PlugwiseHAController controller = getController();
139             if (controller != null) {
140                 try {
141                     @Nullable
142                     E entity = getEntity(controller, false);
143                     if (entity != null) {
144                         if (this.isLinked(channelUID)) {
145                             if (command instanceof RefreshType) {
146                                 refreshChannel(entity, channelUID);
147                             } else {
148                                 handleCommand(entity, channelUID, command);
149                             }
150                         }
151                     }
152                 } catch (PlugwiseHAException e) {
153                     logger.warn("Unexpected error handling command = {} for channel = {} : {}", command, channelUID,
154                             e.getMessage());
155                 }
156             }
157         }
158     }
159
160     // Public member methods
161
162     public @Nullable PlugwiseHABridgeHandler getPlugwiseHABridge() {
163         Bridge bridge = this.getBridge();
164         if (bridge != null) {
165             return (PlugwiseHABridgeHandler) bridge.getHandler();
166         }
167
168         return null;
169     }
170
171     @SuppressWarnings("unchecked")
172     public C getPlugwiseThingConfig() {
173         return (C) getConfigAs(clazz);
174     }
175
176     // Private & protected methods
177
178     private @Nullable PlugwiseHAController getController() {
179         PlugwiseHABridgeHandler bridgeHandler = getPlugwiseHABridge();
180
181         if (bridgeHandler != null) {
182             return bridgeHandler.getController();
183         }
184
185         return null;
186     }
187
188     /**
189      * Checks the configuration for validity, result is reflected in the status of
190      * the Thing
191      */
192     private boolean checkConfig(C config) {
193         if (!config.isValid()) {
194             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
195                     "Configuration is missing or corrupted");
196             return false;
197         } else {
198             return true;
199         }
200     }
201
202     @Override
203     public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
204         super.bridgeStatusChanged(bridgeStatusInfo);
205         if (bridgeStatusInfo.getStatus() == ThingStatus.OFFLINE) {
206             setLinkedChannelsUndef();
207         }
208     }
209
210     private void setLinkedChannelsUndef() {
211         for (Channel channel : getThing().getChannels()) {
212             ChannelUID channelUID = channel.getUID();
213             if (this.isLinked(channelUID)) {
214                 updateState(channelUID, UnDefType.UNDEF);
215             }
216         }
217     }
218
219     protected final void refresh() {
220         PlugwiseHABridgeHandler bridgeHandler = getPlugwiseHABridge();
221         if (bridgeHandler != null) {
222             if (bridgeHandler.getThing().getStatusInfo().getStatus() == ThingStatus.ONLINE) {
223                 PlugwiseHAController controller = getController();
224                 if (controller != null) {
225                     @Nullable
226                     E entity = null;
227                     try {
228                         entity = getEntity(controller, false);
229                     } catch (PlugwiseHAException e) {
230                         updateStatus(OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
231                         setLinkedChannelsUndef();
232                     }
233                     if (entity != null) {
234                         for (Channel channel : getThing().getChannels()) {
235                             ChannelUID channelUID = channel.getUID();
236                             if (this.isLinked(channelUID)) {
237                                 refreshChannel(entity, channelUID);
238                             }
239                         }
240                     }
241                 }
242             }
243         }
244     }
245 }