diff --git a/api/implement/implementations.go b/api/implement/implementations.go index 882ecb1ac..ccadc39a7 100644 --- a/api/implement/implementations.go +++ b/api/implement/implementations.go @@ -378,6 +378,21 @@ func (i *iPhaseVoltages) Voltages() (float64, float64, float64, error) { return i.phaseVoltages0() } +func PowerLimiter(powerLimiter0 func() (float64, float64, error)) api.PowerLimiter { + if powerLimiter0 == nil { + return nil + } + return &iPowerLimiter{powerLimiter0} +} + +type iPowerLimiter struct { + powerLimiter0 func() (float64, float64, error) +} + +func (i *iPowerLimiter) GetMinMaxPower() (float64, float64, error) { + return i.powerLimiter0() +} + func Resurrector(resurrector0 func() error) api.Resurrector { if resurrector0 == nil { return nil diff --git a/charger/eebus-ohpcf.go b/charger/eebus-ohpcf.go index 7f8798453..f2a364639 100644 --- a/charger/eebus-ohpcf.go +++ b/charger/eebus-ohpcf.go @@ -15,6 +15,7 @@ import ( spineapi "github.com/enbility/spine-go/api" "github.com/enbility/spine-go/model" "github.com/evcc-io/evcc/api" + "github.com/evcc-io/evcc/api/implement" "github.com/evcc-io/evcc/server/eebus" "github.com/evcc-io/evcc/util" ) @@ -27,6 +28,7 @@ import ( // enabling the charger schedules or resumes the optional consumption, disabling // it pauses or aborts the running process. type EEBusOHPCF struct { + implement.Caps *embed cem *eebus.CustomerEnergyManagement ma *eebus.MonitoringAppliance @@ -58,10 +60,11 @@ func init() { // NewEEBusOHPCFFromConfig creates an EEBus OHPCF charger from generic config func NewEEBusOHPCFFromConfig(ctx context.Context, other map[string]any) (api.Charger, error) { cc := struct { - embed `mapstructure:",squash"` - Ski string - Ip string - Reboost time.Duration + embed `mapstructure:",squash"` + Ski string + Ip string + Reboost time.Duration + DisablePowerLimiter bool }{ embed: embed{ Icon_: "heatpump", @@ -74,18 +77,19 @@ func NewEEBusOHPCFFromConfig(ctx context.Context, other map[string]any) (api.Cha return nil, err } - return NewEEBusOHPCF(ctx, &cc.embed, cc.Ski, cc.Ip, cc.Reboost) + return NewEEBusOHPCF(ctx, &cc.embed, cc.Ski, cc.Ip, cc.Reboost, cc.DisablePowerLimiter) } // NewEEBusOHPCF creates an EEBus OHPCF charger, registers it with the EEBus // instance and waits for the connection. -func NewEEBusOHPCF(ctx context.Context, embed *embed, ski, ip string, reboost time.Duration) (api.Charger, error) { +func NewEEBusOHPCF(ctx context.Context, embed *embed, ski, ip string, reboost time.Duration, disablePowerLimiter bool) (api.Charger, error) { inst, err := eebus.Instance() if err != nil { return nil, err } c := &EEBusOHPCF{ + Caps: implement.New(), embed: embed, log: util.NewLogger("eebus-ohpcf"), cem: inst.CustomerEnergyManagement(), @@ -96,6 +100,10 @@ func NewEEBusOHPCF(ctx context.Context, embed *embed, ski, ip string, reboost ti reboost: reboost, } + if !disablePowerLimiter { + implement.Has(c, implement.PowerLimiter(c.getMinMaxPower)) + } + if err := inst.RegisterDevice(ski, ip, c); err != nil { return nil, err } @@ -460,11 +468,8 @@ func (c *EEBusOHPCF) apply(enable bool) error { return nil } -var _ api.PowerLimiter = (*EEBusOHPCF)(nil) - -// GetMinMaxPower implements the api.PowerLimiter interface, reporting the -// optional consumption as expected min/max or ErrNotAvailable if none. -func (c *EEBusOHPCF) GetMinMaxPower() (float64, float64, error) { +// getMinMaxPower is the callback used to provide the optional power limits. +func (c *EEBusOHPCF) getMinMaxPower() (float64, float64, error) { entity, ok := c.connectedCompressor() if !ok { return 0, 0, errNotConnected diff --git a/cmd/implement/implement.go b/cmd/implement/implement.go index 1f5319450..7903d4e7a 100644 --- a/cmd/implement/implement.go +++ b/cmd/implement/implement.go @@ -86,6 +86,7 @@ func generate(out io.Writer) error { reflect.TypeFor[api.PhasePowers](), reflect.TypeFor[api.PhaseSwitcher](), reflect.TypeFor[api.PhaseVoltages](), + reflect.TypeFor[api.PowerLimiter](), reflect.TypeFor[api.Resurrector](), reflect.TypeFor[api.SocLimiter](), reflect.TypeFor[api.StatusReasoner](), diff --git a/templates/definition/charger/eebus-ohpcf-wolfvaillant.yaml b/templates/definition/charger/eebus-ohpcf-wolfvaillant.yaml index 1152c40b2..f09d80910 100644 --- a/templates/definition/charger/eebus-ohpcf-wolfvaillant.yaml +++ b/templates/definition/charger/eebus-ohpcf-wolfvaillant.yaml @@ -29,7 +29,17 @@ params: help: de: Wartezeit, nach der eine neu angekündigte optionale Leistungsaufnahme erneut eingeplant wird. en: Wait time after which a newly announced optional power consumption is scheduled again. + - name: disablepowerlimiter + type: bool + advanced: true + description: + de: Leistungsgrenzen ignorieren + en: Ignore power limits + help: + de: Die vom Gerät gemeldete optionale Leistungsaufnahme nicht als Min-/Max-Leistung verwenden. + en: Do not use the device's announced optional power consumption as min/max power. render: | type: eebus-ohpcf {{ include "eebus" . }} reboost: {{ .reboost }} + disablepowerlimiter: {{ .disablepowerlimiter }} diff --git a/templates/definition/charger/eebus-ohpcf.yaml b/templates/definition/charger/eebus-ohpcf.yaml index 9582775fe..53c00aff6 100644 --- a/templates/definition/charger/eebus-ohpcf.yaml +++ b/templates/definition/charger/eebus-ohpcf.yaml @@ -17,7 +17,17 @@ params: help: de: Wartezeit, nach der eine neu angekündigte optionale Leistungsaufnahme erneut eingeplant wird. en: Wait time after which a newly announced optional power consumption is scheduled again. + - name: disablepowerlimiter + type: bool + advanced: true + description: + de: Leistungsgrenzen ignorieren + en: Ignore power limits + help: + de: Die vom Gerät gemeldete optionale Leistungsaufnahme nicht als Min-/Max-Leistung verwenden. + en: Do not use the device's announced optional power consumption as min/max power. render: | type: eebus-ohpcf {{ include "eebus" . }} reboost: {{ .reboost }} + disablepowerlimiter: {{ .disablepowerlimiter }}