VW ID: fix api (#5401)

This removes odometer as it's no longer available
This commit is contained in:
andig 2022-12-07 09:15:09 +01:00
parent e26bebb579
commit d8ea2d0482
6 changed files with 226 additions and 877 deletions

View file

@ -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)

View file

@ -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

View file

@ -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": {}
}

View file

@ -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."
}
}
}

View file

@ -1,42 +1,197 @@
package id
import (
"fmt"
"strings"
"time"
)
// 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
}
Error ErrorMap
}
type ErrorMap map[string]Error
func (e ErrorMap) Extract(key string) error {
for k, v := range e {
if k == key {
return fmt.Errorf("%s: %s", v.Info, v.Message)
}
}
return nil
}
// Error is the error status
type Error struct {
Code int
Message, Info string
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"`
}
// BatteryStatus is the /status.batteryStatus api

View file

@ -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")
}
}