[evcc] Adjust to API changes & Add new channels for evcc 0.117.0 (#14983)

* [evcc] Remove `hasVehicle` channel
* [evcc] Update API for evcc 0.117.0
* [evcc] Fix targetSoC and targetTime not working

Also:
- Use new Java 17 features.

Fixes #14348.

* [evcc] Add `targetEnergy` channel
* [evcc] Make `batteryPrioritySoC` channel writable

Closes #14347.

Signed-off-by: Florian Hotze <florianh_dev@icloud.com>
This commit is contained in:
Florian Hotze 2023-05-21 21:21:38 +02:00 committed by GitHub
parent 0724c3febc
commit 095a5df323
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 253 additions and 242 deletions

View File

@ -1,7 +1,7 @@
# evcc Binding # evcc Binding
This binding integrates [evcc - electric vehicle charging control](https://evcc.io), a project that provides a control center for electric vehicle charging. This binding integrates [evcc - electric vehicle charging control](https://evcc.io), a project that provides a control center for electric vehicle charging.
The binding requires evcc [version 0.111.0](https://github.com/evcc-io/evcc/releases/tag/0.111.0) or newer and is tested with this version. The binding requires evcc [version 0.117.0](https://github.com/evcc-io/evcc/releases/tag/0.117.0) or newer and is tested with this version.
You can easily install and upgrade evcc on openHABian using `sudo openhabian-config`. You can easily install and upgrade evcc on openHABian using `sudo openhabian-config`.
@ -43,7 +43,7 @@ Please note that some of them are only available when evcc is properly configure
| general#batteryCapacity | Number:Energy | R | Capacity of (home) battery. | | general#batteryCapacity | Number:Energy | R | Capacity of (home) battery. |
| general#batteryPower | Number:Power | R | Current power from battery. | | general#batteryPower | Number:Power | R | Current power from battery. |
| general#batterySoC | Number:Dimensionless | R | Current State of Charge of battery. | | general#batterySoC | Number:Dimensionless | R | Current State of Charge of battery. |
| general#batteryPrioritySoC | Number:Dimensionless | R | State of State of Charge for which the battery has priority over charging the ev when charging mode is "pv". | | general#batteryPrioritySoC | Number:Dimensionless | RW | State of State of Charge for which the battery has priority over charging the ev when charging mode is "pv". |
| general#gridPower | Number:Power | R | Current power from grid (negative means feed-in) | | general#gridPower | Number:Power | R | Current power from grid (negative means feed-in) |
| general#homePower | Number:Power | R | Current power taken by home. | | general#homePower | Number:Power | R | Current power taken by home. |
| general#pvPower | Number:Power | R | Current power from photovoltaik. | | general#pvPower | Number:Power | R | Current power from photovoltaik. |
@ -64,12 +64,12 @@ Please note that you have to replace _N_ with your loadpoint number.
| loadpointN#chargedEnergy | Number:Energy | R | Energy charged since plugged-in | | loadpointN#chargedEnergy | Number:Energy | R | Energy charged since plugged-in |
| loadpointN#charging | Switch | R | Loadpoint is currently charging | | loadpointN#charging | Switch | R | Loadpoint is currently charging |
| loadpointN#enabled | Switch | R | Charging enabled (mode is not "off") | | loadpointN#enabled | Switch | R | Charging enabled (mode is not "off") |
| loadpointN#hasVehicle | Switch | R | Whether vehicle is configured for loadpoint |
| loadpointN#maxCurrent | Number:ElectricCurrent | RW | Maximum amperage per connected phase with which the car should be charged | | loadpointN#maxCurrent | Number:ElectricCurrent | RW | Maximum amperage per connected phase with which the car should be charged |
| loadpointN#minCurrent | Number:ElectricCurrent | RW | Minimum amperage per connected phase with which the car should be charged | | loadpointN#minCurrent | Number:ElectricCurrent | RW | Minimum amperage per connected phase with which the car should be charged |
| loadpointN#minSoC | Number:Dimensionless | RW | Charge immediately with maximum power up to the defined SoC, if the charge mode is not set to "off" | | loadpointN#minSoC | Number:Dimensionless | RW | Charge immediately with maximum power up to the defined SoC, if the charge mode is not set to "off" |
| loadpointN#mode | String | RW | Charging mode: "off", "now", "minpv", "pv" | | loadpointN#mode | String | RW | Charging mode: "off", "now", "minpv", "pv" |
| loadpointN#phases | Number | RW | The maximum number of phases which can be used | | loadpointN#phases | Number | RW | The maximum number of phases which can be used |
| loadpointN#targetEnergy | Number:Energy | RW | Amount of energy to charge the vehicle with |
| loadpointN#targetSoC | Number:Dimensionless | RW | Until which state of charge (SoC) should the vehicle be charged | | loadpointN#targetSoC | Number:Dimensionless | RW | Until which state of charge (SoC) should the vehicle be charged |
| loadpointN#targetTime | DateTime | RW | When the target SoC should be reached | | loadpointN#targetTime | DateTime | RW | When the target SoC should be reached |
| loadpointN#targetTimeEnabled | Switch | RW | Target time for charging enabled | | loadpointN#targetTimeEnabled | Switch | RW | Target time for charging enabled |
@ -113,12 +113,12 @@ Number:Power evcc_loadpoint0_chargePower "Charging
Number:Energy evcc_loadpoint0_chargedEnergy "Charged energy [%.1f kWh]" <energy> {channel="evcc:device:demo:loadpoint0#chargedEnergy"} Number:Energy evcc_loadpoint0_chargedEnergy "Charged energy [%.1f kWh]" <energy> {channel="evcc:device:demo:loadpoint0#chargedEnergy"}
Switch evcc_loadpoint0_charging "Currently charging [%s]" <battery> {channel="evcc:device:demo:loadpoint0#charging"} Switch evcc_loadpoint0_charging "Currently charging [%s]" <battery> {channel="evcc:device:demo:loadpoint0#charging"}
Switch evcc_loadpoint0_enabled "Charging enabled [%s]" <switch> {channel="evcc:device:demo:loadpoint0#enabled"} Switch evcc_loadpoint0_enabled "Charging enabled [%s]" <switch> {channel="evcc:device:demo:loadpoint0#enabled"}
Switch evcc_loadpoint0_hasVehicle "Vehicle configured [%s]" <switch> {channel="evcc:device:demo:loadpoint0#hasVehicle"}
Number:ElectricCurrent evcc_loadpoint0_maxCurrent "Maximum current [%.0f A]" <energy> {channel="evcc:device:demo:loadpoint0#maxCurrent"} Number:ElectricCurrent evcc_loadpoint0_maxCurrent "Maximum current [%.0f A]" <energy> {channel="evcc:device:demo:loadpoint0#maxCurrent"}
Number:ElectricCurrent evcc_loadpoint0_minCurrent "Minimum current [%.0f A]" <energy> {channel="evcc:device:demo:loadpoint0#minCurrent"} Number:ElectricCurrent evcc_loadpoint0_minCurrent "Minimum current [%.0f A]" <energy> {channel="evcc:device:demo:loadpoint0#minCurrent"}
Number:Dimensionless evcc_loadpoint0_minSoC "Minimum SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:loadpoint0#minSoC"} Number:Dimensionless evcc_loadpoint0_minSoC "Minimum SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:loadpoint0#minSoC"}
String evcc_loadpoint0_mode "Mode [%s]" {channel="evcc:device:demo:loadpoint0#mode"} String evcc_loadpoint0_mode "Mode [%s]" {channel="evcc:device:demo:loadpoint0#mode"}
Number evcc_loadpoint0_phases "Enabled phases [%d]" {channel="evcc:device:demo:loadpoint0#phases"} Number evcc_loadpoint0_phases "Enabled phases [%d]" {channel="evcc:device:demo:loadpoint0#phases"}
Number:Energy evcc_loadpoint0_targetEnergy "Target energy [%.1f kWh]" <batterylevel> {channel="evcc:device:demo:loadpoint0#targetEnergy"}
Number:Dimensionless evcc_loadpoint0_targetSoC "Target SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:loadpoint0#targetSoC"} Number:Dimensionless evcc_loadpoint0_targetSoC "Target SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:loadpoint0#targetSoC"}
DateTime evcc_loadpoint0_targetTime "Target time [%1$td.%1$tm.%1$tY, %1$tH:%1$tM]" <time> {channel="evcc:device:demo:loadpoint0#targetTime"} DateTime evcc_loadpoint0_targetTime "Target time [%1$td.%1$tm.%1$tY, %1$tH:%1$tM]" <time> {channel="evcc:device:demo:loadpoint0#targetTime"}
Switch evcc_loadpoint0_targetTimeEnabled "Target time enabled [%s]" <switch> {channel="evcc:device:demo:loadpoint0#targetTimeEnabled"} Switch evcc_loadpoint0_targetTimeEnabled "Target time enabled [%s]" <switch> {channel="evcc:device:demo:loadpoint0#targetTimeEnabled"}
@ -158,6 +158,7 @@ sitemap evcc label="evcc Demo" {
} }
Switch item=evcc_loadpoint0_mode mappings=["off"="Stop","now"="Now","minpv"="Min + PV", "pv"="Only PV"] Switch item=evcc_loadpoint0_mode mappings=["off"="Stop","now"="Now","minpv"="Min + PV", "pv"="Only PV"]
Text label="Charging settings" icon="settings" { Text label="Charging settings" icon="settings" {
Setpoint item=evcc_loadpoint0_targetEnergy minValue=5 maxValue=100 step=5
Setpoint item=evcc_loadpoint0_targetSoC minValue=5 maxValue=100 step=5 Setpoint item=evcc_loadpoint0_targetSoC minValue=5 maxValue=100 step=5
Setpoint item=evcc_loadpoint0_minCurrent minValue=6 maxValue=96 step=2 Setpoint item=evcc_loadpoint0_minCurrent minValue=6 maxValue=96 step=2
Setpoint item=evcc_loadpoint0_maxCurrent minValue=6 maxValue=96 step=2 Setpoint item=evcc_loadpoint0_maxCurrent minValue=6 maxValue=96 step=2

View File

@ -27,6 +27,8 @@ public class EvccBindingConstants {
private static final String BINDING_ID = "evcc"; private static final String BINDING_ID = "evcc";
public static final String CHANNEL_GROUP_ID_GENERAL = "general";
// List of all Channel ids // List of all Channel ids
public static final String CHANNEL_BATTERY_CAPACITY = "batteryCapacity"; public static final String CHANNEL_BATTERY_CAPACITY = "batteryCapacity";
public static final String CHANNEL_BATTERY_POWER = "batteryPower"; public static final String CHANNEL_BATTERY_POWER = "batteryPower";
@ -45,13 +47,14 @@ public class EvccBindingConstants {
public static final String CHANNEL_LOADPOINT_CHARGING = "charging"; public static final String CHANNEL_LOADPOINT_CHARGING = "charging";
public static final String CHANNEL_LOADPOINT_CONNECTED = "vehicleConnected"; public static final String CHANNEL_LOADPOINT_CONNECTED = "vehicleConnected";
public static final String CHANNEL_LOADPOINT_CONNECTED_DURATION = "vehicleConnectedDuration"; public static final String CHANNEL_LOADPOINT_CONNECTED_DURATION = "vehicleConnectedDuration";
public static final String CHANNEL_LOADPOINT_ENABLED = "enabled";
public static final String CHANNEL_LOADPOINT_HAS_VEHICLE = "hasVehicle"; public static final String CHANNEL_LOADPOINT_HAS_VEHICLE = "hasVehicle";
public static final String CHANNEL_LOADPOINT_ENABLED = "enabled";
public static final String CHANNEL_LOADPOINT_MAX_CURRENT = "maxCurrent"; public static final String CHANNEL_LOADPOINT_MAX_CURRENT = "maxCurrent";
public static final String CHANNEL_LOADPOINT_MIN_CURRENT = "minCurrent"; public static final String CHANNEL_LOADPOINT_MIN_CURRENT = "minCurrent";
public static final String CHANNEL_LOADPOINT_MIN_SOC = "minSoC"; public static final String CHANNEL_LOADPOINT_MIN_SOC = "minSoC";
public static final String CHANNEL_LOADPOINT_MODE = "mode"; public static final String CHANNEL_LOADPOINT_MODE = "mode";
public static final String CHANNEL_LOADPOINT_PHASES = "phases"; public static final String CHANNEL_LOADPOINT_PHASES = "phases";
public static final String CHANNEL_LOADPOINT_TARGET_ENERGY = "targetEnergy";
public static final String CHANNEL_LOADPOINT_TARGET_SOC = "targetSoC"; public static final String CHANNEL_LOADPOINT_TARGET_SOC = "targetSoC";
public static final String CHANNEL_LOADPOINT_TARGET_TIME = "targetTime"; public static final String CHANNEL_LOADPOINT_TARGET_TIME = "targetTime";
/** /**
@ -103,8 +106,6 @@ public class EvccBindingConstants {
CHANNEL_LOADPOINT_CONNECTED_DURATION); CHANNEL_LOADPOINT_CONNECTED_DURATION);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_ENABLED = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_ENABLED = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_ENABLED); CHANNEL_LOADPOINT_ENABLED);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_HAS_VEHICLE = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_HAS_VEHICLE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_MAX_CURRENT = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_MAX_CURRENT = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_MAX_CURRENT); CHANNEL_LOADPOINT_MAX_CURRENT);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_MIN_CURRENT = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_MIN_CURRENT = new ChannelTypeUID(BINDING_ID,
@ -115,6 +116,8 @@ public class EvccBindingConstants {
CHANNEL_LOADPOINT_MODE); CHANNEL_LOADPOINT_MODE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_PHASES = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_PHASES = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_PHASES); CHANNEL_LOADPOINT_PHASES);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_TARGET_ENERGY = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_TARGET_ENERGY);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_TARGET_SOC = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_TARGET_SOC = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_TARGET_SOC); CHANNEL_LOADPOINT_TARGET_SOC);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_TARGET_TIME = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_TARGET_TIME = new ChannelTypeUID(BINDING_ID,

View File

@ -34,7 +34,6 @@ import org.openhab.core.library.types.StringType;
import org.openhab.core.library.unit.MetricPrefix; import org.openhab.core.library.unit.MetricPrefix;
import org.openhab.core.library.unit.SIUnits; import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.Units; import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatus;
@ -42,7 +41,6 @@ import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingUID; import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.builder.ChannelBuilder; import org.openhab.core.thing.binding.builder.ChannelBuilder;
import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType; import org.openhab.core.types.RefreshType;
@ -67,7 +65,6 @@ public class EvccHandler extends BaseThingHandler {
private boolean gridConfigured = false; private boolean gridConfigured = false;
private boolean pvConfigured = false; private boolean pvConfigured = false;
private float targetSoC = 100;
private boolean targetTimeEnabled = false; private boolean targetTimeEnabled = false;
private ZonedDateTime targetTimeZDT = ZonedDateTime.now().plusHours(12); private ZonedDateTime targetTimeZDT = ZonedDateTime.now().plusHours(12);
@ -85,97 +82,116 @@ public class EvccHandler extends BaseThingHandler {
if (groupId == null) { if (groupId == null) {
return; return;
} }
String channelGroupId = channelUID.getGroupId();
String channelIdWithoutGroup = channelUID.getIdWithoutGroup(); String channelIdWithoutGroup = channelUID.getIdWithoutGroup();
int loadpoint = Integer.parseInt(groupId.substring(9)) + 1;
EvccAPI evccAPI = this.evccAPI; EvccAPI evccAPI = this.evccAPI;
if (evccAPI == null) { if (evccAPI == null) {
return; return;
} }
try { try {
switch (channelIdWithoutGroup) { if (channelGroupId.equals(CHANNEL_GROUP_ID_GENERAL)) {
case CHANNEL_LOADPOINT_MODE: if (!channelIdWithoutGroup.equals(CHANNEL_BATTERY_PRIORITY_SOC)) {
if (command instanceof StringType) {
evccAPI.setMode(loadpoint, command.toString());
} else {
logger.debug("Command has wrong type, StringType required!");
}
break;
case CHANNEL_LOADPOINT_MIN_SOC:
if (command instanceof QuantityType) {
evccAPI.setMinSoC(loadpoint, ((QuantityType<?>) command).toUnit(Units.PERCENT).intValue());
} else if (command instanceof DecimalType) {
evccAPI.setMinSoC(loadpoint, ((DecimalType) command).intValue());
} else {
logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
break;
case CHANNEL_LOADPOINT_TARGET_SOC:
if (command instanceof QuantityType) {
evccAPI.setTargetSoC(loadpoint,
((QuantityType<?>) command).toUnit(Units.PERCENT).intValue());
} else if (command instanceof DecimalType) {
evccAPI.setTargetSoC(loadpoint, ((DecimalType) command).intValue());
} else {
logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
break;
case CHANNEL_LOADPOINT_TARGET_TIME:
if (command instanceof DateTimeType) {
targetTimeZDT = ((DateTimeType) command).getZonedDateTime();
ChannelUID channel = new ChannelUID(getThing().getUID(), "loadpoint" + loadpoint,
CHANNEL_LOADPOINT_TARGET_TIME);
updateState(channel, new DateTimeType(targetTimeZDT));
if (targetTimeEnabled) {
try {
evccAPI.setTargetCharge(loadpoint, targetSoC, targetTimeZDT);
} catch (DateTimeParseException e) {
logger.debug("Failed to set target charge: ", e);
}
}
} else {
logger.debug("Command has wrong type, DateTimeType required!");
}
break;
case CHANNEL_LOADPOINT_TARGET_TIME_ENABLED:
if (command == OnOffType.ON) {
evccAPI.setTargetCharge(loadpoint, targetSoC, targetTimeZDT);
targetTimeEnabled = true;
} else if (command == OnOffType.OFF) {
evccAPI.unsetTargetCharge(loadpoint);
targetTimeEnabled = false;
} else {
logger.debug("Command has wrong type, OnOffType required!");
}
break;
case CHANNEL_LOADPOINT_PHASES:
if (command instanceof DecimalType) {
evccAPI.setPhases(loadpoint, ((DecimalType) command).intValue());
} else {
logger.debug("Command has wrong type, DecimalType required!");
}
break;
case CHANNEL_LOADPOINT_MIN_CURRENT:
if (command instanceof QuantityType) {
evccAPI.setMinCurrent(loadpoint,
((QuantityType<?>) command).toUnit(Units.AMPERE).intValue());
} else if (command instanceof DecimalType) {
evccAPI.setMinCurrent(loadpoint, ((DecimalType) command).intValue());
} else {
logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
break;
case CHANNEL_LOADPOINT_MAX_CURRENT:
if (command instanceof QuantityType) {
evccAPI.setMaxCurrent(loadpoint,
((QuantityType<?>) command).toUnit(Units.AMPERE).intValue());
} else if (command instanceof DecimalType) {
evccAPI.setMaxCurrent(loadpoint, ((DecimalType) command).intValue());
} else {
logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
break;
default:
return; return;
}
if (command instanceof QuantityType<?> qt) {
evccAPI.setBatteryPrioritySoC(qt.toUnit(Units.PERCENT).intValue());
} else if (command instanceof DecimalType dt) {
evccAPI.setBatteryPrioritySoC(dt.intValue());
} else {
logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
} else {
int loadpoint = Integer.parseInt(groupId.substring(9)) + 1;
switch (channelIdWithoutGroup) {
case CHANNEL_LOADPOINT_MODE -> {
if (command instanceof StringType) {
evccAPI.setMode(loadpoint, command.toString());
} else {
logger.debug("Command has wrong type, StringType required!");
}
}
case CHANNEL_LOADPOINT_MIN_SOC -> {
if (command instanceof QuantityType<?> qt) {
evccAPI.setMinSoC(loadpoint, qt.toUnit(Units.PERCENT).intValue());
} else if (command instanceof DecimalType dt) {
evccAPI.setMinSoC(loadpoint, dt.intValue());
} else {
logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
}
case CHANNEL_LOADPOINT_TARGET_ENERGY -> {
if (command instanceof QuantityType<?> qt) {
evccAPI.setTargetEnergy(loadpoint, qt.toUnit(Units.WATT_HOUR).floatValue());
} else {
logger.debug("Command has wrong type, QuantityType required!");
}
}
case CHANNEL_LOADPOINT_TARGET_SOC -> {
if (command instanceof QuantityType<?> qt) {
evccAPI.setTargetSoC(loadpoint, qt.toUnit(Units.PERCENT).intValue());
} else if (command instanceof DecimalType dt) {
evccAPI.setTargetSoC(loadpoint, dt.intValue());
} else {
logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
}
case CHANNEL_LOADPOINT_TARGET_TIME -> {
if (command instanceof DateTimeType dtt) {
targetTimeZDT = dtt.getZonedDateTime();
ChannelUID channel = new ChannelUID(getThing().getUID(), "loadpoint" + loadpoint,
CHANNEL_LOADPOINT_TARGET_TIME);
updateState(channel, new DateTimeType(targetTimeZDT));
if (targetTimeEnabled) {
try {
evccAPI.setTargetTime(loadpoint, targetTimeZDT);
} catch (DateTimeParseException e) {
logger.debug("Failed to set target charge: ", e);
}
}
} else {
logger.debug("Command has wrong type, DateTimeType required!");
}
}
case CHANNEL_LOADPOINT_TARGET_TIME_ENABLED -> {
if (command == OnOffType.ON) {
evccAPI.setTargetTime(loadpoint, targetTimeZDT);
targetTimeEnabled = true;
} else if (command == OnOffType.OFF) {
evccAPI.removeTargetTime(loadpoint);
targetTimeEnabled = false;
} else {
logger.debug("Command has wrong type, OnOffType required!");
}
}
case CHANNEL_LOADPOINT_PHASES -> {
if (command instanceof DecimalType dt) {
evccAPI.setPhases(loadpoint, dt.intValue());
} else {
logger.debug("Command has wrong type, DecimalType required!");
}
}
case CHANNEL_LOADPOINT_MIN_CURRENT -> {
if (command instanceof QuantityType<?> qt) {
evccAPI.setMinCurrent(loadpoint, qt.toUnit(Units.AMPERE).intValue());
} else if (command instanceof DecimalType dt) {
evccAPI.setMinCurrent(loadpoint, dt.intValue());
} else {
logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
}
case CHANNEL_LOADPOINT_MAX_CURRENT -> {
if (command instanceof QuantityType<?> qt) {
evccAPI.setMaxCurrent(loadpoint, qt.toUnit(Units.AMPERE).intValue());
} else if (command instanceof DecimalType dt) {
evccAPI.setMaxCurrent(loadpoint, dt.intValue());
} else {
logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
}
default -> {
return;
}
}
} }
} catch (EvccApiException e) { } catch (EvccApiException e) {
Throwable cause = e.getCause(); Throwable cause = e.getCause();
@ -256,20 +272,22 @@ public class EvccHandler extends BaseThingHandler {
// Utility functions // Utility functions
private void createChannelsGeneral() { private void createChannelsGeneral() {
final String channelGroup = "general";
if (batteryConfigured) { if (batteryConfigured) {
createChannel(CHANNEL_BATTERY_CAPACITY, channelGroup, CHANNEL_TYPE_UID_BATTERY_CAPACITY, "Number:Energy"); createChannel(CHANNEL_BATTERY_CAPACITY, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_BATTERY_CAPACITY,
createChannel(CHANNEL_BATTERY_POWER, channelGroup, CHANNEL_TYPE_UID_BATTERY_POWER, "Number:Power"); "Number:Energy");
createChannel(CHANNEL_BATTERY_SOC, channelGroup, CHANNEL_TYPE_UID_BATTERY_SOC, "Number:Dimensionless"); createChannel(CHANNEL_BATTERY_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_BATTERY_POWER,
createChannel(CHANNEL_BATTERY_PRIORITY_SOC, channelGroup, CHANNEL_TYPE_UID_BATTERY_PRIORITY_SOC, "Number:Power");
createChannel(CHANNEL_BATTERY_SOC, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_BATTERY_SOC,
"Number:Dimensionless");
createChannel(CHANNEL_BATTERY_PRIORITY_SOC, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_BATTERY_PRIORITY_SOC,
"Number:Dimensionless"); "Number:Dimensionless");
} }
if (gridConfigured) { if (gridConfigured) {
createChannel(CHANNEL_GRID_POWER, channelGroup, CHANNEL_TYPE_UID_GRID_POWER, "Number:Power"); createChannel(CHANNEL_GRID_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_GRID_POWER, "Number:Power");
} }
createChannel(CHANNEL_HOME_POWER, channelGroup, CHANNEL_TYPE_UID_HOME_POWER, "Number:Power"); createChannel(CHANNEL_HOME_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_HOME_POWER, "Number:Power");
if (pvConfigured) { if (pvConfigured) {
createChannel(CHANNEL_PV_POWER, channelGroup, CHANNEL_TYPE_UID_PV_POWER, "Number:Power"); createChannel(CHANNEL_PV_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_PV_POWER, "Number:Power");
} }
} }
@ -297,8 +315,6 @@ public class EvccHandler extends BaseThingHandler {
"Number:Time"); "Number:Time");
createChannel(CHANNEL_LOADPOINT_ENABLED, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_ENABLED, createChannel(CHANNEL_LOADPOINT_ENABLED, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_ENABLED,
CoreItemFactory.SWITCH); CoreItemFactory.SWITCH);
createChannel(CHANNEL_LOADPOINT_HAS_VEHICLE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_HAS_VEHICLE,
CoreItemFactory.SWITCH);
createChannel(CHANNEL_LOADPOINT_MAX_CURRENT, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_MAX_CURRENT, createChannel(CHANNEL_LOADPOINT_MAX_CURRENT, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_MAX_CURRENT,
"Number:ElectricCurrent"); "Number:ElectricCurrent");
createChannel(CHANNEL_LOADPOINT_MIN_CURRENT, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_MIN_CURRENT, createChannel(CHANNEL_LOADPOINT_MIN_CURRENT, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_MIN_CURRENT,
@ -308,6 +324,8 @@ public class EvccHandler extends BaseThingHandler {
createChannel(CHANNEL_LOADPOINT_MODE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_MODE, CoreItemFactory.STRING); createChannel(CHANNEL_LOADPOINT_MODE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_MODE, CoreItemFactory.STRING);
createChannel(CHANNEL_LOADPOINT_PHASES, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_PHASES, createChannel(CHANNEL_LOADPOINT_PHASES, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_PHASES,
CoreItemFactory.NUMBER); CoreItemFactory.NUMBER);
createChannel(CHANNEL_LOADPOINT_TARGET_ENERGY, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TARGET_ENERGY,
"Number:Energy");
createChannel(CHANNEL_LOADPOINT_TARGET_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TARGET_SOC, createChannel(CHANNEL_LOADPOINT_TARGET_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TARGET_SOC,
"Number:Dimensionless"); "Number:Dimensionless");
createChannel(CHANNEL_LOADPOINT_TARGET_TIME, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TARGET_TIME, createChannel(CHANNEL_LOADPOINT_TARGET_TIME, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TARGET_TIME,
@ -327,6 +345,8 @@ public class EvccHandler extends BaseThingHandler {
"Number:Dimensionless"); "Number:Dimensionless");
createChannel(CHANNEL_LOADPOINT_VEHICLE_TITLE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_TITLE, createChannel(CHANNEL_LOADPOINT_VEHICLE_TITLE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_TITLE,
CoreItemFactory.STRING); CoreItemFactory.STRING);
removeChannel(CHANNEL_LOADPOINT_HAS_VEHICLE, channelGroup);
} }
// Units and description for vars: https://docs.evcc.io/docs/reference/configuration/messaging/#msg // Units and description for vars: https://docs.evcc.io/docs/reference/configuration/messaging/#msg
@ -340,34 +360,34 @@ public class EvccHandler extends BaseThingHandler {
boolean batteryConfigured = this.batteryConfigured; boolean batteryConfigured = this.batteryConfigured;
if (batteryConfigured) { if (batteryConfigured) {
float batteryCapacity = result.getBatteryCapacity(); float batteryCapacity = result.getBatteryCapacity();
channel = new ChannelUID(uid, "general", CHANNEL_BATTERY_CAPACITY); channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_BATTERY_CAPACITY);
updateState(channel, new QuantityType<>(batteryCapacity, Units.KILOWATT_HOUR)); updateState(channel, new QuantityType<>(batteryCapacity, Units.KILOWATT_HOUR));
float batteryPower = result.getBatteryPower(); float batteryPower = result.getBatteryPower();
channel = new ChannelUID(uid, "general", CHANNEL_BATTERY_POWER); channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_BATTERY_POWER);
updateState(channel, new QuantityType<>(batteryPower, Units.WATT)); updateState(channel, new QuantityType<>(batteryPower, Units.WATT));
float batterySoC = result.getBatterySoC(); float batterySoC = result.getBatterySoC();
channel = new ChannelUID(uid, "general", CHANNEL_BATTERY_SOC); channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_BATTERY_SOC);
updateState(channel, new QuantityType<>(batterySoC, Units.PERCENT)); updateState(channel, new QuantityType<>(batterySoC, Units.PERCENT));
float batteryPrioritySoC = result.getBatteryPrioritySoC(); float batteryPrioritySoC = result.getBatteryPrioritySoC();
channel = new ChannelUID(uid, "general", CHANNEL_BATTERY_PRIORITY_SOC); channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_BATTERY_PRIORITY_SOC);
updateState(channel, new QuantityType<>(batteryPrioritySoC, Units.PERCENT)); updateState(channel, new QuantityType<>(batteryPrioritySoC, Units.PERCENT));
} }
boolean gridConfigured = this.gridConfigured; boolean gridConfigured = this.gridConfigured;
if (gridConfigured) { if (gridConfigured) {
float gridPower = result.getGridPower(); float gridPower = result.getGridPower();
channel = new ChannelUID(uid, "general", CHANNEL_GRID_POWER); channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_GRID_POWER);
updateState(channel, new QuantityType<>(gridPower, Units.WATT)); updateState(channel, new QuantityType<>(gridPower, Units.WATT));
} }
float homePower = result.getHomePower(); float homePower = result.getHomePower();
channel = new ChannelUID(uid, "general", CHANNEL_HOME_POWER); channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_HOME_POWER);
updateState(channel, new QuantityType<>(homePower, Units.WATT)); updateState(channel, new QuantityType<>(homePower, Units.WATT));
boolean pvConfigured = this.pvConfigured; boolean pvConfigured = this.pvConfigured;
if (pvConfigured) { if (pvConfigured) {
float pvPower = result.getPvPower(); float pvPower = result.getPvPower();
channel = new ChannelUID(uid, "general", CHANNEL_PV_POWER); channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_PV_POWER);
updateState(channel, new QuantityType<>(pvPower, Units.WATT)); updateState(channel, new QuantityType<>(pvPower, Units.WATT));
} }
} }
@ -426,10 +446,6 @@ public class EvccHandler extends BaseThingHandler {
channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_ENABLED); channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_ENABLED);
updateState(channel, OnOffType.from(enabled)); updateState(channel, OnOffType.from(enabled));
boolean hasVehicle = loadpoint.getHasVehicle();
channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_HAS_VEHICLE);
updateState(channel, OnOffType.from(hasVehicle));
float maxCurrent = loadpoint.getMaxCurrent(); float maxCurrent = loadpoint.getMaxCurrent();
channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_MAX_CURRENT); channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_MAX_CURRENT);
updateState(channel, new QuantityType<>(maxCurrent, Units.AMPERE)); updateState(channel, new QuantityType<>(maxCurrent, Units.AMPERE));
@ -450,12 +466,16 @@ public class EvccHandler extends BaseThingHandler {
channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_PHASES); channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_PHASES);
updateState(channel, new DecimalType(phases)); updateState(channel, new DecimalType(phases));
targetSoC = loadpoint.getTargetSoC(); float targetEnergy = loadpoint.getTargetEnergy();
channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_TARGET_ENERGY);
updateState(channel, new QuantityType<>(targetEnergy, Units.WATT_HOUR));
float targetSoC = loadpoint.getTargetSoC();
channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_TARGET_SOC); channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_TARGET_SOC);
updateState(channel, new QuantityType<>(targetSoC, Units.PERCENT)); updateState(channel, new QuantityType<>(targetSoC, Units.PERCENT));
String targetTime = loadpoint.getTargetTime(); String targetTime = loadpoint.getTargetTime();
if (targetTime == null) { if (targetTime == null || targetTime.equals("0001-01-01T00:00:00Z")) {
channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_TARGET_TIME_ENABLED); channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_TARGET_TIME_ENABLED);
updateState(channel, OnOffType.OFF); updateState(channel, OnOffType.OFF);
targetTimeEnabled = false; targetTimeEnabled = false;
@ -498,14 +518,17 @@ public class EvccHandler extends BaseThingHandler {
} }
private void createChannel(String channel, String channelGroupId, ChannelTypeUID channelTypeUID, String itemType) { private void createChannel(String channel, String channelGroupId, ChannelTypeUID channelTypeUID, String itemType) {
ChannelUID channelToCheck = new ChannelUID(thing.getUID(), channelGroupId, channel); ChannelUID channelUid = new ChannelUID(thing.getUID(), channelGroupId, channel);
if (thing.getChannel(channelToCheck) == null) { if (thing.getChannel(channelUid) == null) {
ThingBuilder thingBuilder = editThing(); updateThing(editThing()
Channel testchannel = ChannelBuilder .withChannel(ChannelBuilder.create(channelUid, itemType).withType(channelTypeUID).build()).build());
.create(new ChannelUID(getThing().getUID(), channelGroupId, channel), itemType) }
.withType(channelTypeUID).build(); }
thingBuilder.withChannel(testchannel);
updateThing(thingBuilder.build()); private void removeChannel(String channel, String channelGroupId) {
ChannelUID channelUid = new ChannelUID(thing.getUID(), channelGroupId, channel);
if (thing.getChannel(channelUid) != null) {
updateThing(editThing().withoutChannel(channelUid).build());
} }
} }
} }

View File

@ -31,6 +31,7 @@ import com.google.gson.JsonSyntaxException;
/** /**
* The {@link EvccAPI} is responsible for API calls to evcc. * The {@link EvccAPI} is responsible for API calls to evcc.
* API requests were written for evcc version 0.117.0
* *
* @author Florian Hotze - Initial contribution * @author Florian Hotze - Initial contribution
*/ */
@ -84,6 +85,11 @@ public class EvccAPI {
} }
} }
// Site API calls.
public String setBatteryPrioritySoC(int prioritySoc) throws EvccApiException {
return httpRequest(this.host + EVCC_REST_API + "prioritysoc/" + prioritySoc, "POST");
}
// Loadpoint specific API calls. // Loadpoint specific API calls.
public String setMode(int loadpoint, String mode) throws EvccApiException { public String setMode(int loadpoint, String mode) throws EvccApiException {
return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/mode/" + mode, "POST"); return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/mode/" + mode, "POST");
@ -93,8 +99,13 @@ public class EvccAPI {
return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/minsoc/" + minSoC, "POST"); return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/minsoc/" + minSoC, "POST");
} }
public String setTargetEnergy(int loadpoint, float targetEnergy) throws EvccApiException {
return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/target/energy/" + targetEnergy,
"POST");
}
public String setTargetSoC(int loadpoint, int targetSoC) throws EvccApiException { public String setTargetSoC(int loadpoint, int targetSoC) throws EvccApiException {
return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/targetsoc/" + targetSoC, "POST"); return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/target/soc/" + targetSoC, "POST");
} }
public String setPhases(int loadpoint, int phases) throws EvccApiException { public String setPhases(int loadpoint, int phases) throws EvccApiException {
@ -109,13 +120,12 @@ public class EvccAPI {
return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/maxcurrent/" + maxCurrent, "POST"); return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/maxcurrent/" + maxCurrent, "POST");
} }
public String setTargetCharge(int loadpoint, float targetSoC, ZonedDateTime targetTime) throws EvccApiException { public String setTargetTime(int loadpoint, ZonedDateTime targetTime) throws EvccApiException {
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/target/time/"
return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/targetcharge/" + targetSoC + "/" + targetTime.toLocalDateTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + "Z", "POST");
+ targetTime.toLocalDateTime().format(formatter), "POST");
} }
public String unsetTargetCharge(int loadpoint) throws EvccApiException { public String removeTargetTime(int loadpoint) throws EvccApiException {
return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/targetcharge", "DELETE"); return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/target/time", "DELETE");
} }
} }

