]> git.basschouten.com Git - openhab-addons.git/blob
c9ff2142336e8e2f4db18a2bd09c0a94eadd2c5a
[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.haassohnpelletstove.internal;
14
15 import static org.openhab.binding.haassohnpelletstove.internal.HaasSohnpelletstoveBindingConstants.*;
16
17 import java.text.DecimalFormat;
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
22
23 import javax.measure.Unit;
24 import javax.measure.quantity.Temperature;
25
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
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.SIUnits;
32 import org.openhab.core.thing.Channel;
33 import org.openhab.core.thing.ChannelUID;
34 import org.openhab.core.thing.Thing;
35 import org.openhab.core.thing.ThingStatus;
36 import org.openhab.core.thing.ThingStatusDetail;
37 import org.openhab.core.thing.binding.BaseThingHandler;
38 import org.openhab.core.types.Command;
39 import org.openhab.core.types.State;
40 import org.openhab.core.types.UnDefType;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 /**
45  * The {@link HaasSohnpelletstoveHandler} is responsible for handling commands, which are
46  * sent to one of the channels.
47  *
48  * @author Christian Feininger - Initial contribution
49  */
50 @NonNullByDefault
51 public class HaasSohnpelletstoveHandler extends BaseThingHandler {
52
53     private final Logger logger = LoggerFactory.getLogger(HaasSohnpelletstoveHandler.class);
54
55     private @Nullable ScheduledFuture<?> refreshJob;
56
57     private HaasSohnpelletstoveConfiguration config = new HaasSohnpelletstoveConfiguration();
58     boolean resultOk = false;
59
60     private HaasSohnpelletstoveJSONCommunication serviceCommunication;
61
62     private boolean automaticRefreshing = false;
63
64     private Map<String, Boolean> linkedChannels = new HashMap<String, Boolean>();
65
66     public HaasSohnpelletstoveHandler(Thing thing) {
67         super(thing);
68         serviceCommunication = new HaasSohnpelletstoveJSONCommunication();
69     }
70
71     @Override
72     public void handleCommand(ChannelUID channelUID, Command command) {
73         if (channelUID.getId().equals(CHANNELPOWER)) {
74             String postData = null;
75             if (command.equals(OnOffType.ON)) {
76                 postData = "{\"prg\":true}";
77             } else if (command.equals(OnOffType.OFF)) {
78                 postData = "{\"prg\":false}";
79             }
80             if (postData != null) {
81                 logger.debug("Executing {} command", CHANNELPOWER);
82                 updateOvenData(postData);
83             }
84         } else if (channelUID.getId().equals(CHANNELSPTEMP)) {
85             if (command instanceof QuantityType<?> quantityCommand) {
86                 Unit<Temperature> unit = SIUnits.CELSIUS;
87                 QuantityType<?> value = quantityCommand.toUnit(unit);
88                 if (value != null) {
89                     double a = value.doubleValue();
90                     String postdata = "{\"sp_temp\":" + a + "}";
91                     logger.debug("Executing {} command", CHANNELSPTEMP);
92                     updateOvenData(postdata);
93                 }
94             } else {
95                 logger.debug("Error. Command is the wrong type: {}", command.toString());
96             }
97         } else if (channelUID.getId().equals(CHANNELECOMODE)) {
98             String postData = null;
99             if (command.equals(OnOffType.ON)) {
100                 postData = "{\"eco_mode\":true}";
101             } else if (command.equals(OnOffType.OFF)) {
102                 postData = "{\"eco_mode\":false}";
103             }
104             if (postData != null) {
105                 logger.debug("Executing {} command", CHANNELECOMODE);
106                 updateOvenData(postData);
107             }
108         }
109     }
110
111     /**
112      * Calls the service to update the oven data
113      *
114      * @param postdata
115      */
116     private boolean updateOvenData(@Nullable String postdata) {
117         Helper message = new Helper();
118         if (serviceCommunication.updateOvenData(postdata, message, this.getThing().getUID().toString())) {
119             updateStatus(ThingStatus.ONLINE);
120             return true;
121         } else {
122             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
123                     message.getStatusDesription());
124             return false;
125         }
126     }
127
128     @Override
129     public void initialize() {
130         logger.debug("Initializing haassohnpelletstove handler for thing {}", getThing().getUID());
131         config = getConfigAs(HaasSohnpelletstoveConfiguration.class);
132         boolean validConfig = true;
133         String errors = "";
134         String statusDescr = null;
135         if (config.refreshRate < 0 && config.refreshRate > 999) {
136             errors += " Parameter 'refresh Rate' greater then 0 and less then 1000.";
137             statusDescr = "Parameter 'refresh Rate' greater then 0 and less then 1000.";
138             validConfig = false;
139         }
140         if (config.hostIP == null) {
141             errors += " Parameter 'hostIP' must be configured.";
142             statusDescr = "IP Address must be configured!";
143             validConfig = false;
144         }
145         if (config.hostPIN == null) {
146             errors += " Parameter 'hostPin' must be configured.";
147             statusDescr = "PIN must be configured!";
148             validConfig = false;
149         }
150         errors = errors.trim();
151         Helper message = new Helper();
152         message.setStatusDescription(statusDescr);
153         if (validConfig) {
154             serviceCommunication.setConfig(config);
155             if (serviceCommunication.refreshOvenConnection(message, this.getThing().getUID().toString())) {
156                 if (updateOvenData(null)) {
157                     updateStatus(ThingStatus.ONLINE);
158                     updateLinkedChannels();
159                 }
160             } else {
161                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription());
162             }
163         } else {
164             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription());
165         }
166     }
167
168     private void updateLinkedChannels() {
169         verifyLinkedChannel(CHANNELISTEMP);
170         verifyLinkedChannel(CHANNELMODE);
171         verifyLinkedChannel(CHANNELPOWER);
172         verifyLinkedChannel(CHANNELSPTEMP);
173         verifyLinkedChannel(CHANNELECOMODE);
174         verifyLinkedChannel(CHANNELIGNITIONS);
175         verifyLinkedChannel(CHANNELMAINTENANCEIN);
176         verifyLinkedChannel(CHANNELCLEANINGIN);
177         verifyLinkedChannel(CHANNELCONSUMPTION);
178         verifyLinkedChannel(CHANNELONTIME);
179         if (!linkedChannels.isEmpty()) {
180             updateOvenData(null);
181             for (Channel channel : getThing().getChannels()) {
182                 updateChannel(channel.getUID().getId());
183             }
184             startAutomaticRefresh();
185             automaticRefreshing = true;
186         }
187     }
188
189     private void verifyLinkedChannel(String channelID) {
190         if (isLinked(channelID) && !linkedChannels.containsKey(channelID)) {
191             linkedChannels.put(channelID, true);
192         }
193     }
194
195     @Override
196     public void dispose() {
197         stopScheduler();
198     }
199
200     private void stopScheduler() {
201         ScheduledFuture<?> job = refreshJob;
202         if (job != null) {
203             job.cancel(true);
204         }
205         refreshJob = null;
206     }
207
208     /**
209      * Start the job refreshing the oven status
210      */
211     private void startAutomaticRefresh() {
212         ScheduledFuture<?> job = refreshJob;
213         if (job == null || job.isCancelled()) {
214             int period = config.refreshRate;
215             refreshJob = scheduler.scheduleWithFixedDelay(this::run, 0, period, TimeUnit.SECONDS);
216         }
217     }
218
219     private void run() {
220         updateOvenData(null);
221         for (Channel channel : getThing().getChannels()) {
222             updateChannel(channel.getUID().getId());
223         }
224     }
225
226     @Override
227     public void channelLinked(ChannelUID channelUID) {
228         if (!automaticRefreshing) {
229             logger.debug("Start automatic refreshing");
230             startAutomaticRefresh();
231             automaticRefreshing = true;
232         }
233         verifyLinkedChannel(channelUID.getId());
234         updateChannel(channelUID.getId());
235     }
236
237     @Override
238     public void channelUnlinked(ChannelUID channelUID) {
239         linkedChannels.remove(channelUID.getId());
240         if (linkedChannels.isEmpty()) {
241             automaticRefreshing = false;
242             stopScheduler();
243             logger.debug("Stop automatic refreshing");
244         }
245     }
246
247     private void updateChannel(String channelId) {
248         if (isLinked(channelId)) {
249             State state = null;
250             HaasSohnpelletstoveJsonDataDTO data = serviceCommunication.getOvenData();
251             if (data != null) {
252                 switch (channelId) {
253                     case CHANNELISTEMP:
254                         state = new QuantityType<Temperature>(Double.valueOf(data.getisTemp()), SIUnits.CELSIUS);
255                         update(state, channelId);
256                         break;
257                     case CHANNELMODE:
258                         state = new StringType(data.getMode());
259                         update(state, channelId);
260                         break;
261                     case CHANNELPOWER:
262                         update(OnOffType.from(data.getPrg()), channelId);
263                         break;
264                     case CHANNELECOMODE:
265                         update(OnOffType.from(data.getEcoMode()), channelId);
266                         break;
267                     case CHANNELSPTEMP:
268                         state = new QuantityType<Temperature>(Double.valueOf(data.getspTemp()), SIUnits.CELSIUS);
269                         update(state, channelId);
270                         break;
271                     case CHANNELCLEANINGIN:
272                         String cleaning = data.getCleaningIn();
273                         double time = Double.parseDouble(cleaning);
274                         time = time / 60;
275                         DecimalFormat df = new DecimalFormat("0.00");
276                         state = new StringType(df.format(time));
277                         update(state, channelId);
278                         break;
279                     case CHANNELCONSUMPTION:
280                         state = new StringType(data.getConsumption());
281                         update(state, channelId);
282                         break;
283                     case CHANNELIGNITIONS:
284                         state = new StringType(data.getIgnitions());
285                         update(state, channelId);
286                         break;
287                     case CHANNELMAINTENANCEIN:
288                         state = new StringType(data.getMaintenanceIn());
289                         update(state, channelId);
290                         break;
291                     case CHANNELONTIME:
292                         state = new StringType(data.getOnTime());
293                         update(state, channelId);
294                         break;
295                 }
296             }
297         }
298     }
299
300     /**
301      * Updates the State of the given channel
302      *
303      * @param state
304      * @param channelId
305      */
306     private void update(@Nullable State state, String channelId) {
307         logger.debug("Update channel {} with state {}", channelId, (state == null) ? "null" : state.toString());
308
309         if (state != null) {
310             updateState(channelId, state);
311
312         } else {
313             updateState(channelId, UnDefType.NULL);
314         }
315     }
316 }