From 8cab3ac6ece6c9a7e73ae16d81d92db152e19de8 Mon Sep 17 00:00:00 2001 From: andig Date: Wed, 7 Dec 2022 09:15:09 +0100 Subject: [PATCH] VW ID: fix api (#5401) This removes odometer as it's no longer available --- vehicle/vw/id/api.go | 3 +- vehicle/vw/id/provider.go | 74 ++--- vehicle/vw/id/samples/status.json | 298 ------------------ vehicle/vw/id/samples/status2.json | 474 ----------------------------- vehicle/vw/id/types.go | 195 +++++++++++- vehicle/vw/id/types_test.go | 39 --- 6 files changed, 226 insertions(+), 857 deletions(-) delete mode 100644 vehicle/vw/id/samples/status.json delete mode 100644 vehicle/vw/id/samples/status2.json delete mode 100644 vehicle/vw/id/types_test.go diff --git a/vehicle/vw/id/api.go b/vehicle/vw/id/api.go index a403eda1a..51263a7eb 100644 --- a/vehicle/vw/id/api.go +++ b/vehicle/vw/id/api.go @@ -75,7 +75,8 @@ func (v *API) Vehicles() (res []string, err error) { // Status implements the /status response. // It is callers responsibility to check for embedded (partial) errors. func (v *API) Status(vin string) (res Status, err error) { - uri := fmt.Sprintf("%s/vehicles/%s/status", BaseURL, vin) + // NOTE use `all` to retrieve entire status + uri := fmt.Sprintf("%s/vehicles/%s/selectivestatus?jobs=charging,fuelStatus,climatisation", BaseURL, vin) req, err := request.New(http.MethodGet, uri, nil, request.AcceptJSON) diff --git a/vehicle/vw/id/provider.go b/vehicle/vw/id/provider.go index bc4d67faa..971abfec1 100644 --- a/vehicle/vw/id/provider.go +++ b/vehicle/vw/id/provider.go @@ -1,6 +1,7 @@ package id import ( + "errors" "strings" "time" @@ -32,12 +33,12 @@ var _ api.Battery = (*Provider)(nil) // SoC implements the api.Vehicle interface func (v *Provider) SoC() (float64, error) { res, err := v.statusG() - if err == nil { - err = res.Error.Extract("batteryStatus") + if err == nil && res.FuelStatus == nil { + err = errors.New("missing fuel status") } if err == nil { - return float64(res.Data.BatteryStatus.CurrentSOCPercent), nil + return float64(res.FuelStatus.RangeStatus.Value.PrimaryEngine.CurrentSOCPct), nil } return 0, err @@ -47,18 +48,17 @@ var _ api.ChargeState = (*Provider)(nil) // Status implements the api.ChargeState interface func (v *Provider) Status() (api.ChargeStatus, error) { - status := api.StatusA // disconnected - res, err := v.statusG() - if err == nil { - err = res.Error.Extract("chargingStatus") + if err == nil && res.Charging == nil { + err = errors.New("missing charging status") } + status := api.StatusA // disconnected if err == nil { - if res.Data.PlugStatus.PlugConnectionState == "connected" { + if res.Charging.PlugStatus.Value.PlugConnectionState == "connected" { status = api.StatusB } - if res.Data.ChargingStatus.ChargingState == "charging" { + if res.Charging.ChargingStatus.Value.ChargingState == "charging" { status = api.StatusC } } @@ -71,12 +71,12 @@ var _ api.VehicleFinishTimer = (*Provider)(nil) // FinishTime implements the api.VehicleFinishTimer interface func (v *Provider) FinishTime() (time.Time, error) { res, err := v.statusG() - if err == nil { - err = res.Error.Extract("chargingStatus") + if err == nil && res.Charging == nil { + err = errors.New("missing charging status") } if err == nil { - cst := res.Data.ChargingStatus + cst := res.Charging.ChargingStatus.Value return cst.CarCapturedTimestamp.Add(time.Duration(cst.RemainingChargingTimeToCompleteMin) * time.Minute), err } @@ -88,47 +88,47 @@ var _ api.VehicleRange = (*Provider)(nil) // Range implements the api.VehicleRange interface func (v *Provider) Range() (int64, error) { res, err := v.statusG() - if err == nil { - err = res.Error.Extract("batteryStatus") + if err == nil && res.FuelStatus == nil { + err = errors.New("missing fuel status") } if err == nil { - return int64(res.Data.BatteryStatus.CruisingRangeElectricKm), nil + return int64(res.FuelStatus.RangeStatus.Value.TotalRangeKm), nil } return 0, err } -var _ api.VehicleOdometer = (*Provider)(nil) +// var _ api.VehicleOdometer = (*Provider)(nil) -// Odometer implements the api.VehicleOdometer interface -func (v *Provider) Odometer() (float64, error) { - res, err := v.statusG() - if err == nil { - err = res.Error.Extract("maintenanceStatus") - } +// // Odometer implements the api.VehicleOdometer interface +// func (v *Provider) Odometer() (float64, error) { +// res, err := v.statusG() +// if err == nil { +// err = res.Error.Extract("maintenanceStatus") +// } - if err == nil { - if res.Data.MaintenanceStatus == nil { - return 0, api.ErrNotAvailable - } - return float64(res.Data.MaintenanceStatus.MileageKm), nil - } +// if err == nil { +// if res.Data.MaintenanceStatus == nil { +// return 0, api.ErrNotAvailable +// } +// return float64(res.Data.MaintenanceStatus.MileageKm), nil +// } - return 0, err -} +// return 0, err +// } var _ api.VehicleClimater = (*Provider)(nil) // Climater implements the api.VehicleClimater interface func (v *Provider) Climater() (active bool, outsideTemp, targetTemp float64, err error) { res, err := v.statusG() - if err == nil { - err = res.Error.Extract("climatisationStatus") + if err == nil && res.Climatisation == nil { + err = errors.New("missing climatisation status") } if err == nil { - state := strings.ToLower(res.Data.ClimatisationStatus.ClimatisationState) + state := strings.ToLower(res.Climatisation.ClimatisationStatus.Value.ClimatisationState) if state == "" { return false, 0, 0, api.ErrNotAvailable @@ -136,7 +136,7 @@ func (v *Provider) Climater() (active bool, outsideTemp, targetTemp float64, err active := state != "off" && state != "invalid" && state != "error" - targetTemp = res.Data.ClimatisationSettings.TargetTemperatureC + targetTemp = res.Climatisation.ClimatisationSettings.Value.TargetTemperatureC // TODO not available; use target temp to avoid wrong heating/cooling display outsideTemp = targetTemp @@ -152,8 +152,12 @@ var _ api.SocLimiter = (*Provider)(nil) // TargetSoC implements the api.SocLimiter interface func (v *Provider) TargetSoC() (float64, error) { res, err := v.statusG() + if err == nil && res.Charging == nil { + err = errors.New("missing charging status") + } + if err == nil { - return float64(res.Data.TargetSOCPercent), nil + return float64(res.Charging.ChargingSettings.Value.TargetSOCPct), nil } return 0, err diff --git a/vehicle/vw/id/samples/status.json b/vehicle/vw/id/samples/status.json deleted file mode 100644 index 1b2e113f1..000000000 --- a/vehicle/vw/id/samples/status.json +++ /dev/null @@ -1,298 +0,0 @@ -{ - "data": { - "batteryStatus": { - "carCapturedTimestamp": "2021-09-05T12:04:03Z", - "currentSOC_pct": 62, - "cruisingRangeElectric_km": 229 - }, - "chargingStatus": { - "carCapturedTimestamp": "2021-09-05T12:04:03Z", - "remainingChargingTimeToComplete_min": 120, - "chargingState": "charging", - "chargeMode": "manual", - "chargePower_kW": 4, - "chargeRate_kmph": 29 - }, - "chargingSettings": { - "carCapturedTimestamp": "2021-09-05T11:53:15Z", - "maxChargeCurrentAC": "maximum", - "autoUnlockPlugWhenCharged": "off", - "targetSOC_pct": 80 - }, - "chargeMode": { - "preferredChargeMode": "manual", - "availableChargeModes": [ - "invalid" - ] - }, - "plugStatus": { - "carCapturedTimestamp": "2021-09-05T11:54:04Z", - "plugConnectionState": "connected", - "plugLockState": "locked" - }, - "climatisationStatus": { - "carCapturedTimestamp": "2021-09-05T11:53:17Z", - "remainingClimatisationTime_min": 0, - "climatisationState": "off" - }, - "climatisationSettings": { - "carCapturedTimestamp": "2021-09-05T11:53:17Z", - "targetTemperature_K": 295.15, - "targetTemperature_C": 22, - "climatisationWithoutExternalPower": true, - "climatizationAtUnlock": true, - "windowHeatingEnabled": true, - "zoneFrontLeftEnabled": false, - "zoneFrontRightEnabled": false - }, - "climatisationTimer": { - "timers": [ - { - "id": 1, - "enabled": false, - "singleTimer": { - "startDateTime": "2021-02-23T05:00:00Z" - } - }, - { - "id": 2, - "enabled": false, - "singleTimer": { - "startDateTime": "1999-12-31T22:00:00Z" - } - } - ], - "carCapturedTimestamp": "2021-09-05T11:53:12.226Z", - "timeInCar": "2021-09-05T13:53:12+02:00" - }, - "windowHeatingStatus": { - "carCapturedTimestamp": "2021-09-05T11:53:18Z", - "windowHeatingStatus": [ - { - "windowLocation": "front", - "windowHeatingState": "off" - }, - { - "windowLocation": "rear", - "windowHeatingState": "off" - } - ] - }, - "rangeStatus": { - "carCapturedTimestamp": "2021-09-05T12:04:03Z", - "carType": "electric", - "primaryEngine": { - "type": "electric", - "currentSOC_pct": 62, - "remainingRange_km": 229 - }, - "totalRange_km": 229 - }, - "capabilityStatus": { - "capabilities": [ - { - "id": "automation", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - }, - { - "id": "batteryColdWarning", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "cdisDigitalKey", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "charging", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - }, - { - "id": "chargingStations", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - }, - { - "id": "climatisation", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - }, - { - "id": "dealerAppointment", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "destinations", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - }, - { - "id": "fuelStatus", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": false - }, - { - "id": "ignition", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": false - }, - { - "id": "mapUpdate", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - }, - { - "id": "measurements", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "onlineSpeech", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - }, - { - "id": "parkingBrake", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "parkingInformation", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - }, - { - "id": "parkingPosition", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "personalizationOnline", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "plugAndCharge", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "poiSearch", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "privateEmergencyCall", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "roadExperienceManagementLocalization", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "roadExperienceManagementLocalizationUpload", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "roadsideAssistant", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "routing", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - }, - { - "id": "state", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "trafficInformation", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - }, - { - "id": "vehicleHealth", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "vehicleHealthInspection", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "vehicleHealthWarnings", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "vehicleLights", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "vehicleWakeUpTrigger", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "webRadio", - "expirationDate": "2023-10-06T00:00:00Z", - "userDisablingAllowed": true - } - ] - }, - "lvBatteryStatus": { - "batterySupport": "notAllowed" - } - }, - "error": {} -} diff --git a/vehicle/vw/id/samples/status2.json b/vehicle/vw/id/samples/status2.json deleted file mode 100644 index adfc245d9..000000000 --- a/vehicle/vw/id/samples/status2.json +++ /dev/null @@ -1,474 +0,0 @@ -{ - "data": { - "accessStatus": { - "overallStatus": "safe", - "carCapturedTimestamp": "2021-09-04T16:59:11Z", - "doors": [ - { - "name": "bonnet", - "status": [ - "closed" - ] - }, - { - "name": "frontLeft", - "status": [ - "locked", - "closed" - ] - }, - { - "name": "frontRight", - "status": [ - "locked", - "closed" - ] - }, - { - "name": "rearLeft", - "status": [ - "locked", - "closed" - ] - }, - { - "name": "rearRight", - "status": [ - "locked", - "closed" - ] - }, - { - "name": "trunk", - "status": [ - "locked", - "closed" - ] - } - ], - "windows": [ - { - "name": "frontLeft", - "status": [ - "unsupported" - ] - }, - { - "name": "frontRight", - "status": [ - "unsupported" - ] - }, - { - "name": "rearLeft", - "status": [ - "unsupported" - ] - }, - { - "name": "rearRight", - "status": [ - "unsupported" - ] - }, - { - "name": "roofCover", - "status": [ - "unsupported" - ] - }, - { - "name": "sunRoof", - "status": [ - "unsupported" - ] - } - ] - }, - "batteryStatus": { - "carCapturedTimestamp": "2021-09-04T16:58:08Z", - "currentSOC_pct": 86, - "cruisingRangeElectric_km": 224 - }, - "chargingStatus": { - "carCapturedTimestamp": "2021-09-04T16:58:08Z", - "remainingChargingTimeToComplete_min": 10, - "chargingState": "off", - "chargeMode": "invalid" - }, - "chargingSettings": { - "carCapturedTimestamp": "2021-02-24T15:38:44Z", - "maxChargeCurrentAC": "maximum" - }, - "plugStatus": { - "carCapturedTimestamp": "2021-09-04T16:58:40Z", - "plugConnectionState": "disconnected", - "plugLockState": "locked" - }, - "climatisationStatus": { - "carCapturedTimestamp": "2021-09-04T16:58:05Z", - "remainingClimatisationTime_min": 0, - "climatisationState": "off" - }, - "climatisationSettings": { - "carCapturedTimestamp": "2021-08-26T20:28:20Z", - "targetTemperature_K": 295, - "targetTemperature_C": 22, - "climatisationWithoutExternalPower": true - }, - "windowHeatingStatus": { - "carCapturedTimestamp": "2021-09-04T16:58:10Z", - "windowHeatingStatus": [ - { - "windowLocation": "front", - "windowHeatingState": "off" - }, - { - "windowLocation": "rear", - "windowHeatingState": "off" - } - ] - }, - "lightsStatus": { - "carCapturedTimestamp": "2021-09-04T16:59:11Z", - "lights": [ - { - "name": "right", - "status": "off" - }, - { - "name": "left", - "status": "off" - } - ] - }, - "maintenanceStatus": { - "carCapturedTimestamp": "2021-09-04T14:59:10Z", - "inspectionDue_days": 333, - "inspectionDue_km": 28600, - "mileage_km": 30952, - "oilServiceDue_days": 0, - "oilServiceDue_km": 0 - }, - "rangeStatus": { - "carCapturedTimestamp": "2021-09-04T16:58:08Z", - "carType": "electric", - "primaryEngine": { - "type": "electric", - "currentSOC_pct": 86, - "remainingRange_km": 224 - }, - "totalRange_km": 224 - }, - "capabilityStatus": { - "capabilities": [ - { - "id": "access", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "charging", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "climatisation", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "cubicNetwork", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "cubicNetworkConsumption", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "dealerAppointment", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "digitalKey", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "emergencyCalling", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "fuelStatus", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "geofence", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "googleEarth", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "hybridRadio", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "informationCall", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "mapUpdate", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "measurements", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "news", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "onlineSpeech", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "parkingInformation", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "parkingPosition", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "roadsideAssistant", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "routing", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "speedAlert", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "state", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "theftWarning", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "transactionHistoryAntiTheftAlert", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "transactionHistoryAntiTheftAlertDelete", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "transactionHistoryDigitalKey", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "transactionHistoryGeofence", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "transactionHistoryGeofenceDelete", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "transactionHistoryHonkFlash", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "transactionHistoryLockUnlock", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "transactionHistorySpeedAlert", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "transactionHistorySpeedAlertDelete", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "tripStatistics", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "vehicleHealth", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "vehicleHealthArchive", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "vehicleHealthInspection", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "vehicleHealthSettings", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "vehicleHealthTrigger", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "vehicleHealthWakeUp", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "vehicleHealthWarnings", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "vehicleLights", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "vehicleWakeUp", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "vehicleWakeUpTrigger", - "expirationDate": "2023-02-11T09:35:00Z", - "userDisablingAllowed": false - }, - { - "id": "weatherInformation", - "status": [ - 1008 - ], - "userDisablingAllowed": false - }, - { - "id": "webRadio", - "status": [ - 1008 - ], - "userDisablingAllowed": false - } - ] - } - }, - "error": { - "chargeMode": { - "code": 4104, - "message": "The vehicle does not support the requested operation", - "group": 4, - "info": "Looks like your service has expired. Please update your service subscription." - } - } -} diff --git a/vehicle/vw/id/types.go b/vehicle/vw/id/types.go index 14056850a..12b979638 100644 --- a/vehicle/vw/id/types.go +++ b/vehicle/vw/id/types.go @@ -8,16 +8,191 @@ import ( // Status is the /status api type Status struct { - Data struct { - BatteryStatus `json:"batteryStatus"` - ChargingStatus `json:"chargingStatus"` - ChargingSettings `json:"chargingSettings"` - PlugStatus `json:"plugStatus"` - RangeStatus `json:"rangeStatus"` - ClimatisationSettings `json:"climatisationSettings"` - ClimatisationStatus `json:"climatisationStatus"` // may be temporarily not available - *MaintenanceStatus `json:"maintenanceStatus"` // optional - } + Automation *struct { + ClimatisationTimer struct { + Value struct { + Timers []struct { + ID int `json:"id"` + Enabled bool `json:"enabled"` + RecurringTimer struct { + StartTime string `json:"startTime"` + RecurringOn struct { + Mondays bool `json:"mondays"` + Tuesdays bool `json:"tuesdays"` + Wednesdays bool `json:"wednesdays"` + Thursdays bool `json:"thursdays"` + Fridays bool `json:"fridays"` + Saturdays bool `json:"saturdays"` + Sundays bool `json:"sundays"` + } `json:"recurringOn"` + } `json:"recurringTimer,omitempty"` + SingleTimer struct { + StartDateTime Timestamp `json:"startDateTime"` + } `json:"singleTimer,omitempty"` + } `json:"timers"` + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + TimeInCar Timestamp `json:"timeInCar"` + } `json:"value"` + } `json:"climatisationTimer"` + ChargingProfiles *struct { + Value struct { + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + TimeInCar Timestamp `json:"timeInCar"` + Profiles []interface{} `json:"profiles"` + } `json:"value"` + } `json:"chargingProfiles"` + } `json:"automation"` + UserCapabilities *struct { + CapabilitiesStatus struct { + Value []struct { + ID string `json:"id"` + UserDisablingAllowed bool `json:"userDisablingAllowed"` + ExpirationDate Timestamp `json:"expirationDate,omitempty"` + Status []int `json:"status,omitempty"` + } `json:"value"` + } `json:"capabilitiesStatus"` + } `json:"userCapabilities"` + Charging *struct { + BatteryStatus struct { + Value struct { + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + CurrentSOCPct int `json:"currentSOC_pct"` + CruisingRangeElectricKm int `json:"cruisingRangeElectric_km"` + } `json:"value"` + } `json:"batteryStatus"` + ChargingStatus struct { + Value struct { + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + RemainingChargingTimeToCompleteMin int `json:"remainingChargingTimeToComplete_min"` + ChargingState string `json:"chargingState"` // readyForCharging/off + ChargeMode string `json:"chargeMode"` // invalid + ChargePowerKW int `json:"chargePower_kW"` + ChargeRateKmph int `json:"chargeRate_kmph"` + ChargeType string `json:"chargeType"` + ChargingSettings string `json:"chargingSettings"` + } `json:"value"` + } `json:"chargingStatus"` + ChargingSettings struct { + Value struct { + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + MaxChargeCurrentAC string `json:"maxChargeCurrentAC"` // reduced, maximum + AutoUnlockPlugWhenCharged string `json:"autoUnlockPlugWhenCharged"` + AutoUnlockPlugWhenChargedAC string `json:"autoUnlockPlugWhenChargedAC"` + TargetSOCPct int `json:"targetSOC_pct"` + } `json:"value"` + } `json:"chargingSettings"` + PlugStatus struct { + Value struct { + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + PlugConnectionState string `json:"plugConnectionState"` // connected, disconnected + PlugLockState string `json:"plugLockState"` // locked, unlocked + ExternalPower string `json:"externalPower"` + LedColor string `json:"ledColor"` + } `json:"value"` + } `json:"plugStatus"` + ChargeMode struct { + Value struct { + PreferredChargeMode string `json:"preferredChargeMode"` + AvailableChargeModes []string `json:"availableChargeModes"` + } `json:"value"` + } `json:"chargeMode"` + } `json:"charging"` + Climatisation *struct { + ClimatisationStatus struct { + Value struct { + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + RemainingClimatisationTimeMin int `json:"remainingClimatisationTime_min"` + ClimatisationState string `json:"climatisationState"` // off + } `json:"value"` + } `json:"climatisationStatus"` // may be temporarily not available + ClimatisationSettings struct { + Value struct { + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + TargetTemperatureC float64 `json:"targetTemperature_C"` + TargetTemperatureF float64 `json:"targetTemperature_F"` + UnitInCar string `json:"unitInCar"` + ClimatizationAtUnlock bool `json:"climatizationAtUnlock"` // ClimatizationAtUnlock? + WindowHeatingEnabled bool `json:"windowHeatingEnabled"` + ZoneFrontLeftEnabled bool `json:"zoneFrontLeftEnabled"` + ZoneFrontRightEnabled bool `json:"zoneFrontRightEnabled"` + } `json:"value"` + } `json:"climatisationSettings"` + WindowHeatingStatus struct { + Value struct { + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + WindowHeatingStatus []struct { + WindowLocation string `json:"windowLocation"` + WindowHeatingState string `json:"windowHeatingState"` + } `json:"windowHeatingStatus"` + } `json:"value"` + } `json:"windowHeatingStatus"` + } `json:"climatisation"` + ClimatisationTimers *struct { + ClimatisationTimersStatus struct { + Value struct { + Timers []struct { + ID int `json:"id"` + Enabled bool `json:"enabled"` + RecurringTimer struct { + StartTime string `json:"startTime"` + RecurringOn struct { + Mondays bool `json:"mondays"` + Tuesdays bool `json:"tuesdays"` + Wednesdays bool `json:"wednesdays"` + Thursdays bool `json:"thursdays"` + Fridays bool `json:"fridays"` + Saturdays bool `json:"saturdays"` + Sundays bool `json:"sundays"` + } `json:"recurringOn"` + } `json:"recurringTimer,omitempty"` + SingleTimer struct { + StartDateTime Timestamp `json:"startDateTime"` + } `json:"singleTimer,omitempty"` + } `json:"timers"` + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + TimeInCar Timestamp `json:"timeInCar"` + } `json:"value"` + } `json:"climatisationTimersStatus"` + } `json:"climatisationTimers"` + FuelStatus *struct { + RangeStatus struct { + Value struct { + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + CarType string `json:"carType"` + PrimaryEngine struct { + Type string `json:"type"` + CurrentSOCPct int `json:"currentSOC_pct"` + RemainingRangeKm int `json:"remainingRange_km"` + } `json:"primaryEngine"` + TotalRangeKm int `json:"totalRange_km"` + } `json:"value"` + } `json:"rangeStatus"` + } `json:"fuelStatus"` + Readiness *struct { + ReadinessStatus struct { + Value struct { + ConnectionState struct { + IsOnline bool `json:"isOnline"` + IsActive bool `json:"isActive"` + BatteryPowerLevel string `json:"batteryPowerLevel"` + DailyPowerBudgetAvailable bool `json:"dailyPowerBudgetAvailable"` + } `json:"connectionState"` + ConnectionWarning struct { + InsufficientBatteryLevelWarning bool `json:"insufficientBatteryLevelWarning"` + DailyPowerBudgetWarning bool `json:"dailyPowerBudgetWarning"` + } `json:"connectionWarning"` + } `json:"value"` + } `json:"readinessStatus"` + } `json:"readiness"` + ChargingProfiles *struct { + ChargingProfilesStatus struct { + Value struct { + CarCapturedTimestamp Timestamp `json:"carCapturedTimestamp"` + TimeInCar Timestamp `json:"timeInCar"` + Profiles []interface{} `json:"profiles"` + } `json:"value"` + } `json:"chargingProfilesStatus"` + } `json:"chargingProfiles"` Error ErrorMap } diff --git a/vehicle/vw/id/types_test.go b/vehicle/vw/id/types_test.go deleted file mode 100644 index 04b2ca1c3..000000000 --- a/vehicle/vw/id/types_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package id - -import ( - _ "embed" - "encoding/json" - "testing" -) - -//go:embed samples/status.json -var data []byte - -func TestStatus(t *testing.T) { - var status Status - if err := json.Unmarshal(data, &status); err != nil { - t.Error(err) - } - - if v := status.Data.ChargingStatus.RemainingChargingTimeToCompleteMin; v != 120 { - t.Error("invalid RemainingChargingTimeToCompleteMin", v) - } - - if status.Data.MaintenanceStatus != nil { - t.Error("unexpected MaintenanceStatus") - } -} - -//go:embed samples/status2.json -var data2 []byte - -func TestStatus2(t *testing.T) { - var status Status - if err := json.Unmarshal(data2, &status); err != nil { - t.Error(err) - } - - if status.Data.MaintenanceStatus == nil || status.Data.MaintenanceStatus.MileageKm == 0 { - t.Error("invalid MaintenanceStatus.MileageKm") - } -}