]> git.basschouten.com Git - openhab-addons.git/commitdiff
[evcc] fixed channels vehicle/capacity and vehicle/vehicleName, added channels for...
authorMikeTheTux <44850211+MikeTheTux@users.noreply.github.com>
Fri, 8 Mar 2024 07:44:45 +0000 (08:44 +0100)
committerGitHub <noreply@github.com>
Fri, 8 Mar 2024 07:44:45 +0000 (08:44 +0100)
* removed loadpoint/vehicleCapacity, added vehicle/capacity (bugfix)
implemented currentVehicle / currentHeating per loadpoint (enhancement)
fixed update of channeld vehicleTitle (bugfix)

Signed-off-by: Michael Weger <weger.michael@gmx.net>
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/dto/Loadpoint.java
bundles/org.openhab.binding.evcc/src/main/java/org/openhab/binding/evcc/internal/api/dto/Vehicle.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 8481821a3240c039c8805da710c95f48616d22fc..fce6304c97784d9a2c81afc003c596dceda10e54 100644 (file)
@@ -79,7 +79,6 @@ Please note that you have to replace _\<N\>_ with your loadpoint id/number.
 | loadpoint\<N\>#title                          | String                 | R          | Title of loadpoint                                                                                                |
 | loadpoint\<N\>#vehicleConnected               | Switch                 | R          | Whether vehicle is connected to loadpoint                                                                         |
 | loadpoint\<N\>#vehicleConnectedDuration       | Number:Time            | R          | Duration the vehicle is connected to loadpoint                                                                    |
-| loadpoint\<N\>#vehicleCapacity                | Number:Energy          | R          | Capacity of EV battery                                                                                            |
 | loadpoint\<N\>#vehicleOdometer                | Number:Length          | R          | Total distance travelled by EV                                                                                    |
 | loadpoint\<N\>#vehiclePresent                 | Switch                 | R          | Whether evcc is able to get data from vehicle                                                                     |
 | loadpoint\<N\>#vehicleRange                   | Number:Length          | R          | Battery range for EV                                                                                              |
@@ -105,31 +104,43 @@ Please note that you have to replace _\<N\>_ with your loadpoint id/number.
 
 ### Vehicle Channels
 
-Those channels exist per configured vehicle.
-Please note that you have to replace _\<ID\>_ with your vehicle id/name.
+Those channels exist:
 
-| Channel                          | Type                 | Read/Write | Description                                                              |
-|----------------------------------|----------------------|------------|--------------------------------------------------------------------------|
-| vehicle\<ID\>#vehicleTitle       | String               | R          | Title of vehicle                                                         |
-| vehicle\<ID\>#vehicleMinSoC      | Number:Dimensionless | RW         | Minimum state of charge (SoC) a vehicle should have                      |
-| vehicle\<ID\>#vehicleLimitSoC    | Number:Dimensionless | RW         | Until which state of charge (SoC) should the specific vehicle be charged |
-| vehicle\<ID\>#vehiclePlanEnabled | Switch               | RW         | Plan for charging enabled                                                |
-| vehicle\<ID\>#vehiclePlanSoC     | Number:Dimensionless | RW         | Until which state of charge (SoC) should vehicle be charged in plan      |
-| vehicle\<ID\>#vehiclePlanTime    | DateTime             | RW         | When the plan SoC should be reached                                      |
+* 1 per configured loadpoint with `chargerFeatureHeating = false`:
+  * These channels point to the heating device that is currently active/connected at/to the loadpoint
+  * Please note that you have to replace _\<N\>_ with your loadpoint id/number
+* 1 per configured vehicle:
+  * Please note that you have to replace _\<ID\>_ with your vehicle id/name
+
+| Channel                                            | Type                 | Read/Write | Description                                                              |
+|----------------------------------------------------|----------------------|------------|--------------------------------------------------------------------------|
+| [loadpoint\<N\>\|vehicle\<ID\]>#vehicleTitle       | String               | R          | Title of vehicle                                                         |
+| [loadpoint\<N\>\|vehicle\<ID\]>#vehicleMinSoC      | Number:Dimensionless | RW         | Minimum state of charge (SoC) a vehicle should have                      |
+| [loadpoint\<N\>\|vehicle\<ID\]>#vehicleLimitSoC    | Number:Dimensionless | RW         | Until which state of charge (SoC) should the specific vehicle be charged |
+| [loadpoint\<N\>\|vehicle\<ID\]>#vehicleCapacity    | Number:Energy        | R          | Capacity of EV battery                                                   |
+| [loadpoint\<N\>\|vehicle\<ID\]>#vehiclePlanEnabled | Switch               | RW         | Plan for charging enabled                                                |
+| [loadpoint\<N\>\|vehicle\<ID\]>#vehiclePlanSoC     | Number:Dimensionless | RW         | Until which state of charge (SoC) should vehicle be charged in plan      |
+| [loadpoint\<N\>\|vehicle\<ID\]>#vehiclePlanTime    | DateTime             | RW         | When the plan SoC should be reached                                      |
 
 ### Heating Channels
 
-Those channels exist per configured heating device.
-Please note that you have to replace _\<ID\>_ with your heating device id/name.
+Those channels exist:
+
+* 1 per configured loadpoint with `chargerFeatureHeating = true`:
+  * These channels point to the heating device that is currently active/connected at/to the loadpoint
+  * Please note that you have to replace _\<N\>_ with your loadpoint id/number
+* 1 per configured heating device:
+  * Please note that you have to replace _\<ID\>_ with your heating device id/name
 
