diff --git a/charger/abl.go b/charger/abl.go index 0c0b22185..3cac04647 100644 --- a/charger/abl.go +++ b/charger/abl.go @@ -40,7 +40,8 @@ const ( ablRegAmpsConfig = 0x14 ablRegStatusLong = 0x2E - ablAmpsDisabled uint16 = 0x03E8 + ablAmpsDisabled uint16 = 0x03E8 + ablSensorPresent = 1 << 5 ) var ablStatus = map[byte]string{ @@ -86,6 +87,8 @@ func NewABLeMHFromConfig(other map[string]interface{}) (api.Charger, error) { return NewABLeMH(cc.URI, cc.Device, cc.Comset, cc.Baudrate, cc.ID) } +//go:generate go run ../cmd/tools/decorate.go -f decorateABLeMH -b *ABLeMH -r api.Charger -t "api.Meter,CurrentPower,func() (float64, error)" -t "api.MeterCurrent,Currents,func() (float64, float64, float64, error)" + // NewABLeMH creates ABLeMH charger func NewABLeMH(uri, device, comset string, baudrate int, slaveID uint8) (api.Charger, error) { conn, err := modbus.NewConnection(uri, device, comset, baudrate, modbus.AsciiFormat, slaveID) @@ -106,7 +109,15 @@ func NewABLeMH(uri, device, comset string, baudrate int, slaveID uint8) (api.Cha curr: uint16(6 / 0.06), } - return wb, nil + _, _ = wb.conn.ReadHoldingRegisters(ablRegFirmware, 2) + b, err := wb.conn.ReadHoldingRegisters(ablRegFirmware, 2) + + // check presence of current sensor + if err == nil && (b[3]&ablSensorPresent != 0) { + return decorateABLeMH(wb, wb.currentPower, wb.currents), nil + } + + return wb, err } // Status implements the api.Charger interface @@ -181,18 +192,14 @@ func (wb *ABLeMH) MaxCurrentMillis(current float64) error { return err } -var _ api.Meter = (*ABLeMH)(nil) - -// CurrentPower implements the api.Meter interface -func (wb *ABLeMH) CurrentPower() (float64, error) { - l1, l2, l3, err := wb.Currents() +// currentPower implements the api.Meter interface +func (wb *ABLeMH) currentPower() (float64, error) { + l1, l2, l3, err := wb.currents() return 230 * (l1 + l2 + l3), err } -var _ api.MeterCurrent = (*ABLeMH)(nil) - // Currents implements the api.MeterCurrent interface -func (wb *ABLeMH) Currents() (float64, float64, float64, error) { +func (wb *ABLeMH) currents() (float64, float64, float64, error) { _, _ = wb.conn.ReadHoldingRegisters(ablRegStatusLong, 5) b, err := wb.conn.ReadHoldingRegisters(ablRegStatusLong, 5) if err != nil { diff --git a/charger/abl_decorators.go b/charger/abl_decorators.go new file mode 100644 index 000000000..6ce28354f --- /dev/null +++ b/charger/abl_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 decorateABLeMH(base *ABLeMH, meter func() (float64, error), meterCurrent func() (float64, float64, float64, error)) api.Charger { + switch { + case meter == nil && meterCurrent == nil: + return base + + case meter != nil && meterCurrent == nil: + return &struct { + *ABLeMH + api.Meter + }{ + ABLeMH: base, + Meter: &decorateABLeMHMeterImpl{ + meter: meter, + }, + } + + case meter == nil && meterCurrent != nil: + return &struct { + *ABLeMH + api.MeterCurrent + }{ + ABLeMH: base, + MeterCurrent: &decorateABLeMHMeterCurrentImpl{ + meterCurrent: meterCurrent, + }, + } + + case meter != nil && meterCurrent != nil: + return &struct { + *ABLeMH + api.Meter + api.MeterCurrent + }{ + ABLeMH: base, + Meter: &decorateABLeMHMeterImpl{ + meter: meter, + }, + MeterCurrent: &decorateABLeMHMeterCurrentImpl{ + meterCurrent: meterCurrent, + }, + } + } + + return nil +} + +type decorateABLeMHMeterImpl struct { + meter func() (float64, error) +} + +func (impl *decorateABLeMHMeterImpl) CurrentPower() (float64, error) { + return impl.meter() +} + +type decorateABLeMHMeterCurrentImpl struct { + meterCurrent func() (float64, float64, float64, error) +} + +func (impl *decorateABLeMHMeterCurrentImpl) Currents() (float64, float64, float64, error) { + return impl.meterCurrent() +}