VW ID: fix api (#5401)
This removes odometer as it's no longer available
This commit is contained in:
parent
e26bebb579
commit
d8ea2d0482
6 changed files with 226 additions and 877 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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": {}
|
||||
}
|
||||
|
|
@ -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."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue