2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.haassohnpelletstove.internal;
15 import static org.openhab.binding.haassohnpelletstove.internal.HaasSohnpelletstoveBindingConstants.*;
17 import java.text.DecimalFormat;
18 import java.util.HashMap;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
23 import javax.measure.Unit;
24 import javax.measure.quantity.Temperature;
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;
45 * The {@link HaasSohnpelletstoveHandler} is responsible for handling commands, which are
46 * sent to one of the channels.
48 * @author Christian Feininger - Initial contribution
51 public class HaasSohnpelletstoveHandler extends BaseThingHandler {
53 private final Logger logger = LoggerFactory.getLogger(HaasSohnpelletstoveHandler.class);
55 private @Nullable ScheduledFuture<?> refreshJob;
57 private HaasSohnpelletstoveConfiguration config = new HaasSohnpelletstoveConfiguration();
58 boolean resultOk = false;
60 private HaasSohnpelletstoveJSONCommunication serviceCommunication;
62 private boolean automaticRefreshing = false;
64 private Map<String, Boolean> linkedChannels = new HashMap<String, Boolean>();
66 public HaasSohnpelletstoveHandler(Thing thing) {
68 serviceCommunication = new HaasSohnpelletstoveJSONCommunication();
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}";
80 if (postData != null) {
81 logger.debug("Executing {} command", CHANNELPOWER);
82 updateOvenData(postData);
84 } else if (channelUID.getId().equals(CHANNELSPTEMP)) {
85 if (command instanceof QuantityType<?>) {
86 QuantityType<?> value = (QuantityType<?>) command;
88 Unit<Temperature> unit = SIUnits.CELSIUS;
89 value = value.toUnit(unit);
91 double a = value.doubleValue();
92 String postdata = "{\"sp_temp\":" + a + "}";
93 logger.debug("Executing {} command", CHANNELSPTEMP);
94 updateOvenData(postdata);
97 logger.debug("Error. Command is the wrong type: {}", command.toString());
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}";
106 if (postData != null) {
107 logger.debug("Executing {} command", CHANNELECOMODE);
108 updateOvenData(postData);
114 * Calls the service to update the oven data
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);
124 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
125 message.getStatusDesription());
131 public void initialize() {
132 logger.debug("Initializing haassohnpelletstove handler for thing {}", getThing().getUID());
133 config = getConfigAs(HaasSohnpelletstoveConfiguration.class);
134 boolean validConfig = true;
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.";
142 if (config.hostIP == null) {
143 errors += " Parameter 'hostIP' must be configured.";
144 statusDescr = "IP Address must be configured!";
147 if (config.hostPIN == null) {
148 errors += " Parameter 'hostPin' must be configured.";
149 statusDescr = "PIN must be configured!";
152 errors = errors.trim();
153 Helper message = new Helper();
154 message.setStatusDescription(statusDescr);
156 serviceCommunication.setConfig(config);
157 if (serviceCommunication.refreshOvenConnection(message, this.getThing().getUID().toString())) {
158 if (updateOvenData(null)) {
159 updateStatus(ThingStatus.ONLINE);
160 updateLinkedChannels();
163 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription());
166 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription());
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());
186 startAutomaticRefresh();
187 automaticRefreshing = true;
191 private void verifyLinkedChannel(String channelID) {
192 if (isLinked(channelID) && !linkedChannels.containsKey(channelID)) {
193 linkedChannels.put(channelID, true);
198 public void dispose() {
202 private void stopScheduler() {
203 ScheduledFuture<?> job = refreshJob;
211 * Start the job refreshing the oven status
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);
222 updateOvenData(null);
223 for (Channel channel : getThing().getChannels()) {
224 updateChannel(channel.getUID().getId());
229 public void channelLinked(ChannelUID channelUID) {
230 if (!automaticRefreshing) {
231 logger.debug("Start automatic refreshing");
232 startAutomaticRefresh();
233 automaticRefreshing = true;
235 verifyLinkedChannel(channelUID.getId());
236 updateChannel(channelUID.getId());
240 public void channelUnlinked(ChannelUID channelUID) {
241 linkedChannels.remove(channelUID.getId());
242 if (linkedChannels.isEmpty()) {
243 automaticRefreshing = false;
245 logger.debug("Stop automatic refreshing");
249 private void updateChannel(String channelId) {
250 if (isLinked(channelId)) {
252 HaasSohnpelletstoveJsonDataDTO data = serviceCommunication.getOvenData();
256 state = new QuantityType<Temperature>(Double.valueOf(data.getisTemp()), SIUnits.CELSIUS);
257 update(state, channelId);
260 state = new StringType(data.getMode());
261 update(state, channelId);
264 update(OnOffType.from(data.getPrg()), channelId);
267 update(OnOffType.from(data.getEcoMode()), channelId);
270 state = new QuantityType<Temperature>(Double.valueOf(data.getspTemp()), SIUnits.CELSIUS);
271 update(state, channelId);
273 case CHANNELCLEANINGIN:
274 String cleaning = data.getCleaningIn();
275 double time = Double.parseDouble(cleaning);
277 DecimalFormat df = new DecimalFormat("0.00");
278 state = new StringType(df.format(time));
279 update(state, channelId);
281 case CHANNELCONSUMPTION:
282 state = new StringType(data.getConsumption());
283 update(state, channelId);
285 case CHANNELIGNITIONS:
286 state = new StringType(data.getIgnitions());
287 update(state, channelId);
289 case CHANNELMAINTENANCEIN:
290 state = new StringType(data.getMaintenanceIn());
291 update(state, channelId);
294 state = new StringType(data.getOnTime());
295 update(state, channelId);
303 * Updates the State of the given channel
308 private void update(@Nullable State state, String channelId) {
309 logger.debug("Update channel {} with state {}", channelId, (state == null) ? "null" : state.toString());
312 updateState(channelId, state);
315 updateState(channelId, UnDefType.NULL);