daheimladen-mb: Fix Sessions & setCurrent (#7026)

This commit is contained in:
premultiply 2023-04-02 16:44:08 +02:00 • committed by GitHub
parent 8ae426e4f4
commit aeac2010b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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)