]> git.basschouten.com Git - openhab-addons.git/blob
d212ed91f2ed7df3d7e85f0d191bba7e0722aa45
[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.etherrain.internal.handler;
14
15 import java.io.IOException;
16 import java.util.concurrent.ScheduledFuture;
17 import java.util.concurrent.TimeUnit;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.eclipse.jetty.client.HttpClient;
22 import org.openhab.binding.etherrain.internal.EtherRainBindingConstants;
23 import org.openhab.binding.etherrain.internal.EtherRainException;
24 import org.openhab.binding.etherrain.internal.api.EtherRainCommunication;
25 import org.openhab.binding.etherrain.internal.api.EtherRainStatusResponse;
26 import org.openhab.binding.etherrain.internal.config.EtherRainConfiguration;
27 import org.openhab.core.library.types.DecimalType;
28 import org.openhab.core.library.types.OnOffType;
29 import org.openhab.core.library.types.StringType;
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.thing.binding.BaseThingHandler;
35 import org.openhab.core.types.Command;
36 import org.openhab.core.types.RefreshType;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 /**
41  * The {@link EtherRainHandler} is responsible for handling commands, which are
42  * sent to one of the channels.
43  *
44  * @author Joe Inkenbrandt - Initial contribution
45  */
46 @NonNullByDefault
47 public class EtherRainHandler extends BaseThingHandler {
48
49     private final Logger logger = LoggerFactory.getLogger(EtherRainHandler.class);
50
51     private @Nullable EtherRainCommunication device = null;
52     private boolean connected = false;
53     private @NonNullByDefault({}) EtherRainConfiguration config = null;
54
55     private @Nullable ScheduledFuture<?> updateJob = null;
56
57     private final HttpClient httpClient;
58
59     /*
60      * Constructor class. Only call the parent constructor
61      */
62     public EtherRainHandler(Thing thing, HttpClient httpClient) {
63         super(thing);
64         this.httpClient = httpClient;
65         this.updateJob = null;
66     }
67
68     @Override
69     public void handleCommand(ChannelUID channelUID, Command command) {
70         if (command == RefreshType.REFRESH) {
71             scheduler.execute(this::updateBridge);
72         } else if (channelUID.getId().equals(EtherRainBindingConstants.CHANNEL_ID_EXECUTE)) {
73             execute();
74             updateState(EtherRainBindingConstants.CHANNEL_ID_EXECUTE, OnOffType.OFF);
75         } else if (channelUID.getId().equals(EtherRainBindingConstants.CHANNEL_ID_CLEAR)) {
76             clear();
77             updateState(EtherRainBindingConstants.CHANNEL_ID_CLEAR, OnOffType.OFF);
78         }
79     }
80
81     private boolean connectBridge() {
82         logger.debug("Attempting to connect to Etherrain with config = (Host: {}, Port: {}, Refresh: {}).", config.host,
83                 config.port, config.refresh);
84
85         EtherRainCommunication device = new EtherRainCommunication(config.host, config.port, config.password,
86                 httpClient);
87
88         try {
89             device.commandStatus();
90         } catch (EtherRainException | IOException e) {
91             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
92                     "Could not create a connection to the EtherRain");
93             logger.debug("Could not open API connection to the EtherRain device. Exception received: {}",
94                     e.getMessage());
95             this.device = null;
96             updateStatus(ThingStatus.OFFLINE);
97             return false;
98         }
99         this.device = device;
100
101         updateStatus(ThingStatus.ONLINE);
102
103         return true;
104     }
105
106     private void startUpdateJob() {
107         logger.debug("Starting Etherrain Update Job");
108         this.updateJob = scheduler.scheduleWithFixedDelay(this::updateBridge, 0, config.refresh, TimeUnit.SECONDS);
109
110         logger.debug("EtherRain successfully initialized. Starting status poll at: {}", config.refresh);
111     }
112
113     private void stopUpdateJob() {
114         logger.debug("Stopping Etherrain Update Job");
115
116         final ScheduledFuture<?> updateJob = this.updateJob;
117         if (updateJob != null && !updateJob.isDone()) {
118             updateJob.cancel(false);
119         }
120
121         this.updateJob = null;
122     }
123
124     @SuppressWarnings("null")
125     private boolean updateBridge() {
126         if (!connected || device == null) {
127             connected = connectBridge();
128             if (!connected || device == null) {
129                 connected = false;
130                 device = null;
131                 logger.debug("Could not connect to Etherrain device.");
132                 return false;
133             }
134         }
135
136         EtherRainStatusResponse response;
137
138         try {
139             response = device.commandStatus();
140         } catch (EtherRainException | IOException e) {
141             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
142                     "Could not create a connection to the EtherRain");
143             logger.debug("Could not open API connection to the EtherRain device. Exception received: {}",
144                     e.getMessage());
145             device = null;
146             return false;
147         }
148
149         updateState(EtherRainBindingConstants.CHANNEL_ID_OPERATING_STATUS,
150                 new StringType(response.getOperatingStatus().name()));
151
152         updateState(EtherRainBindingConstants.CHANNEL_ID_COMMAND_STATUS,
153                 new StringType(response.getLastCommandStatus().name()));
154
155         switch (response.getLastCommandResult()) {
156             case OK:
157                 updateState(EtherRainBindingConstants.CHANNEL_ID_OPERATING_RESULT, new StringType("OK"));
158                 break;
159             case RN:
160                 updateState(EtherRainBindingConstants.CHANNEL_ID_OPERATING_RESULT, new StringType("RAIN INTERRUPTED"));
161                 break;
162             case SH:
163                 updateState(EtherRainBindingConstants.CHANNEL_ID_OPERATING_RESULT,
164                         new StringType("INTERRUPPTED SHORT"));
165                 break;
166             case NC:
167                 updateState(EtherRainBindingConstants.CHANNEL_ID_OPERATING_RESULT, new StringType("DID NOT COMPLETE"));
168                 break;
169         }
170
171         updateState(EtherRainBindingConstants.CHANNEL_ID_RELAY_INDEX, new DecimalType(response.getLastActiveValue()));
172
173         OnOffType rs = OnOffType.from(response.isRainSensor());
174
175         updateState(EtherRainBindingConstants.CHANNEL_ID_SENSOR_RAIN, rs);
176
177         logger.debug("Completed Etherrain Update");
178
179         return true;
180     }
181
182     private synchronized boolean execute() {
183         EtherRainCommunication device = this.device;
184
185         if (device != null) {
186             device.commandIrrigate(config.programDelay, config.zoneOnTime1, config.zoneOnTime2, config.zoneOnTime3,
187                     config.zoneOnTime4, config.zoneOnTime5, config.zoneOnTime6, config.zoneOnTime7, config.zoneOnTime8);
188             updateBridge();
189         }
190
191         return true;
192     }
193
194     private boolean clear() {
195         EtherRainCommunication device = this.device;
196         if (device != null) {
197             device.commandClear();
198         }
199
200         updateBridge();
201
202         return true;
203     }
204
205     @Override
206     public void initialize() {
207         config = getConfigAs(EtherRainConfiguration.class);
208         startUpdateJob();
209     }
210
211     @Override
212     public void dispose() {
213         stopUpdateJob();
214     }
215 }