]> git.basschouten.com Git - openhab-addons.git/blob
d16bc6472208ee9b9d4b6323fd1af613bf172d14
[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.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 quantityCommand) {
85                 final QuantityType<?> value = quantityCommand.toUnit(Units.MINUTE);
86                 if (value != null) {
87                     wateringTime = value.intValue();
88                 }
89                 return;
90             }
91             if (channelUID.getId().startsWith("zone")) {
92                 if (OnOffType.ON.equals(command)) {
93                     handler.runZone(deviceId, channelUID.getId().replace("zone_", ""), wateringTime);
94                 }
95                 return;
96             }
97             if (channelUID.getId().startsWith("program")) {
98                 if (OnOffType.ON.equals(command)) {
99                     handler.runProgram(deviceId, channelUID.getId().replace("program_", ""));
100                 }
101                 return;
102             }
103             if (channelUID.getId().startsWith("enable_program") && command instanceof OnOffType) {
104                 String id = channelUID.getId().replace("enable_program_", "");
105                 OrbitBhyveProgram prog = programs.get(id);
106                 if (prog != null) {
107                     handler.enableProgram(prog, OnOffType.ON.equals(command));
108                 } else {
109                     logger.debug("Cannot get program id: {}", id);
110                 }
111                 return;
112             }
113             if (CHANNEL_RAIN_DELAY.equals(channelUID.getId()) && command instanceof DecimalType) {
114                 final QuantityType<?> value = ((QuantityType<?>) command).toUnit(Units.HOUR);
115                 if (value != null) {
116                     handler.setRainDelay(deviceId, value.intValue());
117                 }
118
119             }
120         }
121     }
122
123     private String getSprinklerId() {
124         return getThing().getConfiguration().get("id") != null ? getThing().getConfiguration().get("id").toString()
125                 : "";
126     }
127
128     private @Nullable OrbitBhyveBridgeHandler getBridgeHandler() {
129         Bridge bridge = getBridge();
130         if (bridge != null) {
131             return (OrbitBhyveBridgeHandler) bridge.getHandler();
132         }
133         return null;
134     }
135
136     @Override
137     public void initialize() {
138         Bridge bridge = getBridge();
139         if (bridge != null) {
140             logger.debug("Initializing, bridge is {}", bridge.getStatus());
141             if (ThingStatus.ONLINE == bridge.getStatus()) {
142                 doInit();
143             } else {
144                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
145             }
146         }
147     }
148
149     private synchronized void doInit() {
150         OrbitBhyveBridgeHandler handler = getBridgeHandler();
151         if (handler != null) {
152             deviceId = getSprinklerId();
153             if ("".equals(deviceId)) {
154                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Sprinkler id is missing!");
155             } else {
156                 OrbitBhyveDevice device = handler.getDevice(deviceId);
157                 if (device != null) {
158                     setDeviceOnline(device.isConnected());
159                     createChannels(device.getZones());
160                     updateDeviceStatus(device.getStatus());
161                 }
162                 List<OrbitBhyveProgram> programs = handler.getPrograms();
163                 for (OrbitBhyveProgram program : programs) {
164                     if (deviceId.equals(program.getDeviceId())) {
165                         cacheProgram(program);
166                         createProgram(program);
167                     }
168                 }
169
170                 updateState(CHANNEL_WATERING_TIME, new QuantityType<>(wateringTime, Units.MINUTE));
171                 logger.debug("Finished initializing of sprinkler!");
172             }
173         }
174     }
175
176     @Override
177     public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
178         super.bridgeStatusChanged(bridgeStatusInfo);
179         if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
180             doInit();
181         }
182     }
183
184     private synchronized void cacheProgram(OrbitBhyveProgram program) {
185         if (!programs.containsKey(program.getProgram())) {
186             programs.put(program.getProgram(), program);
187         }
188     }
189
190     public void updateDeviceStatus(OrbitBhyveDeviceStatus status) {
191         if (!status.getMode().isEmpty()) {
192             updateState(CHANNEL_MODE, new StringType(status.getMode()));
193             updateState(CHANNEL_CONTROL, OnOffType.from(!"off".equals(status.getMode())));
194         }
195         if (!status.getNextStartTime().isEmpty()) {
196             DateTimeType dt = new DateTimeType(status.getNextStartTime());
197             updateState(CHANNEL_NEXT_START, dt);
198             logger.debug("Next start time: {}", status.getNextStartTime());
199         }
200         updateState(CHANNEL_RAIN_DELAY, new DecimalType(status.getDelay()));
201     }
202
203     private void createProgram(OrbitBhyveProgram program) {
204         String channelName = "program_" + program.getProgram();
205         if (thing.getChannel(channelName) == null) {
206             logger.debug("Creating channel for program: {} with name: {}", program.getProgram(), program.getName());
207             createProgramChannel(channelName, "Switch", "Program " + program.getName());
208         }
209         String enableChannelName = "enable_" + channelName;
210         if (thing.getChannel(enableChannelName) == null) {
211             logger.debug("Creating enable channel for program: {} with name: {}", program.getProgram(),
212                     program.getName());
213             createProgramChannel(enableChannelName, "Switch", "Enable program " + program.getName());
214         }
215         Channel ch = thing.getChannel(enableChannelName);
216         if (ch != null) {
217             updateState(ch.getUID(), OnOffType.from(program.isEnabled()));
218         }
219     }
220
221     private void createProgramChannel(String name, String type, String label) {
222         ChannelTypeUID program = new ChannelTypeUID(BINDING_ID, "program");
223         createChannel(name, type, label, program);
224     }
225
226     private void createChannels(List<OrbitBhyveZone> zones) {
227         for (OrbitBhyveZone zone : zones) {
228             String channelName = "zone_" + zone.getStation();
229             if (thing.getChannel(channelName) == null) {
230                 logger.debug("Creating channel for zone: {} with name: {}", zone.getStation(), zone.getName());
231                 createZoneChannel(channelName, "Switch", "Zone " + zone.getName());
232             }
233         }
234     }
235
236     private void createZoneChannel(String name, String type, String label) {
237         ChannelTypeUID zone = new ChannelTypeUID(BINDING_ID, "zone");
238         createChannel(name, type, label, zone);
239     }
240
241     private void createChannel(String name, String type, String label, ChannelTypeUID typeUID) {
242         ThingBuilder thingBuilder = editThing();
243         Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), type).withLabel(label)
244                 .withType(typeUID).build();
245         thingBuilder.withChannel(channel);
246         updateThing(thingBuilder.build());
247     }
248
249     public void setDeviceOnline(boolean connected) {
250         if (!connected) {
251             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
252                     "Not connected to Orbit BHyve Cloud");
253         } else {
254             updateStatus(ThingStatus.ONLINE);
255         }
256     }
257
258     public void updateProgram(OrbitBhyveProgram program) {
259         String enableChannelName = "enable_program_" + program.getProgram();
260         Channel ch = thing.getChannel(enableChannelName);
261         if (ch != null) {
262             updateState(ch.getUID(), OnOffType.from(program.isEnabled()));
263         }
264     }
265
266     public void updateSmartWatering(String senseMode) {
267         updateState(CHANNEL_SMART_WATERING, OnOffType.from("auto".equals(senseMode)));
268     }
269 }