]> git.basschouten.com Git - openhab-addons.git/blob
62d81ba2a58860be0bb098d730e0c9601f215765
[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.lutron.internal.handler;
14
15 import static org.openhab.binding.lutron.internal.LutronBindingConstants.*;
16
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.lutron.internal.protocol.LutronCommandType;
23 import org.openhab.core.library.types.DecimalType;
24 import org.openhab.core.library.types.OnOffType;
25 import org.openhab.core.thing.Bridge;
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.types.Command;
31 import org.openhab.core.types.RefreshType;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36  * Handler responsible for communicating with RadioRA 2 Green Mode subsystem
37  *
38  * @author Bob Adair - Initial contribution
39  */
40 @NonNullByDefault
41 public class GreenModeHandler extends LutronHandler {
42     private static final Integer ACTION_STEP = 1;
43     public static final int GREENSTEP_MIN = 1;
44
45     // poll interval parameters are in minutes
46     private static final int POLL_INTERVAL_DEFAULT = 15;
47     private static final int POLL_INTERVAL_MAX = 240;
48     private static final int POLL_INTERVAL_MIN = 0;
49
50     private final Logger logger = LoggerFactory.getLogger(GreenModeHandler.class);
51
52     private int integrationId;
53     private int pollInterval;
54     private @Nullable ScheduledFuture<?> pollJob;
55
56     public GreenModeHandler(Thing thing) {
57         super(thing);
58     }
59
60     @Override
61     public int getIntegrationId() {
62         return integrationId;
63     }
64
65     @Override
66     public void initialize() {
67         Number id = (Number) getThing().getConfiguration().get(INTEGRATION_ID);
68         if (id == null) {
69             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No integrationId");
70             return;
71         }
72         integrationId = id.intValue();
73
74         Number pollInterval = (Number) getThing().getConfiguration().get(POLL_INTERVAL);
75         if (pollInterval == null) {
76             this.pollInterval = POLL_INTERVAL_DEFAULT;
77         } else {
78             this.pollInterval = pollInterval.intValue();
79             this.pollInterval = Math.min(this.pollInterval, POLL_INTERVAL_MAX);
80             this.pollInterval = Math.max(this.pollInterval, POLL_INTERVAL_MIN);
81         }
82         logger.debug("Initializing Green Mode handler for integration ID {} with poll interval {}", integrationId,
83                 this.pollInterval);
84
85         initDeviceState();
86     }
87
88     @Override
89     protected void initDeviceState() {
90         logger.debug("Initializing device state for Green Mode subsystem {}", getIntegrationId());
91         stopPolling();
92         Bridge bridge = getBridge();
93         if (bridge == null) {
94             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No bridge configured");
95         } else if (bridge.getStatus() == ThingStatus.ONLINE) {
96             updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, "Awaiting initial response");
97             queryGreenMode(ACTION_STEP); // handleUpdate() will set thing status to online when response arrives
98         } else {
99             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
100         }
101     }
102
103     @Override
104     protected void thingOfflineNotify() {
105         stopPolling();
106     }
107
108     private void startPolling() {
109         if (pollInterval > 0 && pollJob == null) {
110             logger.debug("Scheduling green mode polling job for integration ID {}", integrationId);
111             pollJob = scheduler.scheduleWithFixedDelay(this::pollState, pollInterval, pollInterval, TimeUnit.MINUTES);
112         }
113     }
114
115     private void stopPolling() {
116         ScheduledFuture<?> pollJob = this.pollJob;
117         if (pollJob != null) {
118             this.pollJob = null;
119             logger.debug("Canceling green mode polling job for integration ID {}", integrationId);
120             pollJob.cancel(true);
121         }
122     }
123
124     private synchronized void pollState() {
125         logger.trace("Executing green mode polling job for integration ID {}", integrationId);
126         queryGreenMode(ACTION_STEP);
127     }
128
129     @Override
130     public void channelLinked(ChannelUID channelUID) {
131         if (channelUID.getId().equals(CHANNEL_STEP)) {
132             queryGreenMode(ACTION_STEP);
133         }
134     }
135
136     @Override
137     public void handleCommand(ChannelUID channelUID, Command command) {
138         if (channelUID.getId().equals(CHANNEL_STEP)) {
139             if (command == OnOffType.ON) {
140                 greenMode(ACTION_STEP, 2);
141             } else if (command == OnOffType.OFF) {
142                 greenMode(ACTION_STEP, 1);
143             } else if (command instanceof Number) {
144                 Integer step = ((Number) command).intValue();
145                 if (step.intValue() >= GREENSTEP_MIN) {
146                     greenMode(ACTION_STEP, step);
147                 }
148             } else if (command instanceof RefreshType) {
149                 queryGreenMode(ACTION_STEP);
150             } else {
151                 logger.debug("Ignoring invalid command {} for id {}", command, integrationId);
152             }
153         } else {
154             logger.debug("Ignoring command to invalid channel {} for id {}", channelUID.getId(), integrationId);
155         }
156     }
157
158     @Override
159     public void handleUpdate(LutronCommandType type, String... parameters) {
160         try {
161             if (type == LutronCommandType.MODE && parameters.length > 1
162                     && ACTION_STEP.toString().equals(parameters[0])) {
163                 Long step = Long.valueOf(parameters[1]);
164                 if (getThing().getStatus() == ThingStatus.UNKNOWN) {
165                     updateStatus(ThingStatus.ONLINE);
166                     startPolling();
167                 }
168                 updateState(CHANNEL_STEP, new DecimalType(step.longValue()));
169             } else {
170                 logger.debug("Ignoring unexpected update for id {}", integrationId);
171             }
172         } catch (NumberFormatException e) {
173             logger.debug("Encountered number format exception while handling update for greenmode {}", integrationId);
174         }
175     }
176
177     @Override
178     public void dispose() {
179         stopPolling();
180     }
181 }