View File

@ -16,7 +16,7 @@ import com.google.gson.annotations.SerializedName;
/** /**
* This class represents a loadpoint object of the status response (/api/state). * This class represents a loadpoint object of the status response (/api/state).
* This DTO was written for evcc version 0.111.1 * This DTO was written for evcc version 0.117.0
* *
* @author Florian Hotze - Initial contribution * @author Florian Hotze - Initial contribution
*/ */
@ -57,12 +57,6 @@ public class Loadpoint {
@SerializedName("enabled") @SerializedName("enabled")
private boolean enabled; private boolean enabled;
@SerializedName("hasVehicle")
private boolean hasVehicle;
@SerializedName("loadpoint")
private int loadpoint;
@SerializedName("maxCurrent") @SerializedName("maxCurrent")
private float maxCurrent; private float maxCurrent;
@ -75,14 +69,14 @@ public class Loadpoint {
@SerializedName("mode") @SerializedName("mode")
private String mode; private String mode;
@SerializedName("phases") @SerializedName("phasesEnabled")
private int phases; private int phases;
@SerializedName("pvAction") @SerializedName("planActive")
private String pvAction; private boolean planActive;
@SerializedName("pvRemaining") @SerializedName("targetEnergy")
private long pvRemaining; private float targetEnergy;
@SerializedName("targetSoc") @SerializedName("targetSoc")
private float targetSoC; private float targetSoC;
@ -188,20 +182,6 @@ public class Loadpoint {
return enabled; return enabled;
} }
/**
* @return whether vehicle is configured for loadpoint
*/
public boolean getHasVehicle() {
return hasVehicle;
}
/**
* @return loadpoint id
*/
public int getLoadpoint() {
return loadpoint;
}
/** /**
* @return maximum current * @return maximum current
*/ */
@ -238,17 +218,17 @@ public class Loadpoint {
} }
/** /**
* @return the pv action * @return whether charging plan is active
*/ */
public String getPvAction() { public boolean getPlanActive() {
return pvAction; return planActive;
} }
/** /**
* @return the pv remaining * @return target energy
*/ */
public long getPvRemaining() { public float getTargetEnergy() {
return pvRemaining; return targetEnergy;
} }
/** /**

View File

@ -16,7 +16,7 @@ import com.google.gson.annotations.SerializedName;
/** /**
* This class represents the result object of the status response (/api/state). * This class represents the result object of the status response (/api/state).
* This DTO was written for evcc version 0.111.1 * This DTO was written for evcc version 0.117.0
* *
* @author Florian Hotze - Initial contribution * @author Florian Hotze - Initial contribution
*/ */

