diff --git a/charger/alfen.go b/charger/alfen.go index f455800d5..db043937c 100644 --- a/charger/alfen.go +++ b/charger/alfen.go @@ -55,21 +55,28 @@ func init() { registry.Add("alfen", NewAlfenFromConfig) } +// go:generate go run ../cmd/tools/decorate.go -f decorateAlfen -b "*Alfen" -r api.Charger -t "api.PhaseSwitcher,Phases1p3p,func(int) error" + // NewAlfenFromConfig creates a Alfen charger from generic config func NewAlfenFromConfig(other map[string]interface{}) (api.Charger, error) { - cc := modbus.TcpSettings{ - ID: 1, + cc := struct { + Phases int + modbus.TcpSettings `mapstructure:",squash"` + }{ + TcpSettings: modbus.TcpSettings{ + ID: 1, + }, } if err := util.DecodeOther(other, &cc); err != nil { return nil, err } - return NewAlfen(cc.URI, cc.ID) + return NewAlfen(cc.URI, cc.ID, cc.Phases) } // NewAlfen creates Alfen charger -func NewAlfen(uri string, slaveID uint8) (api.Charger, error) { +func NewAlfen(uri string, slaveID uint8, phases int) (api.Charger, error) { conn, err := modbus.NewConnection(uri, "", "", 0, modbus.Tcp, slaveID) if err != nil { return nil, err @@ -89,7 +96,12 @@ func NewAlfen(uri string, slaveID uint8) (api.Charger, error) { go wb.heartbeat() - return wb, err + var phases1p3p func(int) error + if phases != 1 { + phases1p3p = wb.phases1p3p + } + + return decorateAlfen(wb, phases1p3p), err } func (wb *Alfen) heartbeat() { @@ -232,10 +244,8 @@ func (wb *Alfen) Currents() (float64, float64, float64, error) { return res[0], res[1], res[2], nil } -var _ api.PhaseSwitcher = (*Alfen)(nil) - -// Phases1p3p implements the api.PhaseSwitcher interface -func (c *Alfen) Phases1p3p(phases int) error { +// phases1p3p implements the api.PhaseSwitcher interface +func (c *Alfen) phases1p3p(phases int) error { _, err := c.conn.WriteSingleRegister(alfenRegPhases, uint16(phases)) return err } diff --git a/charger/alfen_decorators.go b/charger/alfen_decorators.go new file mode 100644 index 000000000..d3d660ec2 --- /dev/null +++ b/charger/alfen_decorators.go @@ -0,0 +1,35 @@ +package charger + +// Code generated by github.com/evcc-io/evcc/cmd/tools/decorate.go. DO NOT EDIT. + +import ( + "github.com/evcc-io/evcc/api" +) + +func decorateAlfen(base *Alfen, phaseSwitcher func(int) error) api.Charger { + switch { + case phaseSwitcher == nil: + return base + + case phaseSwitcher != nil: + return &struct { + *Alfen + api.PhaseSwitcher + }{ + Alfen: base, + PhaseSwitcher: &decorateAlfenPhaseSwitcherImpl{ + phaseSwitcher: phaseSwitcher, + }, + } + } + + return nil +} + +type decorateAlfenPhaseSwitcherImpl struct { + phaseSwitcher func(int) error +} + +func (impl *decorateAlfenPhaseSwitcherImpl) Phases1p3p(phases int) error { + return impl.phaseSwitcher(phases) +} diff --git a/charger/openevse.go b/charger/openevse.go index 201632115..307586214 100644 --- a/charger/openevse.go +++ b/charger/openevse.go @@ -27,7 +27,7 @@ func init() { registry.Add("openevse", NewOpenEVSEFromConfig) } -// go:generate go run ../cmd/tools/decorate.go -f decorateOpenEVSE -b ""*OpenEVSE" -r api.Charger -t "api.PhaseSwitcher,Phases1p3p,func(int) error" +// go:generate go run ../cmd/tools/decorate.go -f decorateOpenEVSE -b "*OpenEVSE" -r api.Charger -t "api.PhaseSwitcher,Phases1p3p,func(int) error" // NewOpenEVSEFromConfig creates a go-e charger from generic config func NewOpenEVSEFromConfig(other map[string]interface{}) (api.Charger, error) { diff --git a/templates/definition/charger/alfen-1p.yaml b/templates/definition/charger/alfen-1p.yaml new file mode 100644 index 000000000..2ac58694d --- /dev/null +++ b/templates/definition/charger/alfen-1p.yaml @@ -0,0 +1,18 @@ +template: alfen-1p +products: + - brand: Alfen + description: + generic: Eve (1p) +capabilities: ["mA"] +requirements: + description: + de: Die "Active load balancing" Lizenz wird benötigt um die Wallbox via Modbus extern zu steuern. In den Einstellungen muss "Active Load Balancing" aktiviert und "Energy Management System" als Data Source ausgewählt werden. Falls die "Double"-Box verwendet wird müssen beide Ladepunkte getrennt voneinander hinzugefügt werden. Der erste Port (oder einzelne Port) ist unter ID 1 zugänglich, der zweite unter ID 2. + en: The "Active load balancing" license is required for external Modbus control of the charger. Enable "Active Load Balancing" and select "Energy Management System" as Data Source in the configuration. When using "Double" charger both loadpoints need to be added. The the first port (or single) is accessible on ID 1, second port on ID 2. + evcc: ["sponsorship"] +params: + - name: modbus + choice: ["tcpip"] +render: | + type: alfen + {{- include "modbus" . }} + phases: 1 diff --git a/templates/definition/charger/alfen.yaml b/templates/definition/charger/alfen.yaml index b88531ace..325936feb 100644 --- a/templates/definition/charger/alfen.yaml +++ b/templates/definition/charger/alfen.yaml @@ -2,7 +2,7 @@ template: alfen products: - brand: Alfen description: - generic: Eve + generic: Eve (3p) capabilities: ["1p3p", "mA"] requirements: description: diff --git a/templates/docs/charger/alfen-1p_0.yaml b/templates/docs/charger/alfen-1p_0.yaml new file mode 100644 index 000000000..196628a20 --- /dev/null +++ b/templates/docs/charger/alfen-1p_0.yaml @@ -0,0 +1,17 @@ +product: + brand: Alfen + description: Eve (1p) +capabilities: ["mA"] +requirements: ["sponsorship"] +description: | + Die "Active load balancing" Lizenz wird benötigt um die Wallbox via Modbus extern zu steuern. In den Einstellungen muss "Active Load Balancing" aktiviert und "Energy Management System" als Data Source ausgewählt werden. Falls die "Double"-Box verwendet wird müssen beide Ladepunkte getrennt voneinander hinzugefügt werden. Der erste Port (oder einzelne Port) ist unter ID 1 zugänglich, der zweite unter ID 2. +render: + - default: | + type: template + template: alfen-1p + + # Modbus TCP + modbus: tcpip + id: 1 + host: 192.0.2.2 # Hostname + port: 502 # Port diff --git a/templates/docs/charger/alfen_0.yaml b/templates/docs/charger/alfen_0.yaml index e28e7a7a2..32470dae1 100644 --- a/templates/docs/charger/alfen_0.yaml +++ b/templates/docs/charger/alfen_0.yaml @@ -1,6 +1,6 @@ product: brand: Alfen - description: Eve + description: Eve (3p) capabilities: ["1p3p", "mA"] requirements: ["sponsorship"] description: |