# 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.117.0](https://github.com/evcc-io/evcc/releases/tag/0.117.0) or newer and is tested with this version.
+The binding requires evcc [version 0.123.1](https://github.com/evcc-io/evcc/releases/tag/0.123.1) or newer and is tested with this version.
You can easily install and upgrade evcc on openHABian using `sudo openhabian-config`.
Those channels exist only once.
Please note that some of them are only available when evcc is properly configured.
-| Channel | Type | Read/Write | Description |
-|----------------------------|----------------------|------------|--------------------------------------------------------------------------------------------------------------|
-| 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 | 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. |
+| Channel | Type | Read/Write | Description |
+|---------------------------------|----------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 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#batteryDischargeControl | Switch | RW | Enable or disable battery discharge control |
+| general#batteryMode | String | R | Current battery mode |
+| general#prioritySoC | Number:Dimensionless | RW | State of State of Charge for which the battery has priority over charging the ev when charging mode is "pv" |
+| general#bufferSoC | Number:Dimensionless | RW | Until this State of Charge the discharging of a house battery is allowed in "pv" mode, when there is insufficient solar surplus (below the minimum charging power) |
+| general#bufferStartSoC | Number:Dimensionless | RW | State of Charge for which a charging session in "pv" mode is started, even if there is insufficient solar surplus |
+| general#residualPower | Number:Power | RW | Target operating point of the surplus regulation at the grid connection (grid meter) |
+| 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 |
### Loadpoint channels
Those channels exist per configured loadpoint.
Please note that you have to replace _N_ with your loadpoint number.
-| Channel | Type | Read/Write | Description |
-|-------------------------------------|------------------------|------------|-----------------------------------------------------------------------------------------------------|
-| loadpointN#activePhases | Number | R | Current number of active phases while charging |
-| loadpointN#chargeCurrent | Number:ElectricCurrent | R | Current amperage per connected phase while charging |
-| loadpointN#chargeDuration | Number:Time | R | Charging duration |
-| loadpointN#chargeRemainingDuration | Number:Time | R | Remaining duration until target SoC is reached |
-| loadpointN#chargeRemainingEnergy | Number:Energy | R | Remaining energy until target SoC is reached |
-| loadpointN#chargePower | Number:Power | R | Current power of charging |
-| 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#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 |
-| loadpointN#title | String | R | Title of loadpoint |
-| loadpointN#vehicleConnected | Switch | R | Whether vehicle is connected to loadpoint |
-| loadpointN#vehicleConnectedDuration | Number:Time | R | Duration the vehicle is connected to loadpoint |
-| loadpointN#vehicleCapacity | Number:Energy | R | Capacity of EV battery |
-| loadpointN#vehicleOdometer | Number:Length | R | Total distance travelled by EV |
-| loadpointN#vehiclePresent | Switch | R | Whether evcc is able to get data from vehicle |
-| loadpointN#vehicleRange | Number:Length | R | Battery range for EV |
-| loadpointN#vehicleSoC | Number:Dimensionless | R | Current State of Charge of EV |
-| loadpointN#vehicleTitle | String | R | Name of EV |
+| Channel | Type | Read/Write | Description |
+|-------------------------------------|------------------------|------------|-------------------------------------------------------------------------------------------------------------------|
+| loadpointN#activePhases | Number | R | Current number of active phases while charging |
+| loadpointN#chargeCurrent | Number:ElectricCurrent | R | Current amperage per connected phase while charging |
+| loadpointN#chargeDuration | Number:Time | R | Charging duration |
+| loadpointN#chargeRemainingDuration | Number:Time | R | Remaining duration until limit SoC is reached |
+| loadpointN#chargeRemainingEnergy | Number:Energy | R | Remaining energy until limit SoC is reached |
+| loadpointN#chargePower | Number:Power | R | Current power of charging |
+| 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#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#mode | String | RW | Charging mode: "off", "now", "minpv", "pv" |
+| loadpointN#phases | Number | RW | The maximum number of phases which can be used |
+| loadpointN#limitEnergy | Number:Energy | RW | Amount of energy to charge the vehicle with |
+| loadpointN#limitSoC | Number:Dimensionless | RW | Until which state of charge (SoC) should the vehicle be charged |
+| loadpointN#title | String | R | Title of loadpoint |
+| loadpointN#vehicleConnected | Switch | R | Whether vehicle is connected to loadpoint |
+| loadpointN#vehicleConnectedDuration | Number:Time | R | Duration the vehicle is connected to loadpoint |
+| loadpointN#vehicleCapacity | Number:Energy | R | Capacity of EV battery |
+| loadpointN#vehicleOdometer | Number:Length | R | Total distance travelled by EV |
+| loadpointN#vehiclePresent | Switch | R | Whether evcc is able to get data from vehicle |
+| loadpointN#vehicleRange | Number:Length | R | Battery range for EV |
+| loadpointN#vehicleSoC | Number:Dimensionless | R | Current State of Charge of EV |
+| loadpointN#vehicleName | String | R | The unique identifier of the EV used in the evcc configuration (containing no whitespaces nor special characters) |
+
+### Vehicle channels
+
+Those channels exist per configured vehicle.
+Please note that you have to replace _ID_ with your vehicle id/name.
+
+| Channel | Type | Read/Write | Description |
+|------------------------------|----------------------|------------|--------------------------------------------------------------------------|
+| vehicleID#vehicleTitle | String | R | Title of vehicle |
+| vehicleID#vehicleMinSoC | Number:Dimensionless | RW | Minimum state of charge (SoC) a vehicle should have |
+| vehicleID#vehicleLimitSoC | Number:Dimensionless | RW | Until which state of charge (SoC) should the specific vehicle be charged |
+| vehicleID#vehiclePlanEnabled | Switch | RW | Plan for charging enabled |
+| vehicleID#vehiclePlanSoC | Number:Dimensionless | RW | Until which state of charge (SoC) should vehicle be charged in plan |
+| vehicleID#vehiclePlanTime | DateTime | RW | When the plan SoC should be reached |
## Full Example
```java
// General
-Number:General evcc_batteryCapacity "Battery Capacity [%.0f kWH]" <energy> {channel="evcc:device:demo:general#batteryCapacity"}
-Number:Power evcc_batteryPower "Battery Power [%.1f kW]" <energy> {channel="evcc:device:demo:general#batteryPower"}
-Number:Dimensionless evcc_batterySoC "Battery SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:general#batterySoC"}
-Number:Dimensionless evcc_batteryPrioritySoC "Battery Priority SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:general#batteryPrioritySoC"}
-Number:Power evcc_gridPower "Grid Power [%.1f kW]" <energy> {channel="evcc:device:demo:general#gridPower"}
-Number:Power evcc_homePower "Home Power [%.1f kW]" <energy> {channel="evcc:device:demo:general#homePower"}
-Number:Power evcc_pvPower "PV Power [%.1f kW]" <energy> {channel="evcc:device:demo:general#pvPower"}
+Number:Energy evcc_batteryCapacity "Battery Capacity [%.0f kWh]" <energy> {channel="evcc:device:demo:general#batteryCapacity"}
+Number:Power evcc_batteryPower "Battery Power [%.1f kW]" <energy> {channel="evcc:device:demo:general#batteryPower"}
+Number:Dimensionless evcc_batterySoC "Battery SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:general#batterySoC"}
+Switch evcc_batteryDischargeControl "Battery Discharge Control [%s]" <switch> {channel="evcc:device:demo:general#batteryDischargeControl"}
+String evcc_batteryMode "Battery Mode [%s]" <battery> {channel="evcc:device:demo:general#batteryMode"}
+Number:Dimensionless evcc_prioritySoC "Battery Priority SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:general#prioritySoC"}
+Number:Dimensionless evcc_bufferSoC "Battery Buffer SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:general#bufferSoC"}
+Number:Dimensionless evcc_bufferStartSoC "Battery Buffer Start SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:general#bufferStartSoC"}
+Number:Power evcc_residualPower "Grid Residual Power [%.1f kW]" <energy> {channel="evcc:device:demo:general#residualPower"}
+Number:Power evcc_gridPower "Grid Power [%.1f kW]" <energy> {channel="evcc:device:demo:general#gridPower"}
+Number:Power evcc_homePower "Home Power [%.1f kW]" <energy> {channel="evcc:device:demo:general#homePower"}
+Number:Power evcc_pvPower "PV Power [%.1f kW]" <energy> {channel="evcc:device:demo:general#pvPower"}
// Loadpoint
-Number evcc_loadpoint0_activePhases "Active Phases [%d]" {channel="evcc:device:demo:loadpoint0#activePhases"}
-Number:ElectricCurrent evcc_loadpoint0_chargeCurrent "Charging current [%.0f A]" <energy> {channel="evcc:device:demo:loadpoint0#chargeCurrent"}
-Number:Time evcc_loadpoint0_chargeDuration "Charging duration [%1$tH:%1$tM]" <time> {channel="evcc:device:demo:loadpoint0#chargeDuration"}
-Number:Time evcc_loadpoint0_chargeRemainingDuration "Charging remaining duration [%1$tH:%1$tM]" <time> {channel="evcc:device:demo:loadpoint0#chargeRemainingDuration"}
-Number:Energy evcc_loadpoint0_chargeRemainingEnergy "Charging remaining energy [%.1f kWh]" <energy> {channel="evcc:device:demo:loadpoint0#chargeRemainingEnergy"}
-Number:Power evcc_loadpoint0_chargePower "Charging power [%.1f kW]" <energy> {channel="evcc:device:demo:loadpoint0#chargePower"}
-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"}
-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"}
-String evcc_loadpoint0_title "Loadpoint title [%s]" <text> {channel="evcc:device:demo:loadpoint0#title"}
+Number evcc_loadpoint0_activePhases "Active Phases [%d]" {channel="evcc:device:demo:loadpoint0#activePhases"}
+Number:ElectricCurrent evcc_loadpoint0_chargeCurrent "Charging current [%.0f A]" <energy> {channel="evcc:device:demo:loadpoint0#chargeCurrent"}
+Number:Time evcc_loadpoint0_chargeDuration "Charging duration [%1$tH:%1$tM]" <time> {channel="evcc:device:demo:loadpoint0#chargeDuration"}
+Number:Time evcc_loadpoint0_chargeRemainingDuration "Charging remaining duration [%1$tH:%1$tM]" <time> {channel="evcc:device:demo:loadpoint0#chargeRemainingDuration"}
+Number:Energy evcc_loadpoint0_chargeRemainingEnergy "Charging remaining energy [%.1f kWh]" <energy> {channel="evcc:device:demo:loadpoint0#chargeRemainingEnergy"}
+Number:Power evcc_loadpoint0_chargePower "Charging power [%.1f kW]" <energy> {channel="evcc:device:demo:loadpoint0#chargePower"}
+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"}
+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"}
+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_limitEnergy "Limit energy [%.1f kWh]" <batterylevel> {channel="evcc:device:demo:loadpoint0#limitEnergy"}
+Number:Dimensionless evcc_loadpoint0_limitSoC "Limit SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:loadpoint0#limitSoC"}
+String evcc_loadpoint0_title "Loadpoint title [%s]" <text> {channel="evcc:device:demo:loadpoint0#title"}
// Vehicle on loadpoint
-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#vehicleTitle"}
+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:loadpoint0#targetTime"}
```
### Sitemap
}
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_limitEnergy minValue=5 maxValue=100 step=5
+ Setpoint item=evcc_loadpoint0_limitSoC 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
Setpoint item=evcc_loadpoint0_minSoC minValue=0 maxValue=100 step=5
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
}
}
}
* used across the whole binding.
*
* @author Florian Hotze - Initial contribution
+ * @author Luca Arnecke - Update to evcc version 0.123.1
*/
@NonNullByDefault
public class EvccBindingConstants {
private static final String BINDING_ID = "evcc";
public static final String CHANNEL_GROUP_ID_GENERAL = "general";
+ public static final String CHANNEL_GROUP_ID_LOADPOINT = "loadpoint";
+ public static final String CHANNEL_GROUP_ID_VEHICLE = "vehicle";
// List of all Channel ids
public static final String CHANNEL_BATTERY_CAPACITY = "batteryCapacity";
public static final String CHANNEL_BATTERY_POWER = "batteryPower";
public static final String CHANNEL_BATTERY_SOC = "batterySoC";
- public static final String CHANNEL_BATTERY_PRIORITY_SOC = "batteryPrioritySoC";
+ public static final String CHANNEL_BATTERY_DISCHARGE_CONTROL = "batteryDischargeControl";
+ public static final String CHANNEL_BATTERY_MODE = "batteryMode";
+ public static final String CHANNEL_PRIORITY_SOC = "prioritySoC";
+ public static final String CHANNEL_BUFFER_SOC = "bufferSoC";
+ public static final String CHANNEL_BUFFER_START_SOC = "bufferStartSoC";
+ public static final String CHANNEL_RESIDUAL_POWER = "residualPower";
public static final String CHANNEL_GRID_POWER = "gridPower";
public static final String CHANNEL_HOME_POWER = "homePower";
public static final String CHANNEL_PV_POWER = "pvPower";
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_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";
- /**
- * Whether a target time is set on loadpoint.
- */
- public static final String CHANNEL_LOADPOINT_TARGET_TIME_ENABLED = "targetTimeEnabled";
+ public static final String CHANNEL_LOADPOINT_LIMIT_ENERGY = "limitEnergy";
+ public static final String CHANNEL_LOADPOINT_LIMIT_SOC = "limitSoC";
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";
public static final String CHANNEL_LOADPOINT_VEHICLE_SOC = "vehicleSoC";
- public static final String CHANNEL_LOADPOINT_VEHICLE_TITLE = "vehicleTitle";
+ public static final String CHANNEL_LOADPOINT_VEHICLE_NAME = "vehicleName";
+ public static final String CHANNEL_VEHICLE_TITLE = "vehicleTitle";
+ public static final String CHANNEL_VEHICLE_MIN_SOC = "vehicleMinSoC";
+ public static final String CHANNEL_VEHICLE_LIMIT_SOC = "vehicleLimitSoC";
+ public static final String CHANNEL_VEHICLE_PLAN_ENABLED = "vehiclePlanEnabled";
+ public static final String CHANNEL_VEHICLE_PLAN_SOC = "vehiclePlanSoC";
+ public static final String CHANNEL_VEHICLE_PLAN_TIME = "vehiclePlanTime";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "device");
CHANNEL_BATTERY_POWER);
public static final ChannelTypeUID CHANNEL_TYPE_UID_BATTERY_SOC = new ChannelTypeUID(BINDING_ID,
CHANNEL_BATTERY_SOC);
- public static final ChannelTypeUID CHANNEL_TYPE_UID_BATTERY_PRIORITY_SOC = new ChannelTypeUID(BINDING_ID,
- CHANNEL_BATTERY_PRIORITY_SOC);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_BATTERY_DISCHARGE_CONTROL = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_BATTERY_DISCHARGE_CONTROL);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_BATTERY_MODE = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_BATTERY_MODE);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_PRIORITY_SOC = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_PRIORITY_SOC);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_BUFFER_SOC = new ChannelTypeUID(BINDING_ID, CHANNEL_BUFFER_SOC);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_BUFFER_START_SOC = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_BUFFER_START_SOC);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_RESIDUAL_POWER = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_RESIDUAL_POWER);
public static final ChannelTypeUID CHANNEL_TYPE_UID_GRID_POWER = new ChannelTypeUID(BINDING_ID, CHANNEL_GRID_POWER);
public static final ChannelTypeUID CHANNEL_TYPE_UID_HOME_POWER = new ChannelTypeUID(BINDING_ID, CHANNEL_HOME_POWER);
public static final ChannelTypeUID CHANNEL_TYPE_UID_PV_POWER = new ChannelTypeUID(BINDING_ID, CHANNEL_PV_POWER);
CHANNEL_LOADPOINT_MAX_CURRENT);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_MIN_CURRENT = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_MIN_CURRENT);
- public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_MIN_SOC = new ChannelTypeUID(BINDING_ID,
- CHANNEL_LOADPOINT_MIN_SOC);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_MODE = new ChannelTypeUID(BINDING_ID,
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,
- CHANNEL_LOADPOINT_TARGET_TIME);
- public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_TARGET_TIME_ENABLED = new ChannelTypeUID(BINDING_ID,
- CHANNEL_LOADPOINT_TARGET_TIME_ENABLED);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_LIMIT_ENERGY = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_LOADPOINT_LIMIT_ENERGY);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_LIMIT_SOC = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_LOADPOINT_LIMIT_SOC);
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_RANGE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_SOC = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_VEHICLE_SOC);
- public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_TITLE = new ChannelTypeUID(BINDING_ID,
- CHANNEL_LOADPOINT_VEHICLE_TITLE);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_NAME = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_LOADPOINT_VEHICLE_NAME);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_TITLE = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_VEHICLE_TITLE);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_MIN_SOC = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_VEHICLE_MIN_SOC);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_LIMIT_SOC = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_VEHICLE_LIMIT_SOC);
+ 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_VEHICLE_PLAN_SOC = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_VEHICLE_PLAN_SOC);
+ public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_PLAN_TIME = new ChannelTypeUID(BINDING_ID,
+ CHANNEL_VEHICLE_PLAN_TIME);
public static final int CONNECTION_TIMEOUT_MILLISEC = 5000;
public static final int LONG_CONNECTION_TIMEOUT_MILLISEC = 60000;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.openhab.binding.evcc.internal.api.EvccAPI;
import org.openhab.binding.evcc.internal.api.EvccApiException;
import org.openhab.binding.evcc.internal.api.dto.Loadpoint;
+import org.openhab.binding.evcc.internal.api.dto.Plan;
import org.openhab.binding.evcc.internal.api.dto.Result;
+import org.openhab.binding.evcc.internal.api.dto.Vehicle;
import org.openhab.core.library.CoreItemFactory;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
* sent to one of the channels.
*
* @author Florian Hotze - Initial contribution
+ * @author Luca Arnecke - Update to evcc version 0.123.1
*/
@NonNullByDefault
public class EvccHandler extends BaseThingHandler {
private boolean batteryConfigured = false;
private boolean gridConfigured = false;
private boolean pvConfigured = false;
-
- private boolean targetTimeEnabled = false;
- private ZonedDateTime targetTimeZDT = ZonedDateTime.now().plusHours(12);
+ Map<String, Triple<Boolean, Float, ZonedDateTime>> vehiclePlans = new HashMap<>();
public EvccHandler(Thing thing) {
super(thing);
if (groupId == null) {
return;
}
- String channelGroupId = channelUID.getGroupId();
String channelIdWithoutGroup = channelUID.getIdWithoutGroup();
EvccAPI evccAPI = this.evccAPI;
if (evccAPI == null) {
return;
}
try {
- 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;
+ if (groupId.equals(CHANNEL_GROUP_ID_GENERAL)) {
switch (channelIdWithoutGroup) {
- case CHANNEL_LOADPOINT_MODE -> {
- if (command instanceof StringType) {
- evccAPI.setMode(loadpoint, command.toString());
- } else {
- logger.debug("Command has wrong type, StringType required!");
- }
- }
- case CHANNEL_LOADPOINT_MIN_SOC -> {
+ case CHANNEL_PRIORITY_SOC -> {
if (command instanceof QuantityType<?> qt) {
- evccAPI.setMinSoC(loadpoint, qt.toUnit(Units.PERCENT).intValue());
+ evccAPI.setPrioritySoC(qt.toUnit(Units.PERCENT).intValue());
} else if (command instanceof DecimalType dt) {
- evccAPI.setMinSoC(loadpoint, dt.intValue());
+ evccAPI.setPrioritySoC(dt.intValue());
} else {
logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
}
- case CHANNEL_LOADPOINT_TARGET_ENERGY -> {
+ case CHANNEL_BUFFER_SOC -> {
if (command instanceof QuantityType<?> qt) {
- evccAPI.setTargetEnergy(loadpoint, qt.toUnit(Units.WATT_HOUR).floatValue());
+ evccAPI.setBufferSoC(qt.toUnit(Units.PERCENT).intValue());
+ } else if (command instanceof DecimalType dt) {
+ evccAPI.setBufferSoC(dt.intValue());
} else {
- logger.debug("Command has wrong type, QuantityType required!");
+ logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
}
- case CHANNEL_LOADPOINT_TARGET_SOC -> {
+ case CHANNEL_BUFFER_START_SOC -> {
if (command instanceof QuantityType<?> qt) {
- evccAPI.setTargetSoC(loadpoint, qt.toUnit(Units.PERCENT).intValue());
+ evccAPI.setBufferStartSoC(qt.toUnit(Units.PERCENT).intValue());
} else if (command instanceof DecimalType dt) {
- evccAPI.setTargetSoC(loadpoint, dt.intValue());
+ evccAPI.setBufferStartSoC(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);
- }
- }
+ case CHANNEL_RESIDUAL_POWER -> {
+ if (command instanceof QuantityType<?> qt) {
+ evccAPI.setResidualPower(qt.toUnit(Units.WATT).intValue());
+ } else if (command instanceof DecimalType dt) {
+ evccAPI.setResidualPower(dt.intValue());
} else {
- logger.debug("Command has wrong type, DateTimeType required!");
+ logger.debug("Command has wrong type, QuantityType or DecimalType required!");
}
}
- case CHANNEL_LOADPOINT_TARGET_TIME_ENABLED -> {
+ case CHANNEL_BATTERY_DISCHARGE_CONTROL -> {
if (command == OnOffType.ON) {
- evccAPI.setTargetTime(loadpoint, targetTimeZDT);
- targetTimeEnabled = true;
+ evccAPI.setBatteryDischargeControl(true);
} else if (command == OnOffType.OFF) {
- evccAPI.removeTargetTime(loadpoint);
- targetTimeEnabled = false;
+ evccAPI.setBatteryDischargeControl(false);
} else {
logger.debug("Command has wrong type, OnOffType required!");
}
}
+ default -> {
+ return;
+ }
+ }
+ } else if (groupId.startsWith(CHANNEL_GROUP_ID_LOADPOINT)) {
+ int loadpoint = Integer.parseInt(groupId.substring(9)) + 1;
+ switch (channelIdWithoutGroup) {
+ case CHANNEL_LOADPOINT_MODE -> {
+ if (command instanceof StringType) {
+ evccAPI.setMode(loadpoint, command.toString());
+ } else {
+ logger.debug("Command has wrong type, StringType required!");
+ }
+ }
+ case CHANNEL_LOADPOINT_LIMIT_ENERGY -> {
+ if (command instanceof QuantityType<?> qt) {
+ evccAPI.setLimitEnergy(loadpoint, qt.toUnit(Units.WATT_HOUR).floatValue());
+ } else if (command instanceof DecimalType dt) {
+ // DecimalType commands are interpreted as 'kWh'
+ evccAPI.setLimitEnergy(loadpoint, dt.intValue() * 1000);
+ } else {
+ logger.debug("Command has wrong type, QuantityType required!");
+ }
+ }
+ case CHANNEL_LOADPOINT_LIMIT_SOC -> {
+ if (command instanceof QuantityType<?> qt) {
+ evccAPI.setLimitSoC(loadpoint, qt.toUnit(Units.PERCENT).intValue());
+ } else if (command instanceof DecimalType dt) {
+ evccAPI.setLimitSoC(loadpoint, dt.intValue());
+ } else {
+ logger.debug("Command has wrong type, QuantityType or DecimalType required!");
+ }
+ }
case CHANNEL_LOADPOINT_PHASES -> {
if (command instanceof DecimalType dt) {
evccAPI.setPhases(loadpoint, dt.intValue());
return;
}
}
+ } else if (groupId.startsWith(CHANNEL_GROUP_ID_VEHICLE)) {
+ String vehicleName = groupId.substring(7);
+ switch (channelIdWithoutGroup) {
+ case CHANNEL_VEHICLE_MIN_SOC -> {
+ if (command instanceof QuantityType<?> qt) {
+ evccAPI.setVehicleMinSoC(vehicleName, qt.toUnit(Units.PERCENT).intValue());
+ } else if (command instanceof DecimalType dt) {
+ evccAPI.setVehicleMinSoC(vehicleName, dt.intValue());
+ } else {
+ logger.debug("Command has wrong type, QuantityType or DecimalType required!");
+ }
+ }
+ case CHANNEL_VEHICLE_LIMIT_SOC -> {
+ if (command instanceof QuantityType<?> qt) {
+ evccAPI.setVehicleLimitSoC(vehicleName, qt.toUnit(Units.PERCENT).intValue());
+ } else if (command instanceof DecimalType dt) {
+ evccAPI.setVehicleLimitSoC(vehicleName, dt.intValue());
+ } else {
+ logger.debug("Command has wrong type, QuantityType or DecimalType required!");
+ }
+ }
+ case CHANNEL_VEHICLE_PLAN_ENABLED -> {
+ Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName);
+ if (command == OnOffType.ON) {
+ evccAPI.setVehiclePlan(vehicleName, planValues.getMiddle().intValue(),
+ planValues.getRight());
+ vehiclePlans.put(vehicleName,
+ new Triple<>(true, planValues.getMiddle(), planValues.getRight()));
+ } else if (command == OnOffType.OFF) {
+ evccAPI.removeVehiclePlan(vehicleName);
+ vehiclePlans.put(vehicleName,
+ new Triple<>(false, planValues.getMiddle(), planValues.getRight()));
+ } else {
+ logger.debug("Command has wrong type, OnOffType required!");
+ }
+ }
+ case CHANNEL_VEHICLE_PLAN_SOC -> {
+ Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName);
+ if (command instanceof QuantityType<?> qt) {
+ vehiclePlans.put(vehicleName, new Triple<>(planValues.getLeft(),
+ qt.toUnit(Units.PERCENT).floatValue(), planValues.getRight()));
+ if (planValues.getLeft()) {
+ evccAPI.setVehiclePlan(vehicleName, qt.toUnit(Units.PERCENT).intValue(),
+ planValues.getRight());
+ }
+ } else if (command instanceof DecimalType dt) {
+ vehiclePlans.put(vehicleName,
+ new Triple<>(planValues.getLeft(), dt.floatValue(), planValues.getRight()));
+ if (planValues.getLeft()) {
+ evccAPI.setVehiclePlan(vehicleName, dt.intValue(), planValues.getRight());
+ }
+ } else {
+ logger.debug("Command has wrong type, QuantityType or DecimalType required!");
+ }
+ }
+ case CHANNEL_VEHICLE_PLAN_TIME -> {
+ Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName);
+ if (command instanceof DateTimeType dtt) {
+ vehiclePlans.put(vehicleName, new Triple<>(planValues.getLeft(), planValues.getMiddle(),
+ dtt.getZonedDateTime()));
+ if (planValues.getLeft()) {
+ try {
+ evccAPI.setVehiclePlan(vehicleName, planValues.getMiddle().intValue(),
+ dtt.getZonedDateTime());
+ } catch (DateTimeParseException e) {
+ logger.debug("Failed to set vehicle plan time: ", e);
+ }
+ }
+ } else {
+ logger.debug("Command has wrong type, DateTimeType required!");
+ }
+ }
+ default -> {
+ return;
+ }
+ }
}
} catch (EvccApiException e) {
Throwable cause = e.getCause();
String sitename = result.getSiteTitle();
int numberOfLoadpoints = result.getLoadpoints().length;
logger.debug("Found {} loadpoints on site {}.", numberOfLoadpoints, sitename);
+ Map<String, Vehicle> vehicles = result.getVehicles();
+ logger.debug("Found {} vehicles on site {}.", vehicles.size(), sitename);
updateStatus(ThingStatus.ONLINE);
batteryConfigured = result.getBatteryConfigured();
gridConfigured = result.getGridConfigured();
createChannelsLoadpoint(i);
updateChannelsLoadpoint(i);
}
+ for (String vehicleName : vehicles.keySet()) {
+ createChannelsVehicle(vehicleName);
+ updateChannelsVehicle(vehicleName);
+ }
}
}
"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,
+ createChannel(CHANNEL_BATTERY_DISCHARGE_CONTROL, CHANNEL_GROUP_ID_GENERAL,
+ CHANNEL_TYPE_UID_BATTERY_DISCHARGE_CONTROL, "Switch");
+ createChannel(CHANNEL_BATTERY_MODE, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_BATTERY_MODE, "String");
+ createChannel(CHANNEL_PRIORITY_SOC, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_PRIORITY_SOC,
+ "Number:Dimensionless");
+ createChannel(CHANNEL_BUFFER_SOC, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_BUFFER_SOC,
+ "Number:Dimensionless");
+ createChannel(CHANNEL_BUFFER_START_SOC, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_BUFFER_START_SOC,
"Number:Dimensionless");
+ createChannel(CHANNEL_RESIDUAL_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_RESIDUAL_POWER,
+ "Number:Power");
}
if (gridConfigured) {
createChannel(CHANNEL_GRID_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_GRID_POWER, "Number:Power");
if (pvConfigured) {
createChannel(CHANNEL_PV_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_PV_POWER, "Number:Power");
}
+ removeChannel("batteryPrioritySoC", CHANNEL_GROUP_ID_GENERAL);
}
private void createChannelsLoadpoint(int loadpointId) {
- final String channelGroup = "loadpoint" + loadpointId;
+ final String channelGroup = CHANNEL_GROUP_ID_LOADPOINT + loadpointId;
createChannel(CHANNEL_LOADPOINT_ACTIVE_PHASES, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_ACTIVE_PHASES,
CoreItemFactory.NUMBER);
createChannel(CHANNEL_LOADPOINT_CHARGE_CURRENT, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_CHARGE_CURRENT,
"Number:ElectricCurrent");
createChannel(CHANNEL_LOADPOINT_MIN_CURRENT, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_MIN_CURRENT,
"Number:ElectricCurrent");
- createChannel(CHANNEL_LOADPOINT_MIN_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_MIN_SOC,
- "Number:Dimensionless");
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,
+ createChannel(CHANNEL_LOADPOINT_LIMIT_ENERGY, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_LIMIT_ENERGY,
"Number:Energy");
- createChannel(CHANNEL_LOADPOINT_TARGET_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TARGET_SOC,
+ createChannel(CHANNEL_LOADPOINT_LIMIT_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_LIMIT_SOC,
"Number:Dimensionless");
- createChannel(CHANNEL_LOADPOINT_TARGET_TIME, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TARGET_TIME,
- CoreItemFactory.DATETIME);
- createChannel(CHANNEL_LOADPOINT_TARGET_TIME_ENABLED, channelGroup,
- CHANNEL_TYPE_UID_LOADPOINT_TARGET_TIME_ENABLED, CoreItemFactory.SWITCH);
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");
"Number:Length");
createChannel(CHANNEL_LOADPOINT_VEHICLE_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_SOC,
"Number:Dimensionless");
- createChannel(CHANNEL_LOADPOINT_VEHICLE_TITLE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_TITLE,
+ createChannel(CHANNEL_LOADPOINT_VEHICLE_NAME, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_NAME,
CoreItemFactory.STRING);
- removeChannel(CHANNEL_LOADPOINT_HAS_VEHICLE, channelGroup);
+ removeChannel("hasVehicle", channelGroup);
+ removeChannel("minSoC", channelGroup);
+ removeChannel("targetEnergy", channelGroup);
+ removeChannel("targetSoC", channelGroup);
+ removeChannel("targetTime", channelGroup);
+ removeChannel("targetTimeEnabled", channelGroup);
+ }
+
+ private void createChannelsVehicle(String vehicleName) {
+ final String channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName;
+ createChannel(CHANNEL_VEHICLE_TITLE, channelGroup, CHANNEL_TYPE_UID_VEHICLE_TITLE, CoreItemFactory.STRING);
+ 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,
+ "Number:Dimensionless");
+ createChannel(CHANNEL_VEHICLE_PLAN_SOC, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_SOC,
+ "Number:Dimensionless");
+ 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,
+ CoreItemFactory.SWITCH);
+ createChannel(CHANNEL_VEHICLE_PLAN_SOC, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_SOC,
+ "Number:Dimensionless");
+ createChannel(CHANNEL_VEHICLE_PLAN_TIME, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_TIME,
+ CoreItemFactory.DATETIME);
}
// Units and description for vars: https://docs.evcc.io/docs/reference/configuration/messaging/#msg
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, CHANNEL_GROUP_ID_GENERAL, CHANNEL_BATTERY_PRIORITY_SOC);
- updateState(channel, new QuantityType<>(batteryPrioritySoC, Units.PERCENT));
+ boolean batteryDischargeControl = result.getBatteryDischargeControl();
+ channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_BATTERY_DISCHARGE_CONTROL);
+ updateState(channel, OnOffType.from(batteryDischargeControl));
+
+ String batteryMode = result.getBatteryMode();
+ channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_BATTERY_MODE);
+ updateState(channel, new StringType(batteryMode));
+
+ float prioritySoC = result.getPrioritySoC();
+ channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_PRIORITY_SOC);
+ updateState(channel, new QuantityType<>(prioritySoC, Units.PERCENT));
+
+ float bufferSoC = result.getBufferSoC();
+ channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_BUFFER_SOC);
+ updateState(channel, new QuantityType<>(bufferSoC, Units.PERCENT));
+
+ float bufferStartSoC = result.getBufferStartSoC();
+ channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_BUFFER_START_SOC);
+ updateState(channel, new QuantityType<>(bufferStartSoC, Units.PERCENT));
+
+ float residualPower = result.getResidualPower();
+ channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_RESIDUAL_POWER);
+ updateState(channel, new QuantityType<>(residualPower, Units.WATT));
}
boolean gridConfigured = this.gridConfigured;
if (gridConfigured) {
return;
}
final ThingUID uid = getThing().getUID();
- final String loadpointName = "loadpoint" + loadpointId;
+ final String channelGroup = CHANNEL_GROUP_ID_LOADPOINT + loadpointId;
ChannelUID channel;
Loadpoint loadpoint = result.getLoadpoints()[loadpointId];
int activePhases = loadpoint.getActivePhases();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_ACTIVE_PHASES);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_ACTIVE_PHASES);
updateState(channel, new DecimalType(activePhases));
float chargeCurrent = loadpoint.getChargeCurrent();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_CHARGE_CURRENT);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CHARGE_CURRENT);
updateState(channel, new QuantityType<>(chargeCurrent, Units.AMPERE));
long chargeDuration = loadpoint.getChargeDuration();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_CHARGE_DURATION);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CHARGE_DURATION);
updateState(channel, new QuantityType<>(chargeDuration, MetricPrefix.NANO(Units.SECOND)));
float chargePower = loadpoint.getChargePower();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_CHARGE_POWER);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CHARGE_POWER);
updateState(channel, new QuantityType<>(chargePower, Units.WATT));
long chargeRemainingDuration = loadpoint.getChargeRemainingDuration();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_CHARGE_REMAINING_DURATION);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CHARGE_REMAINING_DURATION);
updateState(channel, new QuantityType<>(chargeRemainingDuration, MetricPrefix.NANO(Units.SECOND)));
float chargeRemainingEnergy = loadpoint.getChargeRemainingEnergy();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_CHARGE_REMAINING_ENERGY);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CHARGE_REMAINING_ENERGY);
updateState(channel, new QuantityType<>(chargeRemainingEnergy, Units.WATT_HOUR));
float chargedEnergy = loadpoint.getChargedEnergy();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_CHARGED_ENERGY);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CHARGED_ENERGY);
updateState(channel, new QuantityType<>(chargedEnergy, Units.WATT_HOUR));
boolean charging = loadpoint.getCharging();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_CHARGING);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CHARGING);
updateState(channel, OnOffType.from(charging));
boolean connected = loadpoint.getConnected();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_CONNECTED);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CONNECTED);
updateState(channel, OnOffType.from(connected));
long connectedDuration = loadpoint.getConnectedDuration();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_CONNECTED_DURATION);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CONNECTED_DURATION);
updateState(channel, new QuantityType<>(connectedDuration, MetricPrefix.NANO(Units.SECOND)));
boolean enabled = loadpoint.getEnabled();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_ENABLED);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_ENABLED);
updateState(channel, OnOffType.from(enabled));
float maxCurrent = loadpoint.getMaxCurrent();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_MAX_CURRENT);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_MAX_CURRENT);
updateState(channel, new QuantityType<>(maxCurrent, Units.AMPERE));
float minCurrent = loadpoint.getMinCurrent();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_MIN_CURRENT);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_MIN_CURRENT);
updateState(channel, new QuantityType<>(minCurrent, Units.AMPERE));
- float minSoC = loadpoint.getMinSoC();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_MIN_SOC);
- updateState(channel, new QuantityType<>(minSoC, Units.PERCENT));
-
String mode = loadpoint.getMode();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_MODE);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_MODE);
updateState(channel, new StringType(mode));
int phases = loadpoint.getPhases();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_PHASES);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_PHASES);
updateState(channel, new DecimalType(phases));
- float targetEnergy = loadpoint.getTargetEnergy();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_TARGET_ENERGY);
- updateState(channel, new QuantityType<>(targetEnergy, Units.WATT_HOUR));
+ float limitEnergy = loadpoint.getLimitEnergy();
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_LIMIT_ENERGY);
+ updateState(channel, new QuantityType<>(limitEnergy, 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 || "0001-01-01T00:00:00Z".equals(targetTime)) {
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_TARGET_TIME_ENABLED);
- updateState(channel, OnOffType.OFF);
- targetTimeEnabled = false;
- } else {
- this.targetTimeZDT = ZonedDateTime.parse(targetTime);
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_TARGET_TIME);
- updateState(channel, new DateTimeType(targetTimeZDT));
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_TARGET_TIME_ENABLED);
- updateState(channel, OnOffType.ON);
- targetTimeEnabled = true;
- }
+ float limitSoC = loadpoint.getLimitSoC();
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_LIMIT_SOC);
+ updateState(channel, new QuantityType<>(limitSoC, Units.PERCENT));
String title = loadpoint.getTitle();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_TITLE);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_TITLE);
updateState(channel, new StringType(title));
float vehicleCapacity = loadpoint.getVehicleCapacity();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_VEHICLE_CAPACITY);
+ 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, loadpointName, CHANNEL_LOADPOINT_VEHICLE_ODOMETER);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_ODOMETER);
updateState(channel, new QuantityType<>(vehicleOdometer, MetricPrefix.KILO(SIUnits.METRE)));
boolean vehiclePresent = loadpoint.getVehiclePresent();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_VEHICLE_PRESENT);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_PRESENT);
updateState(channel, OnOffType.from(vehiclePresent));
float vehicleRange = loadpoint.getVehicleRange();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_VEHICLE_RANGE);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_RANGE);
updateState(channel, new QuantityType<>(vehicleRange, MetricPrefix.KILO(SIUnits.METRE)));
float vehicleSoC = loadpoint.getVehicleSoC();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_VEHICLE_SOC);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_SOC);
updateState(channel, new QuantityType<>(vehicleSoC, Units.PERCENT));
- String vehicleTitle = loadpoint.getVehicleTitle();
- channel = new ChannelUID(uid, loadpointName, CHANNEL_LOADPOINT_VEHICLE_TITLE);
- updateState(channel, new StringType(vehicleTitle));
+ String vehicleName = loadpoint.getVehicleName();
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_NAME);
+ updateState(channel, new StringType(vehicleName));
+ }
+
+ private void updateChannelsVehicle(String vehicleName) {
+ final Result result = this.result;
+ if (result == null) {
+ return;
+ }
+ final ThingUID uid = getThing().getUID();
+ final String channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName;
+ ChannelUID channel;
+ Vehicle vehicle = result.getVehicles().get(vehicleName);
+
+ String title = vehicle.getTitle();
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_TITLE);
+ updateState(channel, new StringType(title));
+
+ float minSoC = vehicle.getMinSoC();
+ 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));
+
+ Plan plan = 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);
+ }
+
+ private void updateVehiclePlanChannel(String vehicleName, ThingUID uid, String channelGroup) {
+ Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName);
+
+ ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_PLAN_ENABLED);
+ updateState(channel, planValues.getLeft() ? OnOffType.ON : OnOffType.OFF);
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_PLAN_SOC);
+ updateState(channel, new QuantityType<>(planValues.getMiddle(), Units.PERCENT));
+ channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_PLAN_TIME);
+ updateState(channel, new DateTimeType(planValues.getRight()));
}
private void createChannel(String channel, String channelGroupId, ChannelTypeUID channelTypeUID, String itemType) {
updateThing(editThing().withoutChannel(channelUid).build());
}
}
+
+ private class Triple<L, M, R> {
+ private final L left;
+ private final M middle;
+ private final R right;
+
+ private Triple(L left, M middle, R right) {
+ this.left = left;
+ this.middle = middle;
+ this.right = right;
+ }
+
+ private L getLeft() {
+ return left;
+ }
+
+ private M getMiddle() {
+ return middle;
+ }
+
+ private R getRight() {
+ return right;
+ }
+ }
}
/**
* The {@link EvccAPI} is responsible for API calls to evcc.
- * API requests were written for evcc version 0.117.0
+ * API requests were written for evcc version 0.123.1
*
* @author Florian Hotze - Initial contribution
+ * @author Luca Arnecke - Update to evcc version 0.123.1
*/
@NonNullByDefault
public class EvccAPI {
}
// Site API calls.
- public String setBatteryPrioritySoC(int prioritySoc) throws EvccApiException {
+ public String setPrioritySoC(int prioritySoc) throws EvccApiException {
return httpRequest(this.host + EVCC_REST_API + "prioritysoc/" + prioritySoc, "POST");
}
+ public String setBufferSoC(int bufferSoC) throws EvccApiException {
+ return httpRequest(this.host + EVCC_REST_API + "buffersoc/" + bufferSoC, "POST");
+ }
+
+ public String setBufferStartSoC(int bufferStartSoC) throws EvccApiException {
+ return httpRequest(this.host + EVCC_REST_API + "bufferstartsoc/" + bufferStartSoC, "POST");
+ }
+
+ public String setResidualPower(int residualPower) throws EvccApiException {
+ return httpRequest(this.host + EVCC_REST_API + "residualpower/" + residualPower, "POST");
+ }
+
+ public String setBatteryDischargeControl(boolean batteryDischargeControl) throws EvccApiException {
+ return httpRequest(this.host + EVCC_REST_API + "batterydischargecontrol/" + batteryDischargeControl, "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");
}
- public String setMinSoC(int loadpoint, int minSoC) throws EvccApiException {
- 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,
+ public String setLimitEnergy(int loadpoint, float limitEnergy) throws EvccApiException {
+ return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/limitenergy/" + limitEnergy,
"POST");
}
- public String setTargetSoC(int loadpoint, int targetSoC) throws EvccApiException {
- return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/target/soc/" + targetSoC, "POST");
+ public String setLimitSoC(int loadpoint, int limitSoC) throws EvccApiException {
+ return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/limitsoc/" + limitSoC, "POST");
}
public String setPhases(int loadpoint, int phases) throws EvccApiException {
return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/maxcurrent/" + maxCurrent, "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");
+ // Vehicle specific API calls.
+ public String setVehicleMinSoC(String vehicleName, int minSoC) throws EvccApiException {
+ return httpRequest(this.host + EVCC_REST_API + "vehicles/" + vehicleName + "/minsoc/" + minSoC, "POST");
+ }
+
+ public String setVehicleLimitSoC(String vehicleName, int limitSoC) throws EvccApiException {
+ return httpRequest(this.host + EVCC_REST_API + "vehicles/" + vehicleName + "/limitsoc/" + limitSoC, "POST");
+ }
+
+ public String setVehiclePlan(String vehicleName, int planSoC, ZonedDateTime planTime) throws EvccApiException {
+ return httpRequest(this.host + EVCC_REST_API + "vehicles/" + vehicleName + "/plan/soc/" + planSoC + "/"
+ + planTime.toLocalDateTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + "Z", "POST");
}
- public String removeTargetTime(int loadpoint) throws EvccApiException {
- return httpRequest(this.host + EVCC_REST_API + "loadpoints/" + loadpoint + "/target/time", "DELETE");
+ public String removeVehiclePlan(String vehicleName) throws EvccApiException {
+ return httpRequest(this.host + EVCC_REST_API + "vehicles/" + vehicleName + "/plan/soc", "DELETE");
}
}
/**
* This class represents a loadpoint object of the status response (/api/state).
- * This DTO was written for evcc version 0.117.0
+ * This DTO was written for evcc version 0.123.1
*
* @author Florian Hotze - Initial contribution
+ * @author Luca Arnecke - Update to evcc version 0.123.1
*/
public class Loadpoint {
// Data types from https://github.com/evcc-io/evcc/blob/master/api/api.go
@SerializedName("minCurrent")
private float minCurrent;
- @SerializedName("minSoc")
- private float minSoC;
-
@SerializedName("mode")
private String mode;
@SerializedName("phasesEnabled")
private int phases;
- @SerializedName("planActive")
- private boolean planActive;
-
- @SerializedName("targetEnergy")
- private float targetEnergy;
+ @SerializedName("limitEnergy")
+ private float limitEnergy;
- @SerializedName("targetSoc")
- private float targetSoC;
+ @SerializedName("limitSoc")
+ private float limitSoC;
@SerializedName("targetTime")
private String targetTime;
@SerializedName("vehicleSoc")
private float vehicleSoC;
- @SerializedName("vehicleTitle")
- private String vehicleTitle;
+ @SerializedName("vehicleName")
+ private String vehicleName;
/**
* @return number of active phases
return minCurrent;
}
- /**
- * @return minimum state of charge
- */
- public float getMinSoC() {
- return minSoC;
- }
-
/**
* @return charging mode: off, now, minpv, pv
*/
}
/**
- * @return whether charging plan is active
- */
- public boolean getPlanActive() {
- return planActive;
- }
-
- /**
- * @return target energy
+ * @return limit energy
*/
- public float getTargetEnergy() {
- return targetEnergy;
+ public float getLimitEnergy() {
+ return limitEnergy;
}
/**
- * @return target state of charge (SoC)
+ * @return limit state of charge (SoC)
*/
- public float getTargetSoC() {
- return targetSoC;
+ public float getLimitSoC() {
+ return limitSoC;
}
/**
/**
* @return vehicle's title/name
*/
- public String getVehicleTitle() {
- return vehicleTitle;
+ public String getVehicleName() {
+ return vehicleName;
}
}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.evcc.internal.api.dto;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * This class represents a plan object of the status response (/api/state).
+ * This DTO was written for evcc version 0.123.1
+ *
+ * @author Luca Arnecke - Initial contribution
+ */
+public class Plan {
+ // Data types from https://github.com/evcc-io/evcc/blob/master/api/api.go
+ // and from https://docs.evcc.io/docs/reference/configuration/messaging/#msg
+
+ @SerializedName("soc")
+ private float soc;
+
+ @SerializedName("time")
+ private String time;
+
+ /**
+ * @return state of charge
+ */
+ public float getSoC() {
+ return soc;
+ }
+
+ /**
+ * @return time
+ */
+ public String getTime() {
+ return time;
+ }
+}
*/
package org.openhab.binding.evcc.internal.api.dto;
+import java.util.Map;
+
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.117.0
+ * This DTO was written for evcc version 0.123.1
*
* @author Florian Hotze - Initial contribution
+ * @author Luca Arnecke - update to evcc version 0.123.1
*/
public class Result {
// Data types from https://github.com/evcc-io/evcc/blob/master/api/api.go
@SerializedName("batterySoc")
private float batterySoC;
+ @SerializedName("batteryDischargeControl")
+ private boolean batteryDischargeControl;
+
+ @SerializedName("batteryMode")
+ private String batteryMode;
+
@SerializedName("gridConfigured")
private boolean gridConfigured;
private Loadpoint[] loadpoints;
@SerializedName("prioritySoc")
- private float batteryPrioritySoC;
+ private float prioritySoC;
+
+ @SerializedName("bufferSoc")
+ private float bufferSoC;
+
+ @SerializedName("bufferStartSoc")
+ private float bufferStartSoC;
+
+ @SerializedName("residualPower")
+ private float residualPower;
@SerializedName("pvConfigured")
private boolean pvConfigured;
@SerializedName("siteTitle")
private String siteTitle;
+ @SerializedName("vehicles")
+ private Map<String, Vehicle> vehicles;
+
/**
* @return battery's capacity
*/
/**
* @return battery's priority state of charge
*/
- public float getBatteryPrioritySoC() {
- return batteryPrioritySoC;
+ public float getPrioritySoC() {
+ return prioritySoC;
+ }
+
+ /**
+ * @return Battery Buffer SoC
+ */
+ public float getBufferSoC() {
+ return bufferSoC;
+ }
+
+ /**
+ * @return Battery Buffer Start SoC
+ */
+ public float getBufferStartSoC() {
+ return bufferStartSoC;
+ }
+
+ /**
+ * @return Grid Residual Power
+ */
+ public float getResidualPower() {
+ return residualPower;
}
/**
return batterySoC;
}
+ /**
+ * @return battery discharge control
+ */
+ public boolean getBatteryDischargeControl() {
+ return batteryDischargeControl;
+ }
+
+ /**
+ * @return battery mode
+ */
+ public String getBatteryMode() {
+ return batteryMode;
+ }
+
/**
* @return whether grid is configured
*/
public String getSiteTitle() {
return siteTitle;
}
+
+ public Map<String, Vehicle> getVehicles() {
+ return vehicles;
+ }
}
--- /dev/null
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.evcc.internal.api.dto;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * This class represents a vehicle object of the status response (/api/state).
+ * This DTO was written for evcc version 0.123.1
+ *
+ * @author Luca Arnecke - Initial contribution
+ */
+public class Vehicle {
+ // Data types from https://github.com/evcc-io/evcc/blob/master/api/api.go
+ // and from https://docs.evcc.io/docs/reference/configuration/messaging/#msg
+
+ @SerializedName("title")
+ private String title;
+
+ @SerializedName("minSoc")
+ private float minSoC;
+
+ @SerializedName("limitSoc")
+ private float limitSoC;
+
+ @SerializedName("plans")
+ private Plan[] plans;
+
+ /**
+ * @return vehicle name
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * @return minimum state of charge
+ */
+ public float getMinSoC() {
+ return minSoC;
+ }
+
+ /**
+ * @return limit state of charge
+ */
+ public float getLimitSoC() {
+ return limitSoC;
+ }
+
+ /**
+ * @return current plan for vehicle
+ */
+ public Plan getPlan() {
+ if (plans != null) {
+ return plans[0];
+ } else {
+ return null;
+ }
+ }
+}
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
+channel-type.evcc.batteryDischargeControl.label = Battery Discharge Control
+channel-type.evcc.batteryDischargeControl.description = Enable or disable battery discharge control
+channel-type.evcc.batteryDischargeControl.state.option.ON = Enabled
+channel-type.evcc.batteryDischargeControl.state.option.OFF = Disabled
+channel-type.evcc.batteryMode.label = Battery Mode
+channel-type.evcc.batteryMode.description = Current Battery Mode
channel-type.evcc.batteryPower.label = Battery Power
channel-type.evcc.batteryPower.description = Current power from battery
-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.bufferSoC.label = Battery Buffer SoC
+channel-type.evcc.bufferSoC.description = Until this State of Charge the discharging of a house battery is allowed in "pv" mode, when there is insufficient solar surplus (below the minimum charging power)
+channel-type.evcc.bufferStartSoC.label = Battery Buffer Start SoC
+channel-type.evcc.bufferStartSoC.description = State of Charge for which a charging session in "pv" mode is started, even if there is insufficient solar surplus
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.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.description = Remaining duration until target SoC is reached
+channel-type.evcc.chargeRemainingDuration.description = Remaining duration until limit SoC is reached
channel-type.evcc.chargeRemainingEnergy.label = Charging Remaining Energy
-channel-type.evcc.chargeRemainingEnergy.description = Remaining energy until target SoC is reached
+channel-type.evcc.chargeRemainingEnergy.description = Remaining energy until limit SoC is reached
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.gridPower.description = Current power from grid (negative means feed-in)
channel-type.evcc.homePower.label = Home Power
channel-type.evcc.homePower.description = Current power taken by home
+channel-type.evcc.limitEnergy.label = Charging Limit Energy
+channel-type.evcc.limitEnergy.description = Amount of energy to charge the vehicle with
+channel-type.evcc.limitSoC.label = Charging Limit SoC
+channel-type.evcc.limitSoC.description = Until which state of charge (SoC) should the vehicle be charged
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.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.description = Charging mode: "off", "now", "minpv", "pv"
channel-type.evcc.mode.state.option.off = Off
channel-type.evcc.mode.state.option.pv = Only PV
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.prioritySoC.label = Battery Priority SoC
+channel-type.evcc.prioritySoC.description = State of Charge for which the battery has priority over charging the EV when charging mode is "pv"
channel-type.evcc.pvPower.label = PV Power
channel-type.evcc.pvPower.description = Current power from photovoltaik
-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.description = When the target SoC should be reached
-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.residualPower.label = Grid Residual Power
+channel-type.evcc.residualPower.description = Target operating point of the surplus regulation at the grid connection (grid meter)
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.vehicleConnected.state.option.OFF = Not connected
channel-type.evcc.vehicleConnectedDuration.label = Vehicle Connected Duration
channel-type.evcc.vehicleConnectedDuration.description = Duration the vehicle is connected to loadpoint
+channel-type.evcc.vehicleLimitSoC.label = Vehicle Charging Limit SoC
+channel-type.evcc.vehicleLimitSoC.description = Until which state of charge (SoC) should the specific vehicle be charged
+channel-type.evcc.vehicleMinSoC.label = Vehicle Min SoC
+channel-type.evcc.vehicleMinSoC.description = Minimum state of charge (SoC) a vehicle should have
+channel-type.evcc.vehicleName.label = Vehicle Name
+channel-type.evcc.vehicleName.description = The unique identifier of the EV used in the evcc configuration (containing no whitespaces nor special characters)
channel-type.evcc.vehicleOdometer.label = Vehicle Odometer
channel-type.evcc.vehicleOdometer.description = Total distance travelled by EV
+channel-type.evcc.vehiclePlanEnabled.label = Vehicle Plan Enabled
+channel-type.evcc.vehiclePlanEnabled.description = Plan for charging enabled
+channel-type.evcc.vehiclePlanEnabled.state.option.ON = Enabled
+channel-type.evcc.vehiclePlanEnabled.state.option.OFF = Disabled
+channel-type.evcc.vehiclePlanSoC.label = Vehicle Plan SoC
+channel-type.evcc.vehiclePlanSoC.description = Until which state of charge (SoC) should vehicle be charged in plan
+channel-type.evcc.vehiclePlanTime.label = Vehicle Plan Time
+channel-type.evcc.vehiclePlanTime.description = When the plan SoC should be reached
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.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.description = Name of EV
+channel-type.evcc.vehicleTitle.description = Title of vehicle
+
+# channel types
+
+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".
# thing status description
<category>BatteryLevel</category>
<state pattern="%.0f %unit%" readOnly="true"/>
</channel-type>
- <channel-type id="batteryPrioritySoC">
+ <channel-type id="batteryDischargeControl">
+ <item-type>Switch</item-type>
+ <label>Battery Discharge Control</label>
+ <description>Enable or disable battery discharge control</description>
+ <category>Switch</category>
+ <state readOnly="false">
+ <options>
+ <option value="ON">Enabled</option>
+ <option value="OFF">Disabled</option>
+ </options>
+ </state>
+ </channel-type>
+ <channel-type id="batteryMode">
+ <item-type>String</item-type>
+ <label>Battery Mode</label>
+ <description>Current Battery Mode</description>
+ <category>Battery</category>
+ <state readOnly="true"/>
+ </channel-type>
+ <channel-type id="prioritySoC">
<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>
+ <description>State of Charge for which the battery has priority over charging the EV when charging mode is "pv"
+ </description>
+ <category>BatteryLevel</category>
+ <state min="0" step="0.1" max="100" pattern="%.0f %unit%" readOnly="false"/>
+ </channel-type>
+ <channel-type id="bufferSoC">
+ <item-type>Number:Dimensionless</item-type>
+ <label>Battery Buffer SoC</label>
+ <description>Until this State of Charge the discharging of a house battery is allowed in "pv" mode, when there is
+ insufficient solar surplus (below the minimum charging power)
+ </description>
+ <category>BatteryLevel</category>
+ <state min="0" step="0.1" max="100" pattern="%.0f %unit%" readOnly="false"/>
+ </channel-type>
+ <channel-type id="bufferStartSoC">
+ <item-type>Number:Dimensionless</item-type>
+ <label>Battery Buffer Start SoC</label>
+ <description>State of Charge for which a charging session in "pv" mode is started, even if there is insufficient solar
+ surplus
+ </description>
<category>BatteryLevel</category>
<state min="0" step="0.1" max="100" pattern="%.0f %unit%" readOnly="false"/>
</channel-type>
+ <channel-type id="residualPower">
+ <item-type>Number:Power</item-type>
+ <label>Grid Residual Power</label>
+ <description>Target operating point of the surplus regulation at the grid connection (grid meter)
+ </description>
+ <category>Energy</category>
+ <state min="0" step="1" pattern="%.0f %unit%" readOnly="false"/>
+ </channel-type>
<channel-type id="gridPower">
<item-type>Number:Power</item-type>
<label>Grid Power</label>
<state pattern="%.1f %unit%" readOnly="true"/>
</channel-type>
- <!-- Channels for loadpoints -->
+ <!-- Channel Types for loadpoints -->
<channel-type id="activePhases">
<item-type>Number</item-type>
<label>Charging Active Phases</label>
<channel-type id="chargeRemainingDuration">
<item-type>Number:Time</item-type>
<label>Charging Remaining Duration</label>
- <description>Remaining duration until target SoC is reached</description>
+ <description>Remaining duration until limit 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>
- <description>Remaining energy until target SoC is reached</description>
+ <description>Remaining energy until limit SoC is reached</description>
<category>Energy</category>
<state pattern="%.1f %unit%" readOnly="true"/>
</channel-type>
<state min="0" step="1" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>
- <channel-type id="minSoC">
- <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>
- <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>
<description>Charging mode: "off", "now", "minpv", "pv"</description>
- <category>String</category>
+ <category>Heating</category>
<state readOnly="false">
<options>
<option value="off">Off</option>
<state min="0" step="1" max="3" pattern="%d" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>
- <channel-type id="targetEnergy">
+ <channel-type id="limitEnergy">
<item-type>Number:Energy</item-type>
- <label>Charging Target Energy</label>
+ <label>Charging Limit Energy</label>
<description>Amount of energy to charge the vehicle with</description>
<category>BatteryLevel</category>
<state min="0" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>
- <channel-type id="targetSoC">
+ <channel-type id="limitSoC">
<item-type>Number:Dimensionless</item-type>
- <label>Charging Target SoC</label>
+ <label>Charging Limit SoC</label>
<description>Until which state of charge (SoC) should the vehicle be charged</description>
<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>
- <description>When the target SoC should be reached</description>
- <category>Time</category>
- <state readOnly="false"/>
- <autoUpdatePolicy>veto</autoUpdatePolicy>
- </channel-type>
- <channel-type id="targetTimeEnabled">
- <item-type>Switch</item-type>
- <label>Charging Target Time Enabled</label>
- <description>Target time for charging enabled</description>
- <category>Switch</category>
- <state readOnly="false">
- <options>
- <option value="ON">Enabled</option>
- <option value="OFF">Disabled</option>
- </options>
- </state>
- <autoUpdatePolicy>veto</autoUpdatePolicy>
- </channel-type>
<channel-type id="title">
<item-type>String</item-type>
<label>Loadpoint Title</label>
<description>Title of loadpoint</description>
- <category>Text</category>
+ <category>PowerOutlet</category>
<state readOnly="true"/>
</channel-type>
<channel-type id="vehicleConnected">
<item-type>Number:Length</item-type>
<label>Vehicle Odometer</label>
<description>Total distance travelled by EV</description>
- <category></category>
+ <category>MoveControl</category>
<state pattern="%.1f %unit%" readOnly="true"/>
</channel-type>
<channel-type id="vehiclePresent">
<category>BatteryLevel</category>
<state pattern="%.0f %unit%" readOnly="true"/>
</channel-type>
+ <channel-type id="vehicleName">
+ <item-type>String</item-type>
+ <label>Vehicle Name</label>
+ <description>The unique identifier of the EV used in the evcc configuration (containing no whitespaces nor special
+ characters)</description>
+ <category>Settings</category>
+ <state readOnly="true"/>
+ </channel-type>
+
+ <!-- Channel Types for vehicles -->
<channel-type id="vehicleTitle">
<item-type>String</item-type>
<label>Vehicle Title</label>
- <description>Name of EV</description>
- <category>Text</category>
+ <description>Title of vehicle</description>
+ <category>GarageDoor</category>
<state readOnly="true"/>
</channel-type>
+ <channel-type id="vehicleMinSoC">
+ <item-type>Number:Dimensionless</item-type>
+ <label>Vehicle Min SoC</label>
+ <description>Minimum state of charge (SoC) a vehicle should have</description>
+ <category>BatteryLevel</category>
+ <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
+ <autoUpdatePolicy>veto</autoUpdatePolicy>
+ </channel-type>
+ <channel-type id="vehicleLimitSoC">
+ <item-type>Number:Dimensionless</item-type>
+ <label>Vehicle Charging Limit SoC</label>
+ <description>Until which state of charge (SoC) should the specific vehicle be charged</description>
+ <category>BatteryLevel</category>
+ <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
+ <autoUpdatePolicy>veto</autoUpdatePolicy>
+ </channel-type>
+ <channel-type id="vehiclePlanEnabled">
+ <item-type>Switch</item-type>
+ <label>Vehicle Plan Enabled</label>
+ <description>Plan for charging enabled</description>
+ <category>Switch</category>
+ <state readOnly="false">
+ <options>
+ <option value="ON">Enabled</option>
+ <option value="OFF">Disabled</option>
+ </options>
+ </state>
+ <autoUpdatePolicy>veto</autoUpdatePolicy>
+ </channel-type>
+ <channel-type id="vehiclePlanSoC">
+ <item-type>Number:Dimensionless</item-type>
+ <label>Vehicle Plan SoC</label>
+ <description>Until which state of charge (SoC) should vehicle be charged in plan</description>
+ <category>BatteryLevel</category>
+ <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
+ <autoUpdatePolicy>veto</autoUpdatePolicy>
+ </channel-type>
+ <channel-type id="vehiclePlanTime">
+ <item-type>DateTime</item-type>
+ <label>Vehicle Plan Time</label>
+ <description>When the plan SoC should be reached</description>
+ <category>Time</category>
+ <state readOnly="false"/>
+ <autoUpdatePolicy>veto</autoUpdatePolicy>
+ </channel-type>
</thing:thing-descriptions>