Skip to content

Commit

Permalink
feat(TeslaFleetApiService): use FleetApi Data for updating car state
Browse files Browse the repository at this point in the history
  • Loading branch information
pkuehnel committed Jan 27, 2024
1 parent a0a4e7e commit 71e41c3
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class DtoVehicleDataResult
public List<string> Tokens { get; set; }

[JsonProperty("state")]
public object State { get; set; }
public string State { get; set; }

[JsonProperty("in_service")]
public bool InService { get; set; }
Expand Down Expand Up @@ -131,7 +131,7 @@ public class ChargeState
public int ChargerActualCurrent { get; set; }

[JsonProperty("charger_phases")]
public object ChargerPhases { get; set; }
public int ChargerPhases { get; set; }

[JsonProperty("charger_pilot_current")]
public int ChargerPilotCurrent { get; set; }
Expand Down Expand Up @@ -203,7 +203,7 @@ public class ChargeState
public bool ScheduledChargingPending { get; set; }

[JsonProperty("scheduled_charging_start_time")]
public object ScheduledChargingStartTime { get; set; }
public long? ScheduledChargingStartTime { get; set; }

[JsonProperty("scheduled_departure_time")]
public int? ScheduledDepartureTime { get; set; }
Expand Down Expand Up @@ -389,7 +389,7 @@ public class DriveState
public int Power { get; set; }

[JsonProperty("shift_state")]
public object ShiftState { get; set; }
public string? ShiftState { get; set; }

[JsonProperty("speed")]
public object Speed { get; set; }
Expand Down
80 changes: 78 additions & 2 deletions TeslaSolarCharger/Server/Services/TeslaFleetApiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public class TeslaFleetApiService(
IConstants constants,
ITscConfigurationService tscConfigurationService,
IBackendApiService backendApiService,
ISettings settings)
ISettings settings,
IConfigJsonService configJsonService)
: ITeslaService, ITeslaFleetApiService
{
private DtoFleetApiRequest ChargeStartRequest => new()
Expand Down Expand Up @@ -74,7 +75,7 @@ public class TeslaFleetApiService(

private DtoFleetApiRequest VehicleDataRequest => new()
{
RequestUrl = $"vehicle_data?endpoints={Uri.EscapeDataString("drive_state;location_data;vehicle_state;charge_state")}",
RequestUrl = $"vehicle_data?endpoints={Uri.EscapeDataString("drive_state;location_data;vehicle_state;charge_state;climate_state")}",
NeedsProxy = false,
};

Expand Down Expand Up @@ -234,6 +235,54 @@ public async Task RefreshCarData()
var vehicleData = await SendCommandToTeslaApi<DtoVehicleDataResult>(vin, VehicleDataRequest, HttpMethod.Get)
.ConfigureAwait(false);
logger.LogTrace("Got vehicleData {@vehicleData}", vehicleData);
var teslaResult = vehicleData?.Response;
if (teslaResult == default)
{
await backendApiService.PostErrorInformation(nameof(TeslaFleetApiService), nameof(RefreshCarData),
$"Could not deserialize vehicle data: {JsonConvert.SerializeObject(vehicleData)}").ConfigureAwait(false);
logger.LogError("Could not deserialize vehicle data for car {carId}: {@vehicleData}", carId, vehicleData);
continue;
}

if (configurationWrapper.GetVehicleDataFromTesla())
{
var car = settings.Cars.First(c => c.Id == carId);
var carState = car.CarState;
carState.Name = teslaResult.VehicleState.VehicleName;
carState.SoC = teslaResult.ChargeState.BatteryLevel;
carState.SocLimit = teslaResult.ChargeState.ChargeLimitSoc;
var minimumSettableSocLimit = teslaResult.ChargeState.ChargeLimitSocMin;
if (car.CarConfiguration.MinimumSoC > car.CarState.SocLimit && car.CarState.SocLimit > minimumSettableSocLimit)
{
logger.LogWarning("Reduce Minimum SoC {minimumSoC} as charge limit {chargeLimit} is lower.", car.CarConfiguration.MinimumSoC, car.CarState.SocLimit);
car.CarConfiguration.MinimumSoC = (int)car.CarState.SocLimit;
await configJsonService.UpdateCarConfiguration().ConfigureAwait(false);
}
carState.ChargerPhases = teslaResult.ChargeState.ChargerPhases;
carState.ChargerVoltage = teslaResult.ChargeState.ChargerVoltage;
carState.ChargerActualCurrent = teslaResult.ChargeState.ChargerActualCurrent;
carState.PluggedIn = teslaResult.ChargeState.ChargingState != "Disconnected";
carState.ClimateOn = teslaResult.ClimateState.IsClimateOn;
carState.TimeUntilFullCharge = TimeSpan.FromHours(teslaResult.ChargeState.TimeToFullCharge);
var teslaCarStateString = teslaResult.State;
var teslaCarShiftState = teslaResult.DriveState.ShiftState;
var teslaCarSoftwareUpdateState = teslaResult.VehicleState.SoftwareUpdate.Status;
var chargingState = teslaResult.ChargeState.ChargingState;
carState.State = DetermineCarState(teslaCarStateString, teslaCarShiftState, teslaCarSoftwareUpdateState, chargingState);
if (carState.State == CarStateEnum.Unknown)
{
await backendApiService.PostErrorInformation(nameof(TeslaFleetApiService), nameof(RefreshCarData),
$"Could not determine car state. TeslaCarStateString: {teslaCarStateString}, TeslaCarShiftState: {teslaCarShiftState}, TeslaCarSoftwareUpdateState: {teslaCarSoftwareUpdateState}, ChargingState: {chargingState}").ConfigureAwait(false);
}
carState.Healthy = true;
carState.ChargerRequestedCurrent = teslaResult.ChargeState.ChargeCurrentRequest;
carState.ChargerPilotCurrent = teslaResult.ChargeState.ChargerPilotCurrent;
carState.ScheduledChargingStartTime = teslaResult.ChargeState.ScheduledChargingStartTime == null ? null : DateTimeOffset.FromUnixTimeSeconds(teslaResult.ChargeState.ScheduledChargingStartTime.Value);
carState.Longitude = teslaResult.DriveState.Longitude;
carState.Latitude = teslaResult.DriveState.Latitude;
}


}
catch (Exception ex)
{
Expand All @@ -244,6 +293,33 @@ await backendApiService.PostErrorInformation(nameof(TeslaFleetApiService), nameo
}
}

private CarStateEnum? DetermineCarState(string teslaCarStateString, string? teslaCarShiftState, string teslaCarSoftwareUpdateState, string chargingState)
{
if (teslaCarStateString == "asleep")
{
return CarStateEnum.Asleep;
}

if (teslaCarStateString == "offline")
{
return CarStateEnum.Offline;
}
if (teslaCarShiftState is "R" or "D")
{
return CarStateEnum.Driving;
}
if (chargingState == "Charging")
{
return CarStateEnum.Charging;
}
if (teslaCarSoftwareUpdateState == "installing")
{
return CarStateEnum.Updating;
}
logger.LogWarning("Could not determine car state. TeslaCarStateString: {teslaCarStateString}, TeslaCarShiftState: {teslaCarShiftState}, TeslaCarSoftwareUpdateState: {teslaCarSoftwareUpdateState}, ChargingState: {chargingState}", teslaCarStateString, teslaCarShiftState, teslaCarSoftwareUpdateState, chargingState);
return CarStateEnum.Unknown;
}

private async Task<string> GetVinByCarId(int carId)
{
var vin = await teslamateContext.Cars.Where(c => c.Id == carId).Select(c => c.Vin).FirstAsync().ConfigureAwait(false);
Expand Down

0 comments on commit 71e41c3

Please sign in to comment.