]> git.basschouten.com Git - openhab-addons.git/blob
10191f7e2ede0f074386b8754238d685377c943d
[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.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.ModeCommand;
23 import org.openhab.binding.lutron.internal.protocol.lip.LutronCommandType;
24 import org.openhab.core.library.types.DecimalType;
25 import org.openhab.core.library.types.OnOffType;
26 import org.openhab.core.thing.Bridge;
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.types.Command;
32 import org.openhab.core.types.RefreshType;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * Handler responsible for communicating with RadioRA 2 Green Mode subsystem
38  *
39  * @author Bob Adair - Initial contribution
40  */
41 @NonNullByDefault
42 public class GreenModeHandler extends LutronHandler {
43     private 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(ModeCommand.ACTION_STEP);
98             // handleUpdate() will set thing status to online when response arrives
99         } else {
100             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
101         }
102     }
103
104     @Override
105     protected void thingOfflineNotify() {
106         stopPolling();
107     }
108
109     private void startPolling() {
110         if (pollInterval > 0 && pollJob == null) {
111             logger.debug("Scheduling green mode polling job for integration ID {}", integrationId);
112             pollJob = scheduler.scheduleWithFixedDelay(this::pollState, pollInterval, pollInterval, TimeUnit.MINUTES);
113         }
114     }
115
116     private void stopPolling() {
117         ScheduledFuture<?> pollJob = this.pollJob;
118         if (pollJob != null) {
119             this.pollJob = null;
120             logger.debug("Canceling green mode polling job for integration ID {}", integrationId);
121             pollJob.cancel(true);
122         }
123     }
124
125     private synchronized void pollState() {
126         logger.trace("Executing green mode polling job for integration ID {}", integrationId);
127         queryGreenMode(ModeCommand.ACTION_STEP);
128     }
129
130     @Override
131     public void channelLinked(ChannelUID channelUID) {
132         if (channelUID.getId().equals(CHANNEL_STEP)) {
133             queryGreenMode(ModeCommand.ACTION_STEP);
134         }
135     }
136
137     @Override
138     public void handleCommand(ChannelUID channelUID, Command command) {
139         if (channelUID.getId().equals(CHANNEL_STEP)) {
140             if (command == OnOffType.ON) {
141                 greenMode(ModeCommand.ACTION_STEP, 2);
142             } else if (command == OnOffType.OFF) {
143                 greenMode(ModeCommand.ACTION_STEP, 1);
144             } else if (command instanceof Number) {
145                 Integer step = ((Number) command).intValue();
146                 if (step.intValue() >= GREENSTEP_MIN) {
147                     greenMode(ModeCommand.ACTION_STEP, step);
148                 }
149             } else if (command instanceof RefreshType) {
150                 queryGreenMode(ModeCommand.ACTION_STEP);
151             } else {
152                 logger.debug("Ignoring invalid command {} for id {}", command, integrationId);
153             }
154         } else {
155             logger.debug("Ignoring command to invalid channel {} for id {}", channelUID.getId(), integrationId);
156         }
157     }
158
159     @Override
160     public void handleUpdate(LutronCommandType type, String... parameters) {
161         try {
162             if (type == LutronCommandType.MODE && parameters.length > 1
163                     && ModeCommand.ACTION_STEP.toString().equals(parameters[0])) {
164                 Long step = Long.valueOf(parameters[1]);
165                 if (getThing().getStatus() == ThingStatus.UNKNOWN) {
166                     updateStatus(ThingStatus.ONLINE);
167                     startPolling();
168                 }
169                 updateState(CHANNEL_STEP, new DecimalType(step.longValue()));
170             } else {
171                 logger.debug("Ignoring unexpected update for id {}", integrationId);
172             }
173         } catch (NumberFormatException e) {
174             logger.debug("Encountered number format exception while handling update for greenmode {}", integrationId);
175         }
176     }
177
178     @Override
179     public void dispose() {
180         stopPolling();
181     }
182 }