diff --git a/bundles/org.openhab.binding.haassohnpelletstove/README.md b/bundles/org.openhab.binding.haassohnpelletstove/README.md index c682122fec5..c87068b17c2 100644 --- a/bundles/org.openhab.binding.haassohnpelletstove/README.md +++ b/bundles/org.openhab.binding.haassohnpelletstove/README.md @@ -12,7 +12,7 @@ WIFI module. More information about the WIFI module can be found here: 999) { - errors += " Parameter 'refresh Rate' greater then 0 and less then 1000."; - statusDescr = "Parameter 'refresh Rate' greater then 0 and less then 1000."; - validConfig = false; + if (config.refreshRate < 1 || config.refreshRate > 1000) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Parameter 'refresh Rate' must be in the range 1-1000!"); + return; } - if (config.hostIP == null) { - errors += " Parameter 'hostIP' must be configured."; - statusDescr = "IP Address must be configured!"; - validConfig = false; + if (config.hostIP.isBlank()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "IP Address must be configured!"); + return; } - if (config.hostPIN == null) { - errors += " Parameter 'hostPin' must be configured."; - statusDescr = "PIN must be configured!"; - validConfig = false; + + if (config.hostPIN.isBlank()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Parameter 'hostPin' must be configured!"); + return; } - errors = errors.trim(); - Helper message = new Helper(); - message.setStatusDescription(statusDescr); - if (validConfig) { - serviceCommunication.setConfig(config); - if (serviceCommunication.refreshOvenConnection(message, this.getThing().getUID().toString())) { - if (updateOvenData(null)) { - updateStatus(ThingStatus.ONLINE); - updateLinkedChannels(); + + serviceCommunication.setConfig(config); + updateStatus(ThingStatus.UNKNOWN); + scheduler.submit(() -> { + if (updateOvenData(null)) { + for (Channel channel : getThing().getChannels()) { + if (isLinked(channel.getUID().getId())) { + channelLinked(channel.getUID()); + } } - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription()); } - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message.getStatusDesription()); - } + }); } - private void updateLinkedChannels() { - verifyLinkedChannel(CHANNELISTEMP); - verifyLinkedChannel(CHANNELMODE); - verifyLinkedChannel(CHANNELPOWER); - verifyLinkedChannel(CHANNELSPTEMP); - verifyLinkedChannel(CHANNELECOMODE); - verifyLinkedChannel(CHANNELIGNITIONS); - verifyLinkedChannel(CHANNELMAINTENANCEIN); - verifyLinkedChannel(CHANNELCLEANINGIN); - verifyLinkedChannel(CHANNELCONSUMPTION); - verifyLinkedChannel(CHANNELONTIME); - if (!linkedChannels.isEmpty()) { - updateOvenData(null); - for (Channel channel : getThing().getChannels()) { - updateChannel(channel.getUID().getId()); - } - startAutomaticRefresh(); - automaticRefreshing = true; + /** + * Calls the service to update the oven data + * + * @return true if the update succeeded, false otherwise + */ + private boolean updateOvenData(@Nullable String postdata) { + String error = ""; + if (postdata != null) { + error = serviceCommunication.updateOvenData(postdata); + } else { + error = serviceCommunication.refreshOvenConnection(); } + if (error.isEmpty()) { + if (ThingStatus.OFFLINE.equals(getThing().getStatus())) { + updateStatus(ThingStatus.UNKNOWN); + } + if (!ThingStatus.ONLINE.equals(getThing().getStatus())) { + updateStatus(ThingStatus.ONLINE); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, error); + return false; + } + return error.isEmpty(); } private void verifyLinkedChannel(String channelID) { @@ -195,14 +176,24 @@ public class HaasSohnpelletstoveHandler extends BaseThingHandler { @Override public void dispose() { stopScheduler(); + linkedChannels.clear(); + automaticRefreshing = false; } private void stopScheduler() { ScheduledFuture job = refreshJob; - if (job != null) { - job.cancel(true); + if (job == null || job.isCancelled()) { + refreshJob = scheduler.scheduleWithFixedDelay(this::refreshChannels, 0, config.refreshRate, + TimeUnit.SECONDS); + } + } + + private void refreshChannels() { + if (updateOvenData(null)) { + for (Channel channel : getThing().getChannels()) { + updateChannel(channel.getUID().getId()); + } } - refreshJob = null; } /** @@ -217,9 +208,10 @@ public class HaasSohnpelletstoveHandler extends BaseThingHandler { } private void run() { - updateOvenData(null); - for (Channel channel : getThing().getChannels()) { - updateChannel(channel.getUID().getId()); + if (updateOvenData(null)) { + for (Channel channel : getThing().getChannels()) { + updateChannel(channel.getUID().getId()); + } } } diff --git a/bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/HaasSohnpelletstoveJSONCommunication.java b/bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/HaasSohnpelletstoveJSONCommunication.java index 7173a4a3f59..7b320120104 100644 --- a/bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/HaasSohnpelletstoveJSONCommunication.java +++ b/bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/HaasSohnpelletstoveJSONCommunication.java @@ -26,6 +26,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; /** * This class handles the JSON communication with the Wifi Modul of the Stove @@ -52,105 +53,65 @@ public class HaasSohnpelletstoveJSONCommunication { /** * Refreshes the oven Connection with the internal oven token. * - * @param message Message object to pass errors to the calling method. - * @param thingUID Thing UID for logging purposes - * @return true if no error occurred, false otherwise. + * @return an empty string if no error occurred, the error message otherwise. */ - public boolean refreshOvenConnection(Helper message, String thingUID) { - if (config.hostIP == null || config.hostPIN == null) { - message.setStatusDescription("Error in configuration. Please recreate Thing."); - return false; - } - HaasSohnpelletstoveJsonDataDTO result = null; - boolean resultOk = false; - String error = "", errorDetail = "", statusDescr = ""; + public String refreshOvenConnection() { + String result = ""; + HaasSohnpelletstoveJsonDataDTO responseObject = null; String urlStr = "http://" + config.hostIP + "/status.cgi"; String response = null; try { response = HttpUtil.executeUrl("GET", urlStr, 10000); logger.debug("OvenData = {}", response); - result = gson.fromJson(response, HaasSohnpelletstoveJsonDataDTO.class); - resultOk = true; - } catch (IOException e) { + responseObject = gson.fromJson(response, HaasSohnpelletstoveJsonDataDTO.class); + ovenData = responseObject; + xhspin = getValidXHSPIN(ovenData); + } catch (IOException | JsonSyntaxException e) { logger.debug("Error processiong Get request {}", urlStr); - statusDescr = "Timeout error with" + config.hostIP - + ". Cannot find service on give IP. Please verify the IP-Address!"; - errorDetail = e.getMessage(); - resultOk = false; + result = "Timeout error with " + config.hostIP + + ". Cannot find service on given IP. Please verify the IP-Address!"; + logger.debug("Error in establishing connection: {}", e.getMessage()); } catch (Exception e) { logger.debug("Unknwon Error: {}", e.getMessage()); - errorDetail = e.getMessage(); - resultOk = false; - } - if (resultOk) { - ovenData = result; - xhspin = getValidXHSPIN(ovenData); - } else { - logger.debug("Setting thing '{}' to OFFLINE: Error '{}': {}", thingUID, error, errorDetail); ovenData = new HaasSohnpelletstoveJsonDataDTO(); } - message.setStatusDescription(statusDescr); - return resultOk; + return result; } /** * Gets the status of the oven * - * @return true if success or false in case of error + * @return an empty string if no error occurred, the error message otherwise. */ - public boolean updateOvenData(@Nullable String postData, Helper helper, String thingUID) { - String statusDescr = ""; - boolean resultOk = false; - String error = "", errorDetail = ""; - if (config.hostIP == null || config.hostPIN == null) { - return false; - } + public String updateOvenData(@Nullable String postData) { + String error = ""; String urlStr = "http://" + config.hostIP + "/status.cgi"; - // Run the HTTP POST request and get the JSON response from Oven String response = null; - Properties httpHeader = new Properties(); - if (postData != null) { - try { - InputStream targetStream = new ByteArrayInputStream(postData.getBytes(StandardCharsets.UTF_8)); - refreshOvenConnection(helper, thingUID); - httpHeader = createHeader(postData); - response = HttpUtil.executeUrl("POST", urlStr, httpHeader, targetStream, "application/json", 10000); - resultOk = true; - logger.debug("Execute POST request with content to {} with header: {}", urlStr, httpHeader.toString()); - } catch (IOException e) { - logger.debug("Error processiong POST request {}", urlStr); - statusDescr = "Cannot execute command on Stove. Please verify connection and Thing Status"; - resultOk = false; + try { + InputStream targetStream = null; + if (postData != null) { + targetStream = new ByteArrayInputStream(postData.getBytes(StandardCharsets.UTF_8)); } - } else { - try { - refreshOvenConnection(helper, thingUID); - httpHeader = createHeader(null); - response = HttpUtil.executeUrl("POST", urlStr, httpHeader, null, "", 10000); - resultOk = true; - logger.debug("Execute POST request to {} with header: {}", urlStr, httpHeader.toString()); - } catch (IOException e) { - logger.debug("Error processiong POST request {}", e.getMessage()); - String message = e.getMessage(); - if (message != null && message.contains("Authentication challenge without WWW-Authenticate ")) { - statusDescr = "Cannot connect to stove. Given PIN: " + config.hostPIN + " is incorrect!"; - } - resultOk = false; - } - } - if (resultOk) { - logger.debug("OvenData = {}", response); + refreshOvenConnection(); + httpHeader = createHeader(postData != null ? postData : null); + response = HttpUtil.executeUrl("POST", urlStr, httpHeader, targetStream != null ? targetStream : null, + "application/json", 10000); + logger.debug("Execute POST request with content to {} with header: {}", urlStr, httpHeader.toString()); ovenData = gson.fromJson(response, HaasSohnpelletstoveJsonDataDTO.class); - } else { - logger.debug("Setting thing '{}' to OFFLINE: Error '{}': {}", thingUID, error, errorDetail); - ovenData = new HaasSohnpelletstoveJsonDataDTO(); + logger.debug("OvenData = {}", response); + } catch (IOException e) { + logger.debug("Error processiong POST request {}", urlStr); + error = "Cannot execute command on Stove. Please verify connection or PIN"; + + } catch (JsonSyntaxException e) { + logger.debug("Error in establishing connection: {}", e.getMessage()); + error = "Cannot find service on given IP " + config.hostIP + ". Please verify the IP address!"; } - helper.setStatusDescription(statusDescr); - return resultOk; + return error; } /** diff --git a/bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/Helper.java b/bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/Helper.java deleted file mode 100644 index 128859c4b4d..00000000000 --- a/bundles/org.openhab.binding.haassohnpelletstove/src/main/java/org/openhab/binding/haassohnpelletstove/internal/Helper.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2010-2025 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.haassohnpelletstove.internal; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; - -/** - * The {@link Helper} is a Helper class to overcome Call by value for a Status Description. - * - * - * @author Christian Feininger - Initial contribution - */ -@NonNullByDefault -public class Helper { - - private String statusDescription = ""; - - /*** - * Gets the Status Description - * - * @return - */ - public String getStatusDesription() { - return statusDescription; - } - - /*** - * Sets the Status Description - * - * @param status - */ - public void setStatusDescription(@Nullable String status) { - if (status != null) { - statusDescription = statusDescription + "\n" + status; - } - } -} diff --git a/bundles/org.openhab.binding.haassohnpelletstove/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.haassohnpelletstove/src/main/resources/OH-INF/thing/thing-types.xml index dc0d1a74e98..be637bd6f90 100644 --- a/bundles/org.openhab.binding.haassohnpelletstove/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.haassohnpelletstove/src/main/resources/OH-INF/thing/thing-types.xml @@ -36,7 +36,7 @@ Please add the PIN of your oven here. You can find it in the Menu directly in your oven. - + How often the Pellet Stove should schedule a refresh after a channel is linked to an item. Temperature data will be refreshed according this set time in seconds. Valid input is 0 - 999.