[evcc] Add support of heating devices and three new channels (#16378)

* added effectiveLimitSoC, chargerFeatureHeating and chargerFeatureIntegratedDevice channels
support of heating devices (temperature) in addition to vehicles (SoC)

Signed-off-by: Michael Weger <weger.michael@gmx.net>
Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
MikeTheTux 2024-02-19 18:49:23 +01:00 committed by Ciprian Pascu
parent 90b90d4ca8
commit f4ce21b27b
7 changed files with 612 additions and 136 deletions

View File

@ -33,7 +33,7 @@ Default value for _refreshInterval_ is 60 seconds.
## Channels ## Channels
### General channels ### General Channels
Those channels exist only once. Those channels exist only once.
Please note that some of them are only available when evcc is properly configured. Please note that some of them are only available when evcc is properly configured.
@ -52,52 +52,84 @@ Please note that some of them are only available when evcc is properly configure
| general#gridPower | Number:Power | R | Current power from grid (negative means feed-in) | | general#gridPower | Number:Power | R | Current power from grid (negative means feed-in) |
| general#homePower | Number:Power | R | Current power taken by home | | general#homePower | Number:Power | R | Current power taken by home |
| general#pvPower | Number:Power | R | Current power from photovoltaik | | general#pvPower | Number:Power | R | Current power from photovoltaik |
| general#version | String | R | Current evcc version |
| general#availableVersion | String | R | Available evcc update version |
### Loadpoint channels ### Loadpoint Channels
Those channels exist per configured loadpoint. Those channels exist per configured loadpoint.
Please note that you have to replace _N_ with your loadpoint number. Please note that you have to replace _\<N\>_ with your loadpoint id/number.
| Channel | Type | Read/Write | Description | | Channel | Type | Read/Write | Description |
|-------------------------------------|------------------------|------------|-------------------------------------------------------------------------------------------------------------------| |-----------------------------------------------|------------------------|------------|-------------------------------------------------------------------------------------------------------------------|
| loadpointN#activePhases | Number | R | Current number of active phases while charging | | loadpoint\<N\>#activePhases | Number | R | Current number of active phases while charging |
| loadpointN#chargeCurrent | Number:ElectricCurrent | R | Current amperage per connected phase while charging | | loadpoint\<N\>#chargeCurrent | Number:ElectricCurrent | R | Current amperage per connected phase while charging |
| loadpointN#chargeDuration | Number:Time | R | Charging duration | | loadpoint\<N\>#chargeDuration | Number:Time | R | Charging duration |
| loadpointN#chargeRemainingDuration | Number:Time | R | Remaining duration until limit SoC is reached | | loadpoint\<N\>#chargeRemainingDuration | Number:Time | R | Remaining duration until limit SoC is reached |
| loadpointN#chargeRemainingEnergy | Number:Energy | R | Remaining energy until limit SoC is reached | | loadpoint\<N\>#chargeRemainingEnergy | Number:Energy | R | Remaining energy until limit SoC is reached |
| loadpointN#chargePower | Number:Power | R | Current power of charging | | loadpoint\<N\>#chargePower | Number:Power | R | Current power of charging |
| loadpointN#chargedEnergy | Number:Energy | R | Energy charged since plugged-in | | loadpoint\<N\>#chargedEnergy | Number:Energy | R | Energy charged since plugged-in |
| loadpointN#charging | Switch | R | Loadpoint is currently charging | | loadpoint\<N\>#charging | Switch | R | Loadpoint is currently charging |
| loadpointN#enabled | Switch | R | Charging enabled (mode is not "off") | | loadpoint\<N\>#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 | | loadpoint\<N\>#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 | | loadpoint\<N\>#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" | | loadpoint\<N\>#mode | String | RW | Charging mode: "off", "now", "minpv", "pv" |
| loadpointN#phases | Number | RW | The maximum number of phases which can be used | | loadpoint\<N\>#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 | | loadpoint\<N\>#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 | | loadpoint\<N\>#title | String | R | Title of loadpoint |
| loadpointN#title | String | R | Title of loadpoint | | loadpoint\<N\>#vehicleConnected | Switch | R | Whether vehicle is connected to loadpoint |
| loadpointN#vehicleConnected | Switch | R | Whether vehicle is connected to loadpoint | | loadpoint\<N\>#vehicleConnectedDuration | Number:Time | R | Duration the vehicle is connected to loadpoint |
| loadpointN#vehicleConnectedDuration | Number:Time | R | Duration the vehicle is connected to loadpoint | | loadpoint\<N\>#vehicleCapacity | Number:Energy | R | Capacity of EV battery |
| loadpointN#vehicleCapacity | Number:Energy | R | Capacity of EV battery | | loadpoint\<N\>#vehicleOdometer | Number:Length | R | Total distance travelled by EV |
| loadpointN#vehicleOdometer | Number:Length | R | Total distance travelled by EV | | loadpoint\<N\>#vehiclePresent | Switch | R | Whether evcc is able to get data from vehicle |
| loadpointN#vehiclePresent | Switch | R | Whether evcc is able to get data from vehicle | | loadpoint\<N\>#vehicleRange | Number:Length | R | Battery range for EV |
| loadpointN#vehicleRange | Number:Length | R | Battery range for EV | | loadpoint\<N\>#vehicleName | String | R | The unique identifier of the EV used in the evcc configuration (containing no whitespaces nor special characters) |
| loadpointN#vehicleSoC | Number:Dimensionless | R | Current State of Charge of EV | | loadpoint\<N\>#chargerFeatureHeating | Switch | R | 'True' for heating device: State of Charge in Degree instead of Percent |
| loadpointN#vehicleName | String | R | The unique identifier of the EV used in the evcc configuration (containing no whitespaces nor special characters) | | loadpoint\<N\>#chargerFeatureIntegratedDevice | Switch | R | 'True' for integrated device: Operate without a "vehicle" (e.g. heat pump, eBike) |
### Vehicle channels #### Loadpoint Channels Specific for Vehicles
| Channel | Type | Read/Write | Description |
|----------------------------------|----------------------|------------|-------------------------------------------------------------------------|
| loadpoint\<N\>#limitSoC | Number:Dimensionless | RW | Until which state of charge (SoC) should the vehicle be charged |
| loadpoint\<N\>#effectiveLimitSoC | Number:Dimensionless | R | Effective state of charge (SoC) until which the vehicle will be charged |
| loadpoint\<N\>#vehicleSoC | Number:Dimensionless | R | Current State of Charge of EV |
#### Loadpoint Channels Specific for Heating Devices
| Channel | Type | Read/Write | Description |
|------------------------------------------|--------------------|------------|----------------------------------------------------------------------|
| loadpoint\<N\>#limitTemperature | Number:Temperature | RW | Until which Temperature should the heating device be charged |
| loadpoint\<N\>#effectiveLimitTemperature | Number:Temperature | R | Effective Temperature until which the heating device will be charged |
| loadpoint\<N\>#vehicleTemperature | Number:Temperature | R | Current Temperature of the heating device |
### Vehicle Channels
Those channels exist per configured vehicle. Those channels exist per configured vehicle.
Please note that you have to replace _ID_ with your vehicle id/name. Please note that you have to replace _\<ID\>_ with your vehicle id/name.
| Channel | Type | Read/Write | Description | | Channel | Type | Read/Write | Description |
|------------------------------|----------------------|------------|--------------------------------------------------------------------------| |----------------------------------|----------------------|------------|--------------------------------------------------------------------------|
| vehicleID#vehicleTitle | String | R | Title of vehicle | | vehicle\<ID\>#vehicleTitle | String | R | Title of vehicle |
| vehicleID#vehicleMinSoC | Number:Dimensionless | RW | Minimum state of charge (SoC) a vehicle should have | | vehicle\<ID\>#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 | | vehicle\<ID\>#vehicleLimitSoC | Number:Dimensionless | RW | Until which state of charge (SoC) should the specific vehicle be charged |
| vehicleID#vehiclePlanEnabled | Switch | RW | Plan for charging enabled | | vehicle\<ID\>#vehiclePlanEnabled | Switch | RW | Plan for charging enabled |
| vehicleID#vehiclePlanSoC | Number:Dimensionless | RW | Until which state of charge (SoC) should vehicle be charged in plan | | vehicle\<ID\>#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 | | 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.
| 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 |
## Full Example ## Full Example
@ -111,53 +143,59 @@ Thing evcc:device:demo "evcc Demo" [url="https://demo.evcc.io", refreshInterval=
```java ```java
// General // General
Number:Energy evcc_batteryCapacity "Battery Capacity [%.0f kWh]" <energy> {channel="evcc:device:demo:general#batteryCapacity"} 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: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_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"} 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"} 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_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_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: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_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_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_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:Power evcc_pvPower "PV Power [%.1f kW]" <energy> {channel="evcc:device:demo:general#pvPower"}
String evcc_version "Version [%s]" <text> {channel="evcc:device:demo:general#version"}
String evcc_availableVersion "Available Version [%s]" <text> {channel="evcc:device:demo:general#availableVersion"}
// Loadpoint // Loadpoint
Number evcc_loadpoint0_activePhases "Active Phases [%d]" {channel="evcc:device:demo:loadpoint0#activePhases"} 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: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_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: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: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: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"} Number:Energy evcc_loadpoint0_chargedEnergy "Charged energy [%.1f kWh]" <energy> {channel="evcc:device:demo:loadpoint0#chargedEnergy"}
Switch evcc_loadpoint0_charging "Currently charging [%s]" <battery> {channel="evcc:device:demo:loadpoint0#charging"} Switch evcc_loadpoint0_charging "Currently charging [%s]" <battery> {channel="evcc:device:demo:loadpoint0#charging"}
Switch evcc_loadpoint0_enabled "Charging enabled [%s]" <switch> {channel="evcc:device:demo:loadpoint0#enabled"} Switch evcc_loadpoint0_enabled "Charging enabled [%s]" <switch> {channel="evcc:device:demo:loadpoint0#enabled"}
Number:ElectricCurrent evcc_loadpoint0_maxCurrent "Maximum current [%.0f A]" <energy> {channel="evcc:device:demo:loadpoint0#maxCurrent"} Number:ElectricCurrent evcc_loadpoint0_maxCurrent "Maximum current [%.0f A]" <energy> {channel="evcc:device:demo:loadpoint0#maxCurrent"}
Number:ElectricCurrent evcc_loadpoint0_minCurrent "Minimum current [%.0f A]" <energy> {channel="evcc:device:demo:loadpoint0#minCurrent"} Number:ElectricCurrent evcc_loadpoint0_minCurrent "Minimum current [%.0f A]" <energy> {channel="evcc:device:demo:loadpoint0#minCurrent"}
String evcc_loadpoint0_mode "Mode [%s]" {channel="evcc:device:demo:loadpoint0#mode"} String evcc_loadpoint0_mode "Mode [%s]" {channel="evcc:device:demo:loadpoint0#mode"}
Number evcc_loadpoint0_phases "Enabled phases [%d]" {channel="evcc:device:demo:loadpoint0#phases"} Number evcc_loadpoint0_phases "Enabled phases [%d]" {channel="evcc:device:demo:loadpoint0#phases"}
Number:Energy evcc_loadpoint0_limitEnergy "Limit energy [%.1f kWh]" <batterylevel> {channel="evcc:device:demo:loadpoint0#limitEnergy"} 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"} 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"} Number:Dimensionless evcc_loadpoint0_effectiveLimitSoC "Effective Limit SoC [%d %%]" <batterylevel> {channel="evcc:device:demo:loadpoint0#effectiveLimitSoC"}
String evcc_loadpoint0_title "Loadpoint title [%s]" <text> {channel="evcc:device:demo:loadpoint0#title"}
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 // Vehicle on loadpoint
Switch evcc_loadpoint0_vehicleConnected "Vehicle connected [%s]" <switch> {channel="evcc:device:demo:loadpoint0#vehicleConnected"} 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: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: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"} 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"} 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: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"} 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"} String evcc_loadpoint0_VehicleName "Vehicle name [%s]" <text> {channel="evcc:device:demo:loadpoint0#vehicleName"}
// Vehicle // Vehicle
String evcc_vehicle0_vehicleTitle "Vehicle title [%s]" <text> {channel="evcc:device:demo:vehicle0#vehicleTitle"} 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_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"} 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"} 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"} 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"} DateTime evcc_vehicle0_vehiclePlanTime "Vehicle plan time [%1$td.%1$tm.%1$tY, %1$tH:%1$tM]" <time> {channel="evcc:device:demo:vehicle0#vehiclePlanTime"}
``` ```
### Sitemap ### Sitemap

