]> git.basschouten.com Git - openhab-addons.git/blob
39b41d1052a47a5f74f78291eabcd57f0652ada9
[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.opensprinkler.internal.handler;
14
15 import static org.openhab.binding.opensprinkler.internal.OpenSprinklerBindingConstants.*;
16 import static org.openhab.core.library.unit.MetricPrefix.MILLI;
17 import static org.openhab.core.library.unit.Units.PERCENT;
18
19 import java.math.BigDecimal;
20 import java.util.ArrayList;
21
22 import javax.measure.quantity.Dimensionless;
23 import javax.measure.quantity.ElectricCurrent;
24
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.openhab.binding.opensprinkler.internal.OpenSprinklerStateDescriptionProvider;
27 import org.openhab.binding.opensprinkler.internal.api.OpenSprinklerApi;
28 import org.openhab.binding.opensprinkler.internal.api.exception.CommunicationApiException;
29 import org.openhab.binding.opensprinkler.internal.api.exception.UnauthorizedApiException;
30 import org.openhab.core.library.types.DecimalType;
31 import org.openhab.core.library.types.OnOffType;
32 import org.openhab.core.library.types.QuantityType;
33 import org.openhab.core.library.types.StringType;
34 import org.openhab.core.library.unit.Units;
35 import org.openhab.core.thing.Channel;
36 import org.openhab.core.thing.ChannelUID;
37 import org.openhab.core.thing.Thing;
38 import org.openhab.core.thing.ThingStatus;
39 import org.openhab.core.thing.ThingStatusDetail;
40 import org.openhab.core.thing.binding.builder.ThingBuilder;
41 import org.openhab.core.types.Command;
42 import org.openhab.core.types.RefreshType;
43
44 /**
45  * @author Chris Graham - Initial contribution
46  * @author Florian Schmidt - Refactoring
47  */
48 @NonNullByDefault
49 public class OpenSprinklerDeviceHandler extends OpenSprinklerBaseHandler {
50     public final OpenSprinklerStateDescriptionProvider stateDescriptionProvider;
51
52     public OpenSprinklerDeviceHandler(Thing thing, OpenSprinklerStateDescriptionProvider stateDescriptionProvider) {
53         super(thing);
54         this.stateDescriptionProvider = stateDescriptionProvider;
55     }
56
57     @Override
58     protected void updateChannel(ChannelUID channel) {
59         OpenSprinklerApi localAPI = getApi();
60         if (localAPI == null) {
61             return;
62         }
63         switch (channel.getIdWithoutGroup()) {
64             case SENSOR_RAIN:
65                 if (localAPI.isRainDetected()) {
66                     updateState(channel, OnOffType.ON);
67                 } else {
68                     updateState(channel, OnOffType.OFF);
69                 }
70                 break;
71             case CHANNEL_RAIN_DELAY:
72                 updateState(channel, localAPI.getRainDelay());
73                 break;
74             case SENSOR_2:
75                 if (localAPI.getSensor2State() == 1) {
76                     updateState(channel, OnOffType.ON);
77                 } else {
78                     updateState(channel, OnOffType.OFF);
79                 }
80                 break;
81             case SENSOR_WATERLEVEL:
82                 updateState(channel, QuantityType.valueOf(localAPI.waterLevel(), PERCENT));
83                 break;
84             case SENSOR_CURRENT_DRAW:
85                 updateState(channel, new QuantityType<ElectricCurrent>(localAPI.currentDraw(), MILLI(Units.AMPERE)));
86                 break;
87             case SENSOR_SIGNAL_STRENGTH:
88                 int rssiValue = localAPI.signalStrength();
89                 if (rssiValue < -80) {
90                     updateState(channel, DecimalType.ZERO);
91                 } else if (rssiValue < -70) {
92                     updateState(channel, new DecimalType(1));
93                 } else if (rssiValue < -60) {
94                     updateState(channel, new DecimalType(2));
95                 } else if (rssiValue < -40) {
96                     updateState(channel, new DecimalType(3));
97                 } else if (rssiValue >= -40) {
98                     updateState(channel, new DecimalType(4));
99                 }
100                 break;
101             case SENSOR_FLOW_COUNT:
102                 updateState(channel, new QuantityType<Dimensionless>(localAPI.flowSensorCount(), Units.ONE));
103                 break;
104             case CHANNEL_PROGRAMS:
105                 break;
106             case CHANNEL_ENABLE_PROGRAMS:
107                 if (localAPI.getIsEnabled()) {
108                     updateState(channel, OnOffType.ON);
109                 } else {
110                     updateState(channel, OnOffType.OFF);
111                 }
112                 break;
113             case CHANNEL_STATIONS:
114                 break;
115             case NEXT_DURATION:
116                 break;
117             case CHANNEL_RESET_STATIONS:
118                 break;
119             default:
120                 logger.debug("Can not update the unknown channel {}", channel);
121         }
122     }
123
124     @Override
125     public void initialize() {
126         super.initialize();
127         OpenSprinklerApi localAPI = getApi();
128         // Remove channels due to missing sensors or old firmware
129         if (localAPI != null) {
130             ArrayList<Channel> removeChannels = new ArrayList<>();
131             Channel channel = thing.getChannel(SENSOR_CURRENT_DRAW);
132             if (localAPI.currentDraw() == -1 && channel != null) {
133                 logger.debug("No current sensor detected, removing channel.");
134                 removeChannels.add(channel);
135             }
136             channel = thing.getChannel(SENSOR_SIGNAL_STRENGTH);
137             if (localAPI.signalStrength() == 1 && channel != null) {
138                 removeChannels.add(channel);
139             }
140             channel = thing.getChannel(SENSOR_FLOW_COUNT);
141             if (localAPI.flowSensorCount() == -1 && channel != null) {
142                 removeChannels.add(channel);
143             }
144             channel = thing.getChannel(SENSOR_2);
145             if (localAPI.getSensor2State() == -1 && channel != null) {
146                 removeChannels.add(channel);
147             }
148             if (!removeChannels.isEmpty()) {
149                 ThingBuilder thingBuilder = editThing();
150                 thingBuilder.withoutChannels(removeChannels);
151                 updateThing(thingBuilder.build());
152             }
153             updateProgramsChanOptions(localAPI);
154             updateStationsChanOptions(localAPI);
155             nextDurationTime = new BigDecimal(1800);
156             updateState(NEXT_DURATION, new QuantityType<>(nextDurationTime, Units.SECOND));
157         }
158     }
159
160     /**
161      * Fetch the stored Program list and update the StateOptions on the channel so they match.
162      *
163      * @param api
164      */
165     private void updateProgramsChanOptions(OpenSprinklerApi api) {
166         stateDescriptionProvider.setStateOptions(new ChannelUID(this.getThing().getUID(), CHANNEL_PROGRAMS),
167                 api.getPrograms());
168     }
169
170     private void updateStationsChanOptions(OpenSprinklerApi api) {
171         stateDescriptionProvider.setStateOptions(new ChannelUID(this.getThing().getUID(), CHANNEL_STATIONS),
172                 api.getStations());
173     }
174
175     protected void handleRainDelayCommand(ChannelUID channelUID, Command command, OpenSprinklerApi api)
176             throws UnauthorizedApiException, CommunicationApiException {
177         if (!(command instanceof QuantityType<?>)) {
178             logger.warn("Ignoring implausible non-QuantityType command for rainDelay.");
179             return;
180         }
181         QuantityType<?> quantity = (QuantityType<?>) command;
182         quantity = quantity.toUnit(Units.HOUR);
183         if (quantity != null) {
184             api.setRainDelay(quantity.intValue());
185         }
186     }
187
188     @Override
189     public void handleCommand(ChannelUID channelUID, Command command) {
190         OpenSprinklerApi api = getApi();
191         if (api == null) {
192             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "OpenSprinkler bridge returned no API.");
193             return;
194         }
195         OpenSprinklerHttpBridgeHandler localBridge = bridgeHandler;
196         if (localBridge == null) {
197             return;
198         }
199         try {
200             if (command instanceof RefreshType) {
201                 switch (channelUID.getIdWithoutGroup()) {
202                     case CHANNEL_PROGRAMS:
203                         api.getProgramData();
204                         updateProgramsChanOptions(api);
205                         break;
206                     case CHANNEL_STATIONS:
207                         api.getStationNames();
208                         updateStationsChanOptions(api);
209                         break;
210                 }
211             } else {
212                 switch (channelUID.getIdWithoutGroup()) {
213                     case CHANNEL_PROGRAMS:
214                         api.runProgram(command);
215                         break;
216                     case CHANNEL_ENABLE_PROGRAMS:
217                         api.enablePrograms(command);
218                         break;
219                     case NEXT_DURATION:
220                         handleNextDurationCommand(channelUID, command);
221                         break;
222                     case CHANNEL_RESET_STATIONS:
223                         if (command == OnOffType.ON) {
224                             api.resetStations();
225                         }
226                         break;
227                     case CHANNEL_STATIONS:
228                         if (command instanceof StringType) {
229                             BigDecimal temp = new BigDecimal(command.toString());
230                             api.openStation(temp.intValue(), nextDurationValue());
231                         }
232                         break;
233                     case CHANNEL_RAIN_DELAY:
234                         handleRainDelayCommand(channelUID, command, api);
235                         break;
236                 }
237                 localBridge.delayedRefresh();// update sensors and controls after command is sent
238             }
239         } catch (Exception e) {
240             localBridge.communicationError(e);
241         }
242     }
243 }