-| Channel                               | Type               | Read/Write | Description                                                           |
-|---------------------------------------|--------------------|------------|-----------------------------------------------------------------------|
-| heating\<ID\>#heatingTitle            | String             | R          | Title of heating device                                               |
-| heating\<ID\>#heatingMinTemperature   | Number:Temperature | RW         | Minimum Temperature a heating device should have                      |
-| heating\<ID\>#heatingLimitTemperature | Number:Temperature | RW         | Until which Temperature should the specific heating device be charged |
-| heating\<ID\>#heatingPlanEnabled      | Switch             | RW         | Plan for charging enabled                                             |
-| heating\<ID\>#heatingPlanTemperature  | Number:Temperature | RW         | Until which Temperature should heating device be charged in plan      |
-| heating\<ID\>#heatingPlanTime         | DateTime           | RW         | When the plan Temperature should be reached                           |
+| Channel                                                 | Type               | Read/Write | Description                                                           |
+|---------------------------------------------------------|--------------------|------------|-----------------------------------------------------------------------|
+| [loadpoint\<N\>\|heating\<ID\]>#heatingTitle            | String             | R          | Title of heating device                                               |
+| [loadpoint\<N\>\|heating\<ID\]>#heatingMinTemperature   | Number:Temperature | RW         | Minimum Temperature a heating device should have                      |
+| [loadpoint\<N\>\|heating\<ID\]>#heatingLimitTemperature | Number:Temperature | RW         | Until which Temperature should the specific heating device be charged |
+| [loadpoint\<N\>\|heating\<ID\]>#heatingCapacity         | Number:Energy      | R          | Capacity of heating device                                            |
+| [loadpoint\<N\>\|heating\<ID\]>#heatingPlanEnabled      | Switch             | RW         | Plan for charging enabled                                             |
+| [loadpoint\<N\>\|heating\<ID\]>#heatingPlanTemperature  | Number:Temperature | RW         | Until which Temperature should heating device be charged in plan      |
+| [loadpoint\<N\>\|heating\<ID\]>#heatingPlanTime         | DateTime           | RW         | When the plan Temperature should be reached                           |
 
 ## Full Example
 
@@ -179,23 +190,23 @@ String                 evcc_loadpoint0_title                          "Loadpoint
 Switch                 evcc_loadpoint0_chargerFeatureHeating          "Feature: Heating [%s]"                              <switch>       {channel="evcc:device:demo:loadpoint0#chargerFeatureHeating"}
 Switch                 evcc_loadpoint0_chargerFeatureIntegratedDevice "Feature: Integrated Device [%s]"                    <switch>       {channel="evcc:device:demo:loadpoint0#chargerFeatureIntegratedDevice"}
 
-// Vehicle on loadpoint
+// Loadpoint vehicle channels
 Switch                 evcc_loadpoint0_vehicleConnected               "Vehicle connected [%s]"                             <switch>       {channel="evcc:device:demo:loadpoint0#vehicleConnected"}
 Number:Time            evcc_loadpoint0_vehicleConnectedDuration       "Vehicle connected duration [%.1f h]"                <time>         {channel="evcc:device:demo:loadpoint0#vehicleConnectedDuration"}
-Number:Energy          evcc_loadpoint0_vehicleCapacity                "Vehicle capacity [%.0f kWh]"                        <batterylevel> {channel="evcc:device:demo:loadpoint0#vehicleCapacity"}
 Number:Length          evcc_loadpoint0_vehicleOdometer                "Vehicle odometer [%.1f km]"                                        {channel="evcc:device:demo:loadpoint0#vehicleOdometer"}
 Switch                 evcc_loadpoint0_vehiclePresent                 "Vehicle present [%s]"                               <switch>       {channel="evcc:device:demo:loadpoint0#vehiclePresent"}
 Number:Length          evcc_loadpoint0_vehicleRange                   "Vehicle Range [%.0f km]"                                           {channel="evcc:device:demo:loadpoint0#vehicleRange"}
 Number:Dimensionless   evcc_loadpoint0_vehicleSoC                     "Vehicle SoC [%d %%]"                                <batterylevel> {channel="evcc:device:demo:loadpoint0#vehicleSoC"}
 String                 evcc_loadpoint0_VehicleName                    "Vehicle name [%s]"                                  <text>         {channel="evcc:device:demo:loadpoint0#vehicleName"}
 
