diff --git a/vehicle/polestar/api.go b/vehicle/polestar/api.go index b13dbba2f..aa8d1c91d 100644 --- a/vehicle/polestar/api.go +++ b/vehicle/polestar/api.go @@ -49,12 +49,36 @@ func (v *API) Vehicles(ctx context.Context) ([]ConsumerCar, error) { func (v *API) CarTelemetry(ctx context.Context, vin string) (CarTelemetryData, error) { var res struct { - CarTelemetryData `graphql:"carTelematics(vin: $vin)"` + CarTelemetryData `graphql:"carTelematicsV2(vins: $vins)"` } err := v.client.Query(ctx, &res, map[string]any{ - "vin": vin, - }, graphql.OperationName("CarTelematics")) + "vins": []string{vin}, + }, graphql.OperationName("CarTelematicsV2")) - return res.CarTelemetryData, err + // Filter data for the requested VIN + var filteredData CarTelemetryData + + // Filter health data + for _, health := range res.CarTelemetryData.Health { + if health.VIN == vin { + filteredData.Health = append(filteredData.Health, health) + } + } + + // Filter battery data + for _, battery := range res.CarTelemetryData.Battery { + if battery.VIN == vin { + filteredData.Battery = append(filteredData.Battery, battery) + } + } + + // Filter odometer data + for _, odometer := range res.CarTelemetryData.Odometer { + if odometer.VIN == vin { + filteredData.Odometer = append(filteredData.Odometer, odometer) + } + } + + return filteredData, err } diff --git a/vehicle/polestar/provider.go b/vehicle/polestar/provider.go index 072210161..4f2c35b55 100644 --- a/vehicle/polestar/provider.go +++ b/vehicle/polestar/provider.go @@ -27,23 +27,22 @@ func NewProvider(log *util.Logger, api *API, vin string, timeout, cache time.Dur // SOC via car telemetry func (v *Provider) Soc() (float64, error) { res, err := v.telemetryG() - return res.Battery.BatteryChargeLevelPercentage, err + return float64(res.Battery[0].BatteryChargeLevelPercentage), err } var _ api.ChargeState = (*Provider)(nil) -// Range via car telemetry +// Status via car telemetry func (v *Provider) Status() (api.ChargeStatus, error) { status, err := v.telemetryG() res := api.StatusA - if status.Battery.ChargerConnectionStatus == "CHARGER_CONNECTION_STATUS_CONNECTED" { + if status.Battery[0].ChargingStatus == "CHARGER_CONNECTION_STATUS_CONNECTED" { res = api.StatusB } - if status.Battery.ChargingStatus == "CHARGING_STATUS_CHARGING" { + if status.Battery[0].ChargingStatus == "CHARGING_STATUS_CHARGING" { res = api.StatusB } - return res, err } @@ -52,7 +51,7 @@ var _ api.VehicleRange = (*Provider)(nil) // Range via car telemetry func (v *Provider) Range() (int64, error) { res, err := v.telemetryG() - return int64(res.Battery.EstimatedDistanceToEmptyKm), err + return res.Battery[0].EstimatedDistanceToEmptyKm, err } var _ api.VehicleOdometer = (*Provider)(nil) @@ -60,7 +59,7 @@ var _ api.VehicleOdometer = (*Provider)(nil) // Odometer via car telemetry func (v *Provider) Odometer() (float64, error) { res, err := v.telemetryG() - return res.Odometer.OdometerMeters / 1e3, err + return float64(res.Odometer[0].OdometerMeters) / 1e3, err } var _ api.VehicleFinishTimer = (*Provider)(nil) @@ -68,8 +67,5 @@ var _ api.VehicleFinishTimer = (*Provider)(nil) // FinishTime via car telemetry func (v *Provider) FinishTime() (time.Time, error) { res, err := v.telemetryG() - if err != nil { - return time.Time{}, err - } - return time.Now().Add(time.Duration(res.Battery.EstimatedChargingTimeToFullMinutes) * time.Minute), nil + return time.Now().Add(time.Duration(res.Battery[0].EstimatedChargingTimeToFullMinutes) * time.Minute), err } diff --git a/vehicle/polestar/query.gql b/vehicle/polestar/query.gql index 2103b85a0..02e09fec6 100644 --- a/vehicle/polestar/query.gql +++ b/vehicle/polestar/query.gql @@ -27,37 +27,30 @@ query getCars { } } -query CarTelematics($vin: String!) { - carTelematics(vin: $vin) { +query CarTelematicsV2($vins: [String!]!) { + carTelematicsV2(vins: $vins) { + health { + vin + brakeFluidLevelWarning + daysToService + distanceToServiceKm + engineCoolantLevelWarning + oilLevelWarning + serviceWarning + timestamp { seconds nanos } + } battery { - averageEnergyConsumptionKwhPer100Km + vin batteryChargeLevelPercentage - chargerConnectionStatus - chargingCurrentAmps - chargingPowerWatts chargingStatus - estimatedChargingTimeMinutesToTargetDistance estimatedChargingTimeToFullMinutes estimatedDistanceToEmptyKm - estimatedDistanceToEmptyMiles - eventUpdatedTimestamp { - iso - unix - __typename - } - __typename + timestamp { seconds nanos } } odometer { - averageSpeedKmPerHour - eventUpdatedTimestamp { - iso - unix - __typename - } + vin odometerMeters - tripMeterAutomaticKm - tripMeterManualKm - __typename + timestamp { seconds nanos } } } } \ No newline at end of file diff --git a/vehicle/polestar/types.go b/vehicle/polestar/types.go index 281af42b7..9f045a08b 100644 --- a/vehicle/polestar/types.go +++ b/vehicle/polestar/types.go @@ -1,32 +1,43 @@ package polestar -import "time" - type ConsumerCar struct { VIN string InternalVehicleIdentifier string } +type Timestamp struct { + Seconds string + Nanos int64 +} + +type HealthData struct { + VIN string + BrakeFluidLevelWarning string + DaysToService int64 + DistanceToServiceKm int64 + EngineCoolantLevelWarning string + OilLevelWarning string + ServiceWarning string + Timestamp Timestamp +} + type BatteryData struct { - BatteryChargeLevelPercentage float64 - ChargerConnectionStatus string + VIN string + BatteryChargeLevelPercentage int64 ChargingStatus string - EstimatedChargingTimeToFullMinutes int - EstimatedDistanceToEmptyKm int - EventUpdatedTimestamp EventUpdatedTimestamp + EstimatedChargingTimeToFullMinutes int64 + EstimatedDistanceToEmptyKm int64 + Timestamp Timestamp } type OdometerData struct { - OdometerMeters float64 - EventUpdatedTimestamp EventUpdatedTimestamp + VIN string + OdometerMeters int64 + Timestamp Timestamp } type CarTelemetryData struct { - Battery BatteryData - Odometer OdometerData -} - -type EventUpdatedTimestamp struct { - ISO time.Time - // Unix int64 `json:",string"` + Health []HealthData + Battery []BatteryData + Odometer []OdometerData }