Add RFID support to enable charging on KEBA (#160)
This commit is contained in:
parent
4a1c029abd
commit
fe334e8327
5 changed files with 84 additions and 6 deletions
|
|
@ -50,6 +50,11 @@ type Charger interface {
|
|||
MaxCurrent(current int64) error
|
||||
}
|
||||
|
||||
// Diagnosis is a helper interface that allows to dump diagnostic data to console
|
||||
type Diagnosis interface {
|
||||
Diagnosis()
|
||||
}
|
||||
|
||||
// ChargeTimer provides current charge cycle duration
|
||||
type ChargeTimer interface {
|
||||
ChargingTime() (time.Duration, error)
|
||||
|
|
|
|||
|
|
@ -22,10 +22,16 @@ const (
|
|||
kebaPort = "7090"
|
||||
)
|
||||
|
||||
// RFID contains access credentials
|
||||
type RFID struct {
|
||||
Tag, Class string
|
||||
}
|
||||
|
||||
// Keba is an api.Charger implementation with configurable getters and setters.
|
||||
type Keba struct {
|
||||
log *util.Logger
|
||||
conn string
|
||||
rfid RFID
|
||||
timeout time.Duration
|
||||
recv chan keba.UDPMsg
|
||||
}
|
||||
|
|
@ -35,14 +41,17 @@ func NewKebaFromConfig(log *util.Logger, other map[string]interface{}) api.Charg
|
|||
cc := struct {
|
||||
URI string
|
||||
Timeout time.Duration
|
||||
}{}
|
||||
RFID RFID
|
||||
}{
|
||||
RFID: RFID{Class: "00000000000000000000"}, // default class
|
||||
}
|
||||
util.DecodeOther(log, other, &cc)
|
||||
|
||||
return NewKeba(cc.URI, cc.Timeout)
|
||||
return NewKeba(cc.URI, cc.RFID, cc.Timeout)
|
||||
}
|
||||
|
||||
// NewKeba creates a new charger
|
||||
func NewKeba(conn string, timeout time.Duration) api.Charger {
|
||||
func NewKeba(conn string, rfid RFID, timeout time.Duration) api.Charger {
|
||||
log := util.NewLogger("keba")
|
||||
|
||||
if keba.Instance == nil {
|
||||
|
|
@ -61,6 +70,7 @@ func NewKeba(conn string, timeout time.Duration) api.Charger {
|
|||
c := &Keba{
|
||||
log: log,
|
||||
conn: conn,
|
||||
rfid: rfid,
|
||||
timeout: timeout,
|
||||
recv: make(chan keba.UDPMsg),
|
||||
}
|
||||
|
|
@ -152,10 +162,14 @@ func (c *Keba) Status() (api.ChargeStatus, error) {
|
|||
return api.StatusA, err
|
||||
}
|
||||
|
||||
if kr.AuthON == 1 && c.rfid.Tag == "" {
|
||||
c.log.WARN.Println("missing credentials for RFID authorization")
|
||||
}
|
||||
|
||||
if kr.Plug < 5 {
|
||||
return api.StatusA, nil
|
||||
}
|
||||
if kr.State == 2 {
|
||||
if kr.State == 2 || kr.State == 5 {
|
||||
return api.StatusB, nil
|
||||
}
|
||||
if kr.State == 3 {
|
||||
|
|
@ -176,8 +190,29 @@ func (c *Keba) Enabled() (bool, error) {
|
|||
return kr.EnableSys == 1 || kr.EnableUser == 1, nil
|
||||
}
|
||||
|
||||
// enableRFID sends RFID credentials to enable charge
|
||||
func (c *Keba) enableRFID() error {
|
||||
var resp string
|
||||
err := c.roundtrip(fmt.Sprintf("start %s %s", c.rfid.Tag, c.rfid.Class), 0, &resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp == keba.OK {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("start unexpected response: %s", resp)
|
||||
}
|
||||
|
||||
// Enable implements the Charger.Enable interface
|
||||
func (c *Keba) Enable(enable bool) error {
|
||||
if enable && c.rfid.Tag != "" {
|
||||
if err := c.enableRFID(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var d int
|
||||
if enable {
|
||||
d = 1
|
||||
|
|
@ -246,3 +281,11 @@ func (c *Keba) Currents() (float64, float64, float64, error) {
|
|||
// 1mA to A
|
||||
return float64(kr.I1) / 1e3, float64(kr.I2) / 1e3, float64(kr.I3) / 1e3, err
|
||||
}
|
||||
|
||||
// Diagnosis implements the Diagnosis interface
|
||||
func (c *Keba) Diagnosis() {
|
||||
var kr keba.Report100
|
||||
if err := c.roundtrip("report 100", 100, &kr); err == nil {
|
||||
fmt.Printf("%+v\n", kr)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,3 +58,22 @@ type Report3 struct {
|
|||
ETotal int64 `json:"E total"`
|
||||
Sec int64 `json:"Sec"`
|
||||
}
|
||||
|
||||
// Report100 is the report 100 command answer
|
||||
type Report100 struct {
|
||||
ID int `json:"ID,string"`
|
||||
Serial string `json:"Serial"`
|
||||
SessionID int64 `json:"SessionID"`
|
||||
CurrHW int `json:"Curr HW"`
|
||||
EStart int64 `json:"E start"`
|
||||
EPres int64 `json:"E pres"`
|
||||
Started string `json:"started"`
|
||||
Ended string `json:"ended"`
|
||||
StartedS int64 `json:"started[s]"`
|
||||
EndedS int64 `json:"ended[s]"`
|
||||
Reason int `json:"reason"`
|
||||
TimeQ int `json:"timeQ"`
|
||||
RFIDTag string `json:"RFID tag"`
|
||||
RFIDClass string `json:"RFID class"`
|
||||
Sec int64 `json:"Sec"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,4 +48,9 @@ func dumpAPIs(v interface{}) {
|
|||
fmt.Printf("Duration: %v\n", duration)
|
||||
}
|
||||
}
|
||||
|
||||
if v, ok := v.(api.Diagnosis); ok {
|
||||
fmt.Println("Diagnostic dump:")
|
||||
v.Diagnosis()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,17 +110,23 @@ chargers:
|
|||
- name: evsewifi
|
||||
type: evsewifi # Charger with Phoenix Contact controller
|
||||
uri: http://192.168.1.4 # SimpleEVSE-Wifi address
|
||||
- name: nrg
|
||||
type: nrg # NRGKick charger
|
||||
- name: nrg-1
|
||||
type: nrgkick-connect # NRGKick Connect charger
|
||||
ip: 192.168.1.4 # IP
|
||||
macaddress: 00:99:22 # MAC address
|
||||
password: # password
|
||||
# - name: nrg-2
|
||||
# type: nrgkick-bluetooth # NRGKick charger with Bluetooth
|
||||
# macaddress: 00:99:22 # MAC address
|
||||
# pin: # pin
|
||||
- name: go-e
|
||||
type: go-e # go-eCharger
|
||||
uri: http://192.168.1.4 # go-e address
|
||||
- name: keba
|
||||
type: keba # KEBA charger
|
||||
uri: 192.168.1.4:7090 # KEBA address
|
||||
rfid:
|
||||
tag: 765765348 # RFID tag, see `evcc charger` to show tag
|
||||
- name: mcc
|
||||
type: mcc # Mobile Charger Connect (Audi, Bentley, Porsche)
|
||||
uri: https://192.168.1.4 # Mobile Charger Connect address
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue