ABL: Add wakeup (#2883)

This commit is contained in:
premultiply 2022-03-15 11:25:31 +01:00 • committed by GitHub
parent 3d9be7b157
commit e6b31626d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -3,6 +3,7 @@ package charger
// LICENSE
// Copyright (c) 2019-2022 andig
// Copyright (c) 2022 premultiply
// This module is NOT covered by the MIT license. All rights reserved.
@ -20,6 +21,7 @@ package charger
import (
"encoding/binary"
"fmt"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
@ -34,14 +36,16 @@ type ABLeMH struct {
}
const (
ablRegFirmware = 0x01
ablRegStatus = 0x04
ablRegEnabled = 0x0F
ablRegAmpsConfig = 0x14
ablRegStatusLong = 0x2E
ablRegFirmware = 0x01
ablRegStatus = 0x04
ablRegModifyState = 0x05
ablRegEnabled = 0x0F
ablRegAmpsConfig = 0x14
ablRegStatusLong = 0x2E
ablAmpsDisabled uint16 = 0x03E8
ablSensorPresent = 1 << 5
ablAmpsDisabled uint16 = 0x03E8
ablSensorPresent = 1 << 5
)
var ablStatus = map[byte]string{
@ -108,8 +112,7 @@ func NewABLeMH(uri, device, comset string, baudrate int, slaveID uint8) (api.Cha
curr: uint16(6 / 0.06),
}
_, _ = wb.conn.ReadHoldingRegisters(ablRegFirmware, 2)
b, err := wb.conn.ReadHoldingRegisters(ablRegFirmware, 2)
b, err := wb.get(ablRegFirmware, 2)
// check presence of current sensor
if err == nil && (b[3]&ablSensorPresent != 0) {
@ -119,10 +122,28 @@ func NewABLeMH(uri, device, comset string, baudrate int, slaveID uint8) (api.Cha
return wb, err
}
func (wb *ABLeMH) set(reg, val uint16) error {
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, val)
//write two times
_, _ = wb.conn.WriteMultipleRegisters(reg, 1, b)
_, err := wb.conn.WriteMultipleRegisters(reg, 1, b)
return err
}
func (wb *ABLeMH) get(reg, count uint16) ([]byte, error) {
//read two times
_, _ = wb.conn.ReadHoldingRegisters(reg, count)
b, err := wb.conn.ReadHoldingRegisters(reg, count)
return b, err
}
// Status implements the api.Charger interface
func (wb *ABLeMH) Status() (api.ChargeStatus, error) {
_, _ = wb.conn.ReadHoldingRegisters(ablRegStatus, 1)
b, err := wb.conn.ReadHoldingRegisters(ablRegStatus, 1)
b, err := wb.get(ablRegStatus, 1)
if err != nil {
return api.StatusNone, err
}
@ -144,8 +165,7 @@ func (wb *ABLeMH) Status() (api.ChargeStatus, error) {
// Enabled implements the api.Charger interface
func (wb *ABLeMH) Enabled() (bool, error) {
_, _ = wb.conn.ReadHoldingRegisters(ablRegEnabled, 5)
b, err := wb.conn.ReadHoldingRegisters(ablRegEnabled, 5)
b, err := wb.get(ablRegEnabled, 5)
if err != nil {
return false, err
}
@ -161,17 +181,17 @@ func (wb *ABLeMH) Enable(enable bool) error {
u = wb.curr
}
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, u)
_, _ = wb.conn.WriteMultipleRegisters(ablRegAmpsConfig, 1, b)
_, err := wb.conn.WriteMultipleRegisters(ablRegAmpsConfig, 1, b)
err := wb.set(ablRegAmpsConfig, u)
return err
}
// MaxCurrent implements the api.Charger interface
func (wb *ABLeMH) MaxCurrent(current int64) error {
if current < 6 {
return fmt.Errorf("invalid current %d", current)
}
return wb.MaxCurrentMillis(float64(current))
}
@ -179,14 +199,17 @@ var _ api.ChargerEx = (*ABLeMH)(nil)
// MaxCurrent implements the api.ChargerEx interface
func (wb *ABLeMH) MaxCurrentMillis(current float64) error {
if current < 6 {
return fmt.Errorf("invalid current %.1f", current)
}
// calculate duty cycle according to https://www.goingelectric.de/forum/viewtopic.php?p=1575287#p1575287
wb.curr = uint16(current / 0.06)
cur := uint16(current / 0.06)
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, wb.curr)
_, _ = wb.conn.WriteMultipleRegisters(ablRegAmpsConfig, 1, b)
_, err := wb.conn.WriteMultipleRegisters(ablRegAmpsConfig, 1, b)
err := wb.set(ablRegAmpsConfig, cur)
if err == nil {
wb.curr = cur
}
return err
}
@ -199,8 +222,7 @@ func (wb *ABLeMH) currentPower() (float64, error) {
// Currents implements the api.MeterCurrent interface
func (wb *ABLeMH) currents() (float64, float64, float64, error) {
_, _ = wb.conn.ReadHoldingRegisters(ablRegStatusLong, 5)
b, err := wb.conn.ReadHoldingRegisters(ablRegStatusLong, 5)
b, err := wb.get(ablRegStatusLong, 5)
if err != nil {
return 0, 0, 0, err
}
@ -222,9 +244,23 @@ var _ api.Diagnosis = (*ABLeMH)(nil)
// Diagnose implements the api.Diagnosis interface
func (wb *ABLeMH) Diagnose() {
_, _ = wb.conn.ReadHoldingRegisters(ablRegFirmware, 2)
b, err := wb.conn.ReadHoldingRegisters(ablRegFirmware, 2)
b, err := wb.get(ablRegFirmware, 2)
if err == nil {
fmt.Printf("Firmware: %0 x\n", b)
}
}
var _ api.AlarmClock = (*ABLeMH)(nil)
// WakeUp implements the api.AlarmClock interface
func (wb *ABLeMH) WakeUp() error {
// temporary jump to status E0 (Outlet disabled)
err := wb.set(ablRegModifyState, 0xE0E0)
if err == nil {
time.Sleep(3 * time.Second)
// jump back to state A1 (Waiting for EV)
err = wb.set(ablRegModifyState, 0xA1A1)
}
return err
}