]> git.basschouten.com Git - openhab-addons.git/commitdiff
[evcc] Adjust to API changes & Add new channels for evcc 0.117.0 (#14983)
authorFlorian Hotze <florianh_dev@icloud.com>
Sun, 21 May 2023 19:21:38 +0000 (21:21 +0200)
committerGitHub <noreply@github.com>
Sun, 21 May 2023 19:21:38 +0000 (21:21 +0200)
* [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>
bundles/org.openhab.binding.evcc/README.md
bundles/org.openhab.binding.evcc/src/main/java/org/openhab/binding/evcc/internal/EvccBindingConstants.java
bundles/org.openhab.binding.evcc/src/main/java/org/openhab/binding/evcc/internal/EvccHandler.java
bundles/org.openhab.binding.evcc/src/main/java/org/openhab/binding/evcc/internal/api/EvccAPI.java
bundles/org.openhab.binding.evcc/src/main/java/org/openhab/binding/evcc/internal/api/dto/Loadpoint.java
bundles/org.openhab.binding.evcc/src/main/java/org/openhab/binding/evcc/internal/api/dto/Result.java
bundles/org.openhab.binding.evcc/src/main/java/org/openhab/binding/evcc/internal/api/dto/Status.java
bundles/org.openhab.binding.evcc/src/main/resources/OH-INF/i18n/evcc.properties
bundles/org.openhab.binding.evcc/src/main/resources/OH-INF/thing/thing-types.xml

index 5bcf7853ef6984262b7ed1981c502912b7e81fd7..d4ee769da0cd69572b4d374d7cd39413cdcc528d 100644 (file)
@@ -1,7 +1,7 @@
 # evcc Binding
 
 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`.
 
@@ -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#batteryPower       | Number:Power         | R          | Current power from 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#homePower          | Number:Power         | R          | Current power taken by home.                                                                                 |
 | 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#charging                 | Switch                 | R          | Loadpoint is currently charging                                                                     |
 | 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#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#mode                     | String                 | RW         | Charging mode: "off", "now", "minpv", "pv"                                                          |
 | 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#targetTime               | DateTime               | RW         | When the target SoC should be reached                                                               |
 | 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"}
 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_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_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"}
 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: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"}
 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"}
@@ -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"]
         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_minCurrent minValue=6 maxValue=96 step=2
             Setpoint item=evcc_loadpoint0_maxCurrent minValue=6 maxValue=96 step=2
index 15ff6f427c5e03c686ceb75265abea1412e4b204..dbdd2009e819d514986c7e98c00c91414ecc28cd 100644 (file)
@@ -27,6 +27,8 @@ public class EvccBindingConstants {
 
     private static final String BINDING_ID = "evcc";
 
+    public static final String CHANNEL_GROUP_ID_GENERAL = "general";
+
     // List of all Channel ids
     public static final String CHANNEL_BATTERY_CAPACITY = "batteryCapacity";
     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_CONNECTED = "vehicleConnected";
     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_ENABLED = "enabled";
     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_SOC = "minSoC";
     public static final String CHANNEL_LOADPOINT_MODE = "mode";
     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_TIME = "targetTime";
     /**
@@ -103,8 +106,6 @@ public class EvccBindingConstants {
             CHANNEL_LOADPOINT_CONNECTED_DURATION);
     public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_ENABLED = new ChannelTypeUID(BINDING_ID,
             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,
             CHANNEL_LOADPOINT_MAX_CURRENT);
     public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_MIN_CURRENT = new ChannelTypeUID(BINDING_ID,
@@ -115,6 +116,8 @@ public class EvccBindingConstants {
             CHANNEL_LOADPOINT_MODE);
     public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_PHASES = new ChannelTypeUID(BINDING_ID,
             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,
             CHANNEL_LOADPOINT_TARGET_SOC);
     public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_TARGET_TIME = new ChannelTypeUID(BINDING_ID,
index 1f094127ba0fab17e12bcb6a7b57b3c12e3bb333..d59e3c3e2f4505c03d0856effaac89a4a5d9aee3 100644 (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.SIUnits;
 import org.openhab.core.library.unit.Units;
-import org.openhab.core.thing.Channel;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
 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.binding.BaseThingHandler;
 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.types.Command;
 import org.openhab.core.types.RefreshType;
@@ -67,7 +65,6 @@ public class EvccHandler extends BaseThingHandler {
     private boolean gridConfigured = false;
     private boolean pvConfigured = false;
 
-    private float targetSoC = 100;
     private boolean targetTimeEnabled = false;
     private ZonedDateTime targetTimeZDT = ZonedDateTime.now().plusHours(12);
 
@@ -85,97 +82,116 @@ public class EvccHandler extends BaseThingHandler {
             if (groupId == null) {
                 return;
             }
+            String channelGroupId = channelUID.getGroupId();
             String channelIdWithoutGroup = channelUID.getIdWithoutGroup();
-            int loadpoint = Integer.parseInt(groupId.substring(9)) + 1;
             EvccAPI evccAPI = this.evccAPI;
             if (evccAPI == null) {
                 return;
             }
             try {
-                switch (channelIdWithoutGroup) {
-                    case CHANNEL_LOADPOINT_MODE:
-                        if (command instanceof StringType) {
-                            evccAPI.setMode(loadpoint, command.toString());
-                        } else {
-                            logger.debug("Command has wrong type, StringType required!");
+                if (channelGroupId.equals(CHANNEL_GROUP_ID_GENERAL)) {
+                    if (!channelIdWithoutGroup.equals(CHANNEL_BATTERY_PRIORITY_SOC)) {
+                        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!");
+                            }
                         }
-                        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!");
+                        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!");
+                            }
                         }
-                        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!");
+                        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!");
+                            }
                         }
-                        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);
+                        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!");
                             }
-                        } 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!");
+                        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!");
+                            }
                         }
-                        break;
-                    case CHANNEL_LOADPOINT_PHASES:
-                        if (command instanceof DecimalType) {
-                            evccAPI.setPhases(loadpoint, ((DecimalType) command).intValue());
-                        } else {
-                            logger.debug("Command has wrong type, DecimalType 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!");
+                            }
                         }
-                        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!");
+                        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!");
+                            }
                         }
-                        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!");
+                        default -> {
+                            return;
                         }
-                        break;
-                    default:
-                        return;
+                    }
                 }
             } catch (EvccApiException e) {
                 Throwable cause = e.getCause();
@@ -256,20 +272,22 @@ public class EvccHandler extends BaseThingHandler {
 
     // Utility functions
     private void createChannelsGeneral() {
-        final String channelGroup = "general";
         if (batteryConfigured) {
-            createChannel(CHANNEL_BATTERY_CAPACITY, channelGroup, CHANNEL_TYPE_UID_BATTERY_CAPACITY, "Number:Energy");
-            createChannel(CHANNEL_BATTERY_POWER, channelGroup, CHANNEL_TYPE_UID_BATTERY_POWER, "Number:Power");
-            createChannel(CHANNEL_BATTERY_SOC, channelGroup, CHANNEL_TYPE_UID_BATTERY_SOC, "Number:Dimensionless");
-            createChannel(CHANNEL_BATTERY_PRIORITY_SOC, channelGroup, CHANNEL_TYPE_UID_BATTERY_PRIORITY_SOC,
+            createChannel(CHANNEL_BATTERY_CAPACITY, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_BATTERY_CAPACITY,
+                    "Number:Energy");
+            createChannel(CHANNEL_BATTERY_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_BATTERY_POWER,
+                    "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");
         }
         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) {
-            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");
         createChannel(CHANNEL_LOADPOINT_ENABLED, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_ENABLED,
                 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,
                 "Number:ElectricCurrent");
         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_PHASES, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_PHASES,
                 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,
                 "Number:Dimensionless");
         createChannel(CHANNEL_LOADPOINT_TARGET_TIME, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TARGET_TIME,
@@ -327,6 +345,8 @@ public class EvccHandler extends BaseThingHandler {
                 "Number:Dimensionless");
         createChannel(CHANNEL_LOADPOINT_VEHICLE_TITLE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_TITLE,
                 CoreItemFactory.STRING);
+
+        removeChannel(CHANNEL_LOADPOINT_HAS_VEHICLE, channelGroup);
     }
 
     // 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;
         if (batteryConfigured) {
             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));
 
             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));
 
             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));
 
             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));
         }
         boolean gridConfigured = this.gridConfigured;
         if (gridConfigured) {
             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));
         }
         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));
         boolean pvConfigured = this.pvConfigured;
         if (pvConfigured) {
             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));
         }
     }
@@ -426,10 +446,6 @@ public class EvccHandler extends BaseThingHandler {
         channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_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();
         channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_MAX_CURRENT);
         updateState(channel, new QuantityType<>(maxCurrent, Units.AMPERE));
@@ -450,12 +466,16 @@ public class EvccHandler extends BaseThingHandler {
         channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_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);
         updateState(channel, new QuantityType<>(targetSoC, Units.PERCENT));
 
         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);
             updateState(channel, OnOffType.OFF);
             targetTimeEnabled = false;
@@ -498,14 +518,17 @@ public class EvccHandler extends BaseThingHandler {
     }
 
     private void createChannel(String channel, String channelGroupId, ChannelTypeUID channelTypeUID, String itemType) {
-        ChannelUID channelToCheck = new ChannelUID(thing.getUID(), channelGroupId, channel);
-        if (thing.getChannel(channelToCheck) == null) {
-            ThingBuilder thingBuilder = editThing();
-            Channel testchannel = ChannelBuilder
-                    .create(new ChannelUID(getThing().getUID(), channelGroupId, channel), itemType)
-                    .withType(channelTypeUID).build();
-            thingBuilder.withChannel(testchannel);
-            updateThing(thingBuilder.build());
+        ChannelUID channelUid = new ChannelUID(thing.getUID(), channelGroupId, channel);
+        if (thing.getChannel(channelUid) == null) {
+            updateThing(editThing()
+                    .withChannel(ChannelBuilder.create(channelUid, itemType).withType(channelTypeUID).build()).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());
         }
     }
 }
index a5e3347c107c519acb8106e62dfe53ff003942e3..5a561045cc64fc3aff678e7039bb033fde9f5a88 100644 (file)
@@ -31,7 +31,8 @@ import com.google.gson.JsonSyntaxException;
 
 /**
  * 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
  */
 @NonNullByDefault
@@ -46,7 +47,7 @@ public class EvccAPI {
 
     /**
      * Make a HTTP request.
-     * 
+     *
      * @param url full request URL
      * @param method request method, e.g. GET, POST
      * @return the response body
@@ -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.
     public String setMode(int loadpoint, String mode) throws EvccApiException {
         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");
     }
 
+    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 {
-        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 {
@@ -109,13 +120,12 @@ public class EvccAPI {
         return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/maxcurrent/" + maxCurrent, "POST");
     }
 
-    public String setTargetCharge(int loadpoint, float targetSoC, ZonedDateTime targetTime) throws EvccApiException {
-        DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
-        return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/targetcharge/" + targetSoC + "/"
-                + targetTime.toLocalDateTime().format(formatter), "POST");
+    public String setTargetTime(int loadpoint, ZonedDateTime targetTime) throws EvccApiException {
+        return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/target/time/"
+                + targetTime.toLocalDateTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + "Z", "POST");
     }
 
-    public String unsetTargetCharge(int loadpoint) throws EvccApiException {
-        return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/targetcharge", "DELETE");
+    public String removeTargetTime(int loadpoint) throws EvccApiException {
+        return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/target/time", "DELETE");
     }
 }
index 49f477e76944b24b824cbe9ec985e5ddcc95a6b3..1136666c92049e51f250ba8b287edd4853497171 100644 (file)
@@ -16,7 +16,7 @@ import com.google.gson.annotations.SerializedName;
 
 /**
  * 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
  */
@@ -57,12 +57,6 @@ public class Loadpoint {
     @SerializedName("enabled")
     private boolean enabled;
 
-    @SerializedName("hasVehicle")
-    private boolean hasVehicle;
-
-    @SerializedName("loadpoint")
-    private int loadpoint;
-
     @SerializedName("maxCurrent")
     private float maxCurrent;
 
@@ -75,14 +69,14 @@ public class Loadpoint {
     @SerializedName("mode")
     private String mode;
 
-    @SerializedName("phases")
+    @SerializedName("phasesEnabled")
     private int phases;
 
-    @SerializedName("pvAction")
-    private String pvAction;
+    @SerializedName("planActive")
+    private boolean planActive;
 
-    @SerializedName("pvRemaining")
-    private long pvRemaining;
+    @SerializedName("targetEnergy")
+    private float targetEnergy;
 
     @SerializedName("targetSoc")
     private float targetSoC;
@@ -188,20 +182,6 @@ public class Loadpoint {
         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
      */
@@ -238,17 +218,17 @@ public class Loadpoint {
     }
 
     /**
-     * @return the pv action
+     * @return whether charging plan is active
      */
-    public String getPvAction() {
-        return pvAction;
+    public boolean getPlanActive() {
+        return planActive;
     }
 
     /**
-     * @return the pv remaining
+     * @return target energy
      */
-    public long getPvRemaining() {
-        return pvRemaining;
+    public float getTargetEnergy() {
+        return targetEnergy;
     }
 
     /**
index 908eb41d0f00200d027b5746667461657b9c134b..194867752a3730ce2e01faed0f62f14f517e67a0 100644 (file)
@@ -16,7 +16,7 @@ import com.google.gson.annotations.SerializedName;
 
 /**
  * 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
  */
index c9039d5873f2e669636d183697bad95cfbef94a8..3e1b8853082e9a1d1378f2cca7b008977e0bdc0c 100644 (file)
@@ -16,7 +16,7 @@ import com.google.gson.annotations.SerializedName;
 
 /**
  * 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
  */
index 4fd32c24adf53127262eaff604676c24b6d84ddb..bb9bc5a2b0005e76d0153a55610225f81397749d 100644 (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-type.evcc.general.label = General data
+channel-group-type.evcc.general.label = General Data
 channel-group-type.evcc.loadpoint.label = Loadpoint
 
 # 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.batteryCapacity.label = Battery Capacity
 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.batterySoC.label = Battery SoC
 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.chargeDuration.label = Charging duration
+channel-type.evcc.chargeDuration.label = 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.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.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.chargedEnergy.label = Charged energy
+channel-type.evcc.chargedEnergy.label = Charged Energy
 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.state.option.ON = 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.state.option.ON = Enabled
 channel-type.evcc.enabled.state.option.OFF = Disabled
 channel-type.evcc.gridPower.label = Grid Power
 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.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.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.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.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.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.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.pvPower.label = PV Power
 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.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.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.state.option.ON = Enabled
 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.vehicleCapacity.label = Vehicle capacity
+channel-type.evcc.vehicleCapacity.label = Vehicle Capacity
 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.state.option.ON = 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.vehicleOdometer.label = Vehicle odometer
+channel-type.evcc.vehicleOdometer.label = Vehicle Odometer
 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.state.option.ON = 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.vehicleSoC.label = Vehicle SoC
 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
 
 # thing status description
index d32e3f4de1d5afc43acdac8896c3ad02d665b40e..ed354200966f44645bede2cb2204c3c34c32d439 100644 (file)
@@ -39,7 +39,7 @@
        </thing-type>
 
        <channel-group-type id="general">
-               <label>General data</label>
+               <label>General Data</label>
        </channel-group-type>
        <channel-group-type id="loadpoint">
                <label>Loadpoint</label>
                <item-type>Number:Dimensionless</item-type>
                <label>Battery SoC</label>
                <description>Current State of Charge of battery</description>
-               <category>batterylevel</category>
+               <category>BatteryLevel</category>
                <state pattern="%.0f %unit%" readOnly="true"/>
        </channel-type>
        <channel-type id="batteryPrioritySoC">
                <item-type>Number:Dimensionless</item-type>
                <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>
-               <category>batterylevel</category>
-               <state pattern="%.0f %unit%" readOnly="true"/>
+               <category>BatteryLevel</category>
+               <state min="0" step="0.1" max="100" pattern="%.0f %unit%" readOnly="false"/>
        </channel-type>
        <channel-type id="gridPower">
                <item-type>Number:Power</item-type>
        <!-- Channels for loadpoints -->
        <channel-type id="activePhases">
                <item-type>Number</item-type>
-               <label>Charging active phases</label>
+               <label>Charging Active Phases</label>
                <description>Current number of active phases while charging</description>
                <category></category>
                <state pattern="%d" readOnly="true"/>
        </channel-type>
        <channel-type id="chargeCurrent">
                <item-type>Number:ElectricCurrent</item-type>
-               <label>Charging current</label>
+               <label>Charging Current</label>
                <description>Current amperage per connected phase while charging</description>
                <category>Energy</category>
                <state pattern="%.1f %unit%" readOnly="true"/>
        </channel-type>
        <channel-type id="chargeDuration">
                <item-type>Number:Time</item-type>
-               <label>Charging duration</label>
+               <label>Charging Duration</label>
                <description>Charging duration</description>
                <category>Time</category>
                <state pattern="%.1f min" readOnly="true"/>
        </channel-type>
        <channel-type id="chargePower">
                <item-type>Number:Power</item-type>
-               <label>Charging power</label>
+               <label>Charging Power</label>
                <description>Current power of charging</description>
                <category>Energy</category>
                <state pattern="%.1f %unit%" readOnly="true"/>
        </channel-type>
        <channel-type id="chargeRemainingDuration">
                <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>
                <category>Time</category>
                <state pattern="%.1f min" readOnly="true"/>
        </channel-type>
        <channel-type id="chargeRemainingEnergy">
                <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>
                <category>Energy</category>
                <state pattern="%.1f %unit%" readOnly="true"/>
        </channel-type>
        <channel-type id="chargedEnergy">
                <item-type>Number:Energy</item-type>
-               <label>Charged energy</label>
+               <label>Charged Energy</label>
                <description>Energy charged since plugged-in</description>
                <category>Energy</category>
                <state pattern="%.1f %unit%" readOnly="true"/>
        </channel-type>
        <channel-type id="charging">
                <item-type>Switch</item-type>
-               <label>Charging state</label>
+               <label>Charging State</label>
                <description>Loadpoint is currently charging</description>
                <category>Energy</category>
                <state pattern="%f %unit%" readOnly="true">
        </channel-type>
        <channel-type id="enabled">
                <item-type>Switch</item-type>
-               <label>Charging enabled</label>
+               <label>Charging Enabled</label>
                <description>Charging enabled (mode not "off")</description>
                <category>Switch</category>
                <state readOnly="true">
                        </options>
                </state>
        </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">
                <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>
                <category>Energy</category>
                <state min="0" step="1" pattern="%.0f %unit%" readOnly="false"/>
        </channel-type>
        <channel-type id="minCurrent">
                <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>
                <category>Energy</category>
                <state min="0" step="1" pattern="%.0f %unit%" readOnly="false"/>
                <item-type>Number:Dimensionless</item-type>
                <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>
-               <category>Batterylevel</category>
+               <category>BatteryLevel</category>
                <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
                <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
        <channel-type id="mode">
                <item-type>String</item-type>
-               <label>Charging mode</label>
+               <label>Charging Mode</label>
                <description>Charging mode: "off", "now", "minpv", "pv"</description>
                <category>String</category>
                <state readOnly="false">
                        <options>
                                <option value="off">Off</option>
-                               <option value="now">Now</option>
+                               <option value="now">Fast</option>
                                <option value="minpv">Min + PV</option>
                                <option value="pv">Only PV</option>
                        </options>
        </channel-type>
        <channel-type id="phases">
                <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>
                <category>Energy</category>
                <state min="0" step="1" max="3" pattern="%d" readOnly="false"/>
                <autoUpdatePolicy>veto</autoUpdatePolicy>
        </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">
                <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>
-               <category>Batterylevel</category>
+               <category>BatteryLevel</category>
                <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
                <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
        <channel-type id="targetTime">
                <item-type>DateTime</item-type>
-               <label>Charging target time</label>
+               <label>Charging Target Time</label>
                <description>When the target SoC should be reached</description>
                <category>Time</category>
                <state readOnly="false"/>
        </channel-type>
        <channel-type id="targetTimeEnabled">
                <item-type>Switch</item-type>
-               <label>Charging target time enabled</label>
+               <label>Charging Target Time Enabled</label>
                <description>Target time for charging enabled</description>
                <category>Switch</category>
                <state readOnly="false">
        </channel-type>
        <channel-type id="title">
                <item-type>String</item-type>
-               <label>Loadpoint title</label>
+               <label>Loadpoint Title</label>
                <description>Title of loadpoint</description>
                <category>Text</category>
                <state readOnly="true"/>
        </channel-type>
        <channel-type id="vehicleConnected">
                <item-type>Switch</item-type>
-               <label>Vehicle connected</label>
+               <label>Vehicle Connected</label>
                <description>Whether vehicle is connected to loadpoint</description>
                <category>Switch</category>
                <state readOnly="true">
        </channel-type>
        <channel-type id="vehicleConnectedDuration">
                <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>
                <category>Time</category>
                <state pattern="%.1f %unit%" readOnly="true"/>
        </channel-type>
        <channel-type id="vehicleCapacity">
                <item-type>Number:Energy</item-type>
-               <label>Vehicle capacity</label>
+               <label>Vehicle Capacity</label>
                <description>Capacity of EV battery</description>
                <category>Energy</category>
                <state pattern="%.0f %unit%" readOnly="true"/>
        </channel-type>
        <channel-type id="vehicleOdometer">
                <item-type>Number:Length</item-type>
-               <label>Vehicle odometer</label>
+               <label>Vehicle Odometer</label>
                <description>Total distance travelled by EV</description>
                <category></category>
                <state pattern="%.1f %unit%" readOnly="true"/>
        </channel-type>
        <channel-type id="vehiclePresent">
                <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>
                <category>Switch</category>
                <state readOnly="true">
        </channel-type>
        <channel-type id="vehicleRange">
                <item-type>Number:Length</item-type>
-               <label>Vehicle range</label>
+               <label>Vehicle Range</label>
                <description>Battery range for EV</description>
                <category></category>
                <state pattern="%.1f %unit%" readOnly="true"/>
                <item-type>Number:Dimensionless</item-type>
                <label>Vehicle SoC</label>
                <description>Current State of Charge of EV</description>
-               <category>Batterylevel</category>
+               <category>BatteryLevel</category>
                <state pattern="%.0f %unit%" readOnly="true"/>
        </channel-type>
        <channel-type id="vehicleTitle">
                <item-type>String</item-type>
-               <label>Vehicle title</label>
+               <label>Vehicle Title</label>
                <description>Name of EV</description>
                <category>Text</category>
                <state readOnly="true"/>