]> git.basschouten.com Git - openhab-addons.git/blob
c31c1b777e38c691d9394438c3bf8e4b4e282d4a
[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.powermax.internal.handler;
14
15 import static org.openhab.binding.powermax.internal.PowermaxBindingConstants.*;
16
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.openhab.binding.powermax.internal.config.PowermaxX10Configuration;
19 import org.openhab.binding.powermax.internal.config.PowermaxZoneConfiguration;
20 import org.openhab.binding.powermax.internal.state.PowermaxPanelSettings;
21 import org.openhab.binding.powermax.internal.state.PowermaxPanelSettingsListener;
22 import org.openhab.binding.powermax.internal.state.PowermaxState;
23 import org.openhab.binding.powermax.internal.state.PowermaxStateContainer.Value;
24 import org.openhab.binding.powermax.internal.state.PowermaxX10Settings;
25 import org.openhab.binding.powermax.internal.state.PowermaxZoneSettings;
26 import org.openhab.core.library.types.OnOffType;
27 import org.openhab.core.thing.Bridge;
28 import org.openhab.core.thing.ChannelUID;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.thing.ThingStatusInfo;
33 import org.openhab.core.thing.binding.BaseThingHandler;
34 import org.openhab.core.thing.binding.ThingHandler;
35 import org.openhab.core.types.Command;
36 import org.openhab.core.types.RefreshType;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 /**
41  * The {@link PowermaxThingHandler} is responsible for handling commands, which are
42  * sent to one of the channels.
43  *
44  * @author Laurent Garnier - Initial contribution
45  */
46 public class PowermaxThingHandler extends BaseThingHandler implements PowermaxPanelSettingsListener {
47
48     private final Logger logger = LoggerFactory.getLogger(PowermaxThingHandler.class);
49
50     private static final int ZONE_NR_MIN = 1;
51     private static final int ZONE_NR_MAX = 64;
52     private static final int X10_NR_MIN = 1;
53     private static final int X10_NR_MAX = 16;
54
55     private PowermaxBridgeHandler bridgeHandler;
56
57     public PowermaxThingHandler(Thing thing) {
58         super(thing);
59     }
60
61     @Override
62     public void initialize() {
63         logger.debug("Initializing handler for thing {}", getThing().getUID());
64         Bridge bridge = getBridge();
65         if (bridge == null) {
66             initializeThingState(null, null);
67         } else {
68             initializeThingState(bridge.getHandler(), bridge.getStatus());
69         }
70     }
71
72     @Override
73     public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
74         logger.debug("Bridge status changed to {} for thing {}", bridgeStatusInfo, getThing().getUID());
75         Bridge bridge = getBridge();
76         initializeThingState((bridge == null) ? null : bridge.getHandler(), bridgeStatusInfo.getStatus());
77     }
78
79     private void initializeThingState(ThingHandler bridgeHandler, ThingStatus bridgeStatus) {
80         if (bridgeHandler != null && bridgeStatus != null) {
81             if (bridgeStatus == ThingStatus.ONLINE) {
82                 boolean validConfig = false;
83                 String errorMsg = "Unexpected thing type " + getThing().getThingTypeUID();
84
85                 if (getThing().getThingTypeUID().equals(THING_TYPE_ZONE)) {
86                     PowermaxZoneConfiguration config = getConfigAs(PowermaxZoneConfiguration.class);
87                     if (config.zoneNumber != null && config.zoneNumber >= ZONE_NR_MIN
88                             && config.zoneNumber <= ZONE_NR_MAX) {
89                         validConfig = true;
90                     } else {
91                         errorMsg = "zoneNumber setting must be defined in thing configuration and set between "
92                                 + ZONE_NR_MIN + " and " + ZONE_NR_MAX;
93                     }
94                 } else if (getThing().getThingTypeUID().equals(THING_TYPE_X10)) {
95                     PowermaxX10Configuration config = getConfigAs(PowermaxX10Configuration.class);
96                     if (config.deviceNumber != null && config.deviceNumber >= X10_NR_MIN
97                             && config.deviceNumber <= X10_NR_MAX) {
98                         validConfig = true;
99                     } else {
100                         errorMsg = "deviceNumber setting must be defined in thing configuration and set between "
101                                 + X10_NR_MIN + " and " + X10_NR_MAX;
102                     }
103                 }
104
105                 if (validConfig) {
106                     updateStatus(ThingStatus.UNKNOWN);
107                     logger.debug("Set handler status to UNKNOWN for thing {} (bridge ONLINE)", getThing().getUID());
108                     this.bridgeHandler = (PowermaxBridgeHandler) bridgeHandler;
109                     this.bridgeHandler.registerPanelSettingsListener(this);
110                     onPanelSettingsUpdated(this.bridgeHandler.getPanelSettings());
111                 } else {
112                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMsg);
113                 }
114             } else {
115                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
116                 logger.debug("Set handler status to OFFLINE for thing {} (bridge OFFLINE)", getThing().getUID());
117             }
118         } else {
119             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
120             logger.debug("Set handler status to OFFLINE for thing {}", getThing().getUID());
121         }
122     }
123
124     @Override
125     public void dispose() {
126         logger.debug("Handler disposed for thing {}", getThing().getUID());
127         if (bridgeHandler != null) {
128             bridgeHandler.unregisterPanelSettingsListener(this);
129         }
130         super.dispose();
131     }
132
133     @Override
134     public void handleCommand(ChannelUID channelUID, Command command) {
135         logger.debug("Received command {} from channel {}", command, channelUID.getId());
136
137         if (bridgeHandler == null) {
138             return;
139         } else if (command instanceof RefreshType) {
140             updateChannelFromAlarmState(channelUID.getId(), bridgeHandler.getCurrentState());
141         } else {
142             switch (channelUID.getId()) {
143                 case BYPASSED:
144                     if (command instanceof OnOffType) {
145                         bridgeHandler.zoneBypassed(getConfigAs(PowermaxZoneConfiguration.class).zoneNumber.byteValue(),
146                                 command.equals(OnOffType.ON));
147                     } else {
148                         logger.debug("Command of type {} while OnOffType is expected. Command is ignored.",
149                                 command.getClass().getSimpleName());
150                     }
151                     break;
152                 case X10_STATUS:
153                     bridgeHandler.x10Command(getConfigAs(PowermaxX10Configuration.class).deviceNumber.byteValue(),
154                             command);
155                     break;
156                 default:
157                     logger.debug("No available command for channel {}. Command is ignored.", channelUID.getId());
158                     break;
159             }
160         }
161     }
162
163     /**
164      * Update channel to match a new alarm system state
165      *
166      * @param channel: the channel
167      * @param state: the alarm system state
168      */
169     public void updateChannelFromAlarmState(String channel, PowermaxState state) {
170         if (state == null || channel == null || !isLinked(channel)) {
171             return;
172         }
173
174         if (getThing().getThingTypeUID().equals(THING_TYPE_ZONE)) {
175             int num = getConfigAs(PowermaxZoneConfiguration.class).zoneNumber.intValue();
176
177             for (Value<?> value : state.getZone(num).getValues()) {
178                 String v_channel = value.getChannel();
179
180                 if (channel.equals(v_channel) && (value.getValue() != null)) {
181                     updateState(v_channel, value.getState());
182                 }
183             }
184         } else if (getThing().getThingTypeUID().equals(THING_TYPE_X10)) {
185             int num = getConfigAs(PowermaxX10Configuration.class).deviceNumber.intValue();
186             if (channel.equals(X10_STATUS) && (state.getPGMX10DeviceStatus(num) != null)) {
187                 updateState(X10_STATUS, state.getPGMX10DeviceStatus(num) ? OnOffType.ON : OnOffType.OFF);
188             }
189         }
190     }
191
192     @Override
193     public void onPanelSettingsUpdated(@Nullable PowermaxPanelSettings settings) {
194         if (getThing().getThingTypeUID().equals(THING_TYPE_ZONE)) {
195             PowermaxZoneConfiguration config = getConfigAs(PowermaxZoneConfiguration.class);
196             onZoneSettingsUpdated(config.zoneNumber, settings);
197         } else if (getThing().getThingTypeUID().equals(THING_TYPE_X10)) {
198             if (isNotReadyForThingStatusUpdate()) {
199                 return;
200             }
201
202             PowermaxX10Configuration config = getConfigAs(PowermaxX10Configuration.class);
203             PowermaxX10Settings deviceSettings = (settings == null) ? null
204                     : settings.getX10Settings(config.deviceNumber);
205             if (settings == null) {
206                 if (getThing().getStatus() != ThingStatus.UNKNOWN) {
207                     updateStatus(ThingStatus.UNKNOWN);
208                     logger.debug("Set handler status to UNKNOWN for thing {}", getThing().getUID());
209                 }
210             } else if (deviceSettings == null || !deviceSettings.isEnabled()) {
211                 if (getThing().getStatus() != ThingStatus.OFFLINE) {
212                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Disabled device");
213                     logger.debug("Set handler status to OFFLINE for thing {} (X10 device {} disabled)",
214                             getThing().getUID(), config.deviceNumber);
215                 }
216             } else if (getThing().getStatus() != ThingStatus.ONLINE) {
217                 updateStatus(ThingStatus.ONLINE);
218                 logger.debug("Set handler status to ONLINE for thing {} (X10 device {} enabled)", getThing().getUID(),
219                         config.deviceNumber);
220             }
221         }
222     }
223
224     @Override
225     public void onZoneSettingsUpdated(int zoneNumber, @Nullable PowermaxPanelSettings settings) {
226         if (getThing().getThingTypeUID().equals(THING_TYPE_ZONE)) {
227             PowermaxZoneConfiguration config = getConfigAs(PowermaxZoneConfiguration.class);
228             if (zoneNumber == config.zoneNumber) {
229                 if (isNotReadyForThingStatusUpdate()) {
230                     return;
231                 }
232
233                 PowermaxZoneSettings zoneSettings = (settings == null) ? null
234                         : settings.getZoneSettings(config.zoneNumber);
235                 if (settings == null) {
236                     if (getThing().getStatus() != ThingStatus.UNKNOWN) {
237                         updateStatus(ThingStatus.UNKNOWN);
238                         logger.debug("Set handler status to UNKNOWN for thing {}", getThing().getUID());
239                     }
240                 } else if (zoneSettings == null) {
241                     if (getThing().getStatus() != ThingStatus.OFFLINE) {
242                         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Zone not paired");
243                         logger.debug("Set handler status to OFFLINE for thing {} (zone number {} not paired)",
244                                 getThing().getUID(), config.zoneNumber);
245                     }
246                 } else if (getThing().getStatus() != ThingStatus.ONLINE) {
247                     updateStatus(ThingStatus.ONLINE);
248                     logger.debug("Set handler status to ONLINE for thing {} (zone number {} paired)",
249                             getThing().getUID(), config.zoneNumber);
250                 }
251             }
252         }
253     }
254
255     private boolean isNotReadyForThingStatusUpdate() {
256         return (getThing().getStatus() == ThingStatus.OFFLINE)
257                 && ((getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR)
258                         || (getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.BRIDGE_OFFLINE)
259                         || (getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.BRIDGE_UNINITIALIZED));
260     }
261
262     public PowermaxZoneConfiguration getZoneConfiguration() {
263         return getConfigAs(PowermaxZoneConfiguration.class);
264     }
265
266     public PowermaxX10Configuration getX10Configuration() {
267         return getConfigAs(PowermaxX10Configuration.class);
268     }
269 }