2 * Copyright (c) 2010-2024 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<?> quantityCommand) {
86 Unit<Temperature> unit = SIUnits.CELSIUS;
87 QuantityType<?> value = quantityCommand.toUnit(unit);
89 double a = value.doubleValue();
90 String postdata = "{\"sp_temp\":" + a + "}";
91 logger.debug("Executing {} command", CHANNELSPTEMP);
92 updateOvenData(postdata);
95 logger.debug("Error. Command is the wrong type: {}", command.toString());
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}";
104 if (postData != null) {
105 logger.debug("Executing {} command", CHANNELECOMODE);
106 updateOvenData(postData);
112 * Calls the service to update the oven data
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);
122 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
123 message.getStatusDesription());
129 public void initialize() {
130 logger.debug("Initializing haassohnpelletstove handler for thing {}", getThing().getUID());
131 config = getConfigAs(HaasSohnpelletstoveConfiguration.class);
132 boolean validConfig = true;
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.";
140 if (config.hostIP == null) {
141 errors += " Parameter 'hostIP' must be configured.";
142 statusDescr = "IP Address must be configured!";
145 if (config.hostPIN == null) {
146 errors += " Parameter 'hostPin' must be configured.";
147 statusDescr = "PIN must be configured!";
150 errors = errors.trim();
151 Helper message = new Helper();
152 message.setStatusDescription(statusDescr);
154 serviceCommunication.setConfig(config);
155 if (serviceCommunication.refreshOvenConnection(message, this.getThing().getUID().toString())) {
156 if (updateOvenData(null)) {
157 updateStatus(ThingStatus.ONLINE);
158 updateLinkedChannels();
161 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription());
164 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription());
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());
184 startAutomaticRefresh();
185 automaticRefreshing = true;
189 private void verifyLinkedChannel(String channelID) {
190 if (isLinked(channelID) && !linkedChannels.containsKey(channelID)) {
191 linkedChannels.put(channelID, true);
196 public void dispose() {
200 private void stopScheduler() {
201 ScheduledFuture<?> job = refreshJob;
209 * Start the job refreshing the oven status
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);
220 updateOvenData(null);
221 for (Channel channel : getThing().getChannels()) {
222 updateChannel(channel.getUID().getId());
227 public void channelLinked(ChannelUID channelUID) {
228 if (!automaticRefreshing) {
229 logger.debug("Start automatic refreshing");
230 startAutomaticRefresh();
231 automaticRefreshing = true;
233 verifyLinkedChannel(channelUID.getId());
234 updateChannel(channelUID.getId());
238 public void channelUnlinked(ChannelUID channelUID) {
239 linkedChannels.remove(channelUID.getId());
240 if (linkedChannels.isEmpty()) {
241 automaticRefreshing = false;
243 logger.debug("Stop automatic refreshing");
247 private void updateChannel(String channelId) {
248 if (isLinked(channelId)) {
250 HaasSohnpelletstoveJsonDataDTO data = serviceCommunication.getOvenData();
254 state = new QuantityType<Temperature>(Double.valueOf(data.getisTemp()), SIUnits.CELSIUS);
255 update(state, channelId);
258 state = new StringType(data.getMode());
259 update(state, channelId);
262 update(OnOffType.from(data.getPrg()), channelId);
265 update(OnOffType.from(data.getEcoMode()), channelId);
268 state = new QuantityType<Temperature>(Double.valueOf(data.getspTemp()), SIUnits.CELSIUS);
269 update(state, channelId);
271 case CHANNELCLEANINGIN:
272 String cleaning = data.getCleaningIn();
273 double time = Double.parseDouble(cleaning);
275 DecimalFormat df = new DecimalFormat("0.00");
276 state = new StringType(df.format(time));
277 update(state, channelId);
279 case CHANNELCONSUMPTION:
280 state = new StringType(data.getConsumption());
281 update(state, channelId);
283 case CHANNELIGNITIONS:
284 state = new StringType(data.getIgnitions());
285 update(state, channelId);
287 case CHANNELMAINTENANCEIN:
288 state = new StringType(data.getMaintenanceIn());
289 update(state, channelId);
292 state = new StringType(data.getOnTime());
293 update(state, channelId);
301 * Updates the State of the given channel
306 private void update(@Nullable State state, String channelId) {
307 logger.debug("Update channel {} with state {}", channelId, (state == null) ? "null" : state.toString());
310 updateState(channelId, state);
313 updateState(channelId, UnDefType.NULL);