From 9751f2b25c02da07a2f2343e67bed6a6febc5d41 Mon Sep 17 00:00:00 2001 From: andig Date: Mon, 1 Jan 2024 18:22:23 +0100 Subject: [PATCH] Tasmota: fix charger (#11403) --- charger/tasmota.go | 24 ++++++++---- charger/tasmota_decorators.go | 69 +++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 charger/tasmota_decorators.go diff --git a/charger/tasmota.go b/charger/tasmota.go index 5c0b13ede1..bba34e9afd 100644 --- a/charger/tasmota.go +++ b/charger/tasmota.go @@ -23,6 +23,8 @@ func init() { registry.Add("tasmota", NewTasmotaFromConfig) } +//go:generate go run ../cmd/tools/decorate.go -f decorateTasmota -b *Tasmota -r api.Charger -t "api.PhaseVoltages,Voltages,func() (float64, float64, float64, error)" -t "api.PhaseCurrents,Currents,func() (float64, float64, float64, error)" + // NewTasmotaFromConfig creates a Tasmota charger from generic config func NewTasmotaFromConfig(other map[string]interface{}) (api.Charger, error) { cc := struct { @@ -46,19 +48,29 @@ func NewTasmotaFromConfig(other map[string]interface{}) (api.Charger, error) { } // NewTasmota creates Tasmota charger -func NewTasmota(embed embed, uri, user, password string, channels []int, standbypower float64, cache time.Duration) (*Tasmota, error) { +func NewTasmota(embed embed, uri, user, password string, channels []int, standbypower float64, cache time.Duration) (api.Charger, error) { conn, err := tasmota.NewConnection(uri, user, password, channels, cache) if err != nil { return nil, err } + if err := conn.RelayExists(); err != nil { + return nil, err + } + c := &Tasmota{ conn: conn, } c.switchSocket = NewSwitchSocket(&embed, c.Enabled, c.conn.CurrentPower, standbypower) - return c, c.conn.RelayExists() + var currents, voltages func() (float64, float64, float64, error) + if len(channels) == 3 { + currents = c.currents + voltages = c.voltages + } + + return decorateTasmota(c, currents, voltages), nil } // Enabled implements the api.Charger interface @@ -78,16 +90,12 @@ func (c *Tasmota) TotalEnergy() (float64, error) { return c.conn.TotalEnergy() } -var _ api.PhaseCurrents = (*Tasmota)(nil) - // Currents implements the api.PhaseCurrents interface -func (c *Tasmota) Currents() (float64, float64, float64, error) { +func (c *Tasmota) currents() (float64, float64, float64, error) { return c.conn.Currents() } -var _ api.PhaseVoltages = (*Tasmota)(nil) - // Voltages implements the api.PhaseVoltages interface -func (c *Tasmota) Voltages() (float64, float64, float64, error) { +func (c *Tasmota) voltages() (float64, float64, float64, error) { return c.conn.Voltages() } diff --git a/charger/tasmota_decorators.go b/charger/tasmota_decorators.go new file mode 100644 index 0000000000..2b7cd21eb3 --- /dev/null +++ b/charger/tasmota_decorators.go @@ -0,0 +1,69 @@ +package charger + +// Code generated by github.com/evcc-io/evcc/cmd/tools/decorate.go. DO NOT EDIT. + +import ( + "github.com/evcc-io/evcc/api" +) + +func decorateTasmota(base *Tasmota, phaseVoltages func() (float64, float64, float64, error), phaseCurrents func() (float64, float64, float64, error)) api.Charger { + switch { + case phaseCurrents == nil && phaseVoltages == nil: + return base + + case phaseCurrents == nil && phaseVoltages != nil: + return &struct { + *Tasmota + api.PhaseVoltages + }{ + Tasmota: base, + PhaseVoltages: &decorateTasmotaPhaseVoltagesImpl{ + phaseVoltages: phaseVoltages, + }, + } + + case phaseCurrents != nil && phaseVoltages == nil: + return &struct { + *Tasmota + api.PhaseCurrents + }{ + Tasmota: base, + PhaseCurrents: &decorateTasmotaPhaseCurrentsImpl{ + phaseCurrents: phaseCurrents, + }, + } + + case phaseCurrents != nil && phaseVoltages != nil: + return &struct { + *Tasmota + api.PhaseCurrents + api.PhaseVoltages + }{ + Tasmota: base, + PhaseCurrents: &decorateTasmotaPhaseCurrentsImpl{ + phaseCurrents: phaseCurrents, + }, + PhaseVoltages: &decorateTasmotaPhaseVoltagesImpl{ + phaseVoltages: phaseVoltages, + }, + } + } + + return nil +} + +type decorateTasmotaPhaseCurrentsImpl struct { + phaseCurrents func() (float64, float64, float64, error) +} + +func (impl *decorateTasmotaPhaseCurrentsImpl) Currents() (float64, float64, float64, error) { + return impl.phaseCurrents() +} + +type decorateTasmotaPhaseVoltagesImpl struct { + phaseVoltages func() (float64, float64, float64, error) +} + +func (impl *decorateTasmotaPhaseVoltagesImpl) Voltages() (float64, float64, float64, error) { + return impl.phaseVoltages() +}