From a435ed2cd0924d7ab268ea545c4dec88a44c9e33 Mon Sep 17 00:00:00 2001 From: Alexander Friese Date: Fri, 18 Aug 2023 13:33:19 +0200 Subject: [PATCH] [easee] Migrate charger state API endpoint, add channels (#14614) * reworked the way to retrieve Charger state as API endpoint is now deprecated. * fixed result processing: removed default handling by bridge handler which caused everything to go offline if a single charger had faulty config. * additional channels / removed obsolete firmware channel Signed-off-by: Alexander Friese --- bundles/org.openhab.binding.easee/README.md | 27 ++- .../easee/internal/EaseeBindingConstants.java | 9 +- .../internal/command/AbstractCommand.java | 50 ++-- .../command/AbstractWriteCommand.java | 5 +- .../easee/internal/command/EaseeCommand.java | 7 - .../easee/internal/command/account/Login.java | 5 +- .../command/account/RefreshToken.java | 6 +- .../command/charger/ChangeConfiguration.java | 6 +- .../command/charger/ChargerState.java | 54 ----- .../command/charger/GetConfiguration.java | 5 +- .../charger/LatestChargingSession.java | 5 +- .../internal/command/charger/SendCommand.java | 10 +- .../charger/SendCommandPauseResume.java | 6 +- .../command/charger/SendCommandStartStop.java | 6 +- .../command/circuit/CircuitSettings.java | 5 +- .../circuit/DynamicCircuitCurrent.java | 5 +- .../command/circuit/SetCircuitSettings.java | 6 +- .../circuit/SetDynamicCircuitCurrents.java | 6 +- .../circuit/SetMaxCircuitCurrents.java | 6 +- .../circuit/SetOfflineMaxCircuitCurrents.java | 6 +- .../internal/command/site/SiteState.java | 116 ++++++++++ .../internal/connector/WebInterface.java | 40 +--- .../internal/handler/EaseeChargerHandler.java | 64 ++++-- .../handler/EaseeMasterChargerHandler.java | 12 +- .../internal/handler/EaseeSiteHandler.java | 81 ++++++- .../model/GenericResponseTransformer.java | 16 +- .../OH-INF/thing/charger-channel-groups.xml | 84 ++++++- .../thing/easee-readonly-channel-types.xml | 7 + .../main/resources/OH-INF/thing/things.xml | 6 + .../resources/OH-INF/update/instructions.xml | 215 ++++++++++++++++++ 30 files changed, 675 insertions(+), 201 deletions(-) delete mode 100644 bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/ChargerState.java create mode 100644 bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/site/SiteState.java create mode 100644 bundles/org.openhab.binding.easee/src/main/resources/OH-INF/update/instructions.xml diff --git a/bundles/org.openhab.binding.easee/README.md b/bundles/org.openhab.binding.easee/README.md index 452dd1c25..296fe7eea 100644 --- a/bundles/org.openhab.binding.easee/README.md +++ b/bundles/org.openhab.binding.easee/README.md @@ -63,23 +63,42 @@ The settings that start with "dynamic" can be changed frequently, the others are | state#chargerOpMode | Number | no | 0=Offline, 1=Disconnected, 2=AwaitingStart, 3=Charging, 4=Completed, 5=Error, 6=ReadyToCharge, 7=AwaitingAuthentication, 8=Deauthenticating | | | state#totalPower | Number:Power | no | current session total power (all phases) | | | state#sessionEnergy | Number:Energy | no | current session | | +| state#energyPerHour | Number:Energy | no | energy per hour | | +| state#wiFiRSSI | Number:Power | no | | | +| state#cellRSSI | Number:Power | no | | | | state#dynamicCircuitCurrentP1 | Number:ElectricCurrent | no | | | | state#dynamicCircuitCurrentP2 | Number:ElectricCurrent | no | | | | state#dynamicCircuitCurrentP3 | Number:ElectricCurrent | no | | | | state#latestPulse | DateTime | no | | | | state#chargerFirmware | Number | no | | | -| state#latestFirmware | Number | no | | | | state#voltage | Number:ElectricPotential | no | | | +| state#inCurrentT2 | Number:ElectricCurrent | no | | | +| state#inCurrentT3 | Number:ElectricCurrent | no | | | +| state#inCurrentT4 | Number:ElectricCurrent | no | | | +| state#inCurrentT5 | Number:ElectricCurrent | no | | | | state#outputCurrent | Number:ElectricCurrent | no | | | +| state#inVoltageT1T2 | Number:ElectricPotential | no | | | +| state#inVoltageT1T3 | Number:ElectricPotential | no | | | +| state#inVoltageT1T4 | Number:ElectricPotential | no | | | +| state#inVoltageT1T5 | Number:ElectricPotential | no | | | +| state#inVoltageT2T3 | Number:ElectricPotential | no | | | +| state#inVoltageT2T4 | Number:ElectricPotential | no | | | +| state#inVoltageT2T5 | Number:ElectricPotential | no | | | +| state#inVoltageT3T4 | Number:ElectricPotential | no | | | +| state#inVoltageT3T5 | Number:ElectricPotential | no | | | +| state#inVoltageT4T5 | Number:ElectricPotential | no | | | +| state#ledMode | Number | no | | | +| state#cableRating | Number:ElectricCurrent | no | | | | state#isOnline | Switch | no | | | | state#dynamicChargerCurrent | Number:ElectricCurrent | yes | | 0, 6-32 | | state#reasonForNoCurrent | Number | no | 0=OK, 2=DynamicCircuitCurrentLimitTooLow, 27=DynamicCircuitCurrentCharging, 52=DynamicChargerCurrentLimitTooLow, 55=NotAuthorized, 79=CarLimit, 81=CarLimitedCharging | | | state#lifetimeEnergy | Number:Energy | no | | | | state#errorCode | Number | no | | | | state#fatalErrorCode | Number | no | | | -| config#lockCablePermanently | Switch | yes | | ON/OFF | -| config#authorizationRequired | Switch | yes | | ON/OFF | -| config#limitToSinglePhaseCharging | Switch | yes | | ON/OFF | +| state#connectedToCloud | Switch | no | | | +| config#lockCablePermanently | Switch | yes | | true/false | +| config#authorizationRequired | Switch | yes | | true/false | +| config#limitToSinglePhaseCharging | Switch | yes | | true/false | | config#phaseMode | Number | yes | 1=1phase, 2=auto, 3=3phase | 1-3 | | config#maxChargerCurrent | Number:ElectricCurrent | no | write access not yet implemented | | | commands#genericCommand | String | yes | Generic Endpoint to send commands | reboot, update_firmware, poll_all, smart_charging, start_charging, stop_charging, pause_charging, resume_charging, toggle_charging, override_schedule | diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/EaseeBindingConstants.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/EaseeBindingConstants.java index cb02ab7f8..2c97616dd 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/EaseeBindingConstants.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/EaseeBindingConstants.java @@ -55,7 +55,7 @@ public class EaseeBindingConstants { public static final String CHANNEL_TYPE_VOLT = "Number:ElectricPotential"; public static final String CHANNEL_TYPE_AMPERE = "Number:ElectricCurrent"; public static final String CHANNEL_TYPE_KWH = "Number:Energy"; - public static final String CHANNEL_TYPE_KW = "Number:Power"; + public static final String CHANNEL_TYPE_POWER = "Number:Power"; public static final String CHANNEL_TYPE_DATE = "DateTime"; public static final String CHANNEL_TYPE_STRING = "String"; public static final String CHANNEL_TYPE_NUMBER = "Number"; @@ -63,6 +63,7 @@ public class EaseeBindingConstants { public static final String CHANNEL_TYPEPREFIX_RW = "rw"; public static final String CHANNEL_TYPENAME_INTEGER = "type-integer"; + public static final String CHANNEL_TYPENAME_RSSI = "type-rssi"; // Channels with specific handling public static final String CHANNEL_CHARGER_OP_MODE = "chargerOpMode"; @@ -88,6 +89,7 @@ public class EaseeBindingConstants { public static final String JSON_KEY_GENERIC_NAME = "name"; public static final String JSON_KEY_CIRCUIT_NAME = "panelName"; public static final String JSON_KEY_CIRCUIT_ID = "circuitId"; + public static final String JSON_KEY_CHARGER_ID = "chargerID"; public static final String JSON_KEY_CIRCUITS = "circuits"; public static final String JSON_KEY_CHARGERS = "chargers"; public static final String JSON_KEY_BACK_PLATE = "backPlate"; @@ -99,6 +101,9 @@ public class EaseeBindingConstants { public static final String JSON_KEY_AUTH_ACCESS_TOKEN = "accessToken"; public static final String JSON_KEY_AUTH_REFRESH_TOKEN = "refreshToken"; public static final String JSON_KEY_AUTH_EXPIRES_IN = "expiresIn"; + public static final String JSON_KEY_CIRCUIT_STATES = "circuitStates"; + public static final String JSON_KEY_CHARGER_STATES = "chargerStates"; + public static final String JSON_KEY_CHARGER_STATE = "chargerState"; // Write Commands public static final String COMMAND_CHANGE_CONFIGURATION = "ChangeConfiguration"; @@ -130,7 +135,7 @@ public class EaseeBindingConstants { public static final String REFRESH_TOKEN_URL = API_BASE_URL + "/accounts/refresh_token"; public static final String GET_SITE_URL = API_BASE_URL + "/sites/{siteId}"; public static final String CHARGER_URL = API_BASE_URL + "/chargers/{id}"; - public static final String STATE_URL = API_BASE_URL + "/chargers/{id}/state"; + public static final String SITE_STATE_URL = API_BASE_URL + "/sites/{siteId}/state"; public static final String GET_CONFIGURATION_URL = API_BASE_URL + "/chargers/{id}/config"; public static final String CHANGE_CONFIGURATION_URL = API_BASE_URL + "/chargers/{id}/settings"; public static final String COMMANDS_URL = API_BASE_URL + "/chargers/{id}/commands/{command}"; diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/AbstractCommand.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/AbstractCommand.java index d1bc66861..42cfb43d4 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/AbstractCommand.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/AbstractCommand.java @@ -18,8 +18,6 @@ import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -87,7 +85,7 @@ public abstract class AbstractCommand extends BufferingResponseListener implemen /** * generic transformer which just transfers all values in a plain map. */ - private final GenericResponseTransformer transformer; + protected final GenericResponseTransformer transformer; /** * retry counter. @@ -107,29 +105,20 @@ public abstract class AbstractCommand extends BufferingResponseListener implemen /** * allows further processing of the json result data, if set. */ - private List resultProcessors; - - /** - * the constructor - */ - public AbstractCommand(EaseeThingHandler handler, RetryOnFailure retryOnFailure, - ProcessFailureResponse processFailureResponse) { - this.gson = new GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create(); - this.communicationStatus = new CommunicationStatus(); - this.resultProcessors = new ArrayList<>(); - this.transformer = new GenericResponseTransformer(handler); - this.handler = handler; - this.processFailureResponse = processFailureResponse; - this.retryOnFailure = retryOnFailure; - } + private final JsonResultProcessor resultProcessor; /** * the constructor */ public AbstractCommand(EaseeThingHandler handler, RetryOnFailure retryOnFailure, ProcessFailureResponse processFailureResponse, JsonResultProcessor resultProcessor) { - this(handler, retryOnFailure, processFailureResponse); - this.resultProcessors.add(resultProcessor); + this.gson = new GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create(); + this.communicationStatus = new CommunicationStatus(); + this.transformer = new GenericResponseTransformer(handler); + this.handler = handler; + this.processFailureResponse = processFailureResponse; + this.retryOnFailure = retryOnFailure; + this.resultProcessor = resultProcessor; } /** @@ -237,7 +226,7 @@ public abstract class AbstractCommand extends BufferingResponseListener implemen * @param json * @return */ - private @Nullable JsonObject transform(@Nullable String json) { + protected @Nullable JsonObject transform(@Nullable String json) { if (json != null) { try { return gson.fromJson(json, JsonObject.class); @@ -283,18 +272,16 @@ public abstract class AbstractCommand extends BufferingResponseListener implemen } /** - * calls the registered resultPRocessors. + * calls the registered resultProcessor. * * @param jsonObject */ protected final void processResult(JsonObject jsonObject) { - for (JsonResultProcessor processor : resultProcessors) { - try { - processor.processResult(getCommunicationStatus(), jsonObject); - } catch (Exception ex) { - // this should not happen - logger.warn("Exception caught: {}", ex.getMessage(), ex); - } + try { + resultProcessor.processResult(getCommunicationStatus(), jsonObject); + } catch (Exception ex) { + // this should not happen + logger.warn("Exception caught: {}", ex.getMessage(), ex); } } @@ -320,9 +307,4 @@ public abstract class AbstractCommand extends BufferingResponseListener implemen * @return Url */ protected abstract String getURL(); - - @Override - public void registerResultProcessor(JsonResultProcessor resultProcessor) { - this.resultProcessors.add(resultProcessor); - } } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/AbstractWriteCommand.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/AbstractWriteCommand.java index 2e3a24493..93bfed6a9 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/AbstractWriteCommand.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/AbstractWriteCommand.java @@ -47,8 +47,9 @@ public abstract class AbstractWriteCommand extends AbstractCommand { * @param config */ public AbstractWriteCommand(EaseeThingHandler handler, Channel channel, Command command, - RetryOnFailure retryOnFailure, ProcessFailureResponse processFailureResponse) { - super(handler, retryOnFailure, processFailureResponse); + RetryOnFailure retryOnFailure, ProcessFailureResponse processFailureResponse, + JsonResultProcessor resultProcessor) { + super(handler, retryOnFailure, processFailureResponse, resultProcessor); this.channel = channel; this.command = command; } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/EaseeCommand.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/EaseeCommand.java index 57fcaa4ad..46b3901fa 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/EaseeCommand.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/EaseeCommand.java @@ -37,11 +37,4 @@ public interface EaseeCommand extends SuccessListener, FailureListener, ContentL * @throws ValidationException */ void performAction(HttpClient asyncclient, String token) throws ValidationException; - - /** - * sets a result processor for json result data - * - * @param resultProcessor - */ - void registerResultProcessor(JsonResultProcessor resultProcessor); } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/account/Login.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/account/Login.java index cf6826e3e..045e0fee8 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/account/Login.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/account/Login.java @@ -23,6 +23,7 @@ import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.util.StringContentProvider; import org.eclipse.jetty.http.HttpMethod; import org.openhab.binding.easee.internal.command.AbstractCommand; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeBridgeHandler; import com.google.gson.JsonObject; @@ -47,9 +48,9 @@ public class Login extends AbstractCommand { private final LoginData loginData; - public Login(EaseeBridgeHandler handler) { + public Login(EaseeBridgeHandler handler, JsonResultProcessor resultProcessor) { // flags do not matter as "onComplete" is overwritten in this class. - super(handler, RetryOnFailure.NO, ProcessFailureResponse.NO); + super(handler, RetryOnFailure.NO, ProcessFailureResponse.NO, resultProcessor); loginData = new LoginData(handler.getBridgeConfiguration().getUsername(), handler.getBridgeConfiguration().getPassword()); } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/account/RefreshToken.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/account/RefreshToken.java index 664122d44..7f4bd2fe1 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/account/RefreshToken.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/account/RefreshToken.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.util.StringContentProvider; import org.eclipse.jetty.http.HttpMethod; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeBridgeHandler; /** @@ -40,8 +41,9 @@ public class RefreshToken extends Login { private final RefreshData refreshData; - public RefreshToken(EaseeBridgeHandler handler, String accessToken, String refreshToken) { - super(handler); + public RefreshToken(EaseeBridgeHandler handler, String accessToken, String refreshToken, + JsonResultProcessor resultProcessor) { + super(handler, resultProcessor); refreshData = new RefreshData(accessToken, refreshToken); } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/ChangeConfiguration.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/ChangeConfiguration.java index 4ba56e706..9ff40968c 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/ChangeConfiguration.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/ChangeConfiguration.java @@ -19,6 +19,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.util.StringContentProvider; import org.eclipse.jetty.http.HttpMethod; import org.openhab.binding.easee.internal.command.AbstractWriteCommand; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; import org.openhab.binding.easee.internal.model.ValidationException; import org.openhab.core.thing.Channel; @@ -33,8 +34,9 @@ import org.openhab.core.types.Command; public class ChangeConfiguration extends AbstractWriteCommand { private final String url; - public ChangeConfiguration(EaseeThingHandler handler, String chargerId, Channel channel, Command command) { - super(handler, channel, command, RetryOnFailure.YES, ProcessFailureResponse.YES); + public ChangeConfiguration(EaseeThingHandler handler, String chargerId, Channel channel, Command command, + JsonResultProcessor resultProcessor) { + super(handler, channel, command, RetryOnFailure.YES, ProcessFailureResponse.YES, resultProcessor); this.url = CHANGE_CONFIGURATION_URL.replaceAll("\\{id\\}", chargerId); } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/ChargerState.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/ChargerState.java deleted file mode 100644 index 2b6a222ad..000000000 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/ChargerState.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) 2010-2023 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.easee.internal.command.charger; - -import static org.openhab.binding.easee.internal.EaseeBindingConstants.*; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.http.HttpMethod; -import org.openhab.binding.easee.internal.command.AbstractCommand; -import org.openhab.binding.easee.internal.handler.EaseeThingHandler; - -/** - * implements the state api call of the charger. - * - * @author Alexander Friese - initial contribution - */ -@NonNullByDefault -public class ChargerState extends AbstractCommand { - private final String url; - - public ChargerState(EaseeThingHandler handler, String chargerId) { - // retry does not make much sense as it is a polling command, command should always succeed therefore update - // handler on failure. - super(handler, RetryOnFailure.NO, ProcessFailureResponse.YES); - this.url = STATE_URL.replaceAll("\\{id\\}", chargerId); - } - - @Override - protected Request prepareRequest(Request requestToPrepare) { - requestToPrepare.method(HttpMethod.GET); - return requestToPrepare; - } - - @Override - protected String getURL() { - return url; - } - - @Override - protected String getChannelGroup() { - return CHANNEL_GROUP_CHARGER_STATE; - } -} diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/GetConfiguration.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/GetConfiguration.java index e1067b46a..5f0d4188f 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/GetConfiguration.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/GetConfiguration.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpMethod; import org.openhab.binding.easee.internal.command.AbstractCommand; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; /** @@ -29,10 +30,10 @@ import org.openhab.binding.easee.internal.handler.EaseeThingHandler; public class GetConfiguration extends AbstractCommand { private final String url; - public GetConfiguration(EaseeThingHandler handler, String chargerId) { + public GetConfiguration(EaseeThingHandler handler, String chargerId, JsonResultProcessor resultProcessor) { // retry does not make much sense as it is a polling command, command should always succeed therefore update // handler on failure. - super(handler, RetryOnFailure.NO, ProcessFailureResponse.YES); + super(handler, RetryOnFailure.NO, ProcessFailureResponse.YES, resultProcessor); this.url = GET_CONFIGURATION_URL.replaceAll("\\{id\\}", chargerId); } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/LatestChargingSession.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/LatestChargingSession.java index fea34157b..d45227d64 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/LatestChargingSession.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/LatestChargingSession.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpMethod; import org.openhab.binding.easee.internal.command.AbstractCommand; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; /** @@ -29,10 +30,10 @@ import org.openhab.binding.easee.internal.handler.EaseeThingHandler; public class LatestChargingSession extends AbstractCommand { private final String url; - public LatestChargingSession(EaseeThingHandler handler, String chargerId) { + public LatestChargingSession(EaseeThingHandler handler, String chargerId, JsonResultProcessor resultProcessor) { // retry does not make much sense as it is a polling command, command might fail if no charging sessions are // available, therefore just ignore failure. - super(handler, RetryOnFailure.NO, ProcessFailureResponse.NO); + super(handler, RetryOnFailure.NO, ProcessFailureResponse.NO, resultProcessor); this.url = LATEST_CHARGING_SESSION_URL.replaceAll("\\{id\\}", chargerId); } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommand.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommand.java index fc36e1b71..81992f917 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommand.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommand.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpMethod; import org.openhab.binding.easee.internal.command.AbstractWriteCommand; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; import org.openhab.core.thing.Channel; import org.openhab.core.types.Command; @@ -39,8 +40,9 @@ public class SendCommand extends AbstractWriteCommand { * @param channel the channel that triggered this command * @param command the command to be send */ - public SendCommand(EaseeThingHandler handler, String chargerId, Channel channel, Command command) { - this(handler, channel, command); + public SendCommand(EaseeThingHandler handler, String chargerId, Channel channel, Command command, + JsonResultProcessor resultProcessor) { + this(handler, channel, command, resultProcessor); this.url = COMMANDS_URL.replaceAll("\\{id\\}", chargerId).replaceAll("\\{command\\}", getCommandValue()); } @@ -51,8 +53,8 @@ public class SendCommand extends AbstractWriteCommand { * @param channel the channel that triggered this command * @param command the command to be send */ - SendCommand(EaseeThingHandler handler, Channel channel, Command command) { - super(handler, channel, command, RetryOnFailure.YES, ProcessFailureResponse.YES); + SendCommand(EaseeThingHandler handler, Channel channel, Command command, JsonResultProcessor resultProcessor) { + super(handler, channel, command, RetryOnFailure.YES, ProcessFailureResponse.YES, resultProcessor); } @Override diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommandPauseResume.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommandPauseResume.java index dadce6c5d..6525f0546 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommandPauseResume.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommandPauseResume.java @@ -15,6 +15,7 @@ package org.openhab.binding.easee.internal.command.charger; import static org.openhab.binding.easee.internal.EaseeBindingConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.Channel; @@ -28,8 +29,9 @@ import org.openhab.core.types.Command; @NonNullByDefault public class SendCommandPauseResume extends SendCommand { - public SendCommandPauseResume(EaseeThingHandler handler, String chargerId, Channel channel, Command command) { - super(handler, channel, command); + public SendCommandPauseResume(EaseeThingHandler handler, String chargerId, Channel channel, Command command, + JsonResultProcessor resultProcessor) { + super(handler, channel, command, resultProcessor); String value; if (command.equals(OnOffType.ON)) { value = CMD_VAL_PAUSE_CHARGING; diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommandStartStop.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommandStartStop.java index 77593db44..725ceecad 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommandStartStop.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/charger/SendCommandStartStop.java @@ -15,6 +15,7 @@ package org.openhab.binding.easee.internal.command.charger; import static org.openhab.binding.easee.internal.EaseeBindingConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.Channel; @@ -28,8 +29,9 @@ import org.openhab.core.types.Command; @NonNullByDefault public class SendCommandStartStop extends SendCommand { - public SendCommandStartStop(EaseeThingHandler handler, String chargerId, Channel channel, Command command) { - super(handler, channel, command); + public SendCommandStartStop(EaseeThingHandler handler, String chargerId, Channel channel, Command command, + JsonResultProcessor resultProcessor) { + super(handler, channel, command, resultProcessor); String value; if (command.equals(OnOffType.ON)) { value = CMD_VAL_START_CHARGING; diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/CircuitSettings.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/CircuitSettings.java index 5c79e06d2..cc43f2dd1 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/CircuitSettings.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/CircuitSettings.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpMethod; import org.openhab.binding.easee.internal.command.AbstractCommand; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; /** @@ -29,8 +30,8 @@ import org.openhab.binding.easee.internal.handler.EaseeThingHandler; public class CircuitSettings extends AbstractCommand { private final String url; - public CircuitSettings(EaseeThingHandler handler, String circuitId) { - super(handler, RetryOnFailure.NO, ProcessFailureResponse.YES); + public CircuitSettings(EaseeThingHandler handler, String circuitId, JsonResultProcessor resultProcessor) { + super(handler, RetryOnFailure.NO, ProcessFailureResponse.YES, resultProcessor); String siteId = handler.getBridgeConfiguration().getSiteId(); this.url = CIRCUIT_SETTINGS_URL.replaceAll("\\{siteId\\}", siteId).replaceAll("\\{circuitId\\}", circuitId); } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/DynamicCircuitCurrent.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/DynamicCircuitCurrent.java index 0afac9942..fe130c615 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/DynamicCircuitCurrent.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/DynamicCircuitCurrent.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpMethod; import org.openhab.binding.easee.internal.command.AbstractCommand; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; /** @@ -29,8 +30,8 @@ import org.openhab.binding.easee.internal.handler.EaseeThingHandler; public class DynamicCircuitCurrent extends AbstractCommand { private final String url; - public DynamicCircuitCurrent(EaseeThingHandler handler, String circuitId) { - super(handler, RetryOnFailure.NO, ProcessFailureResponse.YES); + public DynamicCircuitCurrent(EaseeThingHandler handler, String circuitId, JsonResultProcessor resultProcessor) { + super(handler, RetryOnFailure.NO, ProcessFailureResponse.YES, resultProcessor); String siteId = handler.getBridgeConfiguration().getSiteId(); this.url = DYNAMIC_CIRCUIT_CURRENT_URL.replaceAll("\\{siteId\\}", siteId).replaceAll("\\{circuitId\\}", circuitId); diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetCircuitSettings.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetCircuitSettings.java index 41ecf49c9..5a6c07ca6 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetCircuitSettings.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetCircuitSettings.java @@ -19,6 +19,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.util.StringContentProvider; import org.eclipse.jetty.http.HttpMethod; import org.openhab.binding.easee.internal.command.AbstractWriteCommand; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; import org.openhab.binding.easee.internal.model.ValidationException; import org.openhab.core.thing.Channel; @@ -33,8 +34,9 @@ import org.openhab.core.types.Command; public class SetCircuitSettings extends AbstractWriteCommand { private final String url; - public SetCircuitSettings(EaseeThingHandler handler, Channel channel, Command command, String circuitId) { - super(handler, channel, command, RetryOnFailure.YES, ProcessFailureResponse.YES); + public SetCircuitSettings(EaseeThingHandler handler, Channel channel, Command command, String circuitId, + JsonResultProcessor resultProcessor) { + super(handler, channel, command, RetryOnFailure.YES, ProcessFailureResponse.YES, resultProcessor); String siteId = handler.getBridgeConfiguration().getSiteId(); this.url = CIRCUIT_SETTINGS_URL.replaceAll("\\{siteId\\}", siteId).replaceAll("\\{circuitId\\}", circuitId); } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetDynamicCircuitCurrents.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetDynamicCircuitCurrents.java index ca014726f..b26c356b2 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetDynamicCircuitCurrents.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetDynamicCircuitCurrents.java @@ -22,6 +22,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.util.StringContentProvider; import org.eclipse.jetty.http.HttpMethod; import org.openhab.binding.easee.internal.command.AbstractWriteCommand; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; import org.openhab.binding.easee.internal.model.ValidationException; import org.openhab.core.thing.Channel; @@ -39,8 +40,9 @@ public class SetDynamicCircuitCurrents extends AbstractWriteCommand { private static final String PHASE3 = "phase3"; private final String url; - public SetDynamicCircuitCurrents(EaseeThingHandler handler, Channel channel, Command command, String circuitId) { - super(handler, channel, command, RetryOnFailure.YES, ProcessFailureResponse.YES); + public SetDynamicCircuitCurrents(EaseeThingHandler handler, Channel channel, Command command, String circuitId, + JsonResultProcessor resultProcessor) { + super(handler, channel, command, RetryOnFailure.YES, ProcessFailureResponse.YES, resultProcessor); String siteId = handler.getBridgeConfiguration().getSiteId(); this.url = DYNAMIC_CIRCUIT_CURRENT_URL.replaceAll("\\{siteId\\}", siteId).replaceAll("\\{circuitId\\}", circuitId); diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetMaxCircuitCurrents.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetMaxCircuitCurrents.java index bde65e201..f66ed7216 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetMaxCircuitCurrents.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetMaxCircuitCurrents.java @@ -16,6 +16,7 @@ import java.util.HashMap; import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; import org.openhab.binding.easee.internal.model.ValidationException; import org.openhab.core.thing.Channel; @@ -32,8 +33,9 @@ public class SetMaxCircuitCurrents extends SetCircuitSettings { private static final String PHASE2 = "maxCircuitCurrentP2"; private static final String PHASE3 = "maxCircuitCurrentP3"; - public SetMaxCircuitCurrents(EaseeThingHandler handler, Channel channel, Command command, String circuitId) { - super(handler, channel, command, circuitId); + public SetMaxCircuitCurrents(EaseeThingHandler handler, Channel channel, Command command, String circuitId, + JsonResultProcessor resultProcessor) { + super(handler, channel, command, circuitId, resultProcessor); } /** diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetOfflineMaxCircuitCurrents.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetOfflineMaxCircuitCurrents.java index ea386ed1d..3d597272f 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetOfflineMaxCircuitCurrents.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/circuit/SetOfflineMaxCircuitCurrents.java @@ -16,6 +16,7 @@ import java.util.HashMap; import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; import org.openhab.binding.easee.internal.handler.EaseeThingHandler; import org.openhab.binding.easee.internal.model.ValidationException; import org.openhab.core.thing.Channel; @@ -32,8 +33,9 @@ public class SetOfflineMaxCircuitCurrents extends SetCircuitSettings { private static final String PHASE2 = "offlineMaxCircuitCurrentP2"; private static final String PHASE3 = "offlineMaxCircuitCurrentP3"; - public SetOfflineMaxCircuitCurrents(EaseeThingHandler handler, Channel channel, Command command, String circuitId) { - super(handler, channel, command, circuitId); + public SetOfflineMaxCircuitCurrents(EaseeThingHandler handler, Channel channel, Command command, String circuitId, + JsonResultProcessor resultProcessor) { + super(handler, channel, command, circuitId, resultProcessor); } /** diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/site/SiteState.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/site/SiteState.java new file mode 100644 index 000000000..a2d41996b --- /dev/null +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/command/site/SiteState.java @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2010-2023 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.easee.internal.command.site; + +import static org.openhab.binding.easee.internal.EaseeBindingConstants.*; + +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.http.HttpMethod; +import org.openhab.binding.easee.internal.Utils; +import org.openhab.binding.easee.internal.command.AbstractCommand; +import org.openhab.binding.easee.internal.command.JsonResultProcessor; +import org.openhab.binding.easee.internal.handler.EaseeChargerHandler; +import org.openhab.binding.easee.internal.handler.EaseeThingHandler; +import org.openhab.binding.easee.internal.model.GenericResponseTransformer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +/** + * implements the state api call of the site in order to retrieve charger states. + * + * @author Alexander Friese - initial contribution + */ +@NonNullByDefault +public class SiteState extends AbstractCommand { + private final String url; + private final Map chargerHandlers; + + /** + * logger + */ + private final Logger logger = LoggerFactory.getLogger(SiteState.class); + + public SiteState(EaseeThingHandler handler, String siteId, Map chargerHandlers, + JsonResultProcessor resultProcessor) { + // retry does not make much sense as it is a polling command, command should always succeed therefore update + // handler on failure. + super(handler, RetryOnFailure.NO, ProcessFailureResponse.YES, resultProcessor); + this.url = SITE_STATE_URL.replaceAll("\\{siteId\\}", siteId); + this.chargerHandlers = chargerHandlers; + } + + @Override + protected Request prepareRequest(Request requestToPrepare) { + requestToPrepare.method(HttpMethod.GET); + return requestToPrepare; + } + + @Override + protected String getURL() { + return url; + } + + @Override + protected String getChannelGroup() { + return CHANNEL_GROUP_CHARGER_STATE; + } + + /** + * override default behaviour: extract ChargerState from SiteState + */ + @Override + protected void onCompleteCodeOk(@Nullable String json) { + JsonObject jsonObject = transform(json); + + if (jsonObject != null) { + logger.debug("success"); + JsonArray circuitStates = jsonObject.getAsJsonArray(JSON_KEY_CIRCUIT_STATES); + for (JsonElement circuitState : circuitStates) { + JsonArray chargerDataArray = circuitState.getAsJsonObject().getAsJsonArray(JSON_KEY_CHARGER_STATES); + for (JsonElement chargerData : chargerDataArray) { + processChargerStateData(chargerData.getAsJsonObject()); + } + } + } + } + + /** + * processes charger data, also sets online status retrieved from API. + * + * @param chargerData + */ + private void processChargerStateData(JsonObject chargerData) { + JsonElement chargerId = chargerData.get(JSON_KEY_CHARGER_ID); + String id = chargerId != null ? chargerId.getAsString() : null; + if (id != null) { + EaseeChargerHandler handler = chargerHandlers.get(id); + if (handler != null) { + GenericResponseTransformer transformer = new GenericResponseTransformer(handler); + JsonElement chargerState = chargerData.getAsJsonObject().get(JSON_KEY_CHARGER_STATE); + JsonObject jsonObject = chargerState.getAsJsonObject(); + Boolean isOnline = Utils.getAsBool(jsonObject, JSON_KEY_ONLINE); + + handler.updateChannelStatus(transformer.transform(jsonObject, getChannelGroup())); + handler.setOnline(isOnline == null ? false : isOnline); + } + } + } +} diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/connector/WebInterface.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/connector/WebInterface.java index 6c6d29cf9..c14c8e7ee 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/connector/WebInterface.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/connector/WebInterface.java @@ -59,7 +59,7 @@ public class WebInterface implements AtomicReferenceTrait { /** * handler for updating bridge status */ - private final StatusHandler statusHandler; + private final StatusHandler bridgeStatusHandler; /** * holds authentication status @@ -135,7 +135,8 @@ public class WebInterface implements AtomicReferenceTrait { switch (status.getHttpCode()) { case BAD_REQUEST: - statusHandler.updateStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); + bridgeStatusHandler.updateStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + msg); setAuthenticated(false); break; case OK: @@ -151,14 +152,15 @@ public class WebInterface implements AtomicReferenceTrait { logger.debug("access token refreshed: {}, expiry: {}", Utils.formatDate(tokenRefreshDate), Utils.formatDate(tokenExpiry)); - statusHandler.updateStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, + bridgeStatusHandler.updateStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, STATUS_TOKEN_VALIDATED); setAuthenticated(true); handler.startDiscovery(); break; } default: - statusHandler.updateStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, msg); + bridgeStatusHandler.updateStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + msg); setAuthenticated(false); } } @@ -207,8 +209,7 @@ public class WebInterface implements AtomicReferenceTrait { */ private synchronized void authenticate() { setAuthenticated(false); - EaseeCommand loginCommand = new Login(handler); - loginCommand.registerResultProcessor(this::processAuthenticationResult); + EaseeCommand loginCommand = new Login(handler, this::processAuthenticationResult); try { loginCommand.performAction(httpClient, accessToken); } catch (ValidationException e) { @@ -227,8 +228,8 @@ public class WebInterface implements AtomicReferenceTrait { logger.debug("access token needs to be refreshed, last refresh: {}, expiry: {}", Utils.formatDate(tokenRefreshDate), Utils.formatDate(tokenExpiry)); - EaseeCommand refreshCommand = new RefreshToken(handler, accessToken, refreshToken); - refreshCommand.registerResultProcessor(this::processAuthenticationResult); + EaseeCommand refreshCommand = new RefreshToken(handler, accessToken, refreshToken, + this::processAuthenticationResult); try { refreshCommand.performAction(httpClient, accessToken); } catch (ValidationException e) { @@ -245,28 +246,9 @@ public class WebInterface implements AtomicReferenceTrait { private void executeCommand() throws ValidationException { EaseeCommand command = commandQueue.poll(); if (command != null) { - command.registerResultProcessor(this::processExecutionResult); command.performAction(httpClient, accessToken); } } - - private void processExecutionResult(CommunicationStatus status, JsonObject jsonObject) { - String msg = Utils.getAsString(jsonObject, JSON_KEY_ERROR_TITLE); - if (msg == null || msg.isBlank()) { - msg = status.getMessage(); - } - - switch (status.getHttpCode()) { - case OK: - case ACCEPTED: - // no action needed as the thing is already online. - break; - default: - statusHandler.updateStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, msg); - setAuthenticated(false); - - } - } } /** @@ -275,9 +257,9 @@ public class WebInterface implements AtomicReferenceTrait { * @param config Bridge configuration */ public WebInterface(ScheduledExecutorService scheduler, EaseeBridgeHandler handler, HttpClient httpClient, - StatusHandler statusHandler) { + StatusHandler bridgeStatusHandler) { this.handler = handler; - this.statusHandler = statusHandler; + this.bridgeStatusHandler = bridgeStatusHandler; this.scheduler = scheduler; this.httpClient = httpClient; this.tokenExpiry = OUTDATED_DATE; diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeChargerHandler.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeChargerHandler.java index 9ac3e1fa5..508fc4209 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeChargerHandler.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeChargerHandler.java @@ -27,7 +27,6 @@ import org.openhab.binding.easee.internal.Utils; import org.openhab.binding.easee.internal.command.EaseeCommand; import org.openhab.binding.easee.internal.command.charger.ChangeConfiguration; import org.openhab.binding.easee.internal.command.charger.Charger; -import org.openhab.binding.easee.internal.command.charger.ChargerState; import org.openhab.binding.easee.internal.command.charger.GetConfiguration; import org.openhab.binding.easee.internal.command.charger.LatestChargingSession; import org.openhab.binding.easee.internal.command.charger.SendCommand; @@ -72,16 +71,20 @@ public class EaseeChargerHandler extends BaseThingHandler implements EaseeThingH @Override public void initialize() { logger.debug("About to initialize Charger"); - String chargerId = getConfig().get(EaseeBindingConstants.THING_CONFIG_ID).toString(); - logger.debug("Easee Charger initialized with id: {}", chargerId); + logger.debug("Easee Charger initialized with id: {}", getId()); updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, STATUS_WAITING_FOR_BRIDGE); startPolling(); - enqueueCommand(new Charger(this, chargerId, this::updateProperties)); + enqueueCommand(new Charger(this, getId(), this::updatePropertiesAndOnlineStatus)); } - private void updateProperties(CommunicationStatus status, JsonObject charger) { + public String getId() { + return getConfig().get(EaseeBindingConstants.THING_CONFIG_ID).toString(); + } + + private void updatePropertiesAndOnlineStatus(CommunicationStatus status, JsonObject charger) { + updateOnlineStatus(status, charger); Map properties = editProperties(); String backPlateId = Utils.getAsString(charger.getAsJsonObject(JSON_KEY_BACK_PLATE), JSON_KEY_GENERIC_ID); @@ -123,35 +126,48 @@ public class EaseeChargerHandler extends BaseThingHandler implements EaseeThingH String chargerId = getConfig().get(EaseeBindingConstants.THING_CONFIG_ID).toString(); logger.debug("polling charger data for {}", chargerId); - ChargerState state = new ChargerState(this, chargerId); - state.registerResultProcessor(this::updateStatusInfo); - enqueueCommand(state); - // proceed if charger is online if (getThing().getStatus() == ThingStatus.ONLINE) { - enqueueCommand(new GetConfiguration(this, chargerId)); - enqueueCommand(new LatestChargingSession(this, chargerId)); + enqueueCommand(new GetConfiguration(this, chargerId, this::updateOnlineStatus)); + enqueueCommand(new LatestChargingSession(this, chargerId, this::updateOnlineStatus)); } } /** - * updates status depending on online information received from the API. + * updates online status depending on online information received from the API. this is called by the SiteState + * Command which retrieves whole site data inclusing charger status. * - * @param status - * @param jsonObject */ - private void updateStatusInfo(CommunicationStatus status, JsonObject jsonObject) { - Boolean isOnline = Utils.getAsBool(jsonObject, JSON_KEY_ONLINE); - - if (isOnline == null) { - super.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, STATUS_NO_VALID_DATA); - } else if (isOnline) { + public void setOnline(boolean isOnline) { + if (isOnline) { super.updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); } else { super.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, STATUS_NO_CONNECTION); } } + /** + * result processor to handle online status updates + * + * @param status of command execution + * @param jsonObject json respone result + */ + protected final void updateOnlineStatus(CommunicationStatus status, JsonObject jsonObject) { + String msg = Utils.getAsString(jsonObject, JSON_KEY_ERROR_TITLE); + if (msg == null || msg.isBlank()) { + msg = status.getMessage(); + } + + switch (status.getHttpCode()) { + case OK: + case ACCEPTED: + super.updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); + break; + default: + super.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); + } + } + /** * Disposes the thing. */ @@ -214,13 +230,13 @@ public class EaseeChargerHandler extends BaseThingHandler implements EaseeThingH switch (Utils.getWriteCommand(channel)) { case COMMAND_CHANGE_CONFIGURATION: - return new ChangeConfiguration(this, chargerId, channel, command); + return new ChangeConfiguration(this, chargerId, channel, command, this::updateOnlineStatus); case COMMAND_SEND_COMMAND: - return new SendCommand(this, chargerId, channel, command); + return new SendCommand(this, chargerId, channel, command, this::updateOnlineStatus); case COMMAND_SEND_COMMAND_START_STOP: - return new SendCommandStartStop(this, chargerId, channel, command); + return new SendCommandStartStop(this, chargerId, channel, command, this::updateOnlineStatus); case COMMAND_SEND_COMMAND_PAUSE_RESUME: - return new SendCommandPauseResume(this, chargerId, channel, command); + return new SendCommandPauseResume(this, chargerId, channel, command, this::updateOnlineStatus); default: // this should not happen logger.error("write command '{}' not found for channel '{}'", command.toString(), diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeMasterChargerHandler.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeMasterChargerHandler.java index fcf7fc27a..08543f156 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeMasterChargerHandler.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeMasterChargerHandler.java @@ -57,8 +57,8 @@ public class EaseeMasterChargerHandler extends EaseeChargerHandler { String circuitId = getConfig().get(EaseeBindingConstants.THING_CONFIG_CIRCUIT_ID).toString(); logger.debug("polling circuit data for {}", circuitId); - enqueueCommand(new DynamicCircuitCurrent(this, circuitId)); - enqueueCommand(new CircuitSettings(this, circuitId)); + enqueueCommand(new DynamicCircuitCurrent(this, circuitId, this::updateOnlineStatus)); + enqueueCommand(new CircuitSettings(this, circuitId, this::updateOnlineStatus)); } } @@ -68,13 +68,13 @@ public class EaseeMasterChargerHandler extends EaseeChargerHandler { switch (Utils.getWriteCommand(channel)) { case COMMAND_SET_CIRCUIT_SETTINGS: - return new SetCircuitSettings(this, channel, command, circuitId); + return new SetCircuitSettings(this, channel, command, circuitId, this::updateOnlineStatus); case COMMAND_SET_DYNAMIC_CIRCUIT_CURRENTS: - return new SetDynamicCircuitCurrents(this, channel, command, circuitId); + return new SetDynamicCircuitCurrents(this, channel, command, circuitId, this::updateOnlineStatus); case COMMAND_SET_MAX_CIRCUIT_CURRENTS: - return new SetMaxCircuitCurrents(this, channel, command, circuitId); + return new SetMaxCircuitCurrents(this, channel, command, circuitId, this::updateOnlineStatus); case COMMAND_SET_OFFLINE_MAX_CIRCUIT_CURRENTS: - return new SetOfflineMaxCircuitCurrents(this, channel, command, circuitId); + return new SetOfflineMaxCircuitCurrents(this, channel, command, circuitId, this::updateOnlineStatus); default: return super.buildEaseeCommand(command, channel); } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeSiteHandler.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeSiteHandler.java index 612c985fd..ef007fe58 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeSiteHandler.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/handler/EaseeSiteHandler.java @@ -16,14 +16,21 @@ import static org.openhab.binding.easee.internal.EaseeBindingConstants.*; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; +import org.openhab.binding.easee.internal.AtomicReferenceTrait; +import org.openhab.binding.easee.internal.EaseeBindingConstants; import org.openhab.binding.easee.internal.Utils; import org.openhab.binding.easee.internal.command.EaseeCommand; import org.openhab.binding.easee.internal.command.site.GetSite; +import org.openhab.binding.easee.internal.command.site.SiteState; import org.openhab.binding.easee.internal.config.EaseeConfiguration; import org.openhab.binding.easee.internal.connector.CommunicationStatus; import org.openhab.binding.easee.internal.connector.WebInterface; @@ -46,9 +53,14 @@ import com.google.gson.JsonObject; * @author Alexander Friese - initial contribution */ @NonNullByDefault -public class EaseeSiteHandler extends BaseBridgeHandler implements EaseeBridgeHandler { +public class EaseeSiteHandler extends BaseBridgeHandler implements EaseeBridgeHandler, AtomicReferenceTrait { private final Logger logger = LoggerFactory.getLogger(EaseeSiteHandler.class); + /** + * Schedule for polling live data + */ + private final AtomicReference<@Nullable Future> dataPollingJobReference; + private @Nullable DiscoveryService discoveryService; /** @@ -58,6 +70,7 @@ public class EaseeSiteHandler extends BaseBridgeHandler implements EaseeBridgeHa public EaseeSiteHandler(Bridge bridge, HttpClient httpClient) { super(bridge); + this.dataPollingJobReference = new AtomicReference<>(null); this.webInterface = new WebInterface(scheduler, this, httpClient, super::updateStatus); } @@ -69,6 +82,7 @@ public class EaseeSiteHandler extends BaseBridgeHandler implements EaseeBridgeHa updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, STATUS_WAITING_FOR_LOGIN); webInterface.start(); + startPolling(); enqueueCommand(new GetSite(this, this::updateProperties)); } @@ -86,12 +100,77 @@ public class EaseeSiteHandler extends BaseBridgeHandler implements EaseeBridgeHa updateProperties(properties); } + /** + * Start the polling. + */ + private void startPolling() { + updateJobReference(dataPollingJobReference, scheduler.scheduleWithFixedDelay(this::pollingRun, + POLLING_INITIAL_DELAY, getBridgeConfiguration().getDataPollingInterval(), TimeUnit.SECONDS)); + } + + /** + * Poll the Easee Cloud API one time. + */ + void pollingRun() { + String siteId = getConfig().get(EaseeBindingConstants.THING_CONFIG_SITE_ID).toString(); + logger.debug("polling site data for {}", siteId); + + SiteState state = new SiteState(this, siteId, getChildChargerHandlers(), this::updateOnlineStatus); + enqueueCommand(state); + + // proceed if site is online + if (getThing().getStatus() == ThingStatus.ONLINE) { + // add further polling commands here + } + } + + /** + * creates a map containing all child chargers/masterchargers identified by their unique id. + * + * @return the map created + */ + private Map getChildChargerHandlers() { + Map chargerHandlers = new HashMap<>(); + + getThing().getThings().stream().filter(x -> x.getThingTypeUID().equals(THING_TYPE_CHARGER) + || x.getThingTypeUID().equals(THING_TYPE_MASTER_CHARGER)).forEach(y -> { + EaseeChargerHandler handler = (EaseeChargerHandler) y.getHandler(); + if (handler != null) { + chargerHandlers.put(handler.getId(), handler); + } + }); + return chargerHandlers; + } + + /** + * result processor to handle online status updates + * + * @param status of command execution + * @param jsonObject json respone result + */ + protected final void updateOnlineStatus(CommunicationStatus status, JsonObject jsonObject) { + String msg = Utils.getAsString(jsonObject, JSON_KEY_ERROR_TITLE); + if (msg == null || msg.isBlank()) { + msg = status.getMessage(); + } + + switch (status.getHttpCode()) { + case OK: + case ACCEPTED: + super.updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); + break; + default: + super.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); + } + } + /** * Disposes the bridge. */ @Override public void dispose() { logger.debug("Handler disposed."); + cancelJobReference(dataPollingJobReference); webInterface.dispose(); } diff --git a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/model/GenericResponseTransformer.java b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/model/GenericResponseTransformer.java index 02a86f438..dc514f3c3 100644 --- a/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/model/GenericResponseTransformer.java +++ b/bundles/org.openhab.binding.easee/src/main/java/org/openhab/binding/easee/internal/model/GenericResponseTransformer.java @@ -73,6 +73,7 @@ public class GenericResponseTransformer { result.put(channel, UnDefType.NULL); } else { try { + String channelTypeId = Utils.getChannelTypeId(channel); switch (channelType) { case CHANNEL_TYPE_SWITCH: result.put(channel, OnOffType.from(Boolean.parseBoolean(value))); @@ -87,9 +88,16 @@ public class GenericResponseTransformer { result.put(channel, new QuantityType<>(Double.parseDouble(value), MetricPrefix.KILO(Units.WATT_HOUR))); break; - case CHANNEL_TYPE_KW: - result.put(channel, - new QuantityType<>(Double.parseDouble(value), MetricPrefix.KILO(Units.WATT))); + case CHANNEL_TYPE_POWER: + if (channelTypeId.equals(CHANNEL_TYPENAME_RSSI)) { + // explicit type long is needed in case of integer/long values otherwise automatic + // transformation to a decimal type is applied. + result.put(channel, + new QuantityType<>(Long.parseLong(value), Units.DECIBEL_MILLIWATTS)); + } else { + result.put(channel, new QuantityType<>(Double.parseDouble(value), + MetricPrefix.KILO(Units.WATT))); + } break; case CHANNEL_TYPE_DATE: result.put(channel, new DateTimeType(Utils.parseDate(value))); @@ -98,7 +106,7 @@ public class GenericResponseTransformer { result.put(channel, new StringType(value)); break; case CHANNEL_TYPE_NUMBER: - if (Utils.getChannelTypeId(channel).contains(CHANNEL_TYPENAME_INTEGER)) { + if (channelTypeId.contains(CHANNEL_TYPENAME_INTEGER)) { // explicit type long is needed in case of integer/long values otherwise automatic // transformation to a decimal type is applied. result.put(channel, new DecimalType(Long.parseLong(value))); diff --git a/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/charger-channel-groups.xml b/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/charger-channel-groups.xml index 37bf84f6a..cb929c75e 100644 --- a/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/charger-channel-groups.xml +++ b/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/charger-channel-groups.xml @@ -30,6 +30,18 @@ Energy for current session. + + + Energy transferred per hour. + + + + Wi-Fi signal quality. + + + + Cell signal quality. + Dynamic set circuit current for phase 1. @@ -50,14 +62,26 @@ Current Firmware of the wallbox. - - - Latest Firmware which is available for the wallbox. - Voltage + + + Input Current on phase T2 + + + + Input Current on phase T3 + + + + Input Current on phase T4 + + + + Input Current on phase T5 + Actual charging current. @@ -66,6 +90,54 @@ Online status of the wallbox. + + + Input voltage between phase T1 and T2 + + + + Input voltage between phase T1 and T3 + + + + Input voltage between phase T1 and T4 + + + + Input voltage between phase T1 and T5 + + + + Input voltage between phase T2 and T3 + + + + Input voltage between phase T2 and T4 + + + + Input voltage between phase T2 and T5 + + + + Input voltage between phase T3 and T4 + + + + Input voltage between phase T3 and T5 + + + + Input voltage between phase T4 and T5 + + + + Led Mode. + + + + Rating of the connected cable. + Dynamic set charging current. @@ -90,6 +162,10 @@ Fatal Error Code. + + + Cloud connection status of the wallbox. + diff --git a/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/easee-readonly-channel-types.xml b/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/easee-readonly-channel-types.xml index 3f2e613fa..eaf3c73ff 100644 --- a/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/easee-readonly-channel-types.xml +++ b/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/easee-readonly-channel-types.xml @@ -3,6 +3,13 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> + + Number:Power + + QualityOfService + + + Number:Power diff --git a/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/things.xml b/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/things.xml index d0f1049ea..f5673e1dd 100644 --- a/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/things.xml +++ b/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/thing/things.xml @@ -22,6 +22,9 @@ + + 1 + @@ -36,6 +39,9 @@ + + 1 + diff --git a/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/update/instructions.xml b/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/update/instructions.xml new file mode 100644 index 000000000..8297766e8 --- /dev/null +++ b/bundles/org.openhab.binding.easee/src/main/resources/OH-INF/update/instructions.xml @@ -0,0 +1,215 @@ + + + + + + easee:type-energy + + Energy transferred per hour. + + + easee:type-rssi + + Wi-Fi signal quality. + + + easee:type-rssi + + Cell signal quality. + + + easee:type-current + + Input Current on phase T2 + + + easee:type-current + + Input Current on phase T3 + + + easee:type-current + + Input Current on phase T4 + + + easee:type-current + + Input Current on phase T5 + + + easee:type-volt + + Input voltage between phase T1 and T2 + + + easee:type-volt + + Input Voltage between phase T1 and T3 + + + easee:type-volt + + Input Voltage between phase T1 and T4 + + + easee:type-volt + + Input Voltage between phase T1 and T5 + + + easee:type-volt + + Input Voltage between phase T2 and T3 + + + easee:type-volt + + Input Voltage between phase T2 and T4 + + + easee:type-volt + + Input Voltage between phase T2 and T5 + + + easee:type-volt + + Input Voltage between phase T3 and T4 + + + easee:type-volt + + Input Voltage between phase T3 and T5 + + + easee:type-volt + + Input Voltage between phase T4 and T5 + + + easee:type-integer + + Led Mode. + + + easee:type-current + + Rating of the connected cable. + + + easee:type-switch + + Cloud connection status of the wallbox. + + + + + + + + easee:type-energy + + Energy transferred per hour. + + + easee:type-rssi + + Wi-Fi signal quality. + + + easee:type-rssi + + Cell signal quality. + + + easee:type-current + + Input Current on phase T2 + + + easee:type-current + + Input Current on phase T3 + + + easee:type-current + + Input Current on phase T4 + + + easee:type-current + + Input Current on phase T5 + + + easee:type-volt + + Input voltage between phase T1 and T2 + + + easee:type-volt + + Input Voltage between phase T1 and T3 + + + easee:type-volt + + Input Voltage between phase T1 and T4 + + + easee:type-volt + + Input Voltage between phase T1 and T5 + + + easee:type-volt + + Input Voltage between phase T2 and T3 + + + easee:type-volt + + Input Voltage between phase T2 and T4 + + + easee:type-volt + + Input Voltage between phase T2 and T5 + + + easee:type-volt + + Input Voltage between phase T3 and T4 + + + easee:type-volt + + Input Voltage between phase T3 and T5 + + + easee:type-volt + + Input Voltage between phase T4 and T5 + + + easee:type-integer + + Led Mode. + + + easee:type-current + + Rating of the connected cable. + + + easee:type-switch + + Cloud connection status of the wallbox. + + + + +