Skip to content

Commit

Permalink
decorate
Browse files Browse the repository at this point in the history
  • Loading branch information
premultiply committed Sep 8, 2024
1 parent 7bcebe7 commit e5377d1
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 25 deletions.
65 changes: 40 additions & 25 deletions charger/delta.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type Delta struct {
curr float64
base uint16
enabled bool
isBasic bool
statusG func(uint16) (api.ChargeStatus, error)
}

const (
Expand Down Expand Up @@ -102,9 +102,14 @@ func NewDelta(uri, device, comset string, baudrate int, proto modbus.Protocol, s

wb.base = connector * 1000

// check for basic or smart register set
if _, err := wb.conn.ReadInputRegisters(wb.base+deltaRegEvseChargerState, 1); err != nil {
wb.isBasic = true
var statusReasonG func() (api.Reason, error)

wb.statusG = wb.statusBasic

// check for smart register set
if _, err := wb.conn.ReadInputRegisters(wb.base+deltaRegEvseChargerState, 1); err == nil {
wb.statusG = wb.statusSmart
statusReasonG = wb.statusReason
}

b, err := wb.conn.ReadHoldingRegisters(deltaRegCommunicationTimeoutEnabled, 1)
Expand All @@ -122,9 +127,11 @@ func NewDelta(uri, device, comset string, baudrate int, proto modbus.Protocol, s
}
}

return wb, nil
return decorateDelta(wb, statusReasonG), nil
}

//go:generate go run ../cmd/tools/decorate.go -f decorateDelta -b *Delta -r api.Charger -t "api.StatusReasoner,StatusReason,func() (api.Reason, error)"

func (wb *Delta) heartbeat(timeout time.Duration) {
for range time.Tick(timeout) {
wb.mu.Lock()
Expand Down Expand Up @@ -156,14 +163,13 @@ func (wb *Delta) Status() (api.ChargeStatus, error) {
// 7: Suspended EVSE
// 8: Not ready
// 9: Faulted
switch s := encoding.Uint16(b); s {
case 0, 1, 2:
return wb.statusG(encoding.Uint16(b))
}

func (wb *Delta) statusBasic(s uint16) (api.ChargeStatus, error) {
switch s {
case 0, 1, 2, 3:
return api.StatusA, nil
case 3:
if wb.isBasic {
return api.StatusA, nil
}
return api.StatusB, nil
case 5, 6, 7, 9:
return api.StatusB, nil
case 4:
Expand All @@ -173,22 +179,31 @@ func (wb *Delta) Status() (api.ChargeStatus, error) {
}
}

var _ api.StatusReasoner = (*Delta)(nil)
func (wb *Delta) statusSmart(s uint16) (api.ChargeStatus, error) {
switch s {
case 0, 1, 2:
return api.StatusA, nil
case 3, 5, 6, 7, 9:
return api.StatusB, nil
case 4:
return api.StatusC, nil
default:
return api.StatusNone, fmt.Errorf("invalid status: %0x", s)
}
}

// statusReason implements the api.StatusReasoner interface
func (wb *Delta) StatusReason() (api.Reason, error) {
if !wb.isBasic {
b, err := wb.conn.ReadInputRegisters(wb.base+deltaRegEvseState, 1)
if err != nil {
return api.ReasonUnknown, err
}
func (wb *Delta) statusReason() (api.Reason, error) {
b, err := wb.conn.ReadInputRegisters(wb.base+deltaRegEvseState, 1)
if err != nil {
return api.ReasonUnknown, err
}

switch s := encoding.Uint16(b); s {
case 3:
return api.ReasonWaitingForAuthorization, nil
case 5:
return api.ReasonDisconnectRequired, nil
}
switch s := encoding.Uint16(b); s {
case 3:
return api.ReasonWaitingForAuthorization, nil
case 5:
return api.ReasonDisconnectRequired, nil
}

return api.ReasonUnknown, nil
Expand Down
35 changes: 35 additions & 0 deletions charger/delta_decorators.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 comment on commit e5377d1

@madmat17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ich habe mir den Quelltext in der fix/delta-status-decorated genauer angesehen und basierend auf den Kommentaren glaube ich, dass ein Missverständnis vorliegt.
Es scheint davon ausgegangen zu werden, dass man in der Smart-Variante mehr Register auslesen kann - dem ist paradoxer Weise aber nicht so. Die Logik stimmt aber grundsätzlich.

Grundsätzliches:

  1. Wenn die Delta AC Max Smart direkt(!) über Modbus TCP angebunden ist (bei der Delta AC Max Basic gibt es die Möglichkeit nicht), dann kann das Register 1001 nicht ausgelesen werden.
  2. Wenn die Delta AC Max Basic über einen RTU/TCP-Konverter angebunden ist (ob das auch bei der Smart der Fall wäre, wissen wir Stand heute nicht), dann kann das Register 1000 ausgelesen werden.

Das war der Grund, warum wir die Verfügbarkeit des Registers 1001 nutzen, um zwischen der Modbux RTU- und der Modubs TCP-Logik zu switchen.

Das Ergebnis sollte sein, dass bei der Delta AC Max Smart beim Auslesen einer 3 aus dem Register 1000 (deltaRegEvseState) der api.StatusB zurückgegeben wird.

Das heißt:
Register 1001 verfügbar = Basic-Logik
Register 1000 nicht verfügbar = Smart-Logik

Kleine Korrektur:

Wir haben im Code des Commits b8d9203 noch einen Knopf in der Zuordnung der Register-Werte zum Status. in der statusOCPP().
Das habe ich adaptiert an jenes aus der dieser delta.go-Version.

Den Code im neuen PR #16094 habe ich getestet - damit läuft die Delta AC Max Smart und wird erkannt.

Randnotiz:

Warum der StatusB bei der RTU-Abfrage (Delta AC Max Basic) überhautp ein Problem verursacht hat, verstehe ich nicht, da das Register 1001 (deltaRegEvseChargerState) gar nicht weiter abgefragt wurde () und eigentlich dieselbe Logik funktionieren sollte.
https://github.com/evcc-io/evcc/blob/70b87715e10bb22bc005b3a05953d2116798a00d/charger/delta.go : Diese Version hat nur mit der Delta AC Max Smart funktioniert
https://github.com/evcc-io/evcc/blob/da91ea630318eae7e3569e6895963f50cd69cf39/charger/delta.go : Diese Version hat nur mit der Delta AC Max Basic funktionert.
Was mir aufgefallen ist: In Zeile 79 hat sich
return NewDelta(cc.URI, cc.Device, cc.Comset, cc.Baudrate, modbus.ProtocolFromRTU(cc.RTU), cc.ID, cc.Connector) in
return NewDelta(cc.URI, cc.Device, cc.Comset, cc.Baudrate, cc.Settings.Protocol(), cc.ID, cc.Connector) geändert.
Kann das der breaking change für die Delta AC Max Basic (Verbindung über RTU/TCP-Converter anstatt über die native TCP-Verbindung der Wallbox) gewesen sein?

Please sign in to comment.