View File

@ -16,7 +16,7 @@ import com.google.gson.annotations.SerializedName;
/** /**
* This class represents the status response (/api/state). * This class represents the status response (/api/state).
* This DTO was written for evcc version 0.111.1 * This DTO was written for evcc version 0.117.0
* *
* @author Florian Hotze - Initial contribution * @author Florian Hotze - Initial contribution
*/ */

View File

@ -17,12 +17,12 @@ thing-type.config.evcc.device.url.description = URL of evcc web UI, e.g. https:/
# channel group types # channel group types
channel-group-type.evcc.general.label = General data channel-group-type.evcc.general.label = General Data
channel-group-type.evcc.loadpoint.label = Loadpoint channel-group-type.evcc.loadpoint.label = Loadpoint
# channel types # channel types
channel-type.evcc.activePhases.label = Charging active phases channel-type.evcc.activePhases.label = Charging Active Phases
channel-type.evcc.activePhases.description = Current number of active phases while charging channel-type.evcc.activePhases.description = Current number of active phases while charging
channel-type.evcc.batteryCapacity.label = Battery Capacity channel-type.evcc.batteryCapacity.label = Battery Capacity
channel-type.evcc.batteryCapacity.description = Capacity of (home) battery channel-type.evcc.batteryCapacity.description = Capacity of (home) battery
@ -32,79 +32,77 @@ channel-type.evcc.batteryPrioritySoC.label = Battery Priority SoC
channel-type.evcc.batteryPrioritySoC.description = State of Charge for which the battery has priority over charging the ev when charging mode is "pv". channel-type.evcc.batteryPrioritySoC.description = State of Charge for which the battery has priority over charging the ev when charging mode is "pv".
channel-type.evcc.batterySoC.label = Battery SoC channel-type.evcc.batterySoC.label = Battery SoC
channel-type.evcc.batterySoC.description = Current State of Charge of battery channel-type.evcc.batterySoC.description = Current State of Charge of battery
channel-type.evcc.chargeCurrent.label = Charging current channel-type.evcc.chargeCurrent.label = Charging Current
channel-type.evcc.chargeCurrent.description = Current amperage per connected phase while charging channel-type.evcc.chargeCurrent.description = Current amperage per connected phase while charging
channel-type.evcc.chargeDuration.label = Charging duration channel-type.evcc.chargeDuration.label = Charging Duration
channel-type.evcc.chargeDuration.description = Charging duration channel-type.evcc.chargeDuration.description = Charging duration
channel-type.evcc.chargePower.label = Charging power channel-type.evcc.chargePower.label = Charging Power
channel-type.evcc.chargePower.description = Current power of charging channel-type.evcc.chargePower.description = Current power of charging
channel-type.evcc.chargeRemainingDuration.label = Charging remaining duration channel-type.evcc.chargeRemainingDuration.label = Charging Remaining Duration
channel-type.evcc.chargeRemainingDuration.description = Remaining duration until target SoC is reached channel-type.evcc.chargeRemainingDuration.description = Remaining duration until target SoC is reached
channel-type.evcc.chargeRemainingEnergy.label = Charging remaining energy channel-type.evcc.chargeRemainingEnergy.label = Charging Remaining Energy
channel-type.evcc.chargeRemainingEnergy.description = Remaining energy until target SoC is reached channel-type.evcc.chargeRemainingEnergy.description = Remaining energy until target SoC is reached
channel-type.evcc.chargedEnergy.label = Charged energy channel-type.evcc.chargedEnergy.label = Charged Energy
channel-type.evcc.chargedEnergy.description = Energy charged since plugged-in channel-type.evcc.chargedEnergy.description = Energy charged since plugged-in
channel-type.evcc.charging.label = Charging state channel-type.evcc.charging.label = Charging State
channel-type.evcc.charging.description = Loadpoint is currently charging channel-type.evcc.charging.description = Loadpoint is currently charging
channel-type.evcc.charging.state.option.ON = Charging channel-type.evcc.charging.state.option.ON = Charging
channel-type.evcc.charging.state.option.OFF = Not charging channel-type.evcc.charging.state.option.OFF = Not charging
channel-type.evcc.enabled.label = Charging enabled channel-type.evcc.enabled.label = Charging Enabled
channel-type.evcc.enabled.description = Charging enabled (mode not "off") channel-type.evcc.enabled.description = Charging enabled (mode not "off")
channel-type.evcc.enabled.state.option.ON = Enabled channel-type.evcc.enabled.state.option.ON = Enabled
channel-type.evcc.enabled.state.option.OFF = Disabled channel-type.evcc.enabled.state.option.OFF = Disabled
channel-type.evcc.gridPower.label = Grid Power channel-type.evcc.gridPower.label = Grid Power
channel-type.evcc.gridPower.description = Current power from grid (negative means feed-in) channel-type.evcc.gridPower.description = Current power from grid (negative means feed-in)
channel-type.evcc.hasVehicle.label = Loadpoint has vehicle configuration
channel-type.evcc.hasVehicle.description = Whether vehicle is configured for loadpoint
channel-type.evcc.hasVehicle.state.option.ON = Configured
channel-type.evcc.hasVehicle.state.option.OFF = Not configured
channel-type.evcc.homePower.label = Home Power channel-type.evcc.homePower.label = Home Power
channel-type.evcc.homePower.description = Current power taken by home channel-type.evcc.homePower.description = Current power taken by home
channel-type.evcc.maxCurrent.label = Charging max current channel-type.evcc.maxCurrent.label = Charging max Current
channel-type.evcc.maxCurrent.description = Maximum amperage per connected phase with which the car should be charged channel-type.evcc.maxCurrent.description = Maximum amperage per connected phase with which the car should be charged
channel-type.evcc.minCurrent.label = Charging min current channel-type.evcc.minCurrent.label = Charging min Current
channel-type.evcc.minCurrent.description = Minimum amperage per connected phase with which the car should be charged channel-type.evcc.minCurrent.description = Minimum amperage per connected phase with which the car should be charged
channel-type.evcc.minSoC.label = Charging min SoC channel-type.evcc.minSoC.label = Charging min SoC
channel-type.evcc.minSoC.description = Charge immediately with maximum power up to the defined SoC, if the charge mode is not set to "off" channel-type.evcc.minSoC.description = Charge immediately with maximum power up to the defined SoC, if the charge mode is not set to "off"
channel-type.evcc.mode.label = Charging mode channel-type.evcc.mode.label = Charging Mode
channel-type.evcc.mode.description = Charging mode: "off", "now", "minpv", "pv" channel-type.evcc.mode.description = Charging mode: "off", "now", "minpv", "pv"
channel-type.evcc.mode.state.option.off = Off channel-type.evcc.mode.state.option.off = Off
channel-type.evcc.mode.state.option.now = Now channel-type.evcc.mode.state.option.now = Fast
channel-type.evcc.mode.state.option.minpv = Min + PV channel-type.evcc.mode.state.option.minpv = Min + PV
channel-type.evcc.mode.state.option.pv = Only PV channel-type.evcc.mode.state.option.pv = Only PV
channel-type.evcc.phases.label = Charging enabled phases channel-type.evcc.phases.label = Charging Enabled Phases
channel-type.evcc.phases.description = The maximum number of phases which can be used channel-type.evcc.phases.description = The maximum number of phases which can be used
channel-type.evcc.pvPower.label = PV Power channel-type.evcc.pvPower.label = PV Power
channel-type.evcc.pvPower.description = Current power from photovoltaik channel-type.evcc.pvPower.description = Current power from photovoltaik
channel-type.evcc.targetSoC.label = Charging target SoC channel-type.evcc.targetEnergy.label = Charging Target Energy
channel-type.evcc.targetEnergy.description = Amount of energy to charge the vehicle with
channel-type.evcc.targetSoC.label = Charging Target SoC
channel-type.evcc.targetSoC.description = Until which state of charge (SoC) should the vehicle be charged channel-type.evcc.targetSoC.description = Until which state of charge (SoC) should the vehicle be charged
channel-type.evcc.targetTime.label = Charging target time channel-type.evcc.targetTime.label = Charging Target Time
channel-type.evcc.targetTime.description = When the target SoC should be reached channel-type.evcc.targetTime.description = When the target SoC should be reached
channel-type.evcc.targetTimeEnabled.label = Charging target time enabled channel-type.evcc.targetTimeEnabled.label = Charging Target Time Enabled
channel-type.evcc.targetTimeEnabled.description = Target time for charging enabled channel-type.evcc.targetTimeEnabled.description = Target time for charging enabled
channel-type.evcc.targetTimeEnabled.state.option.ON = Enabled channel-type.evcc.targetTimeEnabled.state.option.ON = Enabled
channel-type.evcc.targetTimeEnabled.state.option.OFF = Disabled channel-type.evcc.targetTimeEnabled.state.option.OFF = Disabled
channel-type.evcc.title.label = Loadpoint title channel-type.evcc.title.label = Loadpoint Title
channel-type.evcc.title.description = Title of loadpoint channel-type.evcc.title.description = Title of loadpoint
channel-type.evcc.vehicleCapacity.label = Vehicle capacity channel-type.evcc.vehicleCapacity.label = Vehicle Capacity
channel-type.evcc.vehicleCapacity.description = Capacity of EV battery channel-type.evcc.vehicleCapacity.description = Capacity of EV battery
channel-type.evcc.vehicleConnected.label = Vehicle connected channel-type.evcc.vehicleConnected.label = Vehicle Connected
channel-type.evcc.vehicleConnected.description = Whether vehicle is connected to loadpoint channel-type.evcc.vehicleConnected.description = Whether vehicle is connected to loadpoint
channel-type.evcc.vehicleConnected.state.option.ON = Connected channel-type.evcc.vehicleConnected.state.option.ON = Connected
channel-type.evcc.vehicleConnected.state.option.OFF = Not connected channel-type.evcc.vehicleConnected.state.option.OFF = Not connected
channel-type.evcc.vehicleConnectedDuration.label = Vehicle connected duration channel-type.evcc.vehicleConnectedDuration.label = Vehicle Connected Duration
channel-type.evcc.vehicleConnectedDuration.description = Duration the vehicle is connected to loadpoint channel-type.evcc.vehicleConnectedDuration.description = Duration the vehicle is connected to loadpoint
channel-type.evcc.vehicleOdometer.label = Vehicle odometer channel-type.evcc.vehicleOdometer.label = Vehicle Odometer
channel-type.evcc.vehicleOdometer.description = Total distance travelled by EV channel-type.evcc.vehicleOdometer.description = Total distance travelled by EV
channel-type.evcc.vehiclePresent.label = Vehicle data access channel-type.evcc.vehiclePresent.label = Vehicle Data Access
channel-type.evcc.vehiclePresent.description = Whether evcc is able to get data from vehicle channel-type.evcc.vehiclePresent.description = Whether evcc is able to get data from vehicle
channel-type.evcc.vehiclePresent.state.option.ON = Data access channel-type.evcc.vehiclePresent.state.option.ON = Data access
channel-type.evcc.vehiclePresent.state.option.OFF = No data access channel-type.evcc.vehiclePresent.state.option.OFF = No data access
channel-type.evcc.vehicleRange.label = Vehicle range channel-type.evcc.vehicleRange.label = Vehicle Range
channel-type.evcc.vehicleRange.description = Battery range for EV channel-type.evcc.vehicleRange.description = Battery range for EV
channel-type.evcc.vehicleSoC.label = Vehicle SoC channel-type.evcc.vehicleSoC.label = Vehicle SoC
channel-type.evcc.vehicleSoC.description = Current State of Charge of EV channel-type.evcc.vehicleSoC.description = Current State of Charge of EV
channel-type.evcc.vehicleTitle.label = Vehicle title channel-type.evcc.vehicleTitle.label = Vehicle Title
channel-type.evcc.vehicleTitle.description = Name of EV channel-type.evcc.vehicleTitle.description = Name of EV
# thing status description # thing status description

