2 * Copyright (c) 2010-2021 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.orbitbhyve.internal.handler;
15 import static org.openhab.binding.orbitbhyve.internal.OrbitBhyveBindingConstants.*;
17 import java.util.HashMap;
18 import java.util.List;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.openhab.binding.orbitbhyve.internal.model.OrbitBhyveDevice;
23 import org.openhab.binding.orbitbhyve.internal.model.OrbitBhyveDeviceStatus;
24 import org.openhab.binding.orbitbhyve.internal.model.OrbitBhyveProgram;
25 import org.openhab.binding.orbitbhyve.internal.model.OrbitBhyveZone;
26 import org.openhab.core.library.types.DateTimeType;
27 import org.openhab.core.library.types.DecimalType;
28 import org.openhab.core.library.types.OnOffType;
29 import org.openhab.core.library.types.QuantityType;
30 import org.openhab.core.library.types.StringType;
31 import org.openhab.core.library.unit.Units;
32 import org.openhab.core.thing.Bridge;
33 import org.openhab.core.thing.Channel;
34 import org.openhab.core.thing.ChannelUID;
35 import org.openhab.core.thing.Thing;
36 import org.openhab.core.thing.ThingStatus;
37 import org.openhab.core.thing.ThingStatusDetail;
38 import org.openhab.core.thing.ThingStatusInfo;
39 import org.openhab.core.thing.binding.BaseThingHandler;
40 import org.openhab.core.thing.binding.builder.ChannelBuilder;
41 import org.openhab.core.thing.binding.builder.ThingBuilder;
42 import org.openhab.core.thing.type.ChannelTypeUID;
43 import org.openhab.core.types.Command;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
48 * The {@link OrbitBhyveSprinklerHandler} is responsible for handling commands, which are
49 * sent to one of the channels.
51 * @author Ondrej Pecta - Initial contribution
54 public class OrbitBhyveSprinklerHandler extends BaseThingHandler {
56 private final Logger logger = LoggerFactory.getLogger(OrbitBhyveSprinklerHandler.class);
58 public OrbitBhyveSprinklerHandler(Thing thing) {
62 private int wateringTime = 5;
63 private HashMap<String, OrbitBhyveProgram> programs = new HashMap<>();
64 private String deviceId = "";
67 public void handleCommand(ChannelUID channelUID, Command command) {
68 OrbitBhyveBridgeHandler handler = getBridgeHandler();
69 if (handler != null) {
70 if (CHANNEL_CONTROL.equals(channelUID.getId()) && command instanceof OnOffType) {
71 String mode = OnOffType.ON.equals(command) ? "auto" : "off";
72 handler.changeRunMode(deviceId, mode);
75 if (CHANNEL_SMART_WATERING.equals(channelUID.getId()) && command instanceof OnOffType) {
76 boolean enable = OnOffType.ON.equals(command);
77 handler.setSmartWatering(deviceId, enable);
80 if (!channelUID.getId().startsWith("enable_program") && OnOffType.OFF.equals(command)) {
81 handler.stopWatering(deviceId);
84 if (CHANNEL_WATERING_TIME.equals(channelUID.getId()) && command instanceof QuantityType) {
85 final QuantityType<?> value = ((QuantityType<?>) command).toUnit(Units.MINUTE);
87 wateringTime = value.intValue();
88 updateState(CHANNEL_WATERING_TIME, new DecimalType(wateringTime));
92 if (channelUID.getId().startsWith("zone")) {
93 if (OnOffType.ON.equals(command)) {
94 handler.runZone(deviceId, channelUID.getId().replace("zone_", ""), wateringTime);
98 if (channelUID.getId().startsWith("program")) {
99 if (OnOffType.ON.equals(command)) {
100 handler.runProgram(deviceId, channelUID.getId().replace("program_", ""));
104 if (channelUID.getId().startsWith("enable_program") && command instanceof OnOffType) {
105 String id = channelUID.getId().replace("enable_program_", "");
106 OrbitBhyveProgram prog = programs.get(id);
108 handler.enableProgram(prog, OnOffType.ON.equals(command));
110 logger.debug("Cannot get program id: {}", id);
114 if (CHANNEL_RAIN_DELAY.equals(channelUID.getId()) && command instanceof DecimalType) {
115 final QuantityType<?> value = ((QuantityType<?>) command).toUnit(Units.HOUR);
117 handler.setRainDelay(deviceId, value.intValue());
124 private String getSprinklerId() {
125 return getThing().getConfiguration().get("id") != null ? getThing().getConfiguration().get("id").toString()
129 private @Nullable OrbitBhyveBridgeHandler getBridgeHandler() {
130 Bridge bridge = getBridge();
131 if (bridge != null) {
132 return (OrbitBhyveBridgeHandler) bridge.getHandler();
138 public void initialize() {
139 Bridge bridge = getBridge();
140 if (bridge != null) {
141 logger.debug("Initializing, bridge is {}", bridge.getStatus());
142 if (ThingStatus.ONLINE == bridge.getStatus()) {
145 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
150 private synchronized void doInit() {
151 OrbitBhyveBridgeHandler handler = getBridgeHandler();
152 if (handler != null) {
153 deviceId = getSprinklerId();
154 if ("".equals(deviceId)) {
155 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Sprinkler id is missing!");
157 OrbitBhyveDevice device = handler.getDevice(deviceId);
158 if (device != null) {
159 setDeviceOnline(device.isConnected());
160 createChannels(device.getZones());
161 updateDeviceStatus(device.getStatus());
163 List<OrbitBhyveProgram> programs = handler.getPrograms();
164 for (OrbitBhyveProgram program : programs) {
165 if (deviceId.equals(program.getDeviceId())) {
166 cacheProgram(program);
167 createProgram(program);
171 updateState(CHANNEL_WATERING_TIME, new DecimalType(wateringTime));
172 logger.debug("Finished initializing of sprinkler!");
178 public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
179 super.bridgeStatusChanged(bridgeStatusInfo);
180 if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
185 private synchronized void cacheProgram(OrbitBhyveProgram program) {
186 if (!programs.containsKey(program.getProgram())) {
187 programs.put(program.getProgram(), program);
191 public void updateDeviceStatus(OrbitBhyveDeviceStatus status) {
192 if (!status.getMode().isEmpty()) {
193 updateState(CHANNEL_MODE, new StringType(status.getMode()));
194 updateState(CHANNEL_CONTROL, "off".equals(status.getMode()) ? OnOffType.OFF : OnOffType.ON);
196 if (!status.getNextStartTime().isEmpty()) {
197 DateTimeType dt = new DateTimeType(status.getNextStartTime());
198 updateState(CHANNEL_NEXT_START, dt);
199 logger.debug("Next start time: {}", status.getNextStartTime());
201 updateState(CHANNEL_RAIN_DELAY, new DecimalType(status.getDelay()));
204 private void createProgram(OrbitBhyveProgram program) {
205 String channelName = "program_" + program.getProgram();
206 if (thing.getChannel(channelName) == null) {
207 logger.debug("Creating channel for program: {} with name: {}", program.getProgram(), program.getName());
208 createProgramChannel(channelName, "Switch", "Program " + program.getName());
210 String enableChannelName = "enable_" + channelName;
211 if (thing.getChannel(enableChannelName) == null) {
212 logger.debug("Creating enable channel for program: {} with name: {}", program.getProgram(),
214 createProgramChannel(enableChannelName, "Switch", "Enable program " + program.getName());
216 Channel ch = thing.getChannel(enableChannelName);
218 updateState(ch.getUID(), program.isEnabled() ? OnOffType.ON : OnOffType.OFF);
222 private void createProgramChannel(String name, String type, String label) {
223 ChannelTypeUID program = new ChannelTypeUID(BINDING_ID, "program");
224 createChannel(name, type, label, program);
227 private void createChannels(List<OrbitBhyveZone> zones) {
228 for (OrbitBhyveZone zone : zones) {
229 String channelName = "zone_" + zone.getStation();
230 if (thing.getChannel(channelName) == null) {
231 logger.debug("Creating channel for zone: {} with name: {}", zone.getStation(), zone.getName());
232 createZoneChannel(channelName, "Switch", "Zone " + zone.getName());
237 private void createZoneChannel(String name, String type, String label) {
238 ChannelTypeUID zone = new ChannelTypeUID(BINDING_ID, "zone");
239 createChannel(name, type, label, zone);
242 private void createChannel(String name, String type, String label, ChannelTypeUID typeUID) {
243 ThingBuilder thingBuilder = editThing();
244 Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), type).withLabel(label)
245 .withType(typeUID).build();
246 thingBuilder.withChannel(channel);
247 updateThing(thingBuilder.build());
250 public void setDeviceOnline(boolean connected) {
252 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
253 "Not connected to Orbit BHyve Cloud");
255 updateStatus(ThingStatus.ONLINE);
259 public void updateProgram(OrbitBhyveProgram program) {
260 String enableChannelName = "enable_program_" + program.getProgram();
261 Channel ch = thing.getChannel(enableChannelName);
263 updateState(ch.getUID(), program.isEnabled() ? OnOffType.ON : OnOffType.OFF);
267 public void updateSmartWatering(String senseMode) {
268 updateState(CHANNEL_SMART_WATERING, ("auto".equals(senseMode)) ? OnOffType.ON : OnOffType.OFF);