]> git.basschouten.com Git - openhab-addons.git/blob
6673fa4c2792b44c140277bb134e9ff1b6e9363c
[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<?>) {
86                 QuantityType<?> value = (QuantityType<?>) command;
87
88                 Unit<Temperature> unit = SIUnits.CELSIUS;
89                 value = value.toUnit(unit);
90                 if (value != null) {
91                     double a = value.doubleValue();
92                     String postdata = "{\"sp_temp\":" + a + "}";
93                     logger.debug("Executing {} command", CHANNELSPTEMP);
94                     updateOvenData(postdata);
95                 }
96             } else {
97                 logger.debug("Error. Command is the wrong type: {}", command.toString());
98             }
99         } else if (channelUID.getId().equals(CHANNELECOMODE)) {
100             String postData = null;
101             if (command.equals(OnOffType.ON)) {
102                 postData = "{\"eco_mode\":true}";
103             } else if (command.equals(OnOffType.OFF)) {
104                 postData = "{\"eco_mode\":false}";
105             }
106             if (postData != null) {
107                 logger.debug("Executing {} command", CHANNELECOMODE);
108                 updateOvenData(postData);
109             }
110         }
111     }
112
113     /**
114      * Calls the service to update the oven data
115      *
116      * @param postdata
117      */
118     private boolean updateOvenData(@Nullable String postdata) {
119         Helper message = new Helper();
120         if (serviceCommunication.updateOvenData(postdata, message, this.getThing().getUID().toString())) {
121             updateStatus(ThingStatus.ONLINE);
122             return true;
123         } else {
124             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
125                     message.getStatusDesription());
126             return false;
127         }
128     }
129
130     @Override
131     public void initialize() {
132         logger.debug("Initializing haassohnpelletstove handler for thing {}", getThing().getUID());
133         config = getConfigAs(HaasSohnpelletstoveConfiguration.class);
134         boolean validConfig = true;
135         String errors = "";
136         String statusDescr = null;
137         if (config.refreshRate < 0 && config.refreshRate > 999) {
138             errors += " Parameter 'refresh Rate' greater then 0 and less then 1000.";
139             statusDescr = "Parameter 'refresh Rate' greater then 0 and less then 1000.";
140             validConfig = false;
141         }
142         if (config.hostIP == null) {
143             errors += " Parameter 'hostIP' must be configured.";
144             statusDescr = "IP Address must be configured!";
145             validConfig = false;
146         }
147         if (config.hostPIN == null) {
148             errors += " Parameter 'hostPin' must be configured.";
149             statusDescr = "PIN must be configured!";
150             validConfig = false;
151         }
152         errors = errors.trim();
153         Helper message = new Helper();
154         message.setStatusDescription(statusDescr);
155         if (validConfig) {
156             serviceCommunication.setConfig(config);
157             if (serviceCommunication.refreshOvenConnection(message, this.getThing().getUID().toString())) {
158                 if (updateOvenData(null)) {
159                     updateStatus(ThingStatus.ONLINE);
160                     updateLinkedChannels();
161                 }
162             } else {
163                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription());
164             }
165         } else {
166             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription());
167         }
168     }
169
170     private void updateLinkedChannels() {
171         verifyLinkedChannel(CHANNELISTEMP);
172         verifyLinkedChannel(CHANNELMODE);
173         verifyLinkedChannel(CHANNELPOWER);
174         verifyLinkedChannel(CHANNELSPTEMP);
175         verifyLinkedChannel(CHANNELECOMODE);
176         verifyLinkedChannel(CHANNELIGNITIONS);
177         verifyLinkedChannel(CHANNELMAINTENANCEIN);
178         verifyLinkedChannel(CHANNELCLEANINGIN);
179         verifyLinkedChannel(CHANNELCONSUMPTION);
180         verifyLinkedChannel(CHANNELONTIME);
181         if (!linkedChannels.isEmpty()) {
182             updateOvenData(null);
183             for (Channel channel : getThing().getChannels()) {
184                 updateChannel(channel.getUID().getId());
185             }
186             startAutomaticRefresh();
187             automaticRefreshing = true;
188         }
189     }
190
191     private void verifyLinkedChannel(String channelID) {
192         if (isLinked(channelID) && !linkedChannels.containsKey(channelID)) {
193             linkedChannels.put(channelID, true);
194         }
195     }
196
197     @Override
198     public void dispose() {
199         stopScheduler();
200     }
201
202     private void stopScheduler() {
203         ScheduledFuture<?> job = refreshJob;
204         if (job != null) {
205             job.cancel(true);
206         }
207         refreshJob = null;
208     }
209
210     /**
211      * Start the job refreshing the oven status
212      */
213     private void startAutomaticRefresh() {
214         ScheduledFuture<?> job = refreshJob;
215         if (job == null || job.isCancelled()) {
216             int period = config.refreshRate;
217             refreshJob = scheduler.scheduleWithFixedDelay(this::run, 0, period, TimeUnit.SECONDS);
218         }
219     }
220
221     private void run() {
222         updateOvenData(null);
223         for (Channel channel : getThing().getChannels()) {
224             updateChannel(channel.getUID().getId());
225         }
226     }
227
228     @Override
229     public void channelLinked(ChannelUID channelUID) {
230         if (!automaticRefreshing) {
231             logger.debug("Start automatic refreshing");
232             startAutomaticRefresh();
233             automaticRefreshing = true;
234         }
235         verifyLinkedChannel(channelUID.getId());
236         updateChannel(channelUID.getId());
237     }
238
239     @Override
240     public void channelUnlinked(ChannelUID channelUID) {
241         linkedChannels.remove(channelUID.getId());
242         if (linkedChannels.isEmpty()) {
243             automaticRefreshing = false;
244             stopScheduler();
245             logger.debug("Stop automatic refreshing");
246         }
247     }
248
249     private void updateChannel(String channelId) {
250         if (isLinked(channelId)) {
251             State state = null;
252             HaasSohnpelletstoveJsonDataDTO data = serviceCommunication.getOvenData();
253             if (data != null) {
254                 switch (channelId) {
255                     case CHANNELISTEMP:
256                         state = new QuantityType<Temperature>(Double.valueOf(data.getisTemp()), SIUnits.CELSIUS);
257                         update(state, channelId);
258                         break;
259                     case CHANNELMODE:
260                         state = new StringType(data.getMode());
261                         update(state, channelId);
262                         break;
263                     case CHANNELPOWER:
264                         update(OnOffType.from(data.getPrg()), channelId);
265                         break;
266                     case CHANNELECOMODE:
267                         update(OnOffType.from(data.getEcoMode()), channelId);
268                         break;
269                     case CHANNELSPTEMP:
270                         state = new QuantityType<Temperature>(Double.valueOf(data.getspTemp()), SIUnits.CELSIUS);
271                         update(state, channelId);
272                         break;
273                     case CHANNELCLEANINGIN:
274                         String cleaning = data.getCleaningIn();
275                         double time = Double.parseDouble(cleaning);
276                         time = time / 60;
277                         DecimalFormat df = new DecimalFormat("0.00");
278                         state = new StringType(df.format(time));
279                         update(state, channelId);
280                         break;
281                     case CHANNELCONSUMPTION:
282                         state = new StringType(data.getConsumption());
283                         update(state, channelId);
284                         break;
285                     case CHANNELIGNITIONS:
286                         state = new StringType(data.getIgnitions());
287                         update(state, channelId);
288                         break;
289                     case CHANNELMAINTENANCEIN:
290                         state = new StringType(data.getMaintenanceIn());
291                         update(state, channelId);
292                         break;
293                     case CHANNELONTIME:
294                         state = new StringType(data.getOnTime());
295                         update(state, channelId);
296                         break;
297                 }
298             }
299         }
300     }
301
302     /**
303      * Updates the State of the given channel
304      *
305      * @param state
306      * @param channelId
307      */
308     private void update(@Nullable State state, String channelId) {
309         logger.debug("Update channel {} with state {}", channelId, (state == null) ? "null" : state.toString());
310
311         if (state != null) {
312             updateState(channelId, state);
313
314         } else {
315             updateState(channelId, UnDefType.NULL);
316         }
317     }
318 }