2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.opensprinkler.internal.handler;
15 import static org.openhab.binding.opensprinkler.internal.OpenSprinklerBindingConstants.*;
17 import java.math.BigDecimal;
19 import javax.measure.quantity.Time;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.opensprinkler.internal.api.OpenSprinklerApi;
24 import org.openhab.binding.opensprinkler.internal.api.exception.CommunicationApiException;
25 import org.openhab.binding.opensprinkler.internal.api.exception.GeneralApiException;
26 import org.openhab.binding.opensprinkler.internal.config.OpenSprinklerStationConfig;
27 import org.openhab.core.library.types.OnOffType;
28 import org.openhab.core.library.types.QuantityType;
29 import org.openhab.core.library.unit.Units;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.thing.ThingStatus;
33 import org.openhab.core.thing.ThingStatusDetail;
34 import org.openhab.core.types.Command;
35 import org.openhab.core.types.RefreshType;
38 * @author Chris Graham - Initial contribution
39 * @author Florian Schmidt - Refactoring
42 public class OpenSprinklerStationHandler extends OpenSprinklerBaseHandler {
43 private OpenSprinklerStationConfig config = new OpenSprinklerStationConfig();
45 public OpenSprinklerStationHandler(Thing thing) {
50 public void initialize() {
52 config = getConfig().as(OpenSprinklerStationConfig.class);
53 OpenSprinklerApi api = getApi();
54 if (api != null && config.stationIndex >= api.getNumberOfStations()) {
55 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
56 "Station Index is higher than the number of stations that the OpenSprinkler is reporting. Make sure your Station Index is correct.");
61 public void handleCommand(ChannelUID channelUID, Command command) {
62 OpenSprinklerApi api = getApi();
64 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "OpenSprinkler bridge has no initialized API.");
68 if (command != RefreshType.REFRESH) {
69 switch (channelUID.getIdWithoutGroup()) {
71 handleNextDurationCommand(channelUID, command);
74 if (!(command instanceof OnOffType)) {
75 logger.warn("Received invalid command type for OpenSprinkler station ({}).", command);
78 if (command == OnOffType.ON) {
79 api.openStation(config.stationIndex, nextDurationValue());
81 api.closeStation(config.stationIndex);
85 if (command == OnOffType.OFF) {
86 api.closeStation(config.stationIndex);
89 case CHANNEL_IGNORE_RAIN:
90 api.ignoreRain(config.stationIndex, command == OnOffType.ON);
93 OpenSprinklerHttpBridgeHandler localBridge = bridgeHandler;
94 if (localBridge == null) {
97 // update all controls after a command is sent in case a long poll time is set.
98 localBridge.delayedRefresh();
100 } catch (GeneralApiException | CommunicationApiException e) {
101 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
102 "Could not control the station channel " + (config.stationIndex + 1)
103 + " for the OpenSprinkler. Error: " + e.getMessage());
108 * Handles determining a channel's current state from the OpenSprinkler device.
110 * @param stationId Int of the station to control. Starts at 0.
111 * @return State representation for the channel.
114 private OnOffType getStationState(int stationId) {
115 boolean stationOn = false;
116 OpenSprinklerApi api = getApi();
118 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED,
119 "OpenSprinkler bridge has no initialized API.");
124 stationOn = api.isStationOpen(stationId);
125 } catch (GeneralApiException | CommunicationApiException exp) {
126 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
127 "Could not get the station channel " + stationId
128 + " current state from the OpenSprinkler thing. Error: " + exp.getMessage());
134 return OnOffType.OFF;
139 * Handles determining a channel's current state from the OpenSprinkler device.
141 * @param stationId Int of the station to control. Starts at 0.
142 * @return State representation for the channel.
144 private @Nullable QuantityType<Time> getRemainingWaterTime(int stationId) {
145 long remainingWaterTime = 0;
146 OpenSprinklerApi api = getApi();
148 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED,
149 "OpenSprinkler bridge has no initialized API.");
154 remainingWaterTime = api.retrieveProgram(stationId).remainingWaterTime;
155 } catch (CommunicationApiException exp) {
156 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
157 "Could not get current state of station channel " + stationId
158 + " for the OpenSprinkler device. Exception received: " + exp);
161 return new QuantityType<>(remainingWaterTime, Units.SECOND);
165 protected void updateChannel(ChannelUID channel) {
166 OnOffType currentDeviceState = getStationState(config.stationIndex);
167 QuantityType<Time> remainingWaterTime = getRemainingWaterTime(config.stationIndex);
168 OpenSprinklerApi api = getApi();
169 switch (channel.getIdWithoutGroup()) {
171 if (currentDeviceState != null) {
172 updateState(channel, currentDeviceState);
175 case REMAINING_WATER_TIME:
176 if (remainingWaterTime != null) {
177 updateState(channel, remainingWaterTime);
181 BigDecimal duration = nextDurationValue();
182 updateState(channel, new QuantityType<>(duration, Units.SECOND));
185 if (remainingWaterTime != null && currentDeviceState != null && currentDeviceState == OnOffType.OFF
186 && remainingWaterTime.intValue() != 0) {
187 updateState(channel, OnOffType.ON);
189 updateState(channel, OnOffType.OFF);
192 case CHANNEL_IGNORE_RAIN:
193 if (api != null && api.isIgnoringRain(config.stationIndex)) {
194 updateState(channel, OnOffType.ON);
196 updateState(channel, OnOffType.OFF);
200 logger.debug("Not updating unknown channel {}", channel);