From 1056e85af283af2af1fb749f97781ee7423c7a5b Mon Sep 17 00:00:00 2001 From: Markus Kaindl Date: Wed, 17 Jun 2026 21:45:09 +0200 Subject: [PATCH] Vehicle: add autodetectdisabled feature (#30941) --- api/feature.go | 27 ++++++++++---------- api/feature_enumer.go | 12 ++++++--- core/coordinator/coordinator.go | 3 ++- core/coordinator/coordinator_test.go | 2 ++ util/templates/defaults.yaml | 10 ++++++++ util/templates/includes/vehicle-features.tpl | 5 +++- 6 files changed, 40 insertions(+), 19 deletions(-) diff --git a/api/feature.go b/api/feature.go index 0fd024423..9f46f6331 100644 --- a/api/feature.go +++ b/api/feature.go @@ -4,17 +4,18 @@ type Feature int //go:generate go tool enumer -type Feature -text const ( - _ Feature = iota - CoarseCurrent // charger - IntegratedDevice // charger - always connected - no vehicle, no charging sessions - SwitchDevice // charger - no current control - heat pumps or switch sockets - Heating // charger - heating device - soc ist temperature (°C) - Continuous // charger - heating device where disabled means "normal operation" - Average // tariff - Cacheable // tariff - Offline // vehicle - Retryable // vehicle - Streaming // vehicle - WelcomeCharge // vehicle - ClimaterDisabled // vehicle - ignore climater state for charge control + _ Feature = iota + CoarseCurrent // charger + IntegratedDevice // charger - always connected - no vehicle, no charging sessions + SwitchDevice // charger - no current control - heat pumps or switch sockets + Heating // charger - heating device - soc ist temperature (°C) + Continuous // charger - heating device where disabled means "normal operation" + Average // tariff + Cacheable // tariff + Offline // vehicle + Retryable // vehicle + Streaming // vehicle + WelcomeCharge // vehicle + ClimaterDisabled // vehicle - ignore climater state for charge control + AutodetectDisabled // vehicle - do not try to identify vehicle by status ) diff --git a/api/feature_enumer.go b/api/feature_enumer.go index 76d092f0d..b2510adb2 100644 --- a/api/feature_enumer.go +++ b/api/feature_enumer.go @@ -7,11 +7,11 @@ import ( "strings" ) -const _FeatureName = "CoarseCurrentIntegratedDeviceSwitchDeviceHeatingContinuousAverageCacheableOfflineRetryableStreamingWelcomeChargeClimaterDisabled" +const _FeatureName = "CoarseCurrentIntegratedDeviceSwitchDeviceHeatingContinuousAverageCacheableOfflineRetryableStreamingWelcomeChargeClimaterDisabledAutodetectDisabled" -var _FeatureIndex = [...]uint8{0, 13, 29, 41, 48, 58, 65, 74, 81, 90, 99, 112, 128} +var _FeatureIndex = [...]uint8{0, 13, 29, 41, 48, 58, 65, 74, 81, 90, 99, 112, 128, 146} -const _FeatureLowerName = "coarsecurrentintegrateddeviceswitchdeviceheatingcontinuousaveragecacheableofflineretryablestreamingwelcomechargeclimaterdisabled" +const _FeatureLowerName = "coarsecurrentintegrateddeviceswitchdeviceheatingcontinuousaveragecacheableofflineretryablestreamingwelcomechargeclimaterdisabledautodetectdisabled" func (i Feature) String() string { i -= 1 @@ -37,9 +37,10 @@ func _FeatureNoOp() { _ = x[Streaming-(10)] _ = x[WelcomeCharge-(11)] _ = x[ClimaterDisabled-(12)] + _ = x[AutodetectDisabled-(13)] } -var _FeatureValues = []Feature{CoarseCurrent, IntegratedDevice, SwitchDevice, Heating, Continuous, Average, Cacheable, Offline, Retryable, Streaming, WelcomeCharge, ClimaterDisabled} +var _FeatureValues = []Feature{CoarseCurrent, IntegratedDevice, SwitchDevice, Heating, Continuous, Average, Cacheable, Offline, Retryable, Streaming, WelcomeCharge, ClimaterDisabled, AutodetectDisabled} var _FeatureNameToValueMap = map[string]Feature{ _FeatureName[0:13]: CoarseCurrent, @@ -66,6 +67,8 @@ var _FeatureNameToValueMap = map[string]Feature{ _FeatureLowerName[99:112]: WelcomeCharge, _FeatureName[112:128]: ClimaterDisabled, _FeatureLowerName[112:128]: ClimaterDisabled, + _FeatureName[128:146]: AutodetectDisabled, + _FeatureLowerName[128:146]: AutodetectDisabled, } var _FeatureNames = []string{ @@ -81,6 +84,7 @@ var _FeatureNames = []string{ _FeatureName[90:99], _FeatureName[99:112], _FeatureName[112:128], + _FeatureName[128:146], } // FeatureString retrieves an enum value from the enum constants string name. diff --git a/core/coordinator/coordinator.go b/core/coordinator/coordinator.go index 531baaca2..20a2edf0a 100644 --- a/core/coordinator/coordinator.go +++ b/core/coordinator/coordinator.go @@ -1,6 +1,7 @@ package coordinator import ( + "slices" "sync" "github.com/evcc-io/evcc/api" @@ -116,7 +117,7 @@ func (c *Coordinator) availableDetectibleVehicles(owner loadpoint.API) []api.Veh for _, vv := range c.vehicles { // status api available - if api.HasCap[api.ChargeState](vv) { + if api.HasCap[api.ChargeState](vv) && !slices.Contains(vv.Features(), api.AutodetectDisabled) { // available or associated to current loadpoint if o, ok := c.tracked[vv]; o == owner || !ok { res = append(res, vv) diff --git a/core/coordinator/coordinator_test.go b/core/coordinator/coordinator_test.go index b92a3e09e..bb4c4f38f 100644 --- a/core/coordinator/coordinator_test.go +++ b/core/coordinator/coordinator_test.go @@ -48,6 +48,8 @@ func TestVehicleDetectByStatus(t *testing.T) { v2.MockVehicle.EXPECT().GetTitle().Return("v2").AnyTimes() v1.MockVehicle.EXPECT().Identifiers().Return(nil).AnyTimes() v2.MockVehicle.EXPECT().Identifiers().Return([]string{"it's me"}).AnyTimes() + v1.MockVehicle.EXPECT().Features().Return(nil).AnyTimes() + v2.MockVehicle.EXPECT().Features().Return(nil).AnyTimes() var lp loadpoint.API c := New(log, vehicles) diff --git a/util/templates/defaults.yaml b/util/templates/defaults.yaml index 73f3a706a..f29ea1599 100644 --- a/util/templates/defaults.yaml +++ b/util/templates/defaults.yaml @@ -329,6 +329,14 @@ params: help: en: Ignore the vehicle's climater state for charge control, so charging stops at the SoC or energy limit even when the vehicle signals an active climater request. de: Klimatisierungsstatus des Fahrzeugs für die Ladesteuerung ignorieren, sodass der Ladevorgang am SoC- oder Energielimit endet, auch wenn das Fahrzeug einen aktiven Klimatisierungswunsch signalisiert. + - name: autodetectdisabled + type: bool + description: + en: Exclude from auto detection + de: Von automatischer Erkennung ausschließen + help: + en: Ignore the vehicle for auto detection of connected vehicles + de: Das Fahrzeug von der automatischen Erkennung beim Anschließen eines Fahrzeugs ausschließen - name: heating type: bool description: @@ -590,6 +598,8 @@ presets: advanced: true - name: climaterdisabled advanced: true + - name: autodetectdisabled + advanced: true vehicle-climater: - name: climaterdisabled advanced: true diff --git a/util/templates/includes/vehicle-features.tpl b/util/templates/includes/vehicle-features.tpl index 8a842572f..07fa44445 100644 --- a/util/templates/includes/vehicle-features.tpl +++ b/util/templates/includes/vehicle-features.tpl @@ -1,5 +1,5 @@ {{ define "vehicle-features" }} -{{- if or .basefeatures (eq .coarsecurrent "true") (eq .welcomecharge "true") (eq .streaming "true") (eq .climaterdisabled "true") }} +{{- if or .basefeatures (eq .coarsecurrent "true") (eq .welcomecharge "true") (eq .streaming "true") (eq .climaterdisabled "true") (eq .autodetectdisabled "true") }} features: {{- range .basefeatures }} - {{ . }} @@ -16,5 +16,8 @@ features: {{- if eq .climaterdisabled "true" }} - climaterdisabled {{- end }} +{{- if eq .autodetectdisabled "true" }} +- autodetectdisabled +{{- end }} {{- end }} {{- end }}