From baa9aacf5042be895bb0d7fc439c6956c63fa0a1 Mon Sep 17 00:00:00 2001 From: jimtng <2554958+jimtng@users.noreply.github.com> Date: Wed, 16 Feb 2022 08:50:37 +1000 Subject: [PATCH] [fronius] Fix communication errors by retrying failed http requests (#12255) * [fronius] Fix communication errors by retrying failed http requests Signed-off-by: Jimmy Tanagra --- bundles/org.openhab.binding.fronius/pom.xml | 1 - .../FroniusCommunicationException.java | 40 ++++++ .../internal/FroniusHandlerFactory.java | 5 +- .../fronius/internal/FroniusHttpUtil.java | 79 +++++++++++ .../handler/FroniusBaseThingHandler.java | 134 ++++++++++-------- .../handler/FroniusBridgeHandler.java | 70 ++++++--- .../internal/handler/FroniusMeterHandler.java | 17 ++- .../handler/FroniusOhmpilotHandler.java | 17 ++- .../handler/FroniusSymoInverterHandler.java | 14 +- .../main/resources/OH-INF/thing/bridge.xml | 2 +- 10 files changed, 266 insertions(+), 113 deletions(-) create mode 100644 bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusCommunicationException.java create mode 100644 bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHttpUtil.java diff --git a/bundles/org.openhab.binding.fronius/pom.xml b/bundles/org.openhab.binding.fronius/pom.xml index fb9121d0382..db0a962bc49 100644 --- a/bundles/org.openhab.binding.fronius/pom.xml +++ b/bundles/org.openhab.binding.fronius/pom.xml @@ -13,5 +13,4 @@ org.openhab.binding.fronius openHAB Add-ons :: Bundles :: Fronius Binding - diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusCommunicationException.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusCommunicationException.java new file mode 100644 index 00000000000..93fc10d7858 --- /dev/null +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusCommunicationException.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2022 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.fronius.internal; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * Exception for unexpected response from or communication failure with the Fronius controller. + * + * @author Jimmy Tanagra - Initial contribution + */ +@NonNullByDefault +public class FroniusCommunicationException extends IOException { + private static final long serialVersionUID = 619020705591964155L; + + public FroniusCommunicationException(String message) { + super(message); + } + + public FroniusCommunicationException(Throwable ex) { + super(ex); + } + + public FroniusCommunicationException(String message, @Nullable Throwable cause) { + super(message, cause); + } +} diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHandlerFactory.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHandlerFactory.java index 15fea161047..cf2eda7ab96 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHandlerFactory.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHandlerFactory.java @@ -17,6 +17,8 @@ import static org.openhab.binding.fronius.internal.FroniusBindingConstants.*; import java.util.HashSet; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.fronius.internal.handler.FroniusBridgeHandler; import org.openhab.binding.fronius.internal.handler.FroniusMeterHandler; import org.openhab.binding.fronius.internal.handler.FroniusOhmpilotHandler; @@ -37,6 +39,7 @@ import org.osgi.service.component.annotations.Component; * @author Hannes Spenger - Added ohmpilot */ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.fronius") +@NonNullByDefault public class FroniusHandlerFactory extends BaseThingHandlerFactory { private static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet() { @@ -56,7 +59,7 @@ public class FroniusHandlerFactory extends BaseThingHandlerFactory { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(THING_TYPE_INVERTER)) { diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHttpUtil.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHttpUtil.java new file mode 100644 index 00000000000..63a4bda8ff6 --- /dev/null +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusHttpUtil.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2010-2022 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.fronius.internal; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.io.net.http.HttpUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * A version of HttpUtil implementation that retries on failure + * + * @author Jimmy Tanagra - Initial contribution + * + */ +@NonNullByDefault +public class FroniusHttpUtil { + private static final Logger logger = LoggerFactory.getLogger(FroniusHttpUtil.class); + + /** + * Issue a HTTP GET request and retry on failure + * + * @param url the url to execute + * @param timeout the socket timeout in milliseconds to wait for data + * @return the response body + * @throws FroniusCommunicationException when the request execution failed or interrupted + */ + public synchronized static String executeUrl(String url, int timeout) throws FroniusCommunicationException { + int attemptCount = 1; + try { + while (true) { + Throwable lastException = null; + String result = null; + try { + result = HttpUtil.executeUrl("GET", url, timeout); + } catch (IOException e) { + // HttpUtil::executeUrl wraps InterruptedException into IOException. + // Unwrap and rethrow it so that we don't retry on InterruptedException + if (e.getCause() instanceof InterruptedException) { + throw (InterruptedException) e.getCause(); + } + lastException = e; + } + + if (result != null) { + if (attemptCount > 1) { + logger.debug("Attempt #{} successful {}", attemptCount, url); + } + return result; + } + + if (attemptCount >= 3) { + logger.debug("Failed connecting to {} after {} attempts.", url, attemptCount, lastException); + throw new FroniusCommunicationException("Unable to connect", lastException); + } + + logger.debug("HTTP error on attempt #{} {}", attemptCount, url); + Thread.sleep(500 * attemptCount); + attemptCount++; + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new FroniusCommunicationException("Interrupted", e); + } + } +} diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java index 75267633083..974d45bd1a3 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java @@ -12,13 +12,15 @@ */ package org.openhab.binding.fronius.internal.handler; -import java.io.IOException; import java.math.BigDecimal; +import org.eclipse.jdt.annotation.NonNull; import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration; +import org.openhab.binding.fronius.internal.FroniusCommunicationException; +import org.openhab.binding.fronius.internal.FroniusHttpUtil; import org.openhab.binding.fronius.internal.api.BaseFroniusResponse; +import org.openhab.binding.fronius.internal.api.HeadStatus; import org.openhab.binding.fronius.internal.api.ValueUnit; -import org.openhab.core.io.net.http.HttpUtil; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.StringType; @@ -29,7 +31,6 @@ import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BaseThingHandler; -import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; import org.openhab.core.types.State; @@ -45,6 +46,7 @@ import com.google.gson.JsonSyntaxException; * @author Gerrit Beine - Initial contribution * @author Thomas Rokohl - Refactoring to merge the concepts * @author Thomas Kordelle - Added inverter power, battery state of charge and PV solar yield + * @author Jimmy Tanagra - Implement connection retry */ public abstract class FroniusBaseThingHandler extends BaseThingHandler { @@ -69,29 +71,16 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler { @Override public void initialize() { - if (getFroniusBridgeHandler() == null) { - logger.debug("Initializing {} Service is only supported within a bridge", serviceDescription); - updateStatus(ThingStatus.OFFLINE); - return; - } logger.debug("Initializing {} Service", serviceDescription); - getFroniusBridgeHandler().registerService(this); - } - - private synchronized FroniusBridgeHandler getFroniusBridgeHandler() { - if (this.bridgeHandler == null) { - Bridge bridge = getBridge(); - if (bridge == null) { - return null; - } - ThingHandler handler = bridge.getHandler(); - if (handler instanceof FroniusBridgeHandler) { - this.bridgeHandler = (FroniusBridgeHandler) handler; - } else { - return null; - } + // this is important so FroniusBridgeHandler::childHandlerInitialized gets called + Bridge bridge = getBridge(); + if (bridge == null || bridge.getHandler() == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } else if (bridge.getStatus() == ThingStatus.ONLINE) { + updateStatus(ThingStatus.UNKNOWN); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); } - return this.bridgeHandler; } /** @@ -135,7 +124,7 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler { } else { logger.warn("Update channel {}: Unsupported value type {}", channelId, value.getClass().getSimpleName()); } - logger.debug("Update channel {} with state {} ({})", channelId, (state == null) ? "null" : state.toString(), + logger.trace("Update channel {} with state {} ({})", channelId, (state == null) ? "null" : state.toString(), value.getClass().getSimpleName()); // Update the channel @@ -160,12 +149,30 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler { protected abstract Object getValue(String channelId); /** - * do whatever a thing must do to update the values + * Called by the bridge to fetch data and update channels + * + * @param bridgeConfiguration the connected bridge configuration + */ + public void refresh(FroniusBridgeConfiguration bridgeConfiguration) { + try { + handleRefresh(bridgeConfiguration); + if (getThing().getStatus() != ThingStatus.ONLINE) { + updateStatus(ThingStatus.ONLINE); + } + } catch (FroniusCommunicationException | RuntimeException e) { + logger.debug("Exception caught in refresh() for {}", getThing().getUID().getId(), e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + /** + * This method should be overridden to do whatever a thing must do to update its channels * this function is called from the bridge in a given interval * * @param bridgeConfiguration the connected bridge configuration */ - public abstract void refresh(FroniusBridgeConfiguration bridgeConfiguration); + protected abstract void handleRefresh(FroniusBridgeConfiguration bridgeConfiguration) + throws FroniusCommunicationException; /** * @@ -173,46 +180,47 @@ public abstract class FroniusBaseThingHandler extends BaseThingHandler { * @param url to request * @return the object representation of the json response */ - protected T collectDataFormUrl(Class type, String url) { - T result = null; - boolean resultOk = false; - String errorMsg = null; - + protected @NonNull T collectDataFromUrl(Class type, String url) + throws FroniusCommunicationException { try { - logger.debug("URL = {}", url); - String response = HttpUtil.executeUrl("GET", url, API_TIMEOUT); + int attempts = 1; + while (true) { + logger.trace("Fetching URL = {}", url); + String response = FroniusHttpUtil.executeUrl(url, API_TIMEOUT); + logger.trace("aqiResponse = {}", response); - if (response != null) { - logger.debug("aqiResponse = {}", response); - result = gson.fromJson(response, type); - } - - if (result == null) { - errorMsg = "no data returned"; - } else { - if (result.getHead().getStatus().getCode() == 0) { - resultOk = true; - } else { - errorMsg = result.getHead().getStatus().getReason(); + T result = gson.fromJson(response, type); + if (result == null) { + throw new FroniusCommunicationException("Empty json result"); } - } - if (!resultOk) { - logger.debug("Error in fronius response: {}", errorMsg); - } - } catch (JsonSyntaxException | NumberFormatException e) { - errorMsg = "Invalid JSON data received"; - logger.debug("Error running fronius request: {}", e.getMessage()); - } catch (IOException | IllegalStateException e) { - errorMsg = e.getMessage(); - logger.debug("Error running fronius request: {}", errorMsg); - } - // Update the thing status - if (resultOk) { - updateStatus(ThingStatus.ONLINE); - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, errorMsg); + HeadStatus status = result.getHead().getStatus(); + if (status.getCode() == 0) { + return result; + } + + // Sometimes Fronius would return a HTTP status 200 with a proper JSON data + // with Reason: Transfer timeout. + // + // "Status" : { + // "Code" : 8, + // "Reason" : "Transfer timeout.", + // "UserMessage" : "" + // }, + logger.debug("Error from Fronius attempt #{}: {} - {}", attempts, status.getCode(), status.getReason()); + if (attempts >= 3) { + throw new FroniusCommunicationException(status.getReason()); + } + Thread.sleep(500 * attempts); + attempts++; + } + + } catch (JsonSyntaxException | NumberFormatException e) { + logger.debug("Received Invalid JSON Data", e); + throw new FroniusCommunicationException("Invalid JSON data received", e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new FroniusCommunicationException("Data collection interrupted", e); } - return resultOk ? result : null; } } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBridgeHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBridgeHandler.java index 1256f064c98..a2f023bfe78 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBridgeHandler.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBridgeHandler.java @@ -12,19 +12,23 @@ */ package org.openhab.binding.fronius.internal.handler; -import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration; -import org.openhab.core.io.net.http.HttpUtil; +import org.openhab.binding.fronius.internal.FroniusCommunicationException; +import org.openhab.binding.fronius.internal.FroniusHttpUtil; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BaseBridgeHandler; +import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.types.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,13 +39,16 @@ import org.slf4j.LoggerFactory; * @author Gerrit Beine - Initial contribution * @author Thomas Rokohl - Refactoring to merge the concepts. * Check if host is reachable. + * @author Jimmy Tanagra - Refactor the child services registration + * Refactor host online check */ +@NonNullByDefault public class FroniusBridgeHandler extends BaseBridgeHandler { private final Logger logger = LoggerFactory.getLogger(FroniusBridgeHandler.class); private static final int DEFAULT_REFRESH_PERIOD = 10; private final Set services = new HashSet<>(); - private ScheduledFuture refreshJob; + private @Nullable ScheduledFuture refreshJob; public FroniusBridgeHandler(Bridge bridge) { super(bridge); @@ -51,10 +58,6 @@ public class FroniusBridgeHandler extends BaseBridgeHandler { public void handleCommand(ChannelUID channelUID, Command command) { } - public void registerService(final FroniusBaseThingHandler service) { - this.services.add(service); - } - @Override public void initialize() { final FroniusBridgeConfiguration config = getConfigAs(FroniusBridgeConfiguration.class); @@ -74,7 +77,7 @@ public class FroniusBridgeHandler extends BaseBridgeHandler { } if (validConfig) { - startAutomaticRefresh(config); + startAutomaticRefresh(); } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMsg); } @@ -84,38 +87,59 @@ public class FroniusBridgeHandler extends BaseBridgeHandler { public void dispose() { if (refreshJob != null) { refreshJob.cancel(true); + refreshJob = null; + } + } + + @Override + public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof FroniusBaseThingHandler) { + this.services.add((FroniusBaseThingHandler) childHandler); + restartAutomaticRefresh(); + } else { + logger.debug("Child handler {} not added because it is not an instance of FroniusBaseThingHandler", + childThing.getUID().getId()); + } + } + + @Override + public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { + this.services.remove((FroniusBaseThingHandler) childHandler); + } + + private void restartAutomaticRefresh() { + if (refreshJob != null) { // refreshJob should be null if the config isn't valid + refreshJob.cancel(false); + startAutomaticRefresh(); } - services.clear(); } /** * Start the job refreshing the data */ - private void startAutomaticRefresh(FroniusBridgeConfiguration config) { + private void startAutomaticRefresh() { if (refreshJob == null || refreshJob.isCancelled()) { + final FroniusBridgeConfiguration config = getConfigAs(FroniusBridgeConfiguration.class); Runnable runnable = () -> { - boolean online = false; try { - if (HttpUtil.executeUrl("GET", "http://" + config.hostname, 5000) != null) { - online = true; + checkBridgeOnline(config); + if (getThing().getStatus() != ThingStatus.ONLINE) { + updateStatus(ThingStatus.ONLINE); } - } catch (IOException e) { - logger.debug("Connection Error: {}", e.getMessage()); - } - - if (!online) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, - "hostname or ip is not reachable"); - } else { - updateStatus(ThingStatus.ONLINE); for (FroniusBaseThingHandler service : services) { service.refresh(config); } + } catch (FroniusCommunicationException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage()); } }; int delay = (config.refreshInterval != null) ? config.refreshInterval.intValue() : DEFAULT_REFRESH_PERIOD; - refreshJob = scheduler.scheduleWithFixedDelay(runnable, 0, delay, TimeUnit.SECONDS); + refreshJob = scheduler.scheduleWithFixedDelay(runnable, 1, delay, TimeUnit.SECONDS); } } + + private void checkBridgeOnline(FroniusBridgeConfiguration config) throws FroniusCommunicationException { + FroniusHttpUtil.executeUrl("http://" + config.hostname, 5000); + } } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusMeterHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusMeterHandler.java index 32bafbf7a1c..5d3910275ed 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusMeterHandler.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusMeterHandler.java @@ -17,6 +17,7 @@ import java.util.Map; import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration; import org.openhab.binding.fronius.internal.FroniusBindingConstants; import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration; +import org.openhab.binding.fronius.internal.FroniusCommunicationException; import org.openhab.binding.fronius.internal.api.MeterRealtimeBodyDataDTO; import org.openhab.binding.fronius.internal.api.MeterRealtimeResponseDTO; import org.openhab.core.library.types.QuantityType; @@ -46,7 +47,7 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler { } @Override - public void refresh(FroniusBridgeConfiguration bridgeConfiguration) { + protected void handleRefresh(FroniusBridgeConfiguration bridgeConfiguration) throws FroniusCommunicationException { updateData(bridgeConfiguration, config); updateChannels(); updateProperties(); @@ -134,14 +135,11 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler { /** * Get new data */ - private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) { + private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) + throws FroniusCommunicationException { MeterRealtimeResponseDTO meterRealtimeResponse = getMeterRealtimeData(bridgeConfiguration.hostname, config.deviceId); - if (meterRealtimeResponse == null) { - meterRealtimeBodyData = null; - } else { - meterRealtimeBodyData = meterRealtimeResponse.getBody().getData(); - } + meterRealtimeBodyData = meterRealtimeResponse.getBody().getData(); } /** @@ -151,10 +149,11 @@ public class FroniusMeterHandler extends FroniusBaseThingHandler { * @param deviceId of the device * @return {MeterRealtimeResponse} the object representation of the json response */ - private MeterRealtimeResponseDTO getMeterRealtimeData(String ip, int deviceId) { + private MeterRealtimeResponseDTO getMeterRealtimeData(String ip, int deviceId) + throws FroniusCommunicationException { String location = FroniusBindingConstants.METER_REALTIME_DATA_URL.replace("%IP%", (ip != null ? ip.trim() : "")); location = location.replace("%DEVICEID%", Integer.toString(deviceId)); - return collectDataFormUrl(MeterRealtimeResponseDTO.class, location); + return collectDataFromUrl(MeterRealtimeResponseDTO.class, location); } } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusOhmpilotHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusOhmpilotHandler.java index a0ec420405e..a61917a967a 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusOhmpilotHandler.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusOhmpilotHandler.java @@ -17,6 +17,7 @@ import java.util.Map; import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration; import org.openhab.binding.fronius.internal.FroniusBindingConstants; import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration; +import org.openhab.binding.fronius.internal.FroniusCommunicationException; import org.openhab.binding.fronius.internal.api.OhmpilotRealtimeBodyDataDTO; import org.openhab.binding.fronius.internal.api.OhmpilotRealtimeResponseDTO; import org.openhab.core.library.types.DecimalType; @@ -46,7 +47,7 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler { } @Override - public void refresh(FroniusBridgeConfiguration bridgeConfiguration) { + public void handleRefresh(FroniusBridgeConfiguration bridgeConfiguration) throws FroniusCommunicationException { updateData(bridgeConfiguration, config); updateChannels(); updateProperties(); @@ -111,14 +112,11 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler { /** * Get new data */ - private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) { + private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) + throws FroniusCommunicationException { OhmpilotRealtimeResponseDTO ohmpilotRealtimeResponse = getOhmpilotRealtimeData(bridgeConfiguration.hostname, config.deviceId); - if (ohmpilotRealtimeResponse == null) { - ohmpilotRealtimeBodyData = null; - } else { - ohmpilotRealtimeBodyData = ohmpilotRealtimeResponse.getBody().getData(); - } + ohmpilotRealtimeBodyData = ohmpilotRealtimeResponse.getBody().getData(); } /** @@ -128,10 +126,11 @@ public class FroniusOhmpilotHandler extends FroniusBaseThingHandler { * @param deviceId of the device * @return {OhmpilotRealtimeResponse} the object representation of the json response */ - private OhmpilotRealtimeResponseDTO getOhmpilotRealtimeData(String ip, int deviceId) { + private OhmpilotRealtimeResponseDTO getOhmpilotRealtimeData(String ip, int deviceId) + throws FroniusCommunicationException { String location = FroniusBindingConstants.OHMPILOT_REALTIME_DATA_URL.replace("%IP%", (ip != null ? ip.trim() : "")); location = location.replace("%DEVICEID%", Integer.toString(deviceId)); - return collectDataFormUrl(OhmpilotRealtimeResponseDTO.class, location); + return collectDataFromUrl(OhmpilotRealtimeResponseDTO.class, location); } } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java index c36965235e5..d5ea05953fe 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java @@ -17,6 +17,7 @@ import java.util.Map; import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration; import org.openhab.binding.fronius.internal.FroniusBindingConstants; import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration; +import org.openhab.binding.fronius.internal.FroniusCommunicationException; import org.openhab.binding.fronius.internal.api.InverterRealtimeResponse; import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeInverter; import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeResponse; @@ -57,7 +58,7 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler { } @Override - public void refresh(FroniusBridgeConfiguration bridgeConfiguration) { + protected void handleRefresh(FroniusBridgeConfiguration bridgeConfiguration) throws FroniusCommunicationException { updateData(bridgeConfiguration, config); updateChannels(); } @@ -177,7 +178,8 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler { /** * Get new data */ - private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) { + private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) + throws FroniusCommunicationException { inverterRealtimeResponse = getRealtimeData(bridgeConfiguration.hostname, config.deviceId); powerFlowResponse = getPowerFlowRealtime(bridgeConfiguration.hostname); } @@ -188,10 +190,10 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler { * @param ip address of the device * @return {PowerFlowRealtimeResponse} the object representation of the json response */ - private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) { + private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) throws FroniusCommunicationException { String location = FroniusBindingConstants.POWERFLOW_REALTIME_DATA.replace("%IP%", (ip != null ? ip.trim() : "")); - return collectDataFormUrl(PowerFlowRealtimeResponse.class, location); + return collectDataFromUrl(PowerFlowRealtimeResponse.class, location); } /** @@ -201,10 +203,10 @@ public class FroniusSymoInverterHandler extends FroniusBaseThingHandler { * @param deviceId of the device * @return {InverterRealtimeResponse} the object representation of the json response */ - private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) { + private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) throws FroniusCommunicationException { String location = FroniusBindingConstants.INVERTER_REALTIME_DATA_URL.replace("%IP%", (ip != null ? ip.trim() : "")); location = location.replace("%DEVICEID%", Integer.toString(deviceId)); - return collectDataFormUrl(InverterRealtimeResponse.class, location); + return collectDataFromUrl(InverterRealtimeResponse.class, location); } } diff --git a/bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/thing/bridge.xml b/bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/thing/bridge.xml index 756ebb0691c..462889377f5 100644 --- a/bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.fronius/src/main/resources/OH-INF/thing/bridge.xml @@ -13,7 +13,7 @@ The hostname or IP address of the Fronius gateway/device - + Specifies the refresh interval in seconds. 10