DriveSomethingGreater: fix charge status for conservation charging and plugged-in detection (#30879)

This commit is contained in:
Joni Lehtola 2026-06-22 19:38:21 +03:00 • committed by GitHub
parent de33d947c0
commit f700dc6a77
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 62 additions and 1 deletions

View file

@ -43,6 +43,51 @@ func TestStatusPlugStates(t *testing.T) {
}
}
func TestStatusConservationCharging(t *testing.T) {
tc := []struct {
field string
value string
expected api.ChargeStatus
}{
{FieldChargingState, "conservationCharging", api.StatusC},
{FieldCurrentChargeState, "CHARGE_STATE_CONSERVATION_CHARGING", api.StatusC},
}
for _, tc := range tc {
data := map[string]point{tc.field: {Value: tc.value}}
p := testProvider(data)
status, err := p.Status()
require.NoError(t, err)
assert.Equal(t, tc.expected, status, "field=%q value=%q", tc.field, tc.value)
}
}
func TestStatusChargingScenario(t *testing.T) {
tc := []struct {
scenario string
expected api.ChargeStatus
}{
{"CHARGING_SCENARIO_IMMEDIATELY_CHARGING_FINISHED", api.StatusB},
{"CHARGING_SCENARIO_OPTIMISED_CHARGING_FINISHED", api.StatusB},
{"CHARGING_SCENARIO_CHARGING_TO_DEPARTURE_TIME_FINISHED", api.StatusB},
{"CHARGING_SCENARIO_IMMEDIATELY_CHARGING_ACTIVE", api.StatusC},
{"CHARGING_SCENARIO_CHARGING_TO_DEPARTURE_TIME_ACTIVE", api.StatusC},
{"CHARGING_SCENARIO_OFF", api.StatusA},
// case-insensitivity: mixed-case value should behave like its uppercased equivalent
{"Charging_Scenario_Off", api.StatusA},
}
for _, tc := range tc {
data := map[string]point{FieldChargingScenario: {Value: tc.scenario}}
p := testProvider(data)
status, err := p.Status()
require.NoError(t, err)
assert.Equal(t, tc.expected, status, "scenario=%q", tc.scenario)
}
}
func TestResolveBrand(t *testing.T) {
for _, name := range []string{"audi", "AUDI", "Audi", "aUdI"} {
b, ok := resolveBrand(name)

View file

@ -157,15 +157,30 @@ func (v *Provider) Status() (api.ChargeStatus, error) {
return status, err
}
// block 1: explicit plug state
if p := lookup(data, FieldPlugState, FieldChargingPlug1ConnectionState); p != nil && strings.EqualFold(p.Value, "connected") {
status = api.StatusB
}
// block 2: flat charging_state field and the current_charge_state field
if p := lookup(data, FieldChargingState, FieldCurrentChargeState); p != nil &&
(strings.EqualFold(p.Value, "charging") || strings.Contains(strings.ToUpper(p.Value), "CHARGING_HV")) {
(strings.EqualFold(p.Value, "charging") || strings.Contains(strings.ToUpper(p.Value), "CHARGING_HV") ||
strings.EqualFold(p.Value, "conservationCharging") || strings.EqualFold(p.Value, "CHARGE_STATE_CONSERVATION_CHARGING")) {
status = api.StatusC
}
// block 3: charging_scenario is the most explicit plug/charge signal
if p := lookup(data, FieldChargingScenario); p != nil && status != api.StatusC {
upper := strings.ToUpper(p.Value)
switch {
case strings.HasSuffix(upper, "_ACTIVE"):
status = api.StatusC
// the car reports finished if it's plugged in but not charging
case strings.HasSuffix(upper, "_FINISHED"):
status = api.StatusB
}
}
return status, nil
}

View file

@ -104,6 +104,7 @@ const (
FieldChargingState = "charging_state"
FieldChargingPlug1ConnectionState = "charging_plug1_connectionstate"
FieldCurrentChargeState = "charging_state_report.current_charge_state"
FieldChargingScenario = "charging_state_report.charging_scenario"
FieldPlugState = "plug_state"
// soc