EEBus meter: clear cached entity refs on disconnect (#29628)

This commit is contained in:
andig 2026-05-04 17:06:19 +02:00 • committed by GitHub
parent 0f5bfe05c5
commit 0178d32302
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 9 deletions

View file

@ -43,7 +43,7 @@ type EEBus struct {
reconnect bool
current float64
*eebus.Connector
connector *eebus.Connector
}
func init() {
@ -84,14 +84,14 @@ func newEEBus(ctx context.Context, ski, ip string) (*EEBus, error) {
cem: eebus.Instance.CustomerEnergyManagement(),
}
c.Connector = eebus.NewConnector()
c.connector = eebus.NewConnector()
c.minMaxG = util.Cached(c.minMax, time.Second)
if err := eebus.Instance.RegisterDevice(ski, ip, c); err != nil {
return nil, err
}
if err := c.Wait(ctx); err != nil {
if err := c.connector.Wait(ctx); err != nil {
eebus.Instance.UnregisterDevice(ski, c)
return nil, err
}
@ -125,6 +125,24 @@ func NewEEBus(ctx context.Context, ski, ip string, hasMeter, hasChargedEnergy bo
var _ eebus.Device = (*EEBus)(nil)
// Connect implements the eebus.Device interface.
// On SHIP/SPINE disconnect we drop the cached EV entity reference. EvDisconnected
// only fires on a SPINE EntityChange/Remove, not on SHIP-level disconnect, so
// without this we could keep querying an orphan entity until the next reconnect
// re-fires EvConnected.
func (c *EEBus) Connect(connected bool) {
c.connector.Connect(connected)
if connected {
return
}
c.mux.Lock()
defer c.mux.Unlock()
c.ev = nil
}
// UseCaseEvent implements the eebus.Device interface
func (c *EEBus) UseCaseEvent(device spineapi.DeviceRemoteInterface, entity spineapi.EntityRemoteInterface, event eebusapi.EventType) {
c.mux.Lock()

View file

@ -25,10 +25,10 @@ import (
type EEBus struct {
log *util.Logger
*eebus.Connector
ma *eebus.MonitoringAppliance
eg *eebus.EnergyGuard
mm measurements
connector *eebus.Connector
ma *eebus.MonitoringAppliance
eg *eebus.EnergyGuard
mm measurements
mu sync.Mutex
maEntity spineapi.EntityRemoteInterface
@ -87,14 +87,14 @@ func NewEEBus(ctx context.Context, ski, ip string, usage *templates.Usage) (api.
ma: ma,
eg: eebus.Instance.EnergyGuard(),
mm: mm,
Connector: eebus.NewConnector(),
connector: eebus.NewConnector(),
}
if err := eebus.Instance.RegisterDevice(ski, ip, c); err != nil {
return nil, err
}
if err := c.Wait(ctx); err != nil {
if err := c.connector.Wait(ctx); err != nil {
eebus.Instance.UnregisterDevice(ski, c)
return nil, err
}

View file

@ -12,6 +12,26 @@ import (
var _ eebus.Device = (*EEBus)(nil)
// Connect implements the eebus.Device interface.
// On SHIP/SPINE disconnect we drop cached remote-entity references so a
// subsequent re-pair re-populates them from fresh UseCaseSupportUpdate events.
// Without this, Power/Currents/Voltages would keep serving the last value of
// an orphaned entity (see https://github.com/evcc-io/evcc/issues/28518).
func (c *EEBus) Connect(connected bool) {
c.connector.Connect(connected)
if connected {
return
}
c.mu.Lock()
defer c.mu.Unlock()
c.maEntity = nil
c.egLpcEntity = nil
c.egLppEntity = nil
}
// UseCaseEvent implements the eebus.Device interface
func (c *EEBus) UseCaseEvent(_ spineapi.DeviceRemoteInterface, entity spineapi.EntityRemoteInterface, event eebusapi.EventType) {
switch event {