* 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 <af944580@googlemail.com>
| 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 |
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";
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";
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";
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";
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}";
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;
/**
* generic transformer which just transfers all values in a plain map.
*/
- private final GenericResponseTransformer transformer;
+ protected final GenericResponseTransformer transformer;
/**
* retry counter.
/**
* allows further processing of the json result data, if set.
*/
- private List<JsonResultProcessor> resultProcessors;
+ private final JsonResultProcessor resultProcessor;
/**
* the constructor
*/
public AbstractCommand(EaseeThingHandler handler, RetryOnFailure retryOnFailure,
- ProcessFailureResponse processFailureResponse) {
+ ProcessFailureResponse processFailureResponse, JsonResultProcessor resultProcessor) {
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;
- }
-
- /**
- * the constructor
- */
- public AbstractCommand(EaseeThingHandler handler, RetryOnFailure retryOnFailure,
- ProcessFailureResponse processFailureResponse, JsonResultProcessor resultProcessor) {
- this(handler, retryOnFailure, processFailureResponse);
- this.resultProcessors.add(resultProcessor);
+ this.resultProcessor = resultProcessor;
}
/**
* @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);
}
/**
- * 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);
}
}
* @return Url
*/
protected abstract String getURL();
-
- @Override
- public void registerResultProcessor(JsonResultProcessor resultProcessor) {
- this.resultProcessors.add(resultProcessor);
- }
}
* @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;
}
* @throws ValidationException
*/
void performAction(HttpClient asyncclient, String token) throws ValidationException;
-
- /**
- * sets a result processor for json result data
- *
- * @param resultProcessor
- */
- void registerResultProcessor(JsonResultProcessor resultProcessor);
}
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;
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());
}
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;
/**
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);
}
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;
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);
}
+++ /dev/null
-/**
- * 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;
- }
-}
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;
/**
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);
}
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;
/**
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);
}
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;
* @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());
}
* @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
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;
@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;
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;
@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;
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;
/**
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);
}
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;
/**
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);
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;
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);
}
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;
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);
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;
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);
}
/**
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;
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);
}
/**
--- /dev/null
+/**
+ * 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<String, EaseeChargerHandler> chargerHandlers;
+
+ /**
+ * logger
+ */
+ private final Logger logger = LoggerFactory.getLogger(SiteState.class);
+
+ public SiteState(EaseeThingHandler handler, String siteId, Map<String, EaseeChargerHandler> 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);
+ }
+ }
+ }
+}
/**
* handler for updating bridge status
*/
- private final StatusHandler statusHandler;
+ private final StatusHandler bridgeStatusHandler;
/**
* holds authentication status
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:
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);
}
}
*/
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) {
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) {
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);
-
- }
- }
}
/**
* @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;
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;
@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));
+ }
+
+ public String getId() {
+ return getConfig().get(EaseeBindingConstants.THING_CONFIG_ID).toString();
}
- private void updateProperties(CommunicationStatus status, JsonObject charger) {
+ private void updatePropertiesAndOnlineStatus(CommunicationStatus status, JsonObject charger) {
+ updateOnlineStatus(status, charger);
Map<String, String> properties = editProperties();
String backPlateId = Utils.getAsString(charger.getAsJsonObject(JSON_KEY_BACK_PLATE), JSON_KEY_GENERIC_ID);
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.
*/
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(),
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));
}
}
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);
}
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;
* @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;
/**
public EaseeSiteHandler(Bridge bridge, HttpClient httpClient) {
super(bridge);
+ this.dataPollingJobReference = new AtomicReference<>(null);
this.webInterface = new WebInterface(scheduler, this, httpClient, super::updateStatus);
}
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, STATUS_WAITING_FOR_LOGIN);
webInterface.start();
+ startPolling();
enqueueCommand(new GetSite(this, this::updateProperties));
}
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<String, EaseeChargerHandler> getChildChargerHandlers() {
+ Map<String, EaseeChargerHandler> 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();
}
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)));
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)));
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)));
<label>Session Energy</label>
<description>Energy for current session.</description>
</channel>
+ <channel id="energyPerHour" typeId="type-energy">
+ <label>Energy per Hour</label>
+ <description>Energy transferred per hour.</description>
+ </channel>
+ <channel id="wiFiRSSI" typeId="type-rssi">
+ <label>Wi-Fi RSSI</label>
+ <description>Wi-Fi signal quality.</description>
+ </channel>
+ <channel id="cellRSSI" typeId="type-rssi">
+ <label>Cell RSSI</label>
+ <description>Cell signal quality.</description>
+ </channel>
<channel id="dynamicCircuitCurrentP1" typeId="type-current">
<label>Dynamic Circuit Current P1</label>
<description>Dynamic set circuit current for phase 1.</description>
<label>Current Firmware</label>
<description>Current Firmware of the wallbox.</description>
</channel>
- <channel id="latestFirmware" typeId="type-integer">
- <label>Latest Firmware</label>
- <description>Latest Firmware which is available for the wallbox.</description>
- </channel>
<channel id="voltage" typeId="type-volt">
<label>Voltage</label>
<description>Voltage</description>
</channel>
+ <channel id="inCurrentT2" typeId="type-current">
+ <label>Input Current T2</label>
+ <description>Input Current on phase T2</description>
+ </channel>
+ <channel id="inCurrentT3" typeId="type-current">
+ <label>Input Current T3</label>
+ <description>Input Current on phase T3</description>
+ </channel>
+ <channel id="inCurrentT4" typeId="type-current">
+ <label>Input Current T4</label>
+ <description>Input Current on phase T4</description>
+ </channel>
+ <channel id="inCurrentT5" typeId="type-current">
+ <label>Input Current T5</label>
+ <description>Input Current on phase T5</description>
+ </channel>
<channel id="outputCurrent" typeId="type-current">
<label>Output Current</label>
<description>Actual charging current.</description>
<label>Online</label>
<description>Online status of the wallbox.</description>
</channel>
+ <channel id="inVoltageT1T2" typeId="type-volt">
+ <label>Input Voltage T1T2</label>
+ <description>Input voltage between phase T1 and T2</description>
+ </channel>
+ <channel id="inVoltageT1T3" typeId="type-volt">
+ <label>Input Voltage T1T3</label>
+ <description>Input voltage between phase T1 and T3</description>
+ </channel>
+ <channel id="inVoltageT1T4" typeId="type-volt">
+ <label>Input Voltage T1T4</label>
+ <description>Input voltage between phase T1 and T4</description>
+ </channel>
+ <channel id="inVoltageT1T5" typeId="type-volt">
+ <label>Input Voltage T1T5</label>
+ <description>Input voltage between phase T1 and T5</description>
+ </channel>
+ <channel id="inVoltageT2T3" typeId="type-volt">
+ <label>Input Voltage T2T3</label>
+ <description>Input voltage between phase T2 and T3</description>
+ </channel>
+ <channel id="inVoltageT2T4" typeId="type-volt">
+ <label>Input Voltage T2T4</label>
+ <description>Input voltage between phase T2 and T4</description>
+ </channel>
+ <channel id="inVoltageT2T5" typeId="type-volt">
+ <label>Input Voltage T2T5</label>
+ <description>Input voltage between phase T2 and T5</description>
+ </channel>
+ <channel id="inVoltageT3T4" typeId="type-volt">
+ <label>Input Voltage T3T4</label>
+ <description>Input voltage between phase T3 and T4</description>
+ </channel>
+ <channel id="inVoltageT3T5" typeId="type-volt">
+ <label>Input Voltage T3T5</label>
+ <description>Input voltage between phase T3 and T5</description>
+ </channel>
+ <channel id="inVoltageT4T5" typeId="type-volt">
+ <label>Input Voltage T4T5</label>
+ <description>Input voltage between phase T4 and T5</description>
+ </channel>
+ <channel id="ledMode" typeId="type-integer">
+ <label>Led Mode</label>
+ <description>Led Mode.</description>
+ </channel>
+ <channel id="cableRating" typeId="type-current">
+ <label>Cable Rating</label>
+ <description>Rating of the connected cable.</description>
+ </channel>
<channel id="dynamicChargerCurrent" typeId="rwtype-current">
<label>Dynamic Charger Current</label>
<description>Dynamic set charging current.</description>
<label>Fatal Error Code</label>
<description>Fatal Error Code.</description>
</channel>
+ <channel id="connectedToCloud" typeId="type-switch">
+ <label>Connected to Cloud</label>
+ <description>Cloud connection status of the wallbox.</description>
+ </channel>
</channels>
</channel-group-type>
<channel-group-type id="charger-config">
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">
+ <channel-type id="type-rssi">
+ <item-type>Number:Power</item-type>
+ <label>Received Signal Strength Indicator</label>
+ <category>QualityOfService</category>
+ <state pattern="%d %unit%" readOnly="true">
+ </state>
+ </channel-type>
<channel-type id="type-power">
<item-type>Number:Power</item-type>
<label>Power</label>
<channel-group typeId="circuit-dynamicCurrent" id="dynamicCurrent"/>
<channel-group typeId="circuit-settings" id="settings"/>
</channel-groups>
+ <properties>
+ <property name="thingTypeVersion">1</property>
+ </properties>
<config-description-ref uri="thing-type:easee:mastercharger"/>
</thing-type>
<thing-type id="charger">
<channel-group typeId="charger-commands" id="commands"/>
<channel-group typeId="charger-latestSession" id="latestSession"/>
</channel-groups>
+ <properties>
+ <property name="thingTypeVersion">1</property>
+ </properties>
<config-description-ref uri="thing-type:easee:charger"/>
</thing-type>
</thing:thing-descriptions>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
+ xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
+ <thing-type uid="easee:mastercharger">
+ <instruction-set targetVersion="1">
+ <add-channel id="energyPerHour" groupIds="state">
+ <type>easee:type-energy</type>
+ <label>Energy per Hour</label>
+ <description>Energy transferred per hour.</description>
+ </add-channel>
+ <add-channel id="wiFiRSSI" groupIds="state">
+ <type>easee:type-rssi</type>
+ <label>Wi-Fi RSSI</label>
+ <description>Wi-Fi signal quality.</description>
+ </add-channel>
+ <add-channel id="cellRSSI" groupIds="state">
+ <type>easee:type-rssi</type>
+ <label>Cell RSSI</label>
+ <description>Cell signal quality.</description>
+ </add-channel>
+ <add-channel id="inCurrentT2" groupIds="state">
+ <type>easee:type-current</type>
+ <label>Input Current T2</label>
+ <description>Input Current on phase T2</description>
+ </add-channel>
+ <add-channel id="inCurrentT3" groupIds="state">
+ <type>easee:type-current</type>
+ <label>Input Current T3</label>
+ <description>Input Current on phase T3</description>
+ </add-channel>
+ <add-channel id="inCurrentT4" groupIds="state">
+ <type>easee:type-current</type>
+ <label>Input Current T4</label>
+ <description>Input Current on phase T4</description>
+ </add-channel>
+ <add-channel id="inCurrentT5" groupIds="state">
+ <type>easee:type-current</type>
+ <label>Input Current T5</label>
+ <description>Input Current on phase T5</description>
+ </add-channel>
+ <add-channel id="inVoltageT1T2" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T1T2</label>
+ <description>Input voltage between phase T1 and T2</description>
+ </add-channel>
+ <add-channel id="inVoltageT1T3" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T1T3</label>
+ <description>Input Voltage between phase T1 and T3</description>
+ </add-channel>
+ <add-channel id="inVoltageT1T4" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T1T4</label>
+ <description>Input Voltage between phase T1 and T4</description>
+ </add-channel>
+ <add-channel id="inVoltageT1T5" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T1T5</label>
+ <description>Input Voltage between phase T1 and T5</description>
+ </add-channel>
+ <add-channel id="inVoltageT2T3" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T2T3</label>
+ <description>Input Voltage between phase T2 and T3</description>
+ </add-channel>
+ <add-channel id="inVoltageT2T4" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T2T4</label>
+ <description>Input Voltage between phase T2 and T4</description>
+ </add-channel>
+ <add-channel id="inVoltageT2T5" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T2T5</label>
+ <description>Input Voltage between phase T2 and T5</description>
+ </add-channel>
+ <add-channel id="inVoltageT3T4" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T3T4</label>
+ <description>Input Voltage between phase T3 and T4</description>
+ </add-channel>
+ <add-channel id="inVoltageT3T5" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T3T5</label>
+ <description>Input Voltage between phase T3 and T5</description>
+ </add-channel>
+ <add-channel id="inVoltageT4T5" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T4T5</label>
+ <description>Input Voltage between phase T4 and T5</description>
+ </add-channel>
+ <add-channel id="ledMode" groupIds="state">
+ <type>easee:type-integer</type>
+ <label>Led Mode</label>
+ <description>Led Mode.</description>
+ </add-channel>
+ <add-channel id="cableRating" groupIds="state">
+ <type>easee:type-current</type>
+ <label>Cable Rating</label>
+ <description>Rating of the connected cable.</description>
+ </add-channel>
+ <add-channel id="connectedToCloud" groupIds="state">
+ <type>easee:type-switch</type>
+ <label>Connected to Cloud</label>
+ <description>Cloud connection status of the wallbox.</description>
+ </add-channel>
+ <remove-channel id="latestFirmware" groupIds="state"/>
+ </instruction-set>
+ </thing-type>
+ <thing-type uid="easee:charger">
+ <instruction-set targetVersion="1">
+ <add-channel id="energyPerHour" groupIds="state">
+ <type>easee:type-energy</type>
+ <label>Energy per Hour</label>
+ <description>Energy transferred per hour.</description>
+ </add-channel>
+ <add-channel id="wiFiRSSI" groupIds="state">
+ <type>easee:type-rssi</type>
+ <label>Wi-Fi RSSI</label>
+ <description>Wi-Fi signal quality.</description>
+ </add-channel>
+ <add-channel id="cellRSSI" groupIds="state">
+ <type>easee:type-rssi</type>
+ <label>Cell RSSI</label>
+ <description>Cell signal quality.</description>
+ </add-channel>
+ <add-channel id="inCurrentT2" groupIds="state">
+ <type>easee:type-current</type>
+ <label>Input Current T2</label>
+ <description>Input Current on phase T2</description>
+ </add-channel>
+ <add-channel id="inCurrentT3" groupIds="state">
+ <type>easee:type-current</type>
+ <label>Input Current T3</label>
+ <description>Input Current on phase T3</description>
+ </add-channel>
+ <add-channel id="inCurrentT4" groupIds="state">
+ <type>easee:type-current</type>
+ <label>Input Current T4</label>
+ <description>Input Current on phase T4</description>
+ </add-channel>
+ <add-channel id="inCurrentT5" groupIds="state">
+ <type>easee:type-current</type>
+ <label>Input Current T5</label>
+ <description>Input Current on phase T5</description>
+ </add-channel>
+ <add-channel id="inVoltageT1T2" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T1T2</label>
+ <description>Input voltage between phase T1 and T2</description>
+ </add-channel>
+ <add-channel id="inVoltageT1T3" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T1T3</label>
+ <description>Input Voltage between phase T1 and T3</description>
+ </add-channel>
+ <add-channel id="inVoltageT1T4" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T1T4</label>
+ <description>Input Voltage between phase T1 and T4</description>
+ </add-channel>
+ <add-channel id="inVoltageT1T5" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T1T5</label>
+ <description>Input Voltage between phase T1 and T5</description>
+ </add-channel>
+ <add-channel id="inVoltageT2T3" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T2T3</label>
+ <description>Input Voltage between phase T2 and T3</description>
+ </add-channel>
+ <add-channel id="inVoltageT2T4" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T2T4</label>
+ <description>Input Voltage between phase T2 and T4</description>
+ </add-channel>
+ <add-channel id="inVoltageT2T5" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T2T5</label>
+ <description>Input Voltage between phase T2 and T5</description>
+ </add-channel>
+ <add-channel id="inVoltageT3T4" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T3T4</label>
+ <description>Input Voltage between phase T3 and T4</description>
+ </add-channel>
+ <add-channel id="inVoltageT3T5" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T3T5</label>
+ <description>Input Voltage between phase T3 and T5</description>
+ </add-channel>
+ <add-channel id="inVoltageT4T5" groupIds="state">
+ <type>easee:type-volt</type>
+ <label>Input Voltage T4T5</label>
+ <description>Input Voltage between phase T4 and T5</description>
+ </add-channel>
+ <add-channel id="ledMode" groupIds="state">
+ <type>easee:type-integer</type>
+ <label>Led Mode</label>
+ <description>Led Mode.</description>
+ </add-channel>
+ <add-channel id="cableRating" groupIds="state">
+ <type>easee:type-current</type>
+ <label>Cable Rating</label>
+ <description>Rating of the connected cable.</description>
+ </add-channel>
+ <add-channel id="connectedToCloud" groupIds="state">
+ <type>easee:type-switch</type>
+ <label>Connected to Cloud</label>
+ <description>Cloud connection status of the wallbox.</description>
+ </add-channel>
+ <remove-channel id="latestFirmware" groupIds="state"/>
+ </instruction-set>
+ </thing-type>
+</update:update-descriptions>