diff --git a/meter/homeassistant.go b/meter/homeassistant.go index 2f638240e..22e0233eb 100644 --- a/meter/homeassistant.go +++ b/meter/homeassistant.go @@ -21,6 +21,7 @@ func NewHomeAssistantFromConfig(other map[string]any) (api.Meter, error) { homeassistant.Config `mapstructure:",squash"` Power string Energy string + ReturnEnergy string Currents []string Voltages []string Powers []string @@ -64,37 +65,19 @@ func NewHomeAssistantFromConfig(other map[string]any) (api.Meter, error) { return conn.GetFloatState(cc.Power) }) - // decorators for optional interfaces - var energyG func() (float64, error) - var currentsG, voltagesG, powersG func() (float64, float64, float64, error) - + // energy if cc.Energy != "" { - energyG = func() (float64, error) { return conn.GetFloatState(cc.Energy) } + implement.Has(m, implement.MeterEnergy(func() (float64, error) { + return conn.GetFloatState(cc.Energy) + })) } - // phase currents (optional) - if phases, err := homeassistant.ValidatePhaseEntities(cc.Currents); err != nil { - return nil, fmt.Errorf("currents: %w", err) - } else if len(phases) > 0 { - currentsG = func() (float64, float64, float64, error) { return conn.GetPhaseFloatStates(phases) } + if cc.ReturnEnergy != "" { + implement.Has(m, implement.MeterReturnEnergy(func() (float64, error) { + return conn.GetFloatState(cc.ReturnEnergy) + })) } - // phase voltages (optional) - if phases, err := homeassistant.ValidatePhaseEntities(cc.Voltages); err != nil { - return nil, fmt.Errorf("voltages: %w", err) - } else if len(phases) > 0 { - voltagesG = func() (float64, float64, float64, error) { return conn.GetPhaseFloatStates(phases) } - } - - // phase powers (optional) - if phases, err := homeassistant.ValidatePhaseEntities(cc.Powers); err != nil { - return nil, fmt.Errorf("powers: %w", err) - } else if len(phases) > 0 { - powersG = func() (float64, float64, float64, error) { return conn.GetPhaseFloatStates(phases) } - } - - implement.May(m, implement.MeterEnergy(energyG)) - if cc.Soc != "" { socG := func() (float64, error) { return conn.GetFloatState(cc.Soc) } @@ -125,9 +108,33 @@ func NewHomeAssistantFromConfig(other map[string]any) (api.Meter, error) { return m, nil } - implement.May(m, implement.PhaseCurrents(currentsG)) - implement.May(m, implement.PhaseVoltages(voltagesG)) - implement.May(m, implement.PhasePowers(powersG)) + // phase currents (optional) + if phases, err := homeassistant.ValidatePhaseEntities(cc.Currents); err != nil { + return nil, fmt.Errorf("currents: %w", err) + } else if len(phases) > 0 { + implement.Has(m, implement.PhaseCurrents(func() (float64, float64, float64, error) { + return conn.GetPhaseFloatStates(phases) + })) + } + + // phase voltages (optional) + if phases, err := homeassistant.ValidatePhaseEntities(cc.Voltages); err != nil { + return nil, fmt.Errorf("voltages: %w", err) + } else if len(phases) > 0 { + implement.Has(m, implement.PhaseVoltages(func() (float64, float64, float64, error) { + return conn.GetPhaseFloatStates(phases) + })) + } + + // phase powers (optional) + if phases, err := homeassistant.ValidatePhaseEntities(cc.Powers); err != nil { + return nil, fmt.Errorf("powers: %w", err) + } else if len(phases) > 0 { + implement.Has(m, implement.PhasePowers(func() (float64, float64, float64, error) { + return conn.GetPhaseFloatStates(phases) + })) + } + implement.May(m, implement.MaxACPowerGetter(cc.pvMaxACPower.Decorator())) return m, nil diff --git a/templates/definition/meter/homeassistant.yaml b/templates/definition/meter/homeassistant.yaml index 61166af50..b61e69218 100644 --- a/templates/definition/meter/homeassistant.yaml +++ b/templates/definition/meter/homeassistant.yaml @@ -44,8 +44,18 @@ params: example: "sensor.house_energy" advanced: true help: - en: Entity ID for cumulative energy measurement in kWh. Should provide total energy consumed/produced, not daily or interval values. - de: Entitäts-ID für kumulative Energiemessung in kWh. Sollte die gesamte verbrauchte/produzierte Energie liefern, nicht tägliche oder Intervallwerte. + en: Entity ID for total energy in kWh (e.g. grid import or battery charging). No daily or interval values. + de: Entitäts-ID für Gesamtenergie in kWh (z.B. Netzbezug oder Batterieladung). Keine täglichen oder Intervallwerte. + - name: returnEnergy + description: + de: Energieentität (Gegenrichtung) + en: Return Energy Entity + service: homeassistant/entities?uri={uri}&insecure={insecure}&domain=sensor + example: "sensor.house_return_energy" + advanced: true + help: + en: Entity ID for total energy in reverse direction in kWh (e.g. grid export or battery discharging). No daily or interval values. + de: Entitäts-ID für Gesamtenergie in Gegenrichtung in kWh (z.B. Netzeinspeisung oder Batterieentladung). Keine täglichen oder Intervallwerte. - name: currentL1 description: de: L1 Stromentität @@ -160,6 +170,7 @@ render: | insecure: {{ .insecure }} power: {{ .power }} energy: {{ .energy }} + returnenergy: {{ .returnEnergy }} currents: - {{ .currentL1 }} - {{ .currentL2 }}