HomeWizard: support 1p kWh meters (#33293)

This commit is contained in:
github-actions[bot] 2026-08-30 08:15:52 +00:00 • committed by GitHub
parent 490f209e57
commit dbe100b24b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 67 additions and 34 deletions

View file

@ -10,6 +10,7 @@ import (
"github.com/evcc-io/evcc/util" "github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request" "github.com/evcc-io/evcc/util/request"
"github.com/evcc-io/evcc/util/transport" "github.com/evcc-io/evcc/util/transport"
"github.com/samber/lo"
) )
// Connection is the homewizard connection // Connection is the homewizard connection
@ -119,10 +120,17 @@ func (c *Connection) TotalEnergy() (float64, error) {
// Currents implements the api.PhaseCurrents interface // Currents implements the api.PhaseCurrents interface
func (c *Connection) Currents() (float64, float64, float64, error) { func (c *Connection) Currents() (float64, float64, float64, error) {
res, err := c.dataG.Get() res, err := c.dataG.Get()
if c.usage == "pv" {
return -res.ActiveCurrentL1A, -res.ActiveCurrentL2A, -res.ActiveCurrentL3A, err // 1p meters report the total instead of per-phase values
l1, l2, l3 := res.ActiveCurrentA, 0.0, 0.0
if res.ActiveCurrentL1A != nil {
l1, l2, l3 = lo.FromPtr(res.ActiveCurrentL1A), lo.FromPtr(res.ActiveCurrentL2A), lo.FromPtr(res.ActiveCurrentL3A)
} }
return res.ActiveCurrentL1A, res.ActiveCurrentL2A, res.ActiveCurrentL3A, err
if c.usage == "pv" {
return -l1, -l2, -l3, err
}
return l1, l2, l3, err
} }
// Powers implements the api.PhasePowers interface // Powers implements the api.PhasePowers interface
@ -137,5 +145,12 @@ func (c *Connection) Powers() (float64, float64, float64, error) {
// Voltages implements the api.PhaseVoltages interface // Voltages implements the api.PhaseVoltages interface
func (c *Connection) Voltages() (float64, float64, float64, error) { func (c *Connection) Voltages() (float64, float64, float64, error) {
res, err := c.dataG.Get() res, err := c.dataG.Get()
return res.ActiveVoltageL1V, res.ActiveVoltageL2V, res.ActiveVoltageL3V, err
// 1p meters report the total instead of per-phase values
l1, l2, l3 := res.ActiveVoltageV, 0.0, 0.0
if res.ActiveCurrentL1A != nil {
l1, l2, l3 = lo.FromPtr(res.ActiveVoltageL1V), lo.FromPtr(res.ActiveVoltageL2V), lo.FromPtr(res.ActiveVoltageL3V)
}
return l1, l2, l3, err
} }

View file

@ -16,22 +16,24 @@ type StateResponse struct {
// DataResponse returns the most recent measurements from the HomeWizard device // DataResponse returns the most recent measurements from the HomeWizard device
// https://homewizard-energy-api.readthedocs.io/endpoints.html#state-api-v1-state // https://homewizard-energy-api.readthedocs.io/endpoints.html#state-api-v1-state
type DataResponse struct { type DataResponse struct {
ActivePowerW float64 `json:"active_power_w"` ActivePowerW float64 `json:"active_power_w"`
ActivePowerL1W float64 `json:"active_power_l1_w"` ActivePowerL1W float64 `json:"active_power_l1_w"`
ActivePowerL2W float64 `json:"active_power_l2_w"` ActivePowerL2W float64 `json:"active_power_l2_w"`
ActivePowerL3W float64 `json:"active_power_l3_w"` ActivePowerL3W float64 `json:"active_power_l3_w"`
TotalPowerImportT1kWh float64 `json:"total_power_import_t1_kwh"` TotalPowerImportT1kWh float64 `json:"total_power_import_t1_kwh"`
TotalPowerImportT2kWh float64 `json:"total_power_import_t2_kwh"` TotalPowerImportT2kWh float64 `json:"total_power_import_t2_kwh"`
TotalPowerImportT3kWh float64 `json:"total_power_import_t3_kwh"` TotalPowerImportT3kWh float64 `json:"total_power_import_t3_kwh"`
TotalPowerImportT4kWh float64 `json:"total_power_import_t4_kwh"` TotalPowerImportT4kWh float64 `json:"total_power_import_t4_kwh"`
TotalPowerExportT1kWh float64 `json:"total_power_export_t1_kwh"` TotalPowerExportT1kWh float64 `json:"total_power_export_t1_kwh"`
TotalPowerExportT2kWh float64 `json:"total_power_export_t2_kwh"` TotalPowerExportT2kWh float64 `json:"total_power_export_t2_kwh"`
TotalPowerExportT3kWh float64 `json:"total_power_export_t3_kwh"` TotalPowerExportT3kWh float64 `json:"total_power_export_t3_kwh"`
TotalPowerExportT4kWh float64 `json:"total_power_export_t4_kwh"` TotalPowerExportT4kWh float64 `json:"total_power_export_t4_kwh"`
ActiveCurrentL1A float64 `json:"active_current_l1_a"` ActiveCurrentA float64 `json:"active_current_a"`
ActiveCurrentL2A float64 `json:"active_current_l2_a"` ActiveVoltageV float64 `json:"active_voltage_v"`
ActiveCurrentL3A float64 `json:"active_current_l3_a"` ActiveCurrentL1A *float64 `json:"active_current_l1_a"`
ActiveVoltageL1V float64 `json:"active_voltage_l1_v"` ActiveCurrentL2A *float64 `json:"active_current_l2_a"`
ActiveVoltageL2V float64 `json:"active_voltage_l2_v"` ActiveCurrentL3A *float64 `json:"active_current_l3_a"`
ActiveVoltageL3V float64 `json:"active_voltage_l3_v"` ActiveVoltageL1V *float64 `json:"active_voltage_l1_v"`
ActiveVoltageL2V *float64 `json:"active_voltage_l2_v"`
ActiveVoltageL3V *float64 `json:"active_voltage_l3_v"`
} }

View file

@ -47,12 +47,28 @@ func TestUnmarshalKwhDataResponse(t *testing.T) {
assert.Equal(t, float64(28), res.ActivePowerL1W) assert.Equal(t, float64(28), res.ActivePowerL1W)
assert.Equal(t, float64(0), res.ActivePowerL2W) assert.Equal(t, float64(0), res.ActivePowerL2W)
assert.Equal(t, float64(-181), res.ActivePowerL3W) assert.Equal(t, float64(-181), res.ActivePowerL3W)
assert.Equal(t, float64(235.4), res.ActiveVoltageL1V) assert.Equal(t, float64(235.4), *res.ActiveVoltageL1V)
assert.Equal(t, float64(235.8), res.ActiveVoltageL2V) assert.Equal(t, float64(235.8), *res.ActiveVoltageL2V)
assert.Equal(t, float64(236.1), res.ActiveVoltageL3V) assert.Equal(t, float64(236.1), *res.ActiveVoltageL3V)
assert.Equal(t, float64(1.19), res.ActiveCurrentL1A) assert.Equal(t, float64(1.19), *res.ActiveCurrentL1A)
assert.Equal(t, float64(0.37), res.ActiveCurrentL2A) assert.Equal(t, float64(0.37), *res.ActiveCurrentL2A)
assert.Equal(t, float64(-0.93), res.ActiveCurrentL3A) assert.Equal(t, float64(-0.93), *res.ActiveCurrentL3A)
}
}
// Test homewizard kWh Meter 1-Phase response without per-phase current/voltage
func TestUnmarshalKwh1PhaseDataResponse(t *testing.T) {
{
var res DataResponse
// https://api-documentation.homewizard.com/docs/v1/measurement#kwh-meters-1-and-3-phase
jsonstr := `{"total_power_import_kwh":1.097,"total_power_import_t1_kwh":1.097,"total_power_export_kwh":0,"total_power_export_t1_kwh":0,"active_power_w":1381.396,"active_power_l1_w":1381.396,"active_voltage_v":228.641,"active_current_a":6.051,"active_apparent_current_a":6.068,"active_reactive_current_a":0.461,"active_apparent_power_va":1385.536,"active_reactive_power_var":-105.28,"active_power_factor":0.997,"active_frequency_hz":50}`
require.NoError(t, json.Unmarshal([]byte(jsonstr), &res))
assert.Equal(t, float64(1381.396), res.ActivePowerW)
assert.Equal(t, float64(1381.396), res.ActivePowerL1W)
assert.Equal(t, float64(228.641), res.ActiveVoltageV)
assert.Equal(t, float64(6.051), res.ActiveCurrentA)
assert.Nil(t, res.ActiveCurrentL1A)
} }
} }
@ -70,11 +86,11 @@ func TestUnmarshalP1DataResponse(t *testing.T) {
assert.Equal(t, float64(-21), res.ActivePowerL1W) assert.Equal(t, float64(-21), res.ActivePowerL1W)
assert.Equal(t, float64(57), res.ActivePowerL2W) assert.Equal(t, float64(57), res.ActivePowerL2W)
assert.Equal(t, float64(168), res.ActivePowerL3W) assert.Equal(t, float64(168), res.ActivePowerL3W)
assert.Equal(t, float64(228), res.ActiveVoltageL1V) assert.Equal(t, float64(228), *res.ActiveVoltageL1V)
assert.Equal(t, float64(226), res.ActiveVoltageL2V) assert.Equal(t, float64(226), *res.ActiveVoltageL2V)
assert.Equal(t, float64(225), res.ActiveVoltageL3V) assert.Equal(t, float64(225), *res.ActiveVoltageL3V)
assert.Equal(t, float64(-0.092), res.ActiveCurrentL1A) assert.Equal(t, float64(-0.092), *res.ActiveCurrentL1A)
assert.Equal(t, float64(0.252), res.ActiveCurrentL2A) assert.Equal(t, float64(0.252), *res.ActiveCurrentL2A)
assert.Equal(t, float64(0.747), res.ActiveCurrentL3A) assert.Equal(t, float64(0.747), *res.ActiveCurrentL3A)
} }
} }