]> git.basschouten.com Git - openhab-addons.git/blob
55a571299536880307767d5637e48f7e5c3527bc
[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         if (pollJob != null) {
117             logger.debug("Canceling green mode polling job for integration ID {}", integrationId);
118             pollJob.cancel(true);
119             pollJob = null;
120         }
121     }
122
123     private synchronized void pollState() {
124         logger.trace("Executing green mode polling job for integration ID {}", integrationId);
125         queryGreenMode(ACTION_STEP);
126     }
127
128     @Override
129     public void channelLinked(ChannelUID channelUID) {
130         if (channelUID.getId().equals(CHANNEL_STEP)) {
131             queryGreenMode(ACTION_STEP);
132         }
133     }
134
135     @Override
136     public void handleCommand(ChannelUID channelUID, Command command) {
137         if (channelUID.getId().equals(CHANNEL_STEP)) {
138             if (command == OnOffType.ON) {
139                 greenMode(ACTION_STEP, 2);
140             } else if (command == OnOffType.OFF) {
141                 greenMode(ACTION_STEP, 1);
142             } else if (command instanceof Number) {
143                 Integer step = new Integer(((Number) command).intValue());
144                 if (step.intValue() >= GREENSTEP_MIN) {
145                     greenMode(ACTION_STEP, step);
146                 }
147             } else if (command instanceof RefreshType) {
148                 queryGreenMode(ACTION_STEP);
149             } else {
150                 logger.debug("Ignoring invalid command {} for id {}", command, integrationId);
151             }
152         } else {
153             logger.debug("Ignoring command to invalid channel {} for id {}", channelUID.getId(), integrationId);
154         }
155     }
156
157     @Override
158     public void handleUpdate(LutronCommandType type, String... parameters) {
159         try {
160             if (type == LutronCommandType.MODE && parameters.length > 1
161                     && ACTION_STEP.toString().equals(parameters[0])) {
162                 Long step = new Long(parameters[1]);
163                 if (getThing().getStatus() == ThingStatus.UNKNOWN) {
164                     updateStatus(ThingStatus.ONLINE);
165                     startPolling();
166                 }
167                 updateState(CHANNEL_STEP, new DecimalType(step.longValue()));
168             } else {
169                 logger.debug("Ignoring unexpected update for id {}", integrationId);
170             }
171         } catch (NumberFormatException e) {
172             logger.debug("Encountered number format exception while handling update for greenmode {}", integrationId);
173         }
174     }
175
176     @Override
177     public void dispose() {
178         stopPolling();
179     }
180 }