diff --git a/meter/sma.go b/meter/sma.go index 2ea449436..7055c28cb 100644 --- a/meter/sma.go +++ b/meter/sma.go @@ -24,13 +24,14 @@ func init() { registry.Add("sma", NewSMAFromConfig) } -//go:generate go tool decorate -f decorateSMA -b *SMA -r api.Meter -t "api.Battery,Soc,func() (float64, error)" -t "api.BatteryCapacity,Capacity,func() float64" - // NewSMAFromConfig creates an SMA meter from generic config func NewSMAFromConfig(other map[string]any) (api.Meter, error) { cc := struct { batteryCapacity `mapstructure:",squash"` + batteryPowerLimits `mapstructure:",squash"` + batterySocLimits `mapstructure:",squash"` URI, Password, Interface string + Usage string Serial uint32 Scale float64 // power only }{ @@ -42,11 +43,24 @@ func NewSMAFromConfig(other map[string]any) (api.Meter, error) { return nil, err } - return NewSMA(cc.URI, cc.Password, cc.Interface, cc.Serial, cc.Scale, cc.batteryCapacity.Decorator()) + sm, err := NewSMA(cc.URI, cc.Password, cc.Interface, cc.Serial, cc.Scale) + if err != nil { + return nil, err + } + + if cc.Usage == "battery" { + return decorateMeterBattery( + sm, sm.TotalEnergy, + sm.soc, cc.batteryCapacity.Decorator(), + cc.batterySocLimits.Decorator(), cc.batteryPowerLimits.Decorator(), nil, + ), nil + } + + return sm, nil } // NewSMA creates an SMA meter -func NewSMA(uri, password, iface string, serial uint32, scale float64, capacity func() float64) (api.Meter, error) { +func NewSMA(uri, password, iface string, serial uint32, scale float64) (*SMA, error) { sm := &SMA{ uri: uri, scale: scale, @@ -82,20 +96,7 @@ func NewSMA(uri, password, iface string, serial uint32, scale float64, capacity // start update loop manually to get values as fast as possible go sm.device.Run() - // decorate api.Battery in case of inverter - var soc func() (float64, error) - if !sm.device.IsEnergyMeter() { - vals, err := sm.device.Values() - if err != nil { - return nil, err - } - - if _, ok := vals[sunny.BatteryCharge]; ok { - soc = sm.soc - } - } - - return decorateSMA(sm, soc, capacity), nil + return sm, nil } // CurrentPower implements the api.Meter interface @@ -170,7 +171,14 @@ func (sm *SMA) Powers() (float64, float64, float64, error) { // soc implements the api.Battery interface func (sm *SMA) soc() (float64, error) { values, err := sm.device.Values() - return sma.AsFloat(values[sunny.BatteryCharge]), err + if err != nil { + return 0, err + } + soc, ok := values[sunny.BatteryCharge] + if !ok { + return 0, api.ErrNotAvailable + } + return sma.AsFloat(soc), nil } var _ api.Diagnosis = (*SMA)(nil) diff --git a/meter/sma_decorators.go b/meter/sma_decorators.go deleted file mode 100644 index 2c8d0d155..000000000 --- a/meter/sma_decorators.go +++ /dev/null @@ -1,58 +0,0 @@ -package meter - -// Code generated by github.com/evcc-io/evcc/cmd/tools/decorate.go. DO NOT EDIT. - -import ( - "github.com/evcc-io/evcc/api" -) - -func decorateSMA(base *SMA, battery func() (float64, error), batteryCapacity func() float64) api.Meter { - switch { - case battery == nil: - return base - - case battery != nil && batteryCapacity == nil: - return &struct { - *SMA - api.Battery - }{ - SMA: base, - Battery: &decorateSMABatteryImpl{ - battery: battery, - }, - } - - case battery != nil && batteryCapacity != nil: - return &struct { - *SMA - api.Battery - api.BatteryCapacity - }{ - SMA: base, - Battery: &decorateSMABatteryImpl{ - battery: battery, - }, - BatteryCapacity: &decorateSMABatteryCapacityImpl{ - batteryCapacity: batteryCapacity, - }, - } - } - - return nil -} - -type decorateSMABatteryImpl struct { - battery func() (float64, error) -} - -func (impl *decorateSMABatteryImpl) Soc() (float64, error) { - return impl.battery() -} - -type decorateSMABatteryCapacityImpl struct { - batteryCapacity func() float64 -} - -func (impl *decorateSMABatteryCapacityImpl) Capacity() float64 { - return impl.batteryCapacity() -} diff --git a/meter/usage_battery.go b/meter/usage_battery.go index 199319711..9cf56337b 100644 --- a/meter/usage_battery.go +++ b/meter/usage_battery.go @@ -39,6 +39,8 @@ type batterySocLimits struct { MinSoc, MaxSoc float64 } +// var _ api.BatterySocLimiter = (*batterySocLimits)(nil) + // Decorator returns an api.BatterySocLimiter decorator func (m *batterySocLimits) Decorator() func() (float64, float64) { if m.MinSoc == 0 && m.MaxSoc == 0 { diff --git a/templates/definition/charger/ochsner-bwwp.yaml b/templates/definition/charger/ochsner-bwwp.yaml index bcf084eb1..c85c2b011 100644 --- a/templates/definition/charger/ochsner-bwwp.yaml +++ b/templates/definition/charger/ochsner-bwwp.yaml @@ -27,7 +27,7 @@ render: | id: {{ .id }} register: address: 2201 # SUR Überschussleistung Auflösung 1 W - type: writeholding + type: writesingle decode: int16 power: source: modbus diff --git a/templates/definition/meter/sma-inverter-speedwire.yaml b/templates/definition/meter/sma-inverter-speedwire.yaml index 79ebe9829..4c142b16a 100644 --- a/templates/definition/meter/sma-inverter-speedwire.yaml +++ b/templates/definition/meter/sma-inverter-speedwire.yaml @@ -19,6 +19,7 @@ params: - preset: battery-params render: | type: sma + usage: {{ .usage }} uri: {{ .host }} # IP address or hostname password: {{ .password }} # optional {{- if eq .usage "battery" }}