-// Vehicle
-String                 evcc_vehicle0_vehicleTitle                     "Vehicle title [%s]"                                 <text>         {channel="evcc:device:demo:vehicle0#vehicleTitle"}
-Number:Dimensionless   evcc_vehicle0_vehicleMinSoC                    "Vehicle minimum SoC [%d %%]"                        <batterylevel> {channel="evcc:device:demo:vehicle0#vehicleMinSoC"}
-Number:Dimensionless   evcc_vehicle0_vehicleLimitSoC                  "Vehicle limit SoC [%d %%]"                          <batterylevel> {channel="evcc:device:demo:vehicle0#vehicleLimitSoC"}
-Switch                 evcc_vehicle0_vehiclePlanEnabled               "Vehicle plan enabled [%s]"                          <switch>       {channel="evcc:device:demo:vehicle0#vehiclePlanEnabled"}
-Number:Dimensionless   evcc_vehicle0_vehiclePlanSoC                   "Vehicle plan SoC [%d %%]"                           <batterylevel> {channel="evcc:device:demo:vehicle0#vehiclePlanSoC"}
-DateTime               evcc_vehicle0_vehiclePlanTime                  "Vehicle plan time [%1$td.%1$tm.%1$tY, %1$tH:%1$tM]" <time>         {channel="evcc:device:demo:vehicle0#vehiclePlanTime"}
+// Vehicle on loadpoint
+String                 evcc_loadpoint0current_vehicleTitle            "Vehicle title [%s]"                                 <text>         {channel="evcc:device:demo:loadpoint0current#vehicleTitle"}
+Number:Dimensionless   evcc_loadpoint0current_vehicleMinSoC           "Vehicle minimum SoC [%d %%]"                        <batterylevel> {channel="evcc:device:demo:loadpoint0current#vehicleMinSoC"}
+Number:Dimensionless   evcc_loadpoint0current_vehicleLimitSoC         "Vehicle limit SoC [%d %%]"                          <batterylevel> {channel="evcc:device:demo:loadpoint0current#vehicleLimitSoC"}
+Number:Energy          evcc_loadpoint0current_vehicleCapacity         "Vehicle capacity [%.0f kWh]"                        <batterylevel> {channel="evcc:device:demo:loadpoint0current#vehicleCapacity"}
+Switch                 evcc_loadpoint0current_vehiclePlanEnabled      "Vehicle plan enabled [%s]"                          <switch>       {channel="evcc:device:demo:loadpoint0current#vehiclePlanEnabled"}
+Number:Dimensionless   evcc_loadpoint0current_vehiclePlanSoC          "Vehicle plan SoC [%d %%]"                           <batterylevel> {channel="evcc:device:demo:loadpoint0current#vehiclePlanSoC"}
+DateTime               evcc_loadpoint0current_vehiclePlanTime         "Vehicle plan time [%1$td.%1$tm.%1$tY, %1$tH:%1$tM]" <time>         {channel="evcc:device:demo:loadpoint0current#vehiclePlanTime"}
 ```
 
 ### Sitemap
@@ -230,16 +241,16 @@ sitemap evcc label="evcc Demo" {
             Setpoint item=evcc_loadpoint0_phases minValue=1 maxValue=3 step=2
         }
         Text item=evcc_loadpoint0_vehicleName label="Vehicle" {
-            Text item=evcc_loadpoint0_vehicleCapacity
+            Text item=evcc_loadpoint0current_vehicleCapacity
             Text item=evcc_loadpoint0_vehicleOdometer
             Text item=evcc_loadpoint0_vehicleRange
             Text item=evcc_loadpoint0_vehicleSoC
-            Text item=evcc_vehicle0_vehicleTitle
-            Setpoint item=evcc_vehicle0_vehicleMinSoC minValue=0 maxValue=100 step=5
-            Setpoint item=evcc_vehicle0_vehicleLimitSoC minValue=5 maxValue=100 step=5
-            Switch item=evcc_vehicle0_vehiclePlanEnabled
-            Setpoint item=evcc_vehicle0_vehiclePlanSoC minValue=5 maxValue=100 step=5
-            Input item=evcc_vehicle0_vehiclePlanTime
+            Text item=evcc_loadpoint0current_vehicleTitle
+            Setpoint item=evcc_loadpoint0current_vehicleMinSoC minValue=0 maxValue=100 step=5
+            Setpoint item=evcc_loadpoint0current_vehicleLimitSoC minValue=5 maxValue=100 step=5
+            Switch item=evcc_loadpoint0current_vehiclePlanEnabled
+            Setpoint item=evcc_loadpoint0current_vehiclePlanSoC minValue=5 maxValue=100 step=5
+            Input item=evcc_loadpoint0current_vehiclePlanTime
         }
     }
 }
index cb43493cbb8e9e698365db8d1e8ffcaf5b036afc..2c0d37203c894e7c20652a567e3c22a4510c0c46 100644 (file)
@@ -32,6 +32,7 @@ public class EvccBindingConstants {
     public static final String CHANNEL_GROUP_ID_LOADPOINT = "loadpoint";
     public static final String CHANNEL_GROUP_ID_VEHICLE = "vehicle";
     public static final String CHANNEL_GROUP_ID_HEATING = "heating";
+    public static final String CHANNEL_GROUP_ID_CURRENT = "current";
 
     // List of all Channel ids
     public static final String CHANNEL_BATTERY_CAPACITY = "batteryCapacity";
@@ -70,7 +71,6 @@ public class EvccBindingConstants {
     public static final String CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_SOC = "effectiveLimitSoC";
     public static final String CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_TEMPERATURE = "effectiveLimitTemperature";
     public static final String CHANNEL_LOADPOINT_TITLE = "title";
-    public static final String CHANNEL_LOADPOINT_VEHICLE_CAPACITY = "vehicleCapacity";
     public static final String CHANNEL_LOADPOINT_VEHICLE_ODOMETER = "vehicleOdometer";
     public static final String CHANNEL_LOADPOINT_VEHICLE_PRESENT = "vehiclePresent";
     public static final String CHANNEL_LOADPOINT_VEHICLE_RANGE = "vehicleRange";
@@ -86,6 +86,8 @@ public class EvccBindingConstants {
     public static final String CHANNEL_HEATING_MIN_TEMPERATURE = "heatingMinTemperature";
     public static final String CHANNEL_VEHICLE_LIMIT_SOC = "vehicleLimitSoC";
     public static final String CHANNEL_HEATING_LIMIT_TEMPERATURE = "heatingLimitTemperature";
+    public static final String CHANNEL_VEHICLE_CAPACITY = "vehicleCapacity";
+    public static final String CHANNEL_HEATING_CAPACITY = "heatingCapacity";
     public static final String CHANNEL_VEHICLE_PLAN_ENABLED = "vehiclePlanEnabled";
     public static final String CHANNEL_HEATING_PLAN_ENABLED = "heatingPlanEnabled";
     public static final String CHANNEL_VEHICLE_PLAN_SOC = "vehiclePlanSoC";
@@ -163,8 +165,6 @@ public class EvccBindingConstants {
             BINDING_ID, CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_TEMPERATURE);
     public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_TITLE = new ChannelTypeUID(BINDING_ID,
             CHANNEL_LOADPOINT_TITLE);
-    public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_CAPACITY = new ChannelTypeUID(BINDING_ID,
-            CHANNEL_LOADPOINT_VEHICLE_CAPACITY);
     public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_ODOMETER = new ChannelTypeUID(BINDING_ID,
             CHANNEL_LOADPOINT_VEHICLE_ODOMETER);
     public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_PRESENT = new ChannelTypeUID(BINDING_ID,
@@ -194,6 +194,10 @@ public class EvccBindingConstants {
             CHANNEL_VEHICLE_LIMIT_SOC);
     public static final ChannelTypeUID CHANNEL_TYPE_UID_HEATING_LIMIT_TEMPERATURE = new ChannelTypeUID(BINDING_ID,
             CHANNEL_HEATING_LIMIT_TEMPERATURE);
+    public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_CAPACITY = new ChannelTypeUID(BINDING_ID,
+            CHANNEL_VEHICLE_CAPACITY);
+    public static final ChannelTypeUID CHANNEL_TYPE_UID_HEATING_CAPACITY = new ChannelTypeUID(BINDING_ID,
+            CHANNEL_HEATING_CAPACITY);
     public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_PLAN_ENABLED = new ChannelTypeUID(BINDING_ID,
             CHANNEL_VEHICLE_PLAN_ENABLED);
     public static final ChannelTypeUID CHANNEL_TYPE_UID_HEATING_PLAN_ENABLED = new ChannelTypeUID(BINDING_ID,
index 8755b561c6732c3d3ab5ce2eca26515e503012ba..3e6131d2a3ae47d6b86d77bb300508c575a46fb5 100644 (file)
@@ -50,6 +50,7 @@ import org.openhab.core.thing.binding.builder.ChannelBuilder;
 import org.openhab.core.thing.type.ChannelTypeUID;
 import org.openhab.core.types.Command;
 import org.openhab.core.types.RefreshType;
+import org.openhab.core.types.UnDefType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,6 +73,8 @@ public class EvccHandler extends BaseThingHandler {
     private boolean gridConfigured = false;
     private boolean pvConfigured = false;
     private Set<String> vehicleFeatureHeating = new HashSet<String>();
+    private Set<String> loadpointFeatureHeating = new HashSet<String>();
+
     Map<String, Triple<Boolean, Float, ZonedDateTime>> vehiclePlans = new HashMap<>();
 
     public EvccHandler(Thing thing) {
@@ -145,7 +148,8 @@ public class EvccHandler extends BaseThingHandler {
                             return;
                         }
                     }
-                } else if (groupId.startsWith(CHANNEL_GROUP_ID_LOADPOINT)) {
+                } else if (groupId.startsWith(CHANNEL_GROUP_ID_LOADPOINT)
+                        && !groupId.endsWith(CHANNEL_GROUP_ID_CURRENT)) {
                     int loadpoint = Integer.parseInt(groupId.substring(CHANNEL_GROUP_ID_LOADPOINT.length())) + 1;
                     switch (channelIdWithoutGroup) {
                         case CHANNEL_LOADPOINT_MODE -> {
@@ -212,13 +216,31 @@ public class EvccHandler extends BaseThingHandler {
                             return;
                         }
                     }
-                } else if (groupId.startsWith(CHANNEL_GROUP_ID_VEHICLE)
-                        || groupId.startsWith(CHANNEL_GROUP_ID_HEATING)) {
-                    String vehicleName;
-                    if (groupId.startsWith(CHANNEL_GROUP_ID_VEHICLE)) {
-                        vehicleName = groupId.substring(CHANNEL_GROUP_ID_VEHICLE.length());
-                    } else {
-                        vehicleName = groupId.substring(CHANNEL_GROUP_ID_HEATING.length());
+
+                } else if (groupId.startsWith(CHANNEL_GROUP_ID_VEHICLE) || groupId.startsWith(CHANNEL_GROUP_ID_HEATING)
+                        || (groupId.startsWith(CHANNEL_GROUP_ID_LOADPOINT)
+                                && groupId.endsWith(CHANNEL_GROUP_ID_CURRENT))) {
+                    String vehicleName = null;
+                    if (groupId.startsWith(CHANNEL_GROUP_ID_VEHICLE) || groupId.startsWith(CHANNEL_GROUP_ID_HEATING)) {
+                        if (groupId.startsWith(CHANNEL_GROUP_ID_VEHICLE)) {
+                            vehicleName = groupId.substring(CHANNEL_GROUP_ID_VEHICLE.length());
+                        } else {
+                            vehicleName = groupId.substring(CHANNEL_GROUP_ID_HEATING.length());
+                        }
+                    } else if (groupId.startsWith(CHANNEL_GROUP_ID_LOADPOINT)
+                            && groupId.endsWith(CHANNEL_GROUP_ID_CURRENT)) {
+                        final Result result = this.result;
+                        if (result == null) {
+                            return;
+                        }
+                        int loadpointId = Integer.parseInt(groupId.substring(CHANNEL_GROUP_ID_LOADPOINT.length(),
+                                groupId.length() - CHANNEL_GROUP_ID_CURRENT.length()));
+                        Loadpoint loadpoint = result.getLoadpoints()[loadpointId];
+                        vehicleName = loadpoint.getVehicleName();
+                    }
+
+                    if (vehicleName == null) {
+                        return;
                     }
                     switch (channelIdWithoutGroup) {
                         case CHANNEL_VEHICLE_MIN_SOC -> {
@@ -457,10 +479,11 @@ public class EvccHandler extends BaseThingHandler {
         if (result == null) {
             return;
         }
-        final String channelGroup = CHANNEL_GROUP_ID_LOADPOINT + loadpointId;
+        final String channelGroup = CHANNEL_GROUP_ID_LOADPOINT + String.valueOf(loadpointId);
 
         Loadpoint loadpoint = result.getLoadpoints()[loadpointId];
         boolean chargerFeatureHeating = loadpoint.getChargerFeatureHeating();
+        String vehicleName = loadpoint.getVehicleName();
 
         createChannel(CHANNEL_LOADPOINT_ACTIVE_PHASES, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_ACTIVE_PHASES,
                 CoreItemFactory.NUMBER);
@@ -494,6 +517,11 @@ public class EvccHandler extends BaseThingHandler {
         createChannel(CHANNEL_LOADPOINT_LIMIT_ENERGY, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_LIMIT_ENERGY,
                 "Number:Energy");
         if (chargerFeatureHeating) {
+            if ((vehicleName != null) && !vehicleName.isBlank()) {
+                this.vehicleFeatureHeating.add(vehicleName);
+            }
+            this.loadpointFeatureHeating.add(channelGroup);
+
             createChannel(CHANNEL_LOADPOINT_LIMIT_TEMPERATURE, channelGroup,
                     CHANNEL_TYPE_UID_LOADPOINT_LIMIT_TEMPERATURE, "Number:Temperature");
             createChannel(CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_TEMPERATURE, channelGroup,
@@ -505,6 +533,11 @@ public class EvccHandler extends BaseThingHandler {
             removeChannel(CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_SOC, channelGroup);
             removeChannel(CHANNEL_LOADPOINT_VEHICLE_SOC, channelGroup);
         } else {
+            if ((vehicleName != null) && !vehicleName.isBlank()) {
+                this.vehicleFeatureHeating.remove(vehicleName);
+            }
+            this.loadpointFeatureHeating.remove(channelGroup);
+
             createChannel(CHANNEL_LOADPOINT_LIMIT_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_LIMIT_SOC,
                     "Number:Dimensionless");
             createChannel(CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_SOC, channelGroup,
@@ -518,8 +551,6 @@ public class EvccHandler extends BaseThingHandler {
         }
 
         createChannel(CHANNEL_LOADPOINT_TITLE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TITLE, CoreItemFactory.STRING);
-        createChannel(CHANNEL_LOADPOINT_VEHICLE_CAPACITY, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_CAPACITY,
-                "Number:Energy");
         createChannel(CHANNEL_LOADPOINT_VEHICLE_ODOMETER, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_ODOMETER,
                 "Number:Length");
         createChannel(CHANNEL_LOADPOINT_VEHICLE_PRESENT, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_PRESENT,
@@ -539,12 +570,33 @@ public class EvccHandler extends BaseThingHandler {
         removeChannel("targetSoC", channelGroup);
         removeChannel("targetTime", channelGroup);
         removeChannel("targetTimeEnabled", channelGroup);
+        removeChannel("vehicleCapacity", channelGroup);
+
+        if (vehicleName != null) {
+            createChannelsVehicle(vehicleName, channelGroup);
+        }
     }
 
     private void createChannelsVehicle(String vehicleName) {
-        String channelGroup;
-        if (vehicleFeatureHeating.contains(vehicleName)) {
-            channelGroup = CHANNEL_GROUP_ID_HEATING + vehicleName;
+        createChannelsVehicle(vehicleName, null);
+    }
+
+    private void createChannelsVehicle(String vehicleName, @Nullable String loadpointName) {
+        boolean isHeating;
+        if (loadpointName == null) {
+            isHeating = this.vehicleFeatureHeating.contains(vehicleName);
+        } else {
+            isHeating = this.loadpointFeatureHeating.contains(loadpointName);
+        }
+
+        if (isHeating) {
+            String channelGroup;
+            if (loadpointName == null) {
+                channelGroup = CHANNEL_GROUP_ID_HEATING + vehicleName;
+            } else {
+                channelGroup = loadpointName + CHANNEL_GROUP_ID_CURRENT;
+            }
+
             createChannel(CHANNEL_HEATING_MIN_TEMPERATURE, channelGroup, CHANNEL_TYPE_UID_HEATING_MIN_TEMPERATURE,
                     "Number:Temperature");
             createChannel(CHANNEL_HEATING_LIMIT_TEMPERATURE, channelGroup, CHANNEL_TYPE_UID_HEATING_LIMIT_TEMPERATURE,
@@ -552,6 +604,7 @@ public class EvccHandler extends BaseThingHandler {
             createChannel(CHANNEL_HEATING_PLAN_TEMPERATURE, channelGroup, CHANNEL_TYPE_UID_HEATING_PLAN_TEMPERATURE,
                     "Number:Temperature");
             createChannel(CHANNEL_HEATING_TITLE, channelGroup, CHANNEL_TYPE_UID_HEATING_TITLE, CoreItemFactory.STRING);
+            createChannel(CHANNEL_HEATING_CAPACITY, channelGroup, CHANNEL_TYPE_UID_HEATING_CAPACITY, "Number:Energy");
             createChannel(CHANNEL_HEATING_PLAN_TIME, channelGroup, CHANNEL_TYPE_UID_HEATING_PLAN_TIME,
                     CoreItemFactory.DATETIME);
             createChannel(CHANNEL_HEATING_PLAN_ENABLED, channelGroup, CHANNEL_TYPE_UID_HEATING_PLAN_ENABLED,
@@ -567,8 +620,15 @@ public class EvccHandler extends BaseThingHandler {
             removeChannel(CHANNEL_VEHICLE_PLAN_TIME, channelGroup);
             removeChannel(CHANNEL_VEHICLE_PLAN_ENABLED, channelGroup);
             removeChannel(CHANNEL_VEHICLE_PLAN_TIME, channelGroup);
+            removeChannel(CHANNEL_VEHICLE_CAPACITY, channelGroup);
         } else {
-            channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName;
+            String channelGroup;
+            if (loadpointName == null) {
+                channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName;
+            } else {
+                channelGroup = loadpointName + CHANNEL_GROUP_ID_CURRENT;
+            }
+
             createChannel(CHANNEL_VEHICLE_MIN_SOC, channelGroup, CHANNEL_TYPE_UID_VEHICLE_MIN_SOC,
                     "Number:Dimensionless");
             createChannel(CHANNEL_VEHICLE_LIMIT_SOC, channelGroup, CHANNEL_TYPE_UID_VEHICLE_LIMIT_SOC,
@@ -576,6 +636,7 @@ public class EvccHandler extends BaseThingHandler {
             createChannel(CHANNEL_VEHICLE_PLAN_SOC, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_SOC,
                     "Number:Dimensionless");
             createChannel(CHANNEL_VEHICLE_TITLE, channelGroup, CHANNEL_TYPE_UID_VEHICLE_TITLE, CoreItemFactory.STRING);
+            createChannel(CHANNEL_VEHICLE_CAPACITY, channelGroup, CHANNEL_TYPE_UID_VEHICLE_CAPACITY, "Number:Energy");
             createChannel(CHANNEL_VEHICLE_PLAN_TIME, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_TIME,
                     CoreItemFactory.DATETIME);
             createChannel(CHANNEL_VEHICLE_PLAN_ENABLED, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_ENABLED,
@@ -591,6 +652,7 @@ public class EvccHandler extends BaseThingHandler {
             removeChannel(CHANNEL_HEATING_PLAN_TIME, channelGroup);
             removeChannel(CHANNEL_HEATING_PLAN_ENABLED, channelGroup);
             removeChannel(CHANNEL_HEATING_PLAN_TIME, channelGroup);
+            removeChannel(CHANNEL_HEATING_CAPACITY, channelGroup);
         }
     }
 
@@ -752,8 +814,6 @@ public class EvccHandler extends BaseThingHandler {
         updateState(channel, new StringType(vehicleName));
 
         if (chargerFeatureHeating) {
-            vehicleFeatureHeating.add(vehicleName);
-
             float limitSoC = loadpoint.getLimitSoC();
             channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_LIMIT_TEMPERATURE);
             updateState(channel, new QuantityType<>(limitSoC, SIUnits.CELSIUS));
@@ -766,8 +826,6 @@ public class EvccHandler extends BaseThingHandler {
             channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_TEMPERATURE);
             updateState(channel, new QuantityType<>(vehicleSoC, SIUnits.CELSIUS));
         } else {
-            vehicleFeatureHeating.remove(vehicleName);
-
             float limitSoC = loadpoint.getLimitSoC();
             channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_LIMIT_SOC);
             updateState(channel, new QuantityType<>(limitSoC, Units.PERCENT));
@@ -785,10 +843,6 @@ public class EvccHandler extends BaseThingHandler {
         channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_TITLE);
         updateState(channel, new StringType(title));
 
-        float vehicleCapacity = loadpoint.getVehicleCapacity();
-        channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_CAPACITY);
-        updateState(channel, new QuantityType<>(vehicleCapacity, Units.KILOWATT_HOUR));
-
         float vehicleOdometer = loadpoint.getVehicleOdometer();
         channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_ODOMETER);
         updateState(channel, new QuantityType<>(vehicleOdometer, MetricPrefix.KILO(SIUnits.METRE)));
@@ -800,62 +854,124 @@ public class EvccHandler extends BaseThingHandler {
         float vehicleRange = loadpoint.getVehicleRange();
         channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_RANGE);
         updateState(channel, new QuantityType<>(vehicleRange, MetricPrefix.KILO(SIUnits.METRE)));
+
+        if (vehicleName != null) {
+            updateChannelsVehicle(vehicleName, channelGroup);
+        }
     }
 
     private void updateChannelsVehicle(String vehicleName) {
+        updateChannelsVehicle(vehicleName, null);
+    }
+
+    private void updateChannelsVehicle(String vehicleName, @Nullable String loadpointName) {
         final Result result = this.result;
         if (result == null) {
             return;
         }
         final ThingUID uid = getThing().getUID();
-        Vehicle vehicle = result.getVehicles().get(vehicleName);
 
-        final String channelGroup;
-        boolean vehicleFeatureHeating = this.vehicleFeatureHeating.contains(vehicleName);
-        if (vehicleFeatureHeating) {
-            channelGroup = CHANNEL_GROUP_ID_HEATING + vehicleName;
+        boolean isHeating;
+        if (loadpointName == null) {
+            isHeating = this.vehicleFeatureHeating.contains(vehicleName);
+        } else {
+            isHeating = this.loadpointFeatureHeating.contains(loadpointName);
+        }
+        Vehicle vehicle = null;
+        if (!vehicleName.isBlank()) {
+            vehicle = result.getVehicles().get(vehicleName);
+        }
 
-            float minSoC = vehicle.getMinSoC();
-            ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_MIN_TEMPERATURE);
-            updateState(channel, new QuantityType<>(minSoC, SIUnits.CELSIUS));
+        String channelGroup;
+        if (isHeating) {
+            if (loadpointName == null) {
+                channelGroup = CHANNEL_GROUP_ID_HEATING + vehicleName;
+            } else {
+                channelGroup = loadpointName + CHANNEL_GROUP_ID_CURRENT;
+            }
 
-            float limitSoC = vehicle.getLimitSoC();
-            channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_LIMIT_TEMPERATURE);
-            updateState(channel, new QuantityType<>(limitSoC, SIUnits.CELSIUS));
+            if (vehicle == null) {
+                ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_MIN_TEMPERATURE);
+                updateState(channel, UnDefType.UNDEF);
 
-            String title = vehicle.getTitle();
-            channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_TITLE);
-            updateState(channel, new StringType(title));
-        } else {
-            channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName;
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_LIMIT_TEMPERATURE);
+                updateState(channel, UnDefType.UNDEF);
 
-            float minSoC = vehicle.getMinSoC();
-            ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_MIN_SOC);
-            updateState(channel, new QuantityType<>(minSoC, Units.PERCENT));
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_TITLE);
+                updateState(channel, UnDefType.UNDEF);
 
-            float limitSoC = vehicle.getLimitSoC();
-            channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_LIMIT_SOC);
-            updateState(channel, new QuantityType<>(limitSoC, Units.PERCENT));
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_CAPACITY);
+                updateState(channel, UnDefType.UNDEF);
+            } else {
+                float minSoC = vehicle.getMinSoC();
+                ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_MIN_TEMPERATURE);
+                updateState(channel, new QuantityType<>(minSoC, SIUnits.CELSIUS));
+
+                float limitSoC = vehicle.getLimitSoC();
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_LIMIT_TEMPERATURE);
+                updateState(channel, new QuantityType<>(limitSoC, SIUnits.CELSIUS));
 
-            String title = vehicle.getTitle();
-            channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_TITLE);
-            updateState(channel, new StringType(title));
+                String title = vehicle.getTitle();
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_TITLE);
+                updateState(channel, new StringType(title));
+
+                float capacity = vehicle.getCapacity();
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_CAPACITY);
+                updateState(channel, new QuantityType<>(capacity, Units.KILOWATT_HOUR));
+            }
+        } else {
+            if (loadpointName == null) {
+                channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName;
+            } else {
+                channelGroup = loadpointName + CHANNEL_GROUP_ID_CURRENT;
+            }
+            if (vehicle == null) {
+                ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_MIN_SOC);
+                updateState(channel, UnDefType.UNDEF);
+
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_LIMIT_SOC);
+                updateState(channel, UnDefType.UNDEF);
+
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_TITLE);
+                updateState(channel, UnDefType.UNDEF);
+
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_CAPACITY);
+                updateState(channel, UnDefType.UNDEF);
+            } else {
+                float minSoC = vehicle.getMinSoC();
+                ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_MIN_SOC);
+                updateState(channel, new QuantityType<>(minSoC, Units.PERCENT));
+
+                float limitSoC = vehicle.getLimitSoC();
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_LIMIT_SOC);
+                updateState(channel, new QuantityType<>(limitSoC, Units.PERCENT));
+
+                String title = vehicle.getTitle();
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_TITLE);
+                updateState(channel, new StringType(title));
+
+                float capacity = vehicle.getCapacity();
+                channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_CAPACITY);
+                updateState(channel, new QuantityType<>(capacity, Units.KILOWATT_HOUR));
+            }
         }
 
-        Plan plan = vehicle.getPlan();
+        Plan plan = null;
+        if (vehicle != null) {
+            vehicle.getPlan();
+        }
         if (plan == null && vehiclePlans.get(vehicleName) == null) {
             vehiclePlans.put(vehicleName, new Triple<>(false, 100f, ZonedDateTime.now().plusHours(12)));
         } else if (plan != null) {
             vehiclePlans.put(vehicleName, new Triple<>(true, plan.getSoC(), ZonedDateTime.parse(plan.getTime())));
         }
-        updateVehiclePlanChannel(vehicleName, uid, channelGroup, vehicleFeatureHeating);
+        updateVehiclePlanChannel(uid, vehicleName, channelGroup, isHeating);
     }
 
-    private void updateVehiclePlanChannel(String vehicleName, ThingUID uid, String channelGroup,
-            boolean vehicleFeatureHeating) {
+    private void updateVehiclePlanChannel(ThingUID uid, String vehicleName, String channelGroup, boolean isHeating) {
         Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName);
 
-        if (vehicleFeatureHeating) {
+        if (isHeating) {
             ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_PLAN_ENABLED);
             updateState(channel, planValues.getLeft() ? OnOffType.ON : OnOffType.OFF);
             channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_PLAN_TEMPERATURE);
index 6049c50c83e116fa1001a4570507374b3983f682..3792e43ce5b1e5fef0cd5cb494ceac5ef1b35a52 100644 (file)
@@ -82,9 +82,6 @@ public class Loadpoint {
     @SerializedName("title")
     private String title;
 
-    @SerializedName("vehicleCapacity")
-    private float vehicleCapacity;
-
     @SerializedName("vehicleOdometer")
     private float vehicleOdometer;
 
@@ -242,13 +239,6 @@ public class Loadpoint {
         return title;
     }
 
-    /**
-     * @return vehicle's capacity
-     */
-    public float getVehicleCapacity() {
-        return vehicleCapacity;
-    }
-
     /**
      * @return vehicle's odometer
      */
index 26882d15e81be67819c1a070f62a0190b904b82f..17be4740240ab7daa58893d62fdd48b8069162a9 100644 (file)
@@ -33,6 +33,9 @@ public class Vehicle {
     @SerializedName("limitSoc")
     private float limitSoC;
 
+    @SerializedName("capacity")
+    private float capacity;
+
     @SerializedName("plans")
     private Plan[] plans;
 
@@ -57,6 +60,13 @@ public class Vehicle {
         return limitSoC;
     }
 
+    /**
+     * @return vehicle's capacity
+     */
+    public float getCapacity() {
+        return capacity;
+    }
+
     /**
      * @return current plan for vehicle
      */
index d4f10ba981b5de8d577d90e270e10eafb1f7187b..21880c8a160a64bd71c9ac358f3ba417f383a9da 100644 (file)
@@ -18,12 +18,33 @@ 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.loadpoint.label = Loadpoint
+channel-group-type.evcc.loadpoint0.label = Loadpoint 0
+channel-group-type.evcc.loadpoint0current.label = Loadpoint 0: Current
+channel-group-type.evcc.loadpoint1.label = Loadpoint 1
+channel-group-type.evcc.loadpoint1current.label = Loadpoint 1: Current
+channel-group-type.evcc.loadpoint2.label = Loadpoint 2
+channel-group-type.evcc.loadpoint2current.label = Loadpoint 2: Current
+channel-group-type.evcc.loadpoint3.label = Loadpoint 3
+channel-group-type.evcc.loadpoint3current.label = Loadpoint 3: Current
+channel-group-type.evcc.loadpoint4.label = Loadpoint 4
+channel-group-type.evcc.loadpoint4current.label = Loadpoint 4: Current
+channel-group-type.evcc.loadpoint5.label = Loadpoint 5
+channel-group-type.evcc.loadpoint5current.label = Loadpoint 5: Current
+channel-group-type.evcc.loadpoint6.label = Loadpoint 6
+channel-group-type.evcc.loadpoint6current.label = Loadpoint 6: Current
+channel-group-type.evcc.loadpoint7.label = Loadpoint 7
+channel-group-type.evcc.loadpoint7current.label = Loadpoint 7: Current
+channel-group-type.evcc.loadpoint8.label = Loadpoint 8
+channel-group-type.evcc.loadpoint8current.label = Loadpoint 8: Current
+channel-group-type.evcc.loadpoint9.label = Loadpoint 9
+channel-group-type.evcc.loadpoint9current.label = Loadpoint 9: Current
 
 # channel types
 
 channel-type.evcc.activePhases.label = Charging Active Phases
 channel-type.evcc.activePhases.description = Current number of active phases while charging
+channel-type.evcc.availableVersion.label = Available Version
+channel-type.evcc.availableVersion.description = Available evcc update version
 channel-type.evcc.batteryCapacity.label = Battery Capacity
 channel-type.evcc.batteryCapacity.description = Capacity of (home) battery
 channel-type.evcc.batteryDischargeControl.label = Battery Discharge Control
@@ -64,7 +85,7 @@ 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.effectiveLimitSoC.label = Effective Charging Limit SoC
+channel-type.evcc.effectiveLimitSoC.label = Effective Charging Limit
 channel-type.evcc.effectiveLimitSoC.description = Effective state of charge (SoC) until which the vehicle will be charged
 channel-type.evcc.effectiveLimitTemperature.label = Effective Charging Limit Temperature
 channel-type.evcc.effectiveLimitTemperature.description = Effective Temperature until which the heating device will be charged
@@ -74,7 +95,9 @@ 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.heatingLimitTemperature.label = Heating Charging Limit Temperature
+channel-type.evcc.heatingCapacity.label = Heating Capacity
+channel-type.evcc.heatingCapacity.description = Capacity of heating device
+channel-type.evcc.heatingLimitTemperature.label = Charging Temperature Limit
 channel-type.evcc.heatingLimitTemperature.description = Until which Temperature should the specific heating device be charged
 channel-type.evcc.heatingMinTemperature.label = Heating Min Temperature
 channel-type.evcc.heatingMinTemperature.description = Minimum Temperature a heating device should have
@@ -152,6 +175,12 @@ channel-type.evcc.vehicleTemperature.label = Temperature
 channel-type.evcc.vehicleTemperature.description = Current Temperature of the heating device
 channel-type.evcc.vehicleTitle.label = Vehicle Title
 channel-type.evcc.vehicleTitle.description = Title of vehicle
+channel-type.evcc.version.label = Version
+channel-type.evcc.version.description = Current evcc version
+
+# channel group types
+
+channel-group-type.evcc.loadpoint.label = Loadpoint
 
 # channel types
 
index a7ceac75ab91ec6ef16bc5bbd7610dca780de118..b9c062bbd24477af5cc81686e72b3b70e14e899f 100644 (file)
 
                <channel-groups>
                        <channel-group id="general" typeId="general"/>
-                       <channel-group id="loadpoint0" typeId="loadpoint"/>
-                       <channel-group id="loadpoint1" typeId="loadpoint"/>
-                       <channel-group id="loadpoint2" typeId="loadpoint"/>
-                       <channel-group id="loadpoint3" typeId="loadpoint"/>
-                       <channel-group id="loadpoint4" typeId="loadpoint"/>
-                       <channel-group id="loadpoint5" typeId="loadpoint"/>
-                       <channel-group id="loadpoint6" typeId="loadpoint"/>
-                       <channel-group id="loadpoint7" typeId="loadpoint"/>
-                       <channel-group id="loadpoint8" typeId="loadpoint"/>
-                       <channel-group id="loadpoint9" typeId="loadpoint"/>
+                       <channel-group id="loadpoint0" typeId="loadpoint0"/>
+                       <channel-group id="loadpoint1" typeId="loadpoint1"/>
+                       <channel-group id="loadpoint2" typeId="loadpoint2"/>
+                       <channel-group id="loadpoint3" typeId="loadpoint3"/>
+                       <channel-group id="loadpoint4" typeId="loadpoint4"/>
+                       <channel-group id="loadpoint5" typeId="loadpoint5"/>
+                       <channel-group id="loadpoint6" typeId="loadpoint6"/>
+                       <channel-group id="loadpoint7" typeId="loadpoint7"/>
+                       <channel-group id="loadpoint8" typeId="loadpoint8"/>
+                       <channel-group id="loadpoint9" typeId="loadpoint9"/>
+                       <channel-group id="loadpoint0current" typeId="loadpoint0current"/>
+                       <channel-group id="loadpoint1current" typeId="loadpoint1current"/>
+                       <channel-group id="loadpoint2current" typeId="loadpoint2current"/>
+                       <channel-group id="loadpoint3current" typeId="loadpoint3current"/>
+                       <channel-group id="loadpoint4current" typeId="loadpoint4current"/>
+                       <channel-group id="loadpoint5current" typeId="loadpoint5current"/>
+                       <channel-group id="loadpoint6current" typeId="loadpoint6current"/>
+                       <channel-group id="loadpoint7current" typeId="loadpoint7current"/>
+                       <channel-group id="loadpoint8current" typeId="loadpoint8current"/>
+                       <channel-group id="loadpoint9current" typeId="loadpoint9current"/>
                </channel-groups>
 
                <config-description>
        <channel-group-type id="general">
                <label>General Data</label>
        </channel-group-type>
-       <channel-group-type id="loadpoint">
-               <label>Loadpoint</label>
+       <channel-group-type id="loadpoint0">
+               <label>Loadpoint 0</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint1">
+               <label>Loadpoint 1</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint2">
+               <label>Loadpoint 2</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint3">
+               <label>Loadpoint 3</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint4">
+               <label>Loadpoint 4</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint5">
+               <label>Loadpoint 5</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint6">
+               <label>Loadpoint 6</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint7">
+               <label>Loadpoint 7</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint8">
+               <label>Loadpoint 8</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint9">
+               <label>Loadpoint 9</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint0current">
+               <label>Loadpoint 0: Current</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint1current">
+               <label>Loadpoint 1: Current</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint2current">
+               <label>Loadpoint 2: Current</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint3current">
+               <label>Loadpoint 3: Current</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint4current">
+               <label>Loadpoint 4: Current</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint5current">
+               <label>Loadpoint 5: Current</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint6current">
+               <label>Loadpoint 6: Current</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint7current">
+               <label>Loadpoint 7: Current</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint8current">
+               <label>Loadpoint 8: Current</label>
+       </channel-group-type>
+       <channel-group-type id="loadpoint9current">
+               <label>Loadpoint 9: Current</label>
        </channel-group-type>
 
        <!-- Units and description on: https://docs.evcc.io/docs/reference/configuration/messaging/#msg -->
                <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>
-               <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>
                <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
                <autoUpdatePolicy>veto</autoUpdatePolicy>
        </channel-type>
+       <channel-type id="vehicleCapacity">
+               <item-type>Number:Energy</item-type>
+               <label>Vehicle Capacity</label>
+               <description>Capacity of EV battery</description>
+               <category>Energy</category>
+               <state pattern="%.0f %unit%" readOnly="true"/>
+       </channel-type>
+       <channel-type id="heatingCapacity">
+               <item-type>Number:Energy</item-type>
+               <label>Heating Capacity</label>
+               <description>Capacity of heating device</description>
+               <category>Energy</category>
+               <state pattern="%.0f %unit%" readOnly="true"/>
+       </channel-type>
        <channel-type id="vehiclePlanEnabled">
                <item-type>Switch</item-type>
                <label>Vehicle Plan Enabled</label>