View File

@ -39,7 +39,7 @@
</thing-type> </thing-type>
<channel-group-type id="general"> <channel-group-type id="general">
<label>General data</label> <label>General Data</label>
</channel-group-type> </channel-group-type>
<channel-group-type id="loadpoint"> <channel-group-type id="loadpoint">
<label>Loadpoint</label> <label>Loadpoint</label>
@ -64,15 +64,15 @@
<item-type>Number:Dimensionless</item-type> <item-type>Number:Dimensionless</item-type>
<label>Battery SoC</label> <label>Battery SoC</label>
<description>Current State of Charge of battery</description> <description>Current State of Charge of battery</description>
<category>batterylevel</category> <category>BatteryLevel</category>
<state pattern="%.0f %unit%" readOnly="true"/> <state pattern="%.0f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="batteryPrioritySoC"> <channel-type id="batteryPrioritySoC">
<item-type>Number:Dimensionless</item-type> <item-type>Number:Dimensionless</item-type>
<label>Battery Priority SoC</label> <label>Battery Priority SoC</label>
<description>State of Charge for which the battery has priority over charging the ev when charging mode is "pv".</description> <description>State of Charge for which the battery has priority over charging the ev when charging mode is "pv".</description>
<category>batterylevel</category> <category>BatteryLevel</category>
<state pattern="%.0f %unit%" readOnly="true"/> <state min="0" step="0.1" max="100" pattern="%.0f %unit%" readOnly="false"/>
</channel-type> </channel-type>
<channel-type id="gridPower"> <channel-type id="gridPower">
<item-type>Number:Power</item-type> <item-type>Number:Power</item-type>
@ -99,56 +99,56 @@
<!-- Channels for loadpoints --> <!-- Channels for loadpoints -->
<channel-type id="activePhases"> <channel-type id="activePhases">
<item-type>Number</item-type> <item-type>Number</item-type>
<label>Charging active phases</label> <label>Charging Active Phases</label>
<description>Current number of active phases while charging</description> <description>Current number of active phases while charging</description>
<category></category> <category></category>
<state pattern="%d" readOnly="true"/> <state pattern="%d" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="chargeCurrent"> <channel-type id="chargeCurrent">
<item-type>Number:ElectricCurrent</item-type> <item-type>Number:ElectricCurrent</item-type>
<label>Charging current</label> <label>Charging Current</label>
<description>Current amperage per connected phase while charging</description> <description>Current amperage per connected phase while charging</description>
<category>Energy</category> <category>Energy</category>
<state pattern="%.1f %unit%" readOnly="true"/> <state pattern="%.1f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="chargeDuration"> <channel-type id="chargeDuration">
<item-type>Number:Time</item-type> <item-type>Number:Time</item-type>
<label>Charging duration</label> <label>Charging Duration</label>
<description>Charging duration</description> <description>Charging duration</description>
<category>Time</category> <category>Time</category>
<state pattern="%.1f min" readOnly="true"/> <state pattern="%.1f min" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="chargePower"> <channel-type id="chargePower">
<item-type>Number:Power</item-type> <item-type>Number:Power</item-type>
<label>Charging power</label> <label>Charging Power</label>
<description>Current power of charging</description> <description>Current power of charging</description>
<category>Energy</category> <category>Energy</category>
<state pattern="%.1f %unit%" readOnly="true"/> <state pattern="%.1f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="chargeRemainingDuration"> <channel-type id="chargeRemainingDuration">
<item-type>Number:Time</item-type> <item-type>Number:Time</item-type>
<label>Charging remaining duration</label> <label>Charging Remaining Duration</label>
<description>Remaining duration until target SoC is reached</description> <description>Remaining duration until target SoC is reached</description>
<category>Time</category> <category>Time</category>
<state pattern="%.1f min" readOnly="true"/> <state pattern="%.1f min" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="chargeRemainingEnergy"> <channel-type id="chargeRemainingEnergy">
<item-type>Number:Energy</item-type> <item-type>Number:Energy</item-type>
<label>Charging remaining energy</label> <label>Charging Remaining Energy</label>
<description>Remaining energy until target SoC is reached</description> <description>Remaining energy until target SoC is reached</description>
<category>Energy</category> <category>Energy</category>
<state pattern="%.1f %unit%" readOnly="true"/> <state pattern="%.1f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="chargedEnergy"> <channel-type id="chargedEnergy">
<item-type>Number:Energy</item-type> <item-type>Number:Energy</item-type>
<label>Charged energy</label> <label>Charged Energy</label>
<description>Energy charged since plugged-in</description> <description>Energy charged since plugged-in</description>
<category>Energy</category> <category>Energy</category>
<state pattern="%.1f %unit%" readOnly="true"/> <state pattern="%.1f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="charging"> <channel-type id="charging">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Charging state</label> <label>Charging State</label>
<description>Loadpoint is currently charging</description> <description>Loadpoint is currently charging</description>
<category>Energy</category> <category>Energy</category>
<state pattern="%f %unit%" readOnly="true"> <state pattern="%f %unit%" readOnly="true">
@ -160,7 +160,7 @@
</channel-type> </channel-type>
<channel-type id="enabled"> <channel-type id="enabled">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Charging enabled</label> <label>Charging Enabled</label>
<description>Charging enabled (mode not "off")</description> <description>Charging enabled (mode not "off")</description>
<category>Switch</category> <category>Switch</category>
<state readOnly="true"> <state readOnly="true">
@ -170,21 +170,9 @@
</options> </options>
</state> </state>
</channel-type> </channel-type>
<channel-type id="hasVehicle">
<item-type>Switch</item-type>
<label>Loadpoint has vehicle configuration</label>
<description>Whether vehicle is configured for loadpoint</description>
<category>Switch</category>
<state readOnly="true">
<options>
<option value="ON">Configured</option>
<option value="OFF">Not configured</option>
</options>
</state>
</channel-type>
<channel-type id="maxCurrent"> <channel-type id="maxCurrent">
<item-type>Number:ElectricCurrent</item-type> <item-type>Number:ElectricCurrent</item-type>
<label>Charging max current</label> <label>Charging max Current</label>
<description>Maximum amperage per connected phase with which the car should be charged</description> <description>Maximum amperage per connected phase with which the car should be charged</description>
<category>Energy</category> <category>Energy</category>
<state min="0" step="1" pattern="%.0f %unit%" readOnly="false"/> <state min="0" step="1" pattern="%.0f %unit%" readOnly="false"/>
@ -192,7 +180,7 @@
</channel-type> </channel-type>
<channel-type id="minCurrent"> <channel-type id="minCurrent">
<item-type>Number:ElectricCurrent</item-type> <item-type>Number:ElectricCurrent</item-type>
<label>Charging min current</label> <label>Charging min Current</label>
<description>Minimum amperage per connected phase with which the car should be charged</description> <description>Minimum amperage per connected phase with which the car should be charged</description>
<category>Energy</category> <category>Energy</category>
<state min="0" step="1" pattern="%.0f %unit%" readOnly="false"/> <state min="0" step="1" pattern="%.0f %unit%" readOnly="false"/>
@ -202,19 +190,19 @@
<item-type>Number:Dimensionless</item-type> <item-type>Number:Dimensionless</item-type>
<label>Charging min SoC</label> <label>Charging min SoC</label>
<description>Charge immediately with maximum power up to the defined SoC, if the charge mode is not set to "off"</description> <description>Charge immediately with maximum power up to the defined SoC, if the charge mode is not set to "off"</description>
<category>Batterylevel</category> <category>BatteryLevel</category>
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/> <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
<channel-type id="mode"> <channel-type id="mode">
<item-type>String</item-type> <item-type>String</item-type>
<label>Charging mode</label> <label>Charging Mode</label>
<description>Charging mode: "off", "now", "minpv", "pv"</description> <description>Charging mode: "off", "now", "minpv", "pv"</description>
<category>String</category> <category>String</category>
<state readOnly="false"> <state readOnly="false">
<options> <options>
<option value="off">Off</option> <option value="off">Off</option>
<option value="now">Now</option> <option value="now">Fast</option>
<option value="minpv">Min + PV</option> <option value="minpv">Min + PV</option>
<option value="pv">Only PV</option> <option value="pv">Only PV</option>
</options> </options>
@ -223,23 +211,31 @@
</channel-type> </channel-type>
<channel-type id="phases"> <channel-type id="phases">
<item-type>Number</item-type> <item-type>Number</item-type>
<label>Charging enabled phases</label> <label>Charging Enabled Phases</label>
<description>The maximum number of phases which can be used</description> <description>The maximum number of phases which can be used</description>
<category>Energy</category> <category>Energy</category>
<state min="0" step="1" max="3" pattern="%d" readOnly="false"/> <state min="0" step="1" max="3" pattern="%d" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
<channel-type id="targetEnergy">
<item-type>Number:Energy</item-type>
<label>Charging Target Energy</label>
<description>Amount of energy to charge the vehicle with</description>
<category>BatteryLevel</category>
<state min="0" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>
<channel-type id="targetSoC"> <channel-type id="targetSoC">
<item-type>Number:Dimensionless</item-type> <item-type>Number:Dimensionless</item-type>
<label>Charging target SoC</label> <label>Charging Target SoC</label>
<description>Until which state of charge (SoC) should the vehicle be charged</description> <description>Until which state of charge (SoC) should the vehicle be charged</description>
<category>Batterylevel</category> <category>BatteryLevel</category>
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/> <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
<channel-type id="targetTime"> <channel-type id="targetTime">
<item-type>DateTime</item-type> <item-type>DateTime</item-type>
<label>Charging target time</label> <label>Charging Target Time</label>
<description>When the target SoC should be reached</description> <description>When the target SoC should be reached</description>
<category>Time</category> <category>Time</category>
<state readOnly="false"/> <state readOnly="false"/>
@ -247,7 +243,7 @@
</channel-type> </channel-type>
<channel-type id="targetTimeEnabled"> <channel-type id="targetTimeEnabled">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Charging target time enabled</label> <label>Charging Target Time Enabled</label>
<description>Target time for charging enabled</description> <description>Target time for charging enabled</description>
<category>Switch</category> <category>Switch</category>
<state readOnly="false"> <state readOnly="false">
@ -260,14 +256,14 @@
</channel-type> </channel-type>
<channel-type id="title"> <channel-type id="title">
<item-type>String</item-type> <item-type>String</item-type>
<label>Loadpoint title</label> <label>Loadpoint Title</label>
<description>Title of loadpoint</description> <description>Title of loadpoint</description>
<category>Text</category> <category>Text</category>
<state readOnly="true"/> <state readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="vehicleConnected"> <channel-type id="vehicleConnected">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Vehicle connected</label> <label>Vehicle Connected</label>
<description>Whether vehicle is connected to loadpoint</description> <description>Whether vehicle is connected to loadpoint</description>
<category>Switch</category> <category>Switch</category>
<state readOnly="true"> <state readOnly="true">
@ -279,28 +275,28 @@
</channel-type> </channel-type>
<channel-type id="vehicleConnectedDuration"> <channel-type id="vehicleConnectedDuration">
<item-type>Number:Time</item-type> <item-type>Number:Time</item-type>
<label>Vehicle connected duration</label> <label>Vehicle Connected Duration</label>
<description>Duration the vehicle is connected to loadpoint</description> <description>Duration the vehicle is connected to loadpoint</description>
<category>Time</category> <category>Time</category>
<state pattern="%.1f %unit%" readOnly="true"/> <state pattern="%.1f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="vehicleCapacity"> <channel-type id="vehicleCapacity">
<item-type>Number:Energy</item-type> <item-type>Number:Energy</item-type>
<label>Vehicle capacity</label> <label>Vehicle Capacity</label>
<description>Capacity of EV battery</description> <description>Capacity of EV battery</description>
<category>Energy</category> <category>Energy</category>
<state pattern="%.0f %unit%" readOnly="true"/> <state pattern="%.0f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="vehicleOdometer"> <channel-type id="vehicleOdometer">
<item-type>Number:Length</item-type> <item-type>Number:Length</item-type>
<label>Vehicle odometer</label> <label>Vehicle Odometer</label>
<description>Total distance travelled by EV</description> <description>Total distance travelled by EV</description>
<category></category> <category></category>
<state pattern="%.1f %unit%" readOnly="true"/> <state pattern="%.1f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="vehiclePresent"> <channel-type id="vehiclePresent">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Vehicle data access</label> <label>Vehicle Data Access</label>
<description>Whether evcc is able to get data from vehicle</description> <description>Whether evcc is able to get data from vehicle</description>
<category>Switch</category> <category>Switch</category>
<state readOnly="true"> <state readOnly="true">
@ -312,7 +308,7 @@
</channel-type> </channel-type>
<channel-type id="vehicleRange"> <channel-type id="vehicleRange">
<item-type>Number:Length</item-type> <item-type>Number:Length</item-type>
<label>Vehicle range</label> <label>Vehicle Range</label>
<description>Battery range for EV</description> <description>Battery range for EV</description>
<category></category> <category></category>
<state pattern="%.1f %unit%" readOnly="true"/> <state pattern="%.1f %unit%" readOnly="true"/>
@ -321,12 +317,12 @@
<item-type>Number:Dimensionless</item-type> <item-type>Number:Dimensionless</item-type>
<label>Vehicle SoC</label> <label>Vehicle SoC</label>
<description>Current State of Charge of EV</description> <description>Current State of Charge of EV</description>
<category>Batterylevel</category> <category>BatteryLevel</category>
<state pattern="%.0f %unit%" readOnly="true"/> <state pattern="%.0f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="vehicleTitle"> <channel-type id="vehicleTitle">
<item-type>String</item-type> <item-type>String</item-type>
<label>Vehicle title</label> <label>Vehicle Title</label>
<description>Name of EV</description> <description>Name of EV</description>
<category>Text</category> <category>Text</category>
<state readOnly="true"/> <state readOnly="true"/>