From ca3637e062a889edeb008dda5673c6f9a974f315 Mon Sep 17 00:00:00 2001 From: Andreas Linde <42185+DerAndereAndi@users.noreply.github.com> Date: Wed, 26 Apr 2023 11:15:09 +0200 Subject: [PATCH] Improve EEBUS EV connection handling and fix a crash (#7650) * Check for connection before fetching data * Check if an EV is connected first This new check does not only check for the EEBUS charge state but also checks if a minimum dataset is available. This helps in situations where the charge state already provides data, but measurements, loadlimits etc. are not yet available and thus cause evcc to return errors. * Fix crash when no vehicle is assigned to loadpoint * Update EEBUS cemd to v0.2.1 --- charger/eebus.go | 83 ++++++++++++++++-------------------------------- go.mod | 2 +- go.sum | 4 +-- 3 files changed, 31 insertions(+), 58 deletions(-) diff --git a/charger/eebus.go b/charger/eebus.go index 1437d9d8e..51649846d 100644 --- a/charger/eebus.go +++ b/charger/eebus.go @@ -170,10 +170,12 @@ func (c *EEBus) setLoadpointMinMaxLimits() { newMin := minLimits[0] newMax := maxLimits[0] - if c.lp.GetMinCurrent() != newMin && newMin > 0 && c.lp.GetVehicle().OnIdentified().MinCurrent == nil { + vehicle := c.lp.GetVehicle() + + if c.lp.GetMinCurrent() != newMin && newMin > 0 && (vehicle == nil || vehicle.OnIdentified().MinCurrent == nil) { c.lp.SetMinCurrent(newMin) } - if c.lp.GetMaxCurrent() != newMax && newMax > 0 && c.lp.GetVehicle().OnIdentified().MaxCurrent == nil { + if c.lp.GetMaxCurrent() != newMax && newMax > 0 && (vehicle == nil || vehicle.OnIdentified().MaxCurrent == nil) { c.lp.SetMaxCurrent(newMax) } } @@ -222,15 +224,20 @@ func (c *EEBus) isCharging() bool { // d *communication.EVSEClientDataType } func (c *EEBus) updateState() (api.ChargeStatus, error) { + if !c.isConnected() { + return api.StatusNone, api.ErrTimeout + } + + if !c.emobility.EVConnected() { + c.expectedEnableUnpluggedState = false + return api.StatusA, nil + } + currentState, err := c.emobility.EVCurrentChargeState() if err != nil { return api.StatusNone, err } - if !c.isConnected() { - return api.StatusNone, api.ErrTimeout - } - switch currentState { case emobility.EVChargeStateTypeUnknown, emobility.EVChargeStateTypeUnplugged: // Unplugged c.expectedEnableUnpluggedState = false @@ -287,8 +294,7 @@ func (c *EEBus) Enabled() (bool, error) { // Enable implements the api.Charger interface func (c *EEBus) Enable(enable bool) error { // if the ev is unplugged or the state is unknown, there is nothing to be done - state, err := c.updateState() - if err != nil || state == api.StatusA { + if state, err := c.updateState(); err != nil || state == api.StatusA { c.expectedEnableUnpluggedState = enable return nil } @@ -349,29 +355,22 @@ var _ api.ChargerEx = (*EEBus)(nil) // MaxCurrentMillis implements the api.ChargerEx interface func (c *EEBus) MaxCurrentMillis(current float64) error { - chargeState, err := c.emobility.EVCurrentChargeState() - if err != nil { - return err - } - if chargeState == emobility.EVChargeStateTypeUnplugged { + if !c.connected || !c.emobility.EVConnected() { return errors.New("can't set new current as ev is unplugged") } - err = c.writeCurrentLimitData([]float64{current, current, current}) - if err == nil { - c.current = current + if err := c.writeCurrentLimitData([]float64{current, current, current}); err != nil { + return err } - return err + c.current = current + + return nil } // CurrentPower implements the api.Meter interface func (c *EEBus) currentPower() (float64, error) { - chargeState, err := c.emobility.EVCurrentChargeState() - if err != nil { - return 0, err - } - if chargeState == emobility.EVChargeStateTypeUnplugged { + if !c.emobility.EVConnected() { return 0, nil } @@ -398,11 +397,7 @@ func (c *EEBus) currentPower() (float64, error) { // ChargedEnergy implements the api.ChargeRater interface func (c *EEBus) chargedEnergy() (float64, error) { - chargeState, err := c.emobility.EVCurrentChargeState() - if err != nil { - return 0, err - } - if chargeState == emobility.EVChargeStateTypeUnplugged { + if !c.emobility.EVConnected() { return 0, nil } @@ -419,11 +414,7 @@ func (c *EEBus) chargedEnergy() (float64, error) { // Currents implements the api.PhaseCurrents interface func (c *EEBus) currents() (float64, float64, float64, error) { - chargeState, err := c.emobility.EVCurrentChargeState() - if err != nil { - return 0, 0, 0, err - } - if chargeState == emobility.EVChargeStateTypeUnplugged { + if !c.emobility.EVConnected() { return 0, 0, 0, nil } @@ -446,31 +437,18 @@ var _ api.Identifier = (*EEBus)(nil) // Identify implements the api.Identifier interface func (c *EEBus) Identify() (string, error) { - if !c.isConnected() { + if !c.isConnected() || !c.emobility.EVConnected() { return "", nil } - chargeState, err := c.emobility.EVCurrentChargeState() - if err != nil { - return "", err - } - if chargeState == emobility.EVChargeStateTypeUnplugged || chargeState == emobility.EVChargeStateTypeUnknown { + if !c.emobility.EVConnected() { return "", nil } - - identification, err := c.emobility.EVIdentification() - if err != nil { - return "", err - } - if identification != "" { + if identification, _ := c.emobility.EVIdentification(); identification != "" { return identification, nil } - comStandard, err := c.emobility.EVCommunicationStandard() - if err != nil { - return "", err - } - if comStandard == emobility.EVCommunicationStandardTypeIEC61851 { + if comStandard, _ := c.emobility.EVCommunicationStandard(); comStandard == emobility.EVCommunicationStandardTypeIEC61851 { return "", nil } @@ -485,12 +463,7 @@ var _ api.Battery = (*EEBus)(nil) // Soc implements the api.Vehicle interface func (c *EEBus) Soc() (float64, error) { - socSupported, err := c.emobility.EVSoCSupported() - if err != nil { - return 0, api.ErrNotAvailable - } - - if !socSupported { + if socSupported, err := c.emobility.EVSoCSupported(); err != nil || !socSupported { return 0, api.ErrNotAvailable } diff --git a/go.mod b/go.mod index 256291f83..d990ba8a2 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/dustin/go-humanize v1.0.1 github.com/dylanmei/iso8601 v0.1.0 github.com/eclipse/paho.mqtt.golang v1.4.2 - github.com/enbility/cemd v0.2.0 + github.com/enbility/cemd v0.2.1 github.com/enbility/eebus-go v0.2.0 github.com/fatih/structs v1.1.0 github.com/foogod/go-powerwall v0.2.0 diff --git a/go.sum b/go.sum index 7f5805ec3..4b262e33e 100644 --- a/go.sum +++ b/go.sum @@ -347,8 +347,8 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/eclipse/paho.mqtt.golang v1.4.2 h1:66wOzfUHSSI1zamx7jR6yMEI5EuHnT1G6rNA5PM12m4= github.com/eclipse/paho.mqtt.golang v1.4.2/go.mod h1:JGt0RsEwEX+Xa/agj90YJ9d9DH2b7upDZMK9HRbFvCA= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/enbility/cemd v0.2.0 h1:T+XbqX2PYKmbIgtdNAtKk1DVZaXjOAsIt+NqlIs4Ajo= -github.com/enbility/cemd v0.2.0/go.mod h1:BZoHbJQJ9/7le4WMFAJWRSgKCCTfNVEOM0c1E3H1JxE= +github.com/enbility/cemd v0.2.1 h1:5EYO4bWl4BowK//CPEQ3ESjFkK4sDtwRxWIf4VL5F00= +github.com/enbility/cemd v0.2.1/go.mod h1:BZoHbJQJ9/7le4WMFAJWRSgKCCTfNVEOM0c1E3H1JxE= github.com/enbility/eebus-go v0.2.0 h1:znQUfG1QYk0Q+vOacrsSNtXmitF1F2Rx9+ohwcRNlRw= github.com/enbility/eebus-go v0.2.0/go.mod h1:Ozg1eDUfSbHfQ1dWfyAUa3h8dMtgM/01eO30kHca5zk= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=