Stegen Smart EVSE: make charge mode configurable, fix status & keep-alive (#29290)

This commit is contained in:
Vincent Bakker 2026-04-27 18:32:51 +02:00 • committed by GitHub
parent afaf409914
commit 551e7ac0bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 32 additions and 23 deletions

View file

@ -36,6 +36,7 @@ type SmartEVSE3 struct {
*request.Helper
uri string
curr int64
mode int
apiG util.Cacheable[smartEvseRestSettings]
}
@ -110,10 +111,12 @@ func init() {
// NewSmartEVSE3FromConfig creates a SmartEVSE-3.5 REST charger from generic config
func NewSmartEVSE3FromConfig(other map[string]any) (api.Charger, error) {
cc := struct {
URI string
Cache time.Duration
URI string
Cache time.Duration
ChargeMode string
}{
Cache: time.Second,
Cache: time.Second,
ChargeMode: "normal",
}
if err := util.DecodeOther(other, &cc); err != nil {
@ -124,17 +127,27 @@ func NewSmartEVSE3FromConfig(other map[string]any) (api.Charger, error) {
return nil, fmt.Errorf("missing uri")
}
return NewSmartEVSE3(cc.URI, cc.Cache)
mode := smartEvse3ModeNormal
if cc.ChargeMode == "smart" {
mode = smartEvse3ModeSmart
}
return NewSmartEVSE3(cc.URI, cc.Cache, mode)
}
// NewSmartEVSE3 creates a new SmartEVSE-3.5 REST charger
func NewSmartEVSE3(uri string, cache time.Duration) (api.Charger, error) {
func NewSmartEVSE3(uri string, cache time.Duration, mode int) (api.Charger, error) {
log := util.NewLogger("smart-evse")
wb := &SmartEVSE3{
Helper: request.NewHelper(log),
uri: strings.TrimRight(util.DefaultScheme(uri, "http"), "/"),
curr: 60, // 6 A in 1/10 A
mode: mode,
}
wb.Helper.Client.Transport = &http.Transport{
DisableKeepAlives: true,
}
wb.apiG = util.ResettableCached(func() (smartEvseRestSettings, error) {
@ -149,13 +162,6 @@ func NewSmartEVSE3(uri string, cache time.Duration) (api.Charger, error) {
return nil, err
}
// force NORMAL mode so override_current takes effect
if res.ModeID != smartEvse3ModeNormal {
if err := wb.setMode(smartEvse3ModeNormal); err != nil {
return nil, err
}
}
// decorate optional EV meter if configured in SmartEVSE
var currentPower, totalEnergy func() (float64, error)
var currents func() (float64, float64, float64, error)
@ -221,17 +227,11 @@ func (wb *SmartEVSE3) Status() (api.ChargeStatus, error) {
// state IDs from SmartEVSE firmware (main_c.h)
switch res.Evse.StateID {
case 0: // STATE_A
return api.StatusA, nil
case 1, 4, 5, 8, 9, 11, 12, 13, 14:
// STATE_B, STATE_COMM_B, STATE_COMM_B_OK, STATE_ACTSTART, STATE_B1,
// STATE_MODEM_REQUEST, STATE_MODEM_WAIT, STATE_MODEM_DONE, STATE_MODEM_DENIED
return api.StatusB, nil
case 2, 3, 6, 7, 10:
// STATE_C, STATE_D, STATE_COMM_C, STATE_COMM_C_OK, STATE_C1
return api.StatusC, nil
default:
return api.StatusNone, fmt.Errorf("invalid state: %d (%s)", res.Evse.StateID, res.Evse.State)
return api.StatusB, nil
}
}
@ -262,8 +262,8 @@ func (wb *SmartEVSE3) Enable(enable bool) error {
}
if enable {
if res.ModeID != smartEvse3ModeNormal {
return wb.setMode(smartEvse3ModeNormal)
if res.ModeID != wb.mode {
return wb.setMode(wb.mode)
}
return nil
}

View file

@ -8,16 +8,25 @@ requirements:
description:
de: |
Anbindung über die REST API der Smart Evse Firmware (FW >= 3.6.0).
evcc setzt das Gerät in den NORMAL Modus und steuert den Ladestrom über `override_current`.
evcc setzt das Gerät in den konfigurierten Modus und steuert den Ladestrom über `override_current`.
en: |
Uses the REST API of the Smart Evse firmware (FW >= 3.6.0).
evcc puts the device into NORMAL mode and controls the charge current via `override_current`.
evcc puts the device into the configured mode and controls the charge current via `override_current`.
params:
- name: host
- name: cache
default: 1s
advanced: true
- name: chargeMode
default: normal
advanced: true
type: choice
choice: ["normal", "smart"]
description:
en: Charge mode
de: Lademodus
render: |
type: smart-evse
uri: http://{{ .host }}
cache: {{ .cache }}
chargeMode: {{ .chargeMode }}