From aeac2010b5c19132cd66db962fd912a07b75ba66 Mon Sep 17 00:00:00 2001 From: premultiply <4681172+premultiply@users.noreply.github.com> Date: Sun, 2 Apr 2023 16:44:08 +0200 Subject: [PATCH] daheimladen-mb: Fix Sessions & setCurrent (#7026) --- charger/daheimladen-mb.go | 154 ++++++++++++++------------------------ 1 file changed, 55 insertions(+), 99 deletions(-) diff --git a/charger/daheimladen-mb.go b/charger/daheimladen-mb.go index 274d13283..cf5773ce9 100644 --- a/charger/daheimladen-mb.go +++ b/charger/daheimladen-mb.go @@ -54,9 +54,6 @@ const ( dlRegChargeControl = 93 // Uint16 WR ENUM dlRegChargeCmd = 95 // Uint16 WR ENUM dlRegVoltages = 108 // 3xUint32 RO 0.1V - - dlCmdStartSession = 1 - dlCmdStopSession = 2 ) func init() { @@ -92,6 +89,15 @@ func NewDaheimLadenMB(uri string, id uint8) (api.Charger, error) { curr: 60, // assume min current } + // get initial state from charger + curr, err := wb.getCurrent() + if err != nil { + return nil, fmt.Errorf("current limit: %w", err) + } + if curr > 0 { + wb.curr = curr + } + // get failsafe timeout from charger b, err := wb.conn.ReadHoldingRegisters(dlRegCommTimeout, 1) if err != nil { @@ -110,6 +116,37 @@ func (wb *DaheimLadenMB) heartbeat(timeout time.Duration) { } } +func (wb *DaheimLadenMB) setCurrent(current uint16) error { + b := make([]byte, 2) + binary.BigEndian.PutUint16(b, current) + + _, err := wb.conn.WriteMultipleRegisters(dlRegCurrentLimit, 1, b) + + return err +} + +func (wb *DaheimLadenMB) getCurrent() (uint16, error) { + b, err := wb.conn.ReadHoldingRegisters(dlRegCurrentLimit, 1) + if err != nil { + return 0, err + } + + return binary.BigEndian.Uint16(b), nil +} + +// utf16BytesToString converts UTF-16 encoded bytes, in big or little endian byte order, +// to a UTF-8 encoded string. +func utf16BytesToString(b []byte, o binary.ByteOrder) string { + utf := make([]uint16, (len(b)+(2-1))/2) + for i := 0; i+(2-1) < len(b); i += 2 { + utf[i/2] = o.Uint16(b[i:]) + } + if len(b)/2 < len(utf) { + utf[len(utf)-1] = utf8.RuneError + } + return string(utf16.Decode(utf)) +} + // Status implements the api.Charger interface func (wb *DaheimLadenMB) Status() (api.ChargeStatus, error) { b, err := wb.conn.ReadHoldingRegisters(dlRegChargingState, 1) @@ -132,6 +169,8 @@ func (wb *DaheimLadenMB) Status() (api.ChargeStatus, error) { return api.StatusB, err } return api.StatusC, nil + case 5: // Start-UP Fail (B2) + return api.StatusB, nil case 6: // Session Terminated by EVSE return api.StatusB, nil default: // Other @@ -141,68 +180,32 @@ func (wb *DaheimLadenMB) Status() (api.ChargeStatus, error) { // Enabled implements the api.Charger interface func (wb *DaheimLadenMB) Enabled() (bool, error) { - b, err := wb.conn.ReadHoldingRegisters(dlRegCurrentLimit, 1) - if err != nil { - return false, err - } + curr, err := wb.getCurrent() - return binary.BigEndian.Uint16(b) != 0, nil + return curr > 0, err } // Enable implements the api.Charger interface func (wb *DaheimLadenMB) Enable(enable bool) error { var current uint16 - var cmd uint16 = dlCmdStopSession // stop session - if enable { current = wb.curr - cmd = dlCmdStartSession // start (new) session } - _ = wb.setCurrent(current) - b := make([]byte, 2) - binary.BigEndian.PutUint16(b, cmd) - - _, err := wb.conn.WriteMultipleRegisters(dlRegChargeCmd, 1, b) - return err -} - -// setCurrent writes the current limit in coarse 1A steps -func (wb *DaheimLadenMB) setCurrent(current uint16) error { - b := make([]byte, 2) - binary.BigEndian.PutUint16(b, current) - - _, err := wb.conn.WriteMultipleRegisters(dlRegCurrentLimit, 1, b) - if err == nil { - wb.curr = current - } - return err + return wb.setCurrent(current) } // MaxCurrent implements the api.Charger interface func (wb *DaheimLadenMB) MaxCurrent(current int64) error { - //return wb.MaxCurrentMillis(float64(current)) if current < 6 { return fmt.Errorf("invalid current %d", current) } - return wb.setCurrent(uint16(current * 10)) + wb.curr = uint16(current * 10) + + return wb.setCurrent(wb.curr) } -/* -var _ api.ChargerEx = (*DaheimLadenMB)(nil) - -// maxCurrentMillis implements the api.ChargerEx interface - - func (wb *DaheimLadenMB) MaxCurrentMillis(current float64) error { - if current < 6 { - return fmt.Errorf("invalid current %.1g", current) - } - - return wb.setCurrent(uint16(current * 10)) - } -*/ - var _ api.Meter = (*DaheimLadenMB)(nil) // CurrentPower implements the api.Meter interface @@ -215,36 +218,6 @@ func (wb *DaheimLadenMB) CurrentPower() (float64, error) { return float64(binary.BigEndian.Uint32(b)), err } -/* -var _ api.ChargeTimer = (*DaheimLadenMB)(nil) - -// ChargingTime implements the api.ChargeTimer interface - - func (wb *DaheimLadenMB) ChargingTime() (time.Duration, error) { - b, err := wb.conn.ReadHoldingRegisters(dlChargingTime, 2) - if err != nil { - return 0, err - } - - return time.Duration(binary.BigEndian.Uint32(b)) * time.Second, nil - } -*/ - -/* -var _ api.ChargeRater = (*DaheimLadenMB)(nil) - -// ChargedEnergy implements the api.MeterEnergy interface - - func (wb *DaheimLadenMB) ChargedEnergy() (float64, error) { - b, err := wb.conn.ReadHoldingRegisters(dlChargedEnergy, 1) - if err != nil { - return 0, err - } - - return float64(binary.BigEndian.Uint16(b)) / 10, err - } -*/ - var _ api.MeterEnergy = (*DaheimLadenMB)(nil) // TotalEnergy implements the api.MeterEnergy interface @@ -286,33 +259,16 @@ func (wb *DaheimLadenMB) Voltages() (float64, float64, float64, error) { return wb.getPhaseValues(dlRegVoltages) } -// utf16BytesToString converts UTF-16 encoded bytes, in big or little endian byte order, -// to a UTF-8 encoded string. -func utf16BytesToString(b []byte, o binary.ByteOrder) string { - utf := make([]uint16, (len(b)+(2-1))/2) - for i := 0; i+(2-1) < len(b); i += 2 { - utf[i/2] = o.Uint16(b[i:]) - } - if len(b)/2 < len(utf) { - utf[len(utf)-1] = utf8.RuneError - } - return string(utf16.Decode(utf)) -} - -/* var _ api.Identifier = (*DaheimLadenMB)(nil) -// identify implements the api.Identifier interface - - func (wb *DaheimLadenMB) Identify() (string, error) { - b, err := wb.conn.ReadHoldingRegisters(dlCardId, 16) - if err != nil { - return "", err - } - - return UTF16BytesToString(b, binary.BigEndian), nil +// Identify implements the api.Identifier interface +func (wb *DaheimLadenMB) Identify() (string, error) { + b, err := wb.conn.ReadHoldingRegisters(dlRegCardId, 16) + if err != nil { + return "", err } -*/ + return utf16BytesToString(b, binary.BigEndian), nil +} var _ api.Diagnosis = (*DaheimLadenMB)(nil)