View File

@ -31,6 +31,7 @@ public class EvccBindingConstants {
public static final String CHANNEL_GROUP_ID_GENERAL = "general"; 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_LOADPOINT = "loadpoint";
public static final String CHANNEL_GROUP_ID_VEHICLE = "vehicle"; public static final String CHANNEL_GROUP_ID_VEHICLE = "vehicle";
public static final String CHANNEL_GROUP_ID_HEATING = "heating";
// List of all Channel ids // List of all Channel ids
public static final String CHANNEL_BATTERY_CAPACITY = "batteryCapacity"; public static final String CHANNEL_BATTERY_CAPACITY = "batteryCapacity";
@ -45,6 +46,9 @@ public class EvccBindingConstants {
public static final String CHANNEL_GRID_POWER = "gridPower"; public static final String CHANNEL_GRID_POWER = "gridPower";
public static final String CHANNEL_HOME_POWER = "homePower"; public static final String CHANNEL_HOME_POWER = "homePower";
public static final String CHANNEL_PV_POWER = "pvPower"; public static final String CHANNEL_PV_POWER = "pvPower";
public static final String CHANNEL_VERSION = "version";
public static final String CHANNEL_AVAILABLE_VERSION = "availableVersion";
public static final String CHANNEL_LOADPOINT_ACTIVE_PHASES = "activePhases"; public static final String CHANNEL_LOADPOINT_ACTIVE_PHASES = "activePhases";
public static final String CHANNEL_LOADPOINT_CHARGE_CURRENT = "chargeCurrent"; public static final String CHANNEL_LOADPOINT_CHARGE_CURRENT = "chargeCurrent";
public static final String CHANNEL_LOADPOINT_CHARGE_DURATION = "chargeDuration"; public static final String CHANNEL_LOADPOINT_CHARGE_DURATION = "chargeDuration";
@ -62,19 +66,32 @@ public class EvccBindingConstants {
public static final String CHANNEL_LOADPOINT_PHASES = "phases"; public static final String CHANNEL_LOADPOINT_PHASES = "phases";
public static final String CHANNEL_LOADPOINT_LIMIT_ENERGY = "limitEnergy"; public static final String CHANNEL_LOADPOINT_LIMIT_ENERGY = "limitEnergy";
public static final String CHANNEL_LOADPOINT_LIMIT_SOC = "limitSoC"; public static final String CHANNEL_LOADPOINT_LIMIT_SOC = "limitSoC";
public static final String CHANNEL_LOADPOINT_LIMIT_TEMPERATURE = "limitTemperature";
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_TITLE = "title";
public static final String CHANNEL_LOADPOINT_VEHICLE_CAPACITY = "vehicleCapacity"; 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_ODOMETER = "vehicleOdometer";
public static final String CHANNEL_LOADPOINT_VEHICLE_PRESENT = "vehiclePresent"; 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_RANGE = "vehicleRange";
public static final String CHANNEL_LOADPOINT_VEHICLE_SOC = "vehicleSoC"; public static final String CHANNEL_LOADPOINT_VEHICLE_SOC = "vehicleSoC";
public static final String CHANNEL_LOADPOINT_VEHICLE_TEMPERATURE = "vehicleTemperature";
public static final String CHANNEL_LOADPOINT_VEHICLE_NAME = "vehicleName"; public static final String CHANNEL_LOADPOINT_VEHICLE_NAME = "vehicleName";
public static final String CHANNEL_LOADPOINT_CHARGER_FEATURE_HEATING = "chargerFeatureHeating";
public static final String CHANNEL_LOADPOINT_CHARGER_FEATURE_INTEGRATED_DEVICE = "chargerFeatureIntegratedDevice";
public static final String CHANNEL_VEHICLE_TITLE = "vehicleTitle"; public static final String CHANNEL_VEHICLE_TITLE = "vehicleTitle";
public static final String CHANNEL_HEATING_TITLE = "heatingTitle";
public static final String CHANNEL_VEHICLE_MIN_SOC = "vehicleMinSoC"; public static final String CHANNEL_VEHICLE_MIN_SOC = "vehicleMinSoC";
public static final String CHANNEL_HEATING_MIN_TEMPERATURE = "heatingMinTemperature";
public static final String CHANNEL_VEHICLE_LIMIT_SOC = "vehicleLimitSoC"; public static final String CHANNEL_VEHICLE_LIMIT_SOC = "vehicleLimitSoC";
public static final String CHANNEL_HEATING_LIMIT_TEMPERATURE = "heatingLimitTemperature";
public static final String CHANNEL_VEHICLE_PLAN_ENABLED = "vehiclePlanEnabled"; 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"; public static final String CHANNEL_VEHICLE_PLAN_SOC = "vehiclePlanSoC";
public static final String CHANNEL_HEATING_PLAN_TEMPERATURE = "heatingPlanTemperature";
public static final String CHANNEL_VEHICLE_PLAN_TIME = "vehiclePlanTime"; public static final String CHANNEL_VEHICLE_PLAN_TIME = "vehiclePlanTime";
public static final String CHANNEL_HEATING_PLAN_TIME = "heatingPlanTime";
// List of all Thing Type UIDs // List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "device"); public static final ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "device");
@ -100,6 +117,10 @@ public class EvccBindingConstants {
public static final ChannelTypeUID CHANNEL_TYPE_UID_GRID_POWER = new ChannelTypeUID(BINDING_ID, CHANNEL_GRID_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_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); public static final ChannelTypeUID CHANNEL_TYPE_UID_PV_POWER = new ChannelTypeUID(BINDING_ID, CHANNEL_PV_POWER);
public static final ChannelTypeUID CHANNEL_TYPE_UID_VERSION = new ChannelTypeUID(BINDING_ID, CHANNEL_VERSION);
public static final ChannelTypeUID CHANNEL_TYPE_UID_AVAILABLE_VERSION = new ChannelTypeUID(BINDING_ID,
CHANNEL_AVAILABLE_VERSION);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_ACTIVE_PHASES = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_ACTIVE_PHASES = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_ACTIVE_PHASES); CHANNEL_LOADPOINT_ACTIVE_PHASES);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_CHARGE_CURRENT = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_CHARGE_CURRENT = new ChannelTypeUID(BINDING_ID,
@ -134,6 +155,12 @@ public class EvccBindingConstants {
CHANNEL_LOADPOINT_LIMIT_ENERGY); CHANNEL_LOADPOINT_LIMIT_ENERGY);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_LIMIT_SOC = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_LIMIT_SOC = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_LIMIT_SOC); CHANNEL_LOADPOINT_LIMIT_SOC);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_LIMIT_TEMPERATURE = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_LIMIT_TEMPERATURE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_EFFECTIVE_LIMIT_SOC = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_SOC);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_EFFECTIVE_LIMIT_TEMPERATURE = new ChannelTypeUID(
BINDING_ID, CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_TEMPERATURE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_TITLE = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_TITLE = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_TITLE); CHANNEL_LOADPOINT_TITLE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_CAPACITY = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_CAPACITY = new ChannelTypeUID(BINDING_ID,
@ -146,20 +173,39 @@ public class EvccBindingConstants {
CHANNEL_LOADPOINT_VEHICLE_RANGE); CHANNEL_LOADPOINT_VEHICLE_RANGE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_SOC = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_SOC = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_VEHICLE_SOC); CHANNEL_LOADPOINT_VEHICLE_SOC);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_TEMPERATURE = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_VEHICLE_TEMPERATURE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_NAME = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_NAME = new ChannelTypeUID(BINDING_ID,
CHANNEL_LOADPOINT_VEHICLE_NAME); CHANNEL_LOADPOINT_VEHICLE_NAME);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_CHARGER_FEATURE_HEATING = new ChannelTypeUID(
BINDING_ID, CHANNEL_LOADPOINT_CHARGER_FEATURE_HEATING);
public static final ChannelTypeUID CHANNEL_TYPE_UID_LOADPOINT_CHARGER_FEATURE_INTEGRATED_DEVICE = new ChannelTypeUID(
BINDING_ID, CHANNEL_LOADPOINT_CHARGER_FEATURE_INTEGRATED_DEVICE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_TITLE = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_TITLE = new ChannelTypeUID(BINDING_ID,
CHANNEL_VEHICLE_TITLE); CHANNEL_VEHICLE_TITLE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_HEATING_TITLE = new ChannelTypeUID(BINDING_ID,
CHANNEL_HEATING_TITLE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_MIN_SOC = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_MIN_SOC = new ChannelTypeUID(BINDING_ID,
CHANNEL_VEHICLE_MIN_SOC); CHANNEL_VEHICLE_MIN_SOC);
public static final ChannelTypeUID CHANNEL_TYPE_UID_HEATING_MIN_TEMPERATURE = new ChannelTypeUID(BINDING_ID,
CHANNEL_HEATING_MIN_TEMPERATURE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_LIMIT_SOC = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_LIMIT_SOC = new ChannelTypeUID(BINDING_ID,
CHANNEL_VEHICLE_LIMIT_SOC); 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_PLAN_ENABLED = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_PLAN_ENABLED = new ChannelTypeUID(BINDING_ID,
CHANNEL_VEHICLE_PLAN_ENABLED); CHANNEL_VEHICLE_PLAN_ENABLED);
public static final ChannelTypeUID CHANNEL_TYPE_UID_HEATING_PLAN_ENABLED = new ChannelTypeUID(BINDING_ID,
CHANNEL_HEATING_PLAN_ENABLED);
public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_PLAN_SOC = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_PLAN_SOC = new ChannelTypeUID(BINDING_ID,
CHANNEL_VEHICLE_PLAN_SOC); CHANNEL_VEHICLE_PLAN_SOC);
public static final ChannelTypeUID CHANNEL_TYPE_UID_HEATING_PLAN_TEMPERATURE = new ChannelTypeUID(BINDING_ID,
CHANNEL_HEATING_PLAN_TEMPERATURE);
public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_PLAN_TIME = new ChannelTypeUID(BINDING_ID, public static final ChannelTypeUID CHANNEL_TYPE_UID_VEHICLE_PLAN_TIME = new ChannelTypeUID(BINDING_ID,
CHANNEL_VEHICLE_PLAN_TIME); CHANNEL_VEHICLE_PLAN_TIME);
public static final ChannelTypeUID CHANNEL_TYPE_UID_HEATING_PLAN_TIME = new ChannelTypeUID(BINDING_ID,
CHANNEL_HEATING_PLAN_TIME);
public static final int CONNECTION_TIMEOUT_MILLISEC = 5000; public static final int CONNECTION_TIMEOUT_MILLISEC = 5000;
public static final int LONG_CONNECTION_TIMEOUT_MILLISEC = 60000; public static final int LONG_CONNECTION_TIMEOUT_MILLISEC = 60000;

