Skip to content

Commit 08960fb

Browse files
committed
sensonet and vaillant-ebus charger now possible to use with parameter integrateddevice: true
- Upgrade to package sensonet v0.0.4 and sensonetEbus v0.0.1 - Charger modules sensonet and vaillant-ebus now both support to be used as integrated device or with vehicles - New SG Ready charger vaillant-via-ebus - Refactoring of template files for charger modules sensonet, vaillant-ebus and vaillant-via-ebus and their related vehicles - The charger modules sensonet, vaillant-ebus and vaillant-via-ebus and their related vehicles now work in 'evcc configure' - Refactoring of the sample yaml files
1 parent 4e06568 commit 08960fb

21 files changed

+723
-354
lines changed

README.md

+23-26
Original file line numberDiff line numberDiff line change
@@ -10,54 +10,51 @@ All other persons should visit github.com/evcc-io/evcc. There you can also find
1010
- Adds a charger module vaillant-ebus und a vehicle module vaillant-ebus_vehicle to allow PV optimised heating with a Vaillant heat pump
1111
- The vaillant-ebus module connects to an ebus daemon (https://github.com/john30/ebusd) to get system information from the heat pump and to start/stop quick modes. So to use this evcc extension, an ebus adapter (see https://adapter.ebusd.eu/) and the ebusd (=software) are needed.
1212
- The current power consumption of the heat pump is read via ebus, but an external energy meter like Shelly 3EM can be used as well.
13-
- As the vaillant-ebus charger module supports two different charge modes ('Hotwater Boost' and 'Heating Quick Veto'), small additions were made to the
13+
- As the vaillant-ebus charger module supports two different charge modes ('Hotwater Boost' and 'Zone Quick Veto'), small additions were made to the
1414
module loadpoint.go and the vue file Vehicle.vue to display the current charge mode. The usage of these two changes is optional.
1515

1616
(2) sensonet
17-
- Adds a charger module sensonet und a vehicle module sensonet_vehicle to allow PV optimised heating with a Vaillant heat pump
17+
- Adds a charger module sensonet_und a vehicle module sensonet_vehicle to allow PV optimised heating with a Vaillant heat pump
1818
- The sensonet module connects to the myVaillant portal to get system information from the heat pump and to start/stop quick modes.
19-
- As the sensonet charger module supports two different charge modes ('Hotwater Boost' and 'Heating Quick Veto'), small additions were made to the
19+
- As the sensonet charger module supports two different charge modes ('Hotwater Boost' and 'Zone Quick Veto'), small additions were made to the
2020
module loadpoint.go and the vue file Vehicle.vue to display the current charge mode. The usage of these two changes is optional.
2121

2222
## How it works
2323
(1) vaillant-ebus
24-
To use this extension a charger section for 'vaillant-ebus' and a vehicle section for 'vaillant-ebus_vehicle' have to be added to evcc.yaml.
25-
evcc is able to read the current power consumption of the heat pump via ebusd and to display it in the web interface. Thus no external metering device like Shelly 3EM is necessary. (But if an energy meter like Shelly 3EM is present for the Vaillant heatpump and shall be used, then a meter section has to be added to evcc.yaml as well. The vaillant-ebus charger, the vaillant-ebus_vehicle vehicle and the energy meter have to be combinated as a loadpoint in the yaml file.)
24+
To use this extension a charger section for 'vaillant-ebus' has to be added to evcc.yaml. You can use vehicles of type vaillant-ebus_vehicle to switch between different PV use strategies without stopping evcc. Or you set the parameter 'integrateddevice: true' for the vaillant-ebus charger and define no vehicles.
2625

27-
The vaillant-ebus charge module initiates a telnet connection to the ebusd which can reside on the same machine or on another machine in the local network. Via 'read' commands, information about the heat pump state is obtained. The vaillant-ebus_vehicle module is used to present some information like SoC (=current temperature) and TargetSoC (=temperature setpoint) to the loadpoint module of evcc.
26+
The vaillant-ebus charge module initiates a telnet connection to the ebusd which can reside on the same machine or on another machine in the local network. Via 'read' commands, information about the heat pump state is gathered and some of it like SoC (=current temperature), TargetSoC (=temperature setpoint) and current power consumption presented by the evcc web front end.
27+
As evcc is able to read the current power consumption of the heat pump via ebusd, no external metering device like Shelly 3EM is necessary. (But if an energy meter like Shelly 3EM is present for the Vaillant heatpump and shall be used, then a meter section has to be added to evcc.yaml as well.)
28+
The vaillant-ebus charger, the vaillant-ebus_vehicle vehicles and the energy meter have to be combinated as a loadpoint in the yaml file.
2829

2930
If the evcc loadpoint module signals to the vaillant-ebus charger module that a charging session should be started, then the vaillant-ebus module does the following:
3031
(a) If ('pvusestrategy='hotwater') or (pvusestrategy='hotwater_than_heating' and current hotwater temperature is more than 5°C below the setpoint), then a hotwater boost is initiated via a 'write' request to the ebusd.
31-
(b) If ('pvusestrategy='heating') or (pvusestrategy='hotwater_than_heating' and current hotwater temperature is less than 5°C below the setpoint), then
32-
a heating zone quick veto is initiated via a 'write' request to the ebusd for the zone given by the heatingzone parameter in the evcc.yaml file (default=0).
33-
The duration of the veto is 30 minutes and the veto_setpoint= normal_temperature_setpoint + heatingtemperatureoffset (default=2).
32+
(b) If ('pvusestrategy='heating') or (pvusestrategy='hotwater_than_heating' and current hotwater temperature is less than 5°C below the setpoint), then a heating zone quick veto is initiated via a 'write' request to the ebusd for the zone given by the heatingzone parameter in the evcc.yaml file (default=0). The duration of the veto is 30 minutes and the veto_setpoint= normal_temperature_setpoint + heatingtemperatureoffset (default=2).
3433
Via the regular 'read' commands, the vaillant-ebus module notices when the hotwater boost or the zone quick veto ends and changes the enabled() status to false to report this to the loadpoint module of evcc.
3534
If the loadpoint module tells the vaillant-ebus module to stop a charging session, then the vaillant-ebus module ends the hotwater boost or the zone quick veto via a 'write' request to the ebusd.
3635

3736
(2) sensonet
38-
To use this extension a charger section for 'sensonet' and a vehicle section for 'sensonet_vehicle' have to be added to evcc.yaml. If an energy meter
39-
like Shelly 3EM is present for the Vaillant heatpump, then a meter section has to be added to evcc.yaml as well.
40-
The sensonet charger, the sensonet_vehicle vehicle and the energy meter have to be combinated as a loadpoint in the yaml file.
37+
To use this extension a charger section for 'sensonet' has to be added to evcc.yaml. You can use vehicles of type sensonet_vehicle to switch between different PV use strategies. Or you set the parameter 'integrateddevice: true' for the sensonet charger and define no vehicles.
38+
(If an energy meter like Shelly 3EM is present for the Vaillant heatpump, then a meter section has to be added to evcc.yaml as well.)
39+
The sensonet charger, the sensonet_vehicle vehicles and the energy meter have to be combinated as a loadpoint in the yaml file.
4140

42-
The sensonet charge module initiates a http API interface to the myVaillant portal and keeps this connection active by regular refresh token calls.
43-
A json system report is obtained about every two minutes using a http GET call. This report is analysed to extract information about heating zones, operating modes, current temperatures and temperature setpoints.
44-
The sensonet_vehicle module is used to present some information like SoC (=current temperature) and TargetSoC (=temperature setpoint) to the loadpoint module of evcc.
41+
The sensonet charge module initiates a http API interface to the myVaillant portal and keeps this connection active by regular refresh token calls. A json system report is obtained about every two minutes using a http GET call. This report is analysed to extract information about heating zones, operating modes, current temperatures and temperature setpoints.
42+
Some of the gathered data like SoC (=current temperature), TargetSoC (=temperature setpoint) and current power consumption are presented by the evcc web front end. (Some heat pump systems can not provide the current power consumption to the myVaillant portal and therefore the sensonet charger can not read it from there. Then the use of an external metering device is recommended but not mandatory.)
4543

4644
If the evcc loadpoint module signals to the sensonet charger module that a charging session should be started, then the sensonet module does the following:
47-
(a) If ('pvusestrategy='hotwater') or (pvusestrategy='hotwater_than_heating' and current hotwater temperature is more than 5°C below the setpoint), then
48-
a hotwater boost is initiated via http POST request.
49-
(b) If ('pvusestrategy='heating') or (pvusestrategy='hotwater_than_heating' and current hotwater temperature is less than 5°C below the setpoint), then
50-
a heating zone quick veto is initiated via http POST request for the zone given by the heatingzone parameter in the evcc.yaml file (default=0).
51-
The duration of the veto is 30 minutes and the veto_setpoint= normal_temperature_setpoint + heatingtemperatureoffset (default=2).
52-
Via the json system reports, the sensonet module notices when the hotwater boost or the zone quick veto ends and changes the enabled() status to false to report
53-
this to the loadpoint module of evcc.
45+
(a) If ('pvusestrategy='hotwater') or (pvusestrategy='hotwater_than_heating' and current hotwater temperature is more than 5°C below the setpoint), then a hotwater boost is initiated via http POST request.
46+
(b) If ('pvusestrategy='heating') or (pvusestrategy='hotwater_than_heating' and current hotwater temperature is less than 5°C below the setpoint), then a heating zone quick veto is initiated via http POST request for the zone given by the heatingzone parameter in the evcc.yaml file (default=0). The duration of the veto is 3 hours and the veto_setpoint= normal_temperature_setpoint + heatingtemperatureoffset (default=2).
47+
Via the json system reports, the sensonet module notices when the hotwater boost or the zone quick veto ends and changes the enabled() status to false to report this to the loadpoint module of evcc.
5448
If the loadpoint module tells the sensonet module to stop a charging session, then the sensonet module sends a "cancel hotwater boost" or "cancel zone quick veto" to the myVaillant portal via http DELETE request.
5549
It happens, that it takes a few minutes before the json system report from the myVaillant portal reflects an initiated or canceled boost or quick veto. Don't worry!
5650

5751
## Custom ebus message definition file 15.ctlv2.csv
58-
At the moment, some ebus message definitions needed for the initiation of a zone quick veto are missing in the "official" ebus configuration files under https://cfg.ebusd.eu/
59-
Therefore the config files have to be downloaded from https://cfg.ebusd.eu/ to a local path and 15.ctlv2.csv has to be substituted by the file https://github.com/WulfgarW/ebusd-configuration/blob/master/ebusd-2.1.x/de/vaillant/15.ctlv2.csv
52+
At the moment, some ebus message definitions needed for the initiation of a zone quick veto are missing in the "official" ebus configuration files under https://ebus.github.io/.
53+
It works, if you start the ebusd service with the config path https://ebus.github.io/next/. Or you can download the config files to a local path and substitute 15.ctlv2.csv by the file https://github.com/WulfgarW/sensonetEbus/ebusd-config-files/15.ctlv2.csv
6054

61-
## Warning
62-
This extensions are still unstable and in first tests.
55+
## Request for feedback
6356
Feedback of beta testers is welcome.
57+
58+
## Further notes
59+
The vaillant-ebus charger is based on the sensonetEbus package at https://github.com/WulfgarW/sensonetEbus.
60+
The sensonet charger is based on the sensonet package at https://github.com/WulfgarW/sensonet

charger/sensonet.go

+13-17
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package charger
22

33
import (
4-
"fmt"
5-
64
"github.com/evcc-io/evcc/api"
75
"github.com/evcc-io/evcc/charger/sensonet"
86
"github.com/evcc-io/evcc/util"
@@ -66,21 +64,7 @@ func (c *Sensonet) Enabled() (bool, error) {
6664

6765
// Enable implements the api.Charger interface
6866
func (c *Sensonet) Enable(enable bool) error {
69-
err := c.conn.Enable(enable)
70-
if err != nil {
71-
return err
72-
}
73-
74-
enabled, err := c.Enabled()
75-
switch {
76-
case err != nil:
77-
return err
78-
case enable != enabled:
79-
onoff := map[bool]string{true: "on", false: "off"}
80-
return fmt.Errorf("switch %s failed", onoff[enable])
81-
default:
82-
return nil
83-
}
67+
return c.conn.Enable(enable)
8468
}
8569

8670
func (c *Sensonet) Phases() int {
@@ -99,3 +83,15 @@ func (c *Sensonet) Status() (api.ChargeStatus, error) {
9983
func (c *Sensonet) ModeText() string {
10084
return c.conn.ModeText()
10185
}
86+
87+
func (c *Sensonet) Soc() (float64, error) {
88+
return c.conn.CurrentTemp()
89+
}
90+
91+
func (c *Sensonet) CurrentPower() (float64, error) {
92+
return c.conn.CurrentPower()
93+
}
94+
95+
func (c *Sensonet) GetLimitSoc() (int64, error) {
96+
return c.conn.TargetTemp()
97+
}

charger/sensonet/connection.go

+13-18
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ type Connection struct {
3737
heatingTemperatureOffset float64
3838
onoff bool
3939
quickVetoSetPoint float32
40-
quickVetoExpiresAt string
40+
//quickVetoExpiresAt string
4141
}
4242

4343
// Global variable sensoNetConn is used to make data available in vehicle sensonet-vehicle
@@ -88,12 +88,9 @@ func NewConnection(user, password, realm, pvUseStrategy string, heatingZone, pha
8888
sensoNetConn.log.DEBUG.Println("In connection.NewConnection: sensoNetConn already initialised")
8989
return sensoNetConn, nil
9090
} else {
91-
utillog := util.NewLogger("sensonet")
91+
utillog := util.NewLogger("sensonet").Redact(user, password)
9292
client := request.NewClient(utillog)
9393
ctxClient := request.NewClient(utillog)
94-
/*client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
95-
return http.ErrUseLastResponse
96-
}*/
9794

9895
conn := &Connection{
9996
client: client,
@@ -109,11 +106,6 @@ func NewConnection(user, password, realm, pvUseStrategy string, heatingZone, pha
109106
conn.log = utillog
110107

111108
var err error
112-
/*conn.client.Jar, err = cookiejar.New(nil)
113-
if err != nil {
114-
err = fmt.Errorf("could not reset cookie jar. error: %s", err)
115-
return conn, err
116-
}*/
117109

118110
ctx := context.WithValue(context.TODO(), oauth2.HTTPClient, ctxClient)
119111
clientCtx := context.WithValue(ctx, oauth2.HTTPClient, ctxClient)
@@ -214,7 +206,7 @@ func (d *Connection) CurrentTemp() (float64, error) {
214206
}
215207

216208
// TargetTemp is called bei TargetSoc
217-
func (d *Connection) TargetTemp() (float64, error) {
209+
func (d *Connection) TargetTemp() (int64, error) {
218210
state, err := d.sensonetCtrl.GetSystem(d.systemId)
219211
if err != nil {
220212
d.log.ERROR.Println("connection.TargetTemp. Error: ", err)
@@ -243,18 +235,18 @@ func (d *Connection) TargetTemp() (float64, error) {
243235
zoneData := sensonetlib.GetZoneData(state, d.heatingZone)
244236
if zoneData != nil {
245237
if zoneData.State.CurrentSpecialFunction == "QUICK_VETO" {
246-
return float64(zoneData.State.DesiredRoomTemperatureSetpoint), nil
238+
return int64(zoneData.State.DesiredRoomTemperatureSetpoint), nil
247239
} else {
248-
return float64(d.quickVetoSetPoint), nil
240+
return int64(d.quickVetoSetPoint), nil
249241
}
250242
}
251-
return float64(d.quickVetoSetPoint), nil
243+
return int64(d.quickVetoSetPoint), nil
252244
}
253245
if !hotWaterOn {
254246
zoneData := sensonetlib.GetZoneData(state, d.heatingZone)
255-
return zoneData.State.DesiredRoomTemperatureSetpoint, nil
247+
return int64(zoneData.State.DesiredRoomTemperatureSetpoint), nil
256248
} else {
257-
return hotWaterSetpoint, nil
249+
return int64(hotWaterSetpoint), nil
258250
}
259251
}
260252

@@ -309,11 +301,14 @@ func (d *Connection) ModeText() string {
309301
case sensonetlib.QUICKMODE_HOTWATER:
310302
return " (Hotwater Boost active)"
311303
case sensonetlib.QUICKMODE_HEATING:
312-
if d.quickVetoExpiresAt != "" {
313-
return " (Heating Quick Veto active. Ends " + d.quickVetoExpiresAt + ")"
304+
if d.sensonetCtrl.GetQuickModeExpiresAt() != "" {
305+
return " (Heating Quick Veto active. Ends " + d.sensonetCtrl.GetQuickModeExpiresAt() + ")"
314306
}
315307
return " (Heating Quick Veto active)"
316308
case sensonetlib.QUICKMODE_NOTHING:
309+
if d.sensonetCtrl.GetQuickModeExpiresAt() != "" {
310+
return " (charger running idle. Ends " + d.sensonetCtrl.GetQuickModeExpiresAt() + "; " + tempInfo
311+
}
317312
return " (charger running idle; " + tempInfo
318313
}
319314
return " (regular mode; " + tempInfo

charger/sensonet/switch.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package sensonet
22

33
import (
44
"fmt"
5-
"time"
5+
//"time"
66

77
sensonetlib "github.com/WulfgarW/sensonet"
88
)
@@ -29,11 +29,11 @@ func (sh *Switch) Enabled() (bool, error) {
2929
d.log.ERROR.Println("switch.Enabled. Error: ", err)
3030
return d.onoff, err
3131
}
32-
d.log.DEBUG.Println("In Switch.Enabled: Zones[0].CurrentSpecialFunction=", state.State.Zones[0].CurrentSpecialFunction)
32+
d.log.DEBUG.Println(fmt.Sprintf("In Switch.Enabled: Zones[%d].CurrentSpecialFunction=%s", d.heatingZone, state.State.Zones[d.heatingZone].CurrentSpecialFunction))
3333

3434
newQuickmode := d.sensonetCtrl.GetCurrentQuickMode()
3535
d.log.DEBUG.Printf("In Switch.Enabled: GetCurrentQuickmode() returns \"%s\"", newQuickmode)
36-
if newQuickmode == "" || newQuickmode == sensonetlib.QUICKMODE_NOTHING {
36+
if newQuickmode == "" { //|| newQuickmode == sensonetlib.QUICKMODE_NOTHING {
3737
d.onoff = false
3838
} else {
3939
d.onoff = true
@@ -73,11 +73,11 @@ func (sh *Switch) Enable(enable bool) error {
7373
} else {
7474
d.quickVetoSetPoint = heatingPar.VetoSetpoint
7575
}
76-
if heatingPar.VetoDuration < 0.0 {
76+
/*if heatingPar.VetoDuration < 0.0 {
7777
d.quickVetoExpiresAt = (time.Now().Add(time.Duration(int64(sensonetlib.ZONEVETODURATION_DEFAULT*60) * int64(time.Minute)))).Format("15:04")
7878
} else {
7979
d.quickVetoExpiresAt = (time.Now().Add(time.Duration(int64(heatingPar.VetoDuration*60) * int64(time.Minute)))).Format("15:04")
80-
}
80+
}*/
8181
}
8282
} else {
8383
result, err := d.sensonetCtrl.StopStrategybased(d.systemId, &heatingPar, &hotwaterPar)
@@ -87,7 +87,7 @@ func (sh *Switch) Enable(enable bool) error {
8787
}
8888
d.log.DEBUG.Println("In Switch.Enable: StopStrategybased returns: ", result)
8989
d.quickVetoSetPoint = 0.0
90-
d.quickVetoExpiresAt = ""
90+
//d.quickVetoExpiresAt = ""
9191
}
9292
d.onoff = enable
9393
return err

charger/vaillant-ebus.go

+12
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,15 @@ func (c *VaillantEbus) Status() (api.ChargeStatus, error) {
9797
func (c *VaillantEbus) ModeText() string {
9898
return c.conn.ModeText()
9999
}
100+
101+
func (c *VaillantEbus) Soc() (float64, error) {
102+
return c.conn.CurrentTemp()
103+
}
104+
105+
func (c *VaillantEbus) CurrentPower() (float64, error) {
106+
return c.conn.CurrentPower()
107+
}
108+
109+
func (c *VaillantEbus) GetLimitSoc() (int64, error) {
110+
return c.conn.TargetTemp()
111+
}

0 commit comments

Comments
 (0)