]> git.basschouten.com Git - openhab-addons.git/blob
546aeb84281f206673ccdda5e9546dc994d6d43c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.orbitbhyve.internal.handler;
14
15 import static org.openhab.binding.orbitbhyve.internal.OrbitBhyveBindingConstants.*;
16
17 import java.util.HashMap;
18 import java.util.List;
19
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;
46
47 /**
48  * The {@link OrbitBhyveSprinklerHandler} is responsible for handling commands, which are
49  * sent to one of the channels.
50  *
51  * @author Ondrej Pecta - Initial contribution
52  */
53 @NonNullByDefault
54 public class OrbitBhyveSprinklerHandler extends BaseThingHandler {
55
56     private final Logger logger = LoggerFactory.getLogger(OrbitBhyveSprinklerHandler.class);
57
58     public OrbitBhyveSprinklerHandler(Thing thing) {
59         super(thing);
60     }
61
62     private int wateringTime = 5;
63     private HashMap<String, OrbitBhyveProgram> programs = new HashMap<>();
64     private String deviceId = "";
65
66     @Override
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);
73                 return;
74             }
75             if (CHANNEL_SMART_WATERING.equals(channelUID.getId()) && command instanceof OnOffType) {
76                 boolean enable = OnOffType.ON.equals(command);
77                 handler.setSmartWatering(deviceId, enable);
78                 return;
79             }
80             if (!channelUID.getId().startsWith("enable_program") && OnOffType.OFF.equals(command)) {
81                 handler.stopWatering(deviceId);
82                 return;
83             }
84             if (CHANNEL_WATERING_TIME.equals(channelUID.getId()) && command instanceof QuantityType) {
85                 final QuantityType<?> value = ((QuantityType<?>) command).toUnit(Units.MINUTE);
86                 if (value != null) {
87                     wateringTime = value.intValue();
88                     updateState(CHANNEL_WATERING_TIME, new DecimalType(wateringTime));
89                 }
90                 return;
91             }
92             if (channelUID.getId().startsWith("zone")) {
93                 if (OnOffType.ON.equals(command)) {
94                     handler.runZone(deviceId, channelUID.getId().replace("zone_", ""), wateringTime);
95                 }
96                 return;
97             }
98             if (channelUID.getId().startsWith("program")) {
99                 if (OnOffType.ON.equals(command)) {
100                     handler.runProgram(deviceId, channelUID.getId().replace("program_", ""));
101                 }
102                 return;
103             }
104             if (channelUID.getId().startsWith("enable_program") && command instanceof OnOffType) {
105                 String id = channelUID.getId().replace("enable_program_", "");
106                 OrbitBhyveProgram prog = programs.get(id);
107                 if (prog != null) {
108                     handler.enableProgram(prog, OnOffType.ON.equals(command));
109                 } else {
110                     logger.debug("Cannot get program id: {}", id);
111                 }
112                 return;
113             }
114             if (CHANNEL_RAIN_DELAY.equals(channelUID.getId()) && command instanceof DecimalType) {
115                 final QuantityType<?> value = ((QuantityType<?>) command).toUnit(Units.HOUR);
116                 if (value != null) {
117                     handler.setRainDelay(deviceId, value.intValue());
118                 }
119
120             }
121         }
122     }
123
124     private String getSprinklerId() {
125         return getThing().getConfiguration().get("id") != null ? getThing().getConfiguration().get("id").toString()
126                 : "";
127     }
128
129     private @Nullable OrbitBhyveBridgeHandler getBridgeHandler() {
130         Bridge bridge = getBridge();
131         if (bridge != null) {
132             return (OrbitBhyveBridgeHandler) bridge.getHandler();
133         }
134         return null;
135     }
136
137     @Override
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()) {
143                 doInit();
144             } else {
145                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
146             }
147         }
148     }
149
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!");
156             } else {
157                 OrbitBhyveDevice device = handler.getDevice(deviceId);
158                 if (device != null) {
159                     setDeviceOnline(device.isConnected());
160                     createChannels(device.getZones());
161                     updateDeviceStatus(device.getStatus());
162                 }
163                 List<OrbitBhyveProgram> programs = handler.getPrograms();
164                 for (OrbitBhyveProgram program : programs) {
165                     if (deviceId.equals(program.getDeviceId())) {
166                         cacheProgram(program);
167                         createProgram(program);
168                     }
169                 }
170
171                 updateState(CHANNEL_WATERING_TIME, new DecimalType(wateringTime));
172                 logger.debug("Finished initializing of sprinkler!");
173             }
174         }
175     }
176
177     @Override
178     public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
179         super.bridgeStatusChanged(bridgeStatusInfo);
180         if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
181             doInit();
182         }
183     }
184
185     private synchronized void cacheProgram(OrbitBhyveProgram program) {
186         if (!programs.containsKey(program.getProgram())) {
187             programs.put(program.getProgram(), program);
188         }
189     }
190
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);
195         }
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());
200         }
201         updateState(CHANNEL_RAIN_DELAY, new DecimalType(status.getDelay()));
202     }
203
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());
209         }
210         String enableChannelName = "enable_" + channelName;
211         if (thing.getChannel(enableChannelName) == null) {
212             logger.debug("Creating enable channel for program: {} with name: {}", program.getProgram(),
213                     program.getName());
214             createProgramChannel(enableChannelName, "Switch", "Enable program " + program.getName());
215         }
216         Channel ch = thing.getChannel(enableChannelName);
217         if (ch != null) {
218             updateState(ch.getUID(), program.isEnabled() ? OnOffType.ON : OnOffType.OFF);
219         }
220     }
221
222     private void createProgramChannel(String name, String type, String label) {
223         ChannelTypeUID program = new ChannelTypeUID(BINDING_ID, "program");
224         createChannel(name, type, label, program);
225     }
226
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());
233             }
234         }
235     }
236
237     private void createZoneChannel(String name, String type, String label) {
238         ChannelTypeUID zone = new ChannelTypeUID(BINDING_ID, "zone");
239         createChannel(name, type, label, zone);
240     }
241
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());
248     }
249
250     public void setDeviceOnline(boolean connected) {
251         if (!connected) {
252             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
253                     "Not connected to Orbit BHyve Cloud");
254         } else {
255             updateStatus(ThingStatus.ONLINE);
256         }
257     }
258
259     public void updateProgram(OrbitBhyveProgram program) {
260         String enableChannelName = "enable_program_" + program.getProgram();
261         Channel ch = thing.getChannel(enableChannelName);
262         if (ch != null) {
263             updateState(ch.getUID(), program.isEnabled() ? OnOffType.ON : OnOffType.OFF);
264         }
265     }
266
267     public void updateSmartWatering(String senseMode) {
268         updateState(CHANNEL_SMART_WATERING, ("auto".equals(senseMode)) ? OnOffType.ON : OnOffType.OFF);
269     }
270 }