View File

@ -17,7 +17,9 @@ import static org.openhab.binding.evcc.internal.EvccBindingConstants.*;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -69,6 +71,7 @@ public class EvccHandler extends BaseThingHandler {
private boolean batteryConfigured = false; private boolean batteryConfigured = false;
private boolean gridConfigured = false; private boolean gridConfigured = false;
private boolean pvConfigured = false; private boolean pvConfigured = false;
private Set<String> vehicleFeatureHeating = new HashSet<String>();
Map<String, Triple<Boolean, Float, ZonedDateTime>> vehiclePlans = new HashMap<>(); Map<String, Triple<Boolean, Float, ZonedDateTime>> vehiclePlans = new HashMap<>();
public EvccHandler(Thing thing) { public EvccHandler(Thing thing) {
@ -143,7 +146,7 @@ public class EvccHandler extends BaseThingHandler {
} }
} }
} else if (groupId.startsWith(CHANNEL_GROUP_ID_LOADPOINT)) { } else if (groupId.startsWith(CHANNEL_GROUP_ID_LOADPOINT)) {
int loadpoint = Integer.parseInt(groupId.substring(9)) + 1; int loadpoint = Integer.parseInt(groupId.substring(CHANNEL_GROUP_ID_LOADPOINT.length())) + 1;
switch (channelIdWithoutGroup) { switch (channelIdWithoutGroup) {
case CHANNEL_LOADPOINT_MODE -> { case CHANNEL_LOADPOINT_MODE -> {
if (command instanceof StringType) { if (command instanceof StringType) {
@ -171,6 +174,15 @@ public class EvccHandler extends BaseThingHandler {
logger.debug("Command has wrong type, QuantityType or DecimalType required!"); logger.debug("Command has wrong type, QuantityType or DecimalType required!");
} }
} }
case CHANNEL_LOADPOINT_LIMIT_TEMPERATURE -> {
if (command instanceof QuantityType<?> qt) {
evccAPI.setLimitSoC(loadpoint, qt.toUnit(SIUnits.CELSIUS).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 -> { case CHANNEL_LOADPOINT_PHASES -> {
if (command instanceof DecimalType dt) { if (command instanceof DecimalType dt) {
evccAPI.setPhases(loadpoint, dt.intValue()); evccAPI.setPhases(loadpoint, dt.intValue());
@ -200,8 +212,14 @@ public class EvccHandler extends BaseThingHandler {
return; return;
} }
} }
} else if (groupId.startsWith(CHANNEL_GROUP_ID_VEHICLE)) { } else if (groupId.startsWith(CHANNEL_GROUP_ID_VEHICLE)
String vehicleName = groupId.substring(7); || 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());
}
switch (channelIdWithoutGroup) { switch (channelIdWithoutGroup) {
case CHANNEL_VEHICLE_MIN_SOC -> { case CHANNEL_VEHICLE_MIN_SOC -> {
if (command instanceof QuantityType<?> qt) { if (command instanceof QuantityType<?> qt) {
@ -212,6 +230,15 @@ public class EvccHandler extends BaseThingHandler {
logger.debug("Command has wrong type, QuantityType or DecimalType required!"); logger.debug("Command has wrong type, QuantityType or DecimalType required!");
} }
} }
case CHANNEL_HEATING_MIN_TEMPERATURE -> {
if (command instanceof QuantityType<?> qt) {
evccAPI.setVehicleMinSoC(vehicleName, qt.toUnit(SIUnits.CELSIUS).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 -> { case CHANNEL_VEHICLE_LIMIT_SOC -> {
if (command instanceof QuantityType<?> qt) { if (command instanceof QuantityType<?> qt) {
evccAPI.setVehicleLimitSoC(vehicleName, qt.toUnit(Units.PERCENT).intValue()); evccAPI.setVehicleLimitSoC(vehicleName, qt.toUnit(Units.PERCENT).intValue());
@ -221,7 +248,16 @@ public class EvccHandler extends BaseThingHandler {
logger.debug("Command has wrong type, QuantityType or DecimalType required!"); logger.debug("Command has wrong type, QuantityType or DecimalType required!");
} }
} }
case CHANNEL_VEHICLE_PLAN_ENABLED -> { case CHANNEL_HEATING_LIMIT_TEMPERATURE -> {
if (command instanceof QuantityType<?> qt) {
evccAPI.setVehicleLimitSoC(vehicleName, qt.toUnit(SIUnits.CELSIUS).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, CHANNEL_HEATING_PLAN_ENABLED -> {
Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName); Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName);
if (command == OnOffType.ON) { if (command == OnOffType.ON) {
evccAPI.setVehiclePlan(vehicleName, planValues.getMiddle().intValue(), evccAPI.setVehiclePlan(vehicleName, planValues.getMiddle().intValue(),
@ -255,7 +291,26 @@ public class EvccHandler extends BaseThingHandler {
logger.debug("Command has wrong type, QuantityType or DecimalType required!"); logger.debug("Command has wrong type, QuantityType or DecimalType required!");
} }
} }
case CHANNEL_VEHICLE_PLAN_TIME -> { case CHANNEL_HEATING_PLAN_TEMPERATURE -> {
Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName);
if (command instanceof QuantityType<?> qt) {
vehiclePlans.put(vehicleName, new Triple<>(planValues.getLeft(),
qt.toUnit(SIUnits.CELSIUS).floatValue(), planValues.getRight()));
if (planValues.getLeft()) {
evccAPI.setVehiclePlan(vehicleName, qt.toUnit(SIUnits.CELSIUS).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, CHANNEL_HEATING_PLAN_TIME -> {
Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName); Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName);
if (command instanceof DateTimeType dtt) { if (command instanceof DateTimeType dtt) {
vehiclePlans.put(vehicleName, new Triple<>(planValues.getLeft(), planValues.getMiddle(), vehiclePlans.put(vehicleName, new Triple<>(planValues.getLeft(), planValues.getMiddle(),
@ -381,6 +436,7 @@ public class EvccHandler extends BaseThingHandler {
createChannel(CHANNEL_RESIDUAL_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_RESIDUAL_POWER, createChannel(CHANNEL_RESIDUAL_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_RESIDUAL_POWER,
"Number:Power"); "Number:Power");
} }
if (gridConfigured) { if (gridConfigured) {
createChannel(CHANNEL_GRID_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_GRID_POWER, "Number:Power"); createChannel(CHANNEL_GRID_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_GRID_POWER, "Number:Power");
} }
@ -388,11 +444,24 @@ public class EvccHandler extends BaseThingHandler {
if (pvConfigured) { if (pvConfigured) {
createChannel(CHANNEL_PV_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_PV_POWER, "Number:Power"); createChannel(CHANNEL_PV_POWER, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_PV_POWER, "Number:Power");
} }
createChannel(CHANNEL_VERSION, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_VERSION, CoreItemFactory.STRING);
createChannel(CHANNEL_AVAILABLE_VERSION, CHANNEL_GROUP_ID_GENERAL, CHANNEL_TYPE_UID_AVAILABLE_VERSION,
CoreItemFactory.STRING);
removeChannel("batteryPrioritySoC", CHANNEL_GROUP_ID_GENERAL); removeChannel("batteryPrioritySoC", CHANNEL_GROUP_ID_GENERAL);
} }
private void createChannelsLoadpoint(int loadpointId) { private void createChannelsLoadpoint(int loadpointId) {
final Result result = this.result;
if (result == null) {
return;
}
final String channelGroup = CHANNEL_GROUP_ID_LOADPOINT + loadpointId; final String channelGroup = CHANNEL_GROUP_ID_LOADPOINT + loadpointId;
Loadpoint loadpoint = result.getLoadpoints()[loadpointId];
boolean chargerFeatureHeating = loadpoint.getChargerFeatureHeating();
createChannel(CHANNEL_LOADPOINT_ACTIVE_PHASES, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_ACTIVE_PHASES, createChannel(CHANNEL_LOADPOINT_ACTIVE_PHASES, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_ACTIVE_PHASES,
CoreItemFactory.NUMBER); CoreItemFactory.NUMBER);
createChannel(CHANNEL_LOADPOINT_CHARGE_CURRENT, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_CHARGE_CURRENT, createChannel(CHANNEL_LOADPOINT_CHARGE_CURRENT, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_CHARGE_CURRENT,
@ -424,8 +493,30 @@ public class EvccHandler extends BaseThingHandler {
CoreItemFactory.NUMBER); CoreItemFactory.NUMBER);
createChannel(CHANNEL_LOADPOINT_LIMIT_ENERGY, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_LIMIT_ENERGY, createChannel(CHANNEL_LOADPOINT_LIMIT_ENERGY, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_LIMIT_ENERGY,
"Number:Energy"); "Number:Energy");
createChannel(CHANNEL_LOADPOINT_LIMIT_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_LIMIT_SOC, if (chargerFeatureHeating) {
"Number:Dimensionless"); createChannel(CHANNEL_LOADPOINT_LIMIT_TEMPERATURE, channelGroup,
CHANNEL_TYPE_UID_LOADPOINT_LIMIT_TEMPERATURE, "Number:Temperature");
createChannel(CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_TEMPERATURE, channelGroup,
CHANNEL_TYPE_UID_LOADPOINT_EFFECTIVE_LIMIT_TEMPERATURE, "Number:Temperature");
createChannel(CHANNEL_LOADPOINT_VEHICLE_TEMPERATURE, channelGroup,
CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_TEMPERATURE, "Number:Temperature");
removeChannel(CHANNEL_LOADPOINT_LIMIT_SOC, channelGroup);
removeChannel(CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_SOC, channelGroup);
removeChannel(CHANNEL_LOADPOINT_VEHICLE_SOC, channelGroup);
} else {
createChannel(CHANNEL_LOADPOINT_LIMIT_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_LIMIT_SOC,
"Number:Dimensionless");
createChannel(CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_SOC, channelGroup,
CHANNEL_TYPE_UID_LOADPOINT_EFFECTIVE_LIMIT_SOC, "Number:Dimensionless");
createChannel(CHANNEL_LOADPOINT_VEHICLE_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_SOC,
"Number:Dimensionless");
removeChannel(CHANNEL_LOADPOINT_LIMIT_TEMPERATURE, channelGroup);
removeChannel(CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_TEMPERATURE, channelGroup);
removeChannel(CHANNEL_LOADPOINT_VEHICLE_TEMPERATURE, channelGroup);
}
createChannel(CHANNEL_LOADPOINT_TITLE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TITLE, CoreItemFactory.STRING); createChannel(CHANNEL_LOADPOINT_TITLE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_TITLE, CoreItemFactory.STRING);
createChannel(CHANNEL_LOADPOINT_VEHICLE_CAPACITY, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_CAPACITY, createChannel(CHANNEL_LOADPOINT_VEHICLE_CAPACITY, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_CAPACITY,
"Number:Energy"); "Number:Energy");
@ -435,10 +526,12 @@ public class EvccHandler extends BaseThingHandler {
CoreItemFactory.SWITCH); CoreItemFactory.SWITCH);
createChannel(CHANNEL_LOADPOINT_VEHICLE_RANGE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_RANGE, createChannel(CHANNEL_LOADPOINT_VEHICLE_RANGE, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_RANGE,
"Number:Length"); "Number:Length");
createChannel(CHANNEL_LOADPOINT_VEHICLE_SOC, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_SOC,
"Number:Dimensionless");
createChannel(CHANNEL_LOADPOINT_VEHICLE_NAME, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_NAME, createChannel(CHANNEL_LOADPOINT_VEHICLE_NAME, channelGroup, CHANNEL_TYPE_UID_LOADPOINT_VEHICLE_NAME,
CoreItemFactory.STRING); CoreItemFactory.STRING);
createChannel(CHANNEL_LOADPOINT_CHARGER_FEATURE_HEATING, channelGroup,
CHANNEL_TYPE_UID_LOADPOINT_CHARGER_FEATURE_HEATING, CoreItemFactory.SWITCH);
createChannel(CHANNEL_LOADPOINT_CHARGER_FEATURE_INTEGRATED_DEVICE, channelGroup,
CHANNEL_TYPE_UID_LOADPOINT_CHARGER_FEATURE_INTEGRATED_DEVICE, CoreItemFactory.SWITCH);
removeChannel("hasVehicle", channelGroup); removeChannel("hasVehicle", channelGroup);
removeChannel("minSoC", channelGroup); removeChannel("minSoC", channelGroup);
@ -449,21 +542,56 @@ public class EvccHandler extends BaseThingHandler {
} }
private void createChannelsVehicle(String vehicleName) { private void createChannelsVehicle(String vehicleName) {
final String channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName; String channelGroup;
createChannel(CHANNEL_VEHICLE_TITLE, channelGroup, CHANNEL_TYPE_UID_VEHICLE_TITLE, CoreItemFactory.STRING); if (vehicleFeatureHeating.contains(vehicleName)) {
createChannel(CHANNEL_VEHICLE_MIN_SOC, channelGroup, CHANNEL_TYPE_UID_VEHICLE_MIN_SOC, "Number:Dimensionless"); channelGroup = CHANNEL_GROUP_ID_HEATING + vehicleName;
createChannel(CHANNEL_VEHICLE_LIMIT_SOC, channelGroup, CHANNEL_TYPE_UID_VEHICLE_LIMIT_SOC, createChannel(CHANNEL_HEATING_MIN_TEMPERATURE, channelGroup, CHANNEL_TYPE_UID_HEATING_MIN_TEMPERATURE,
"Number:Dimensionless"); "Number:Temperature");
createChannel(CHANNEL_VEHICLE_PLAN_SOC, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_SOC, createChannel(CHANNEL_HEATING_LIMIT_TEMPERATURE, channelGroup, CHANNEL_TYPE_UID_HEATING_LIMIT_TEMPERATURE,
"Number:Dimensionless"); "Number:Temperature");
createChannel(CHANNEL_VEHICLE_PLAN_TIME, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_TIME, createChannel(CHANNEL_HEATING_PLAN_TEMPERATURE, channelGroup, CHANNEL_TYPE_UID_HEATING_PLAN_TEMPERATURE,
CoreItemFactory.DATETIME); "Number:Temperature");
createChannel(CHANNEL_VEHICLE_PLAN_ENABLED, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_ENABLED, createChannel(CHANNEL_HEATING_TITLE, channelGroup, CHANNEL_TYPE_UID_HEATING_TITLE, CoreItemFactory.STRING);
CoreItemFactory.SWITCH); createChannel(CHANNEL_HEATING_PLAN_TIME, channelGroup, CHANNEL_TYPE_UID_HEATING_PLAN_TIME,
createChannel(CHANNEL_VEHICLE_PLAN_SOC, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_SOC, CoreItemFactory.DATETIME);
"Number:Dimensionless"); createChannel(CHANNEL_HEATING_PLAN_ENABLED, channelGroup, CHANNEL_TYPE_UID_HEATING_PLAN_ENABLED,
createChannel(CHANNEL_VEHICLE_PLAN_TIME, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_TIME, CoreItemFactory.SWITCH);
CoreItemFactory.DATETIME); createChannel(CHANNEL_HEATING_PLAN_TIME, channelGroup, CHANNEL_TYPE_UID_HEATING_PLAN_TIME,
CoreItemFactory.DATETIME);
channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName;
removeChannel(CHANNEL_VEHICLE_MIN_SOC, channelGroup);
removeChannel(CHANNEL_VEHICLE_LIMIT_SOC, channelGroup);
removeChannel(CHANNEL_VEHICLE_PLAN_SOC, channelGroup);
removeChannel(CHANNEL_VEHICLE_TITLE, channelGroup);
removeChannel(CHANNEL_VEHICLE_PLAN_TIME, channelGroup);
removeChannel(CHANNEL_VEHICLE_PLAN_ENABLED, channelGroup);
removeChannel(CHANNEL_VEHICLE_PLAN_TIME, channelGroup);
} else {
channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName;
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_TITLE, channelGroup, CHANNEL_TYPE_UID_VEHICLE_TITLE, CoreItemFactory.STRING);
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_TIME, channelGroup, CHANNEL_TYPE_UID_VEHICLE_PLAN_TIME,
CoreItemFactory.DATETIME);
channelGroup = CHANNEL_GROUP_ID_HEATING + vehicleName;
removeChannel(CHANNEL_HEATING_MIN_TEMPERATURE, channelGroup);
removeChannel(CHANNEL_HEATING_LIMIT_TEMPERATURE, channelGroup);
removeChannel(CHANNEL_HEATING_PLAN_TEMPERATURE, channelGroup);
removeChannel(CHANNEL_HEATING_TITLE, channelGroup);
removeChannel(CHANNEL_HEATING_PLAN_TIME, channelGroup);
removeChannel(CHANNEL_HEATING_PLAN_ENABLED, channelGroup);
removeChannel(CHANNEL_HEATING_PLAN_TIME, channelGroup);
}
} }
// Units and description for vars: https://docs.evcc.io/docs/reference/configuration/messaging/#msg // Units and description for vars: https://docs.evcc.io/docs/reference/configuration/messaging/#msg
@ -527,6 +655,14 @@ public class EvccHandler extends BaseThingHandler {
channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_PV_POWER); channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_PV_POWER);
updateState(channel, new QuantityType<>(pvPower, Units.WATT)); updateState(channel, new QuantityType<>(pvPower, Units.WATT));
} }
String version = result.getVersion();
channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_VERSION);
updateState(channel, new StringType(version));
String availableVersion = result.getAvailableVersion();
channel = new ChannelUID(uid, CHANNEL_GROUP_ID_GENERAL, CHANNEL_AVAILABLE_VERSION);
updateState(channel, new StringType(availableVersion));
} }
private void updateChannelsLoadpoint(int loadpointId) { private void updateChannelsLoadpoint(int loadpointId) {
@ -539,6 +675,14 @@ public class EvccHandler extends BaseThingHandler {
ChannelUID channel; ChannelUID channel;
Loadpoint loadpoint = result.getLoadpoints()[loadpointId]; Loadpoint loadpoint = result.getLoadpoints()[loadpointId];
boolean chargerFeatureHeating = loadpoint.getChargerFeatureHeating();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CHARGER_FEATURE_HEATING);
updateState(channel, OnOffType.from(chargerFeatureHeating));
boolean chargerFeatureIntegratedDevice = loadpoint.getChargerFeatureIntegratedDevice();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_CHARGER_FEATURE_INTEGRATED_DEVICE);
updateState(channel, OnOffType.from(chargerFeatureIntegratedDevice));
int activePhases = loadpoint.getActivePhases(); int activePhases = loadpoint.getActivePhases();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_ACTIVE_PHASES); channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_ACTIVE_PHASES);
updateState(channel, new DecimalType(activePhases)); updateState(channel, new DecimalType(activePhases));
@ -603,9 +747,39 @@ public class EvccHandler extends BaseThingHandler {
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_LIMIT_ENERGY); channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_LIMIT_ENERGY);
updateState(channel, new QuantityType<>(limitEnergy, Units.WATT_HOUR)); updateState(channel, new QuantityType<>(limitEnergy, Units.WATT_HOUR));
float limitSoC = loadpoint.getLimitSoC(); String vehicleName = loadpoint.getVehicleName();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_LIMIT_SOC); channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_NAME);
updateState(channel, new QuantityType<>(limitSoC, Units.PERCENT)); 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));
float effectiveLimitSoC = loadpoint.getEffectiveLimitSoC();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_TEMPERATURE);
updateState(channel, new QuantityType<>(effectiveLimitSoC, SIUnits.CELSIUS));
float vehicleSoC = loadpoint.getVehicleSoC();
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));
float effectiveLimitSoC = loadpoint.getEffectiveLimitSoC();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_EFFECTIVE_LIMIT_SOC);
updateState(channel, new QuantityType<>(effectiveLimitSoC, Units.PERCENT));
float vehicleSoC = loadpoint.getVehicleSoC();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_SOC);
updateState(channel, new QuantityType<>(vehicleSoC, Units.PERCENT));
}
String title = loadpoint.getTitle(); String title = loadpoint.getTitle();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_TITLE); channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_TITLE);
@ -626,14 +800,6 @@ public class EvccHandler extends BaseThingHandler {
float vehicleRange = loadpoint.getVehicleRange(); float vehicleRange = loadpoint.getVehicleRange();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_RANGE); channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_RANGE);
updateState(channel, new QuantityType<>(vehicleRange, MetricPrefix.KILO(SIUnits.METRE))); updateState(channel, new QuantityType<>(vehicleRange, MetricPrefix.KILO(SIUnits.METRE)));
float vehicleSoC = loadpoint.getVehicleSoC();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_SOC);
updateState(channel, new QuantityType<>(vehicleSoC, Units.PERCENT));
String vehicleName = loadpoint.getVehicleName();
channel = new ChannelUID(uid, channelGroup, CHANNEL_LOADPOINT_VEHICLE_NAME);
updateState(channel, new StringType(vehicleName));
} }
private void updateChannelsVehicle(String vehicleName) { private void updateChannelsVehicle(String vehicleName) {
@ -642,21 +808,39 @@ public class EvccHandler extends BaseThingHandler {
return; return;
} }
final ThingUID uid = getThing().getUID(); final ThingUID uid = getThing().getUID();
final String channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName;
ChannelUID channel;
Vehicle vehicle = result.getVehicles().get(vehicleName); Vehicle vehicle = result.getVehicles().get(vehicleName);
String title = vehicle.getTitle(); final String channelGroup;
channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_TITLE); boolean vehicleFeatureHeating = this.vehicleFeatureHeating.contains(vehicleName);
updateState(channel, new StringType(title)); if (vehicleFeatureHeating) {
channelGroup = CHANNEL_GROUP_ID_HEATING + vehicleName;
float minSoC = vehicle.getMinSoC(); float minSoC = vehicle.getMinSoC();
channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_MIN_SOC); ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_MIN_TEMPERATURE);
updateState(channel, new QuantityType<>(minSoC, Units.PERCENT)); updateState(channel, new QuantityType<>(minSoC, SIUnits.CELSIUS));
float limitSoC = vehicle.getLimitSoC(); float limitSoC = vehicle.getLimitSoC();
channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_LIMIT_SOC); channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_LIMIT_TEMPERATURE);
updateState(channel, new QuantityType<>(limitSoC, Units.PERCENT)); updateState(channel, new QuantityType<>(limitSoC, SIUnits.CELSIUS));
String title = vehicle.getTitle();
channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_TITLE);
updateState(channel, new StringType(title));
} else {
channelGroup = CHANNEL_GROUP_ID_VEHICLE + vehicleName;
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_HEATING_TITLE);
updateState(channel, new StringType(title));
}
Plan plan = vehicle.getPlan(); Plan plan = vehicle.getPlan();
if (plan == null && vehiclePlans.get(vehicleName) == null) { if (plan == null && vehiclePlans.get(vehicleName) == null) {
@ -664,18 +848,28 @@ public class EvccHandler extends BaseThingHandler {
} else if (plan != null) { } else if (plan != null) {
vehiclePlans.put(vehicleName, new Triple<>(true, plan.getSoC(), ZonedDateTime.parse(plan.getTime()))); vehiclePlans.put(vehicleName, new Triple<>(true, plan.getSoC(), ZonedDateTime.parse(plan.getTime())));
} }
updateVehiclePlanChannel(vehicleName, uid, channelGroup); updateVehiclePlanChannel(vehicleName, uid, channelGroup, vehicleFeatureHeating);
} }
private void updateVehiclePlanChannel(String vehicleName, ThingUID uid, String channelGroup) { private void updateVehiclePlanChannel(String vehicleName, ThingUID uid, String channelGroup,
boolean vehicleFeatureHeating) {
Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName); Triple<Boolean, Float, ZonedDateTime> planValues = vehiclePlans.get(vehicleName);
ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_PLAN_ENABLED); if (vehicleFeatureHeating) {
updateState(channel, planValues.getLeft() ? OnOffType.ON : OnOffType.OFF); ChannelUID channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_PLAN_ENABLED);
channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_PLAN_SOC); updateState(channel, planValues.getLeft() ? OnOffType.ON : OnOffType.OFF);
updateState(channel, new QuantityType<>(planValues.getMiddle(), Units.PERCENT)); channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_PLAN_TEMPERATURE);
channel = new ChannelUID(uid, channelGroup, CHANNEL_VEHICLE_PLAN_TIME); updateState(channel, new QuantityType<>(planValues.getMiddle(), SIUnits.CELSIUS));
updateState(channel, new DateTimeType(planValues.getRight())); channel = new ChannelUID(uid, channelGroup, CHANNEL_HEATING_PLAN_TIME);
updateState(channel, new DateTimeType(planValues.getRight()));
} else {
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) { private void createChannel(String channel, String channelGroupId, ChannelTypeUID channelTypeUID, String itemType) {

View File

@ -100,6 +100,15 @@ public class Loadpoint {
@SerializedName("vehicleName") @SerializedName("vehicleName")
private String vehicleName; private String vehicleName;
@SerializedName("effectiveLimitSoc")
private float effectiveLimitSoC;
@SerializedName("chargerFeatureHeating")
private boolean chargerFeatureHeating;
@SerializedName("chargerFeatureIntegratedDevice")
private boolean chargerFeatureIntegratedDevice;
/** /**
* @return number of active phases * @return number of active phases
*/ */
@ -274,4 +283,25 @@ public class Loadpoint {
public String getVehicleName() { public String getVehicleName() {
return vehicleName; return vehicleName;
} }
/**
* @return effective limit state of charge
*/
public float getEffectiveLimitSoC() {
return effectiveLimitSoC;
}
/**
* @return Charger Feature: Heating
*/
public boolean getChargerFeatureHeating() {
return chargerFeatureHeating;
}
/**
* @return Charger Feature: Integrated Device
*/
public boolean getChargerFeatureIntegratedDevice() {
return chargerFeatureIntegratedDevice;
}
} }

View File

@ -83,6 +83,12 @@ public class Result {
@SerializedName("vehicles") @SerializedName("vehicles")
private Map<String, Vehicle> vehicles; private Map<String, Vehicle> vehicles;
@SerializedName("version")
private String version;
@SerializedName("availableVersion")
private String availableVersion;
/** /**
* @return battery's capacity * @return battery's capacity
*/ */
@ -205,4 +211,18 @@ public class Result {
public Map<String, Vehicle> getVehicles() { public Map<String, Vehicle> getVehicles() {
return vehicles; return vehicles;
} }
/**
* @return evcc version
*/
public String getVersion() {
return version;
}
/**
* @return evcc available version
*/
public String getAvailableVersion() {
return availableVersion;
}
} }

View File

@ -52,22 +52,50 @@ channel-type.evcc.chargeRemainingEnergy.label = Charging Remaining Energy
channel-type.evcc.chargeRemainingEnergy.description = Remaining energy until limit 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.label = Charged Energy
channel-type.evcc.chargedEnergy.description = Energy charged since plugged-in channel-type.evcc.chargedEnergy.description = Energy charged since plugged-in
channel-type.evcc.chargerFeatureHeating.label = Charger Feature: Heating
channel-type.evcc.chargerFeatureHeating.description = 'True' for heating device: State of Charge in Degree instead of Percent
channel-type.evcc.chargerFeatureHeating.state.option.ON = True
channel-type.evcc.chargerFeatureHeating.state.option.OFF = False
channel-type.evcc.chargerFeatureIntegratedDevice.label = Charger Feature: Integrated Device
channel-type.evcc.chargerFeatureIntegratedDevice.description = 'True' for integrated device: Operate without a "vehicle" (e.g. heat pump, eBike)
channel-type.evcc.chargerFeatureIntegratedDevice.state.option.ON = True
channel-type.evcc.chargerFeatureIntegratedDevice.state.option.OFF = False
channel-type.evcc.charging.label = Charging State channel-type.evcc.charging.label = Charging State
channel-type.evcc.charging.description = Loadpoint is currently charging channel-type.evcc.charging.description = Loadpoint is currently charging
channel-type.evcc.charging.state.option.ON = Charging channel-type.evcc.charging.state.option.ON = Charging
channel-type.evcc.charging.state.option.OFF = Not charging channel-type.evcc.charging.state.option.OFF = Not charging
channel-type.evcc.effectiveLimitSoC.label = Effective Charging Limit SoC
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
channel-type.evcc.enabled.label = Charging Enabled channel-type.evcc.enabled.label = Charging Enabled
channel-type.evcc.enabled.description = Charging enabled (mode not "off") channel-type.evcc.enabled.description = Charging enabled (mode not "off")
channel-type.evcc.enabled.state.option.ON = Enabled channel-type.evcc.enabled.state.option.ON = Enabled
channel-type.evcc.enabled.state.option.OFF = Disabled channel-type.evcc.enabled.state.option.OFF = Disabled
channel-type.evcc.gridPower.label = Grid Power channel-type.evcc.gridPower.label = Grid Power
channel-type.evcc.gridPower.description = Current power from grid (negative means feed-in) channel-type.evcc.gridPower.description = Current power from grid (negative means feed-in)
channel-type.evcc.heatingLimitTemperature.label = Heating Charging Limit Temperature
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
channel-type.evcc.heatingPlanEnabled.label = Heating Plan Enabled
channel-type.evcc.heatingPlanEnabled.description = Plan for charging enabled
channel-type.evcc.heatingPlanEnabled.state.option.ON = Enabled
channel-type.evcc.heatingPlanEnabled.state.option.OFF = Disabled
channel-type.evcc.heatingPlanTemperature.label = Heating Plan Temperature
channel-type.evcc.heatingPlanTemperature.description = Until which Temperature should heating device be charged in plan
channel-type.evcc.heatingPlanTime.label = Heating Plan Time
channel-type.evcc.heatingPlanTime.description = When the plan Temperature should be reached
channel-type.evcc.heatingTitle.label = Heating Title
channel-type.evcc.heatingTitle.description = Title of heating device
channel-type.evcc.homePower.label = Home Power channel-type.evcc.homePower.label = Home Power
channel-type.evcc.homePower.description = Current power taken by home channel-type.evcc.homePower.description = Current power taken by home
channel-type.evcc.limitEnergy.label = Charging Limit Energy channel-type.evcc.limitEnergy.label = Charging Limit Energy
channel-type.evcc.limitEnergy.description = Amount of energy to charge the vehicle with 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.label = Charging Limit SoC
channel-type.evcc.limitSoC.description = Until which state of charge (SoC) should the vehicle be charged channel-type.evcc.limitSoC.description = Until which state of charge (SoC) should the vehicle be charged
channel-type.evcc.limitTemperature.label = Charging Limit Temperature
channel-type.evcc.limitTemperature.description = Until which Temperature should the heating device be charged
channel-type.evcc.maxCurrent.label = Charging max Current channel-type.evcc.maxCurrent.label = Charging max Current
channel-type.evcc.maxCurrent.description = Maximum amperage per connected phase with which the car should be charged channel-type.evcc.maxCurrent.description = Maximum amperage per connected phase with which the car should be charged
channel-type.evcc.minCurrent.label = Charging min Current channel-type.evcc.minCurrent.label = Charging min Current
@ -120,6 +148,8 @@ channel-type.evcc.vehicleRange.label = Vehicle Range
channel-type.evcc.vehicleRange.description = Battery range for EV channel-type.evcc.vehicleRange.description = Battery range for EV
channel-type.evcc.vehicleSoC.label = Vehicle SoC channel-type.evcc.vehicleSoC.label = Vehicle SoC
channel-type.evcc.vehicleSoC.description = Current State of Charge of EV channel-type.evcc.vehicleSoC.description = Current State of Charge of EV
channel-type.evcc.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.label = Vehicle Title
channel-type.evcc.vehicleTitle.description = Title of vehicle channel-type.evcc.vehicleTitle.description = Title of vehicle

View File

@ -141,7 +141,20 @@
<category>Energy</category> <category>Energy</category>
<state pattern="%.1f %unit%" readOnly="true"/> <state pattern="%.1f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="version">
<item-type>String</item-type>
<label>Version</label>
<description>Current evcc version</description>
<category>Text</category>
<state readOnly="true"/>
</channel-type>
<channel-type id="availableVersion">
<item-type>String</item-type>
<label>Available Version</label>
<description>Available evcc update version</description>
<category>Text</category>
<state readOnly="true"/>
</channel-type>
<!-- Channel Types for loadpoints --> <!-- Channel Types for loadpoints -->
<channel-type id="activePhases"> <channel-type id="activePhases">
<item-type>Number</item-type> <item-type>Number</item-type>
@ -271,6 +284,28 @@
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/> <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
<channel-type id="limitTemperature">
<item-type>Number:Temperature</item-type>
<label>Charging Limit Temperature</label>
<description>Until which Temperature should the heating device be charged</description>
<category>Temperature</category>
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>
<channel-type id="effectiveLimitSoC">
<item-type>Number:Dimensionless</item-type>
<label>Effective Charging Limit</label>
<description>Effective state of charge (SoC) until which the vehicle will be charged</description>
<category>BatteryLevel</category>
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="true"/>
</channel-type>
<channel-type id="effectiveLimitTemperature">
<item-type>Number:Temperature</item-type>
<label>Effective Charging Limit Temperature</label>
<description>Effective Temperature until which the heating device will be charged</description>
<category>Temperature</category>
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="true"/>
</channel-type>
<channel-type id="title"> <channel-type id="title">
<item-type>String</item-type> <item-type>String</item-type>
<label>Loadpoint Title</label> <label>Loadpoint Title</label>
@ -337,6 +372,13 @@
<category>BatteryLevel</category> <category>BatteryLevel</category>
<state pattern="%.0f %unit%" readOnly="true"/> <state pattern="%.0f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="vehicleTemperature">
<item-type>Number:Temperature</item-type>
<label>Temperature</label>
<description>Current Temperature of the heating device</description>
<category>Temperature</category>
<state pattern="%.0f %unit%" readOnly="true"/>
</channel-type>
<channel-type id="vehicleName"> <channel-type id="vehicleName">
<item-type>String</item-type> <item-type>String</item-type>
<label>Vehicle Name</label> <label>Vehicle Name</label>
@ -345,6 +387,30 @@
<category>Settings</category> <category>Settings</category>
<state readOnly="true"/> <state readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="chargerFeatureHeating">
<item-type>Switch</item-type>
<label>Charger Feature: Heating</label>
<description>'True' for heating device: State of Charge in Degree instead of Percent</description>
<category>Switch</category>
<state readOnly="true">
<options>
<option value="ON">True</option>
<option value="OFF">False</option>
</options>
</state>
</channel-type>
<channel-type id="chargerFeatureIntegratedDevice">
<item-type>Switch</item-type>
<label>Charger Feature: Integrated Device</label>
<description>'True' for integrated device: Operate without a "vehicle" (e.g. heat pump, eBike)</description>
<category>Switch</category>
<state readOnly="true">
<options>
<option value="ON">True</option>
<option value="OFF">False</option>
</options>
</state>
</channel-type>
<!-- Channel Types for vehicles --> <!-- Channel Types for vehicles -->
<channel-type id="vehicleTitle"> <channel-type id="vehicleTitle">
@ -354,6 +420,13 @@
<category>GarageDoor</category> <category>GarageDoor</category>
<state readOnly="true"/> <state readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="heatingTitle">
<item-type>String</item-type>
<label>Heating Title</label>
<description>Title of heating device</description>
<category>Heating</category>
<state readOnly="true"/>
</channel-type>
<channel-type id="vehicleMinSoC"> <channel-type id="vehicleMinSoC">
<item-type>Number:Dimensionless</item-type> <item-type>Number:Dimensionless</item-type>
<label>Vehicle Min SoC</label> <label>Vehicle Min SoC</label>
@ -362,6 +435,14 @@
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/> <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
<channel-type id="heatingMinTemperature">
<item-type>Number:Temperature</item-type>
<label>Heating Min Temperature</label>
<description>Minimum Temperature a heating device should have</description>
<category>Temperature</category>
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>
<channel-type id="vehicleLimitSoC"> <channel-type id="vehicleLimitSoC">
<item-type>Number:Dimensionless</item-type> <item-type>Number:Dimensionless</item-type>
<label>Vehicle Charging Limit SoC</label> <label>Vehicle Charging Limit SoC</label>
@ -370,6 +451,14 @@
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/> <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
<channel-type id="heatingLimitTemperature">
<item-type>Number:Temperature</item-type>
<label>Charging Temperature Limit</label>
<description>Until which Temperature should the specific heating device be charged</description>
<category>Temperature</category>
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>
<channel-type id="vehiclePlanEnabled"> <channel-type id="vehiclePlanEnabled">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Vehicle Plan Enabled</label> <label>Vehicle Plan Enabled</label>
@ -383,6 +472,19 @@
</state> </state>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
<channel-type id="heatingPlanEnabled">
<item-type>Switch</item-type>
<label>Heating 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"> <channel-type id="vehiclePlanSoC">
<item-type>Number:Dimensionless</item-type> <item-type>Number:Dimensionless</item-type>
<label>Vehicle Plan SoC</label> <label>Vehicle Plan SoC</label>
@ -391,6 +493,14 @@
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/> <state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
<channel-type id="heatingPlanTemperature">
<item-type>Number:Temperature</item-type>
<label>Heating Plan Temperature</label>
<description>Until which Temperature should heating device be charged in plan</description>
<category>Temperature</category>
<state min="0" step="1" max="100" pattern="%.0f %unit%" readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>
<channel-type id="vehiclePlanTime"> <channel-type id="vehiclePlanTime">
<item-type>DateTime</item-type> <item-type>DateTime</item-type>
<label>Vehicle Plan Time</label> <label>Vehicle Plan Time</label>
@ -399,4 +509,12 @@
<state readOnly="false"/> <state readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
<channel-type id="heatingPlanTime">
<item-type>DateTime</item-type>
<label>Heating Plan Time</label>
<description>When the plan Temperature should be reached</description>
<category>Time</category>
<state readOnly="false"/>
<autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type>
</thing:thing-descriptions> </thing:thing-descriptions>