Skip to content

Commit

Permalink
Merge pull request #116 from pkuehnel/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
pkuehnel authored Jun 3, 2022
2 parents e9757d9 + 28743f2 commit cdab682
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 22 deletions.
57 changes: 54 additions & 3 deletions SmartTeslaAmpSetter.Tests/Services/ChargingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ public void Gets_relevant_car_IDs()
SoC = 30,
SocLimit = 60,
},
CarConfiguration = new CarConfiguration()
{
ShouldBeManaged = true,
},
},
new Car()
{
Expand All @@ -153,6 +157,27 @@ public void Gets_relevant_car_IDs()
SoC = 30,
SocLimit = 60,
},
CarConfiguration = new CarConfiguration()
{
ShouldBeManaged = true,
},
},
new Car()
{
Id = 3,
CarState = new CarState()
{
Geofence = geofence,
PluggedIn = true,
ClimateOn = false,
ChargerActualCurrent = 3,
SoC = 30,
SocLimit = 60,
},
CarConfiguration = new CarConfiguration()
{
ShouldBeManaged = false,
},
},
};
Mock.Mock<ISettings>().Setup(s => s.Cars).Returns(cars);
Expand Down Expand Up @@ -182,6 +207,10 @@ public void Gets_irrelevant_cars()
SoC = 30,
SocLimit = 60,
},
CarConfiguration = new CarConfiguration()
{
ShouldBeManaged = true,
},
},
new Car()
{
Expand All @@ -195,15 +224,37 @@ public void Gets_irrelevant_cars()
SoC = 30,
SocLimit = 60,
},
CarConfiguration = new CarConfiguration()
{
ShouldBeManaged = true,
},
},
new Car()
{
Id = 3,
CarState = new CarState()
{
Geofence = geofence,
PluggedIn = true,
ClimateOn = false,
ChargerActualCurrent = 3,
SoC = 30,
SocLimit = 60,
},
CarConfiguration = new CarConfiguration()
{
ShouldBeManaged = false,
},
},
};
Mock.Mock<ISettings>().Setup(s => s.Cars).Returns(cars);
var chargingService = Mock.Create<Server.Services.ChargingService>();

var irrelevantCars = chargingService.GetIrrelevantCars(new List<int>(){1});

Assert.Single(irrelevantCars);
var irrelevantCars = chargingService.GetIrrelevantCars(chargingService.GetRelevantCarIds(geofence));
Assert.Equal(2, irrelevantCars.Count);
Assert.Contains(2, irrelevantCars.Select(c => c.Id));
Assert.Contains(3, irrelevantCars.Select(c => c.Id));
}

private Car CreateDemoCar(ChargeMode chargeMode, DateTime latestTimeToReachSoC, int soC, int minimumSoC, bool autoFullSpeedCharge)
Expand Down
68 changes: 68 additions & 0 deletions SmartTeslaAmpSetter.Tests/Services/MqttService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SmartTeslaAmpSetter.Server.Services;
using SmartTeslaAmpSetter.Shared.Dtos.Settings;
using Xunit;
using Xunit.Abstractions;

namespace SmartTeslaAmpSetter.Tests.Services;

public class MqttService : TestBase
{
public MqttService(ITestOutputHelper outputHelper)
: base(outputHelper)
{
}

[Theory]
[InlineData("1")]
[InlineData("3")]
[InlineData("4")]
[InlineData("5")]
[InlineData("8")]
public void ReducesActualCurrentToLastSetAmpIfDifferenceIsOneAndBelow5A(string value)
{
var cars = new List<Car>()
{
new Car()
{
Id = 1,
CarState = new CarState()
{
LastSetAmp = 3,
},
},
};
Mock.Mock<ISettings>().Setup(s => s.Cars).Returns(cars);

var mqttService = Mock.Create<Server.Services.MqttService>();

var teslamateValue = new TeslaMateValue()
{
CarId = 1,
Topic = "charger_actual_current",
Value = value,
};
mqttService.UpdateCar(teslamateValue);

switch (value)
{
case "1":
Assert.Equal(1, cars.First().CarState.ChargerActualCurrent);
break;
case "3":
case "4":
Assert.Equal(3, cars.First().CarState.ChargerActualCurrent);
break;
case "5":
Assert.Equal(5, cars.First().CarState.ChargerActualCurrent);
break;
case "8":
Assert.Equal(8, cars.First().CarState.ChargerActualCurrent);
break;
default:
throw new NotImplementedException();
}
}
}
5 changes: 5 additions & 0 deletions SmartTeslaAmpSetter/Client/Pages/CarSettings.razor
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ else
<input class="col-sm-6 col-md-3 col-lg-2" value="@carBasicConfiguration.UsableEnergy" type="number" id="usableEnergy" name="usableEnergy" min="1" max="120"
@onchange="@(e => carBasicConfiguration.UsableEnergy = Int32.Parse(e.Value?.ToString() ?? "1"))">
</p>
<p>
<label class="col-sm-4 col-md-3 col-lg-2" for="usableEnergy">Auto Set Amp:</label>
<input class="col-sm-6 col-md-3 col-lg-2" checked="@carBasicConfiguration.ShouldBeManaged" type="checkbox" id="ShouldBeManaged" name="ShouldBeManaged" min="1" max="120"
@onchange="@(e => carBasicConfiguration.ShouldBeManaged = Boolean.Parse(e.Value?.ToString() ?? "true"))">
</p>
<p><button class="btn btn-success col-sm-10 col-md-6 col-lg-4" @onclick="() => UpdateCarConfiguration(carBasicConfiguration.CarId, carBasicConfiguration)">@_saveButtonTexts[carBasicConfiguration.CarId]</button></p>
</div>
}
Expand Down
44 changes: 26 additions & 18 deletions SmartTeslaAmpSetter/Server/Services/ChargingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,24 +68,7 @@ public async Task SetNewChargingValues(bool onlyUpdateValues = false)
_logger.LogTrace("Relevant cars: {@relevantCars}", relevantCars);
_logger.LogTrace("Irrelevant cars: {@irrlevantCars}", irrelevantCars);

foreach (var relevantCar in relevantCars)
{
relevantCar.CarState.ChargingPowerAtHome = relevantCar.CarState.ChargingPower;
}

//Do not combine with irrelevant cars because then charging would never start
foreach (var pluggedOutCar in _settings.Cars
.Where(c => c.CarState.PluggedIn != true).ToList())
{
_logger.LogDebug("Resetting ChargeStart and ChargeStop for car {carId}", pluggedOutCar.Id);
UpdateEarliestTimesAfterSwitch(pluggedOutCar.Id);
pluggedOutCar.CarState.ChargingPowerAtHome = 0;
}

foreach (var car in irrelevantCars)
{
car.CarState.ChargingPowerAtHome = 0;
}
UpdateChargingPowerAtHome(geofence);

if (onlyUpdateValues)
{
Expand Down Expand Up @@ -120,6 +103,30 @@ public async Task SetNewChargingValues(bool onlyUpdateValues = false)
}
}

private void UpdateChargingPowerAtHome(string geofence)
{
var carsAtHome = _settings.Cars.Where(c => c.CarState.Geofence == geofence).ToList();
foreach (var car in carsAtHome)
{
car.CarState.ChargingPowerAtHome = car.CarState.ChargingPower;
}
var carsNotAtHome = _settings.Cars.Where(car => !carsAtHome.Select(c => c.Id).Any(i => i == car.Id)).ToList();

foreach (var car in carsNotAtHome)
{
car.CarState.ChargingPowerAtHome = 0;
}

//Do not combine with irrelevant cars because then charging would never start
foreach (var pluggedOutCar in _settings.Cars
.Where(c => c.CarState.PluggedIn != true).ToList())
{
_logger.LogDebug("Resetting ChargeStart and ChargeStop for car {carId}", pluggedOutCar.Id);
UpdateEarliestTimesAfterSwitch(pluggedOutCar.Id);
pluggedOutCar.CarState.ChargingPowerAtHome = 0;
}
}

internal List<Car> GetIrrelevantCars(List<int> relevantCarIds)
{
return _settings.Cars.Where(car => !relevantCarIds.Any(i => i == car.Id)).ToList();
Expand Down Expand Up @@ -150,6 +157,7 @@ internal List<int> GetRelevantCarIds(string geofence)
var relevantIds = _settings.Cars
.Where(c =>
c.CarState.Geofence == geofence
&& c.CarConfiguration.ShouldBeManaged == true
&& c.CarState.PluggedIn == true
&& (c.CarState.ClimateOn == true ||
c.CarState.ChargerActualCurrent > 0 ||
Expand Down
7 changes: 7 additions & 0 deletions SmartTeslaAmpSetter/Server/Services/ConfigJsonService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,13 @@ public async Task AddCarIdsToSettings()
{
car.CarConfiguration.MinimumAmpere = 1;
}

if (car.CarConfiguration.ShouldBeManaged == null)
{
var defaultValue = true;
_logger.LogInformation("Car {carId}: {variable} is not set, use default value {defaultValue}", car.Id, nameof(car.CarConfiguration.ShouldBeManaged), defaultValue);
car.CarConfiguration.ShouldBeManaged = defaultValue;
}
}
_logger.LogDebug("All unset car configurations set.");
}
Expand Down
2 changes: 2 additions & 0 deletions SmartTeslaAmpSetter/Server/Services/ConfigService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public List<CarBasicConfiguration> GetCarBasicConfigurations()
MaximumAmpere = car.CarConfiguration.MaximumAmpere,
MinimumAmpere = car.CarConfiguration.MinimumAmpere,
UsableEnergy = car.CarConfiguration.UsableEnergy,
ShouldBeManaged = car.CarConfiguration.ShouldBeManaged,
});
}

Expand All @@ -67,5 +68,6 @@ public void UpdateCarBasicConfiguration(int carId, CarBasicConfiguration carBasi
car.CarConfiguration.MinimumAmpere = carBasicConfiguration.MinimumAmpere;
car.CarConfiguration.MaximumAmpere = carBasicConfiguration.MaximumAmpere;
car.CarConfiguration.UsableEnergy = carBasicConfiguration.UsableEnergy;
car.CarConfiguration.ShouldBeManaged = carBasicConfiguration.ShouldBeManaged;
}
}
9 changes: 8 additions & 1 deletion SmartTeslaAmpSetter/Server/Services/MqttService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public async Task ConfigureMqttClient()
await _mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
}

private void UpdateCar(TeslaMateValue value)
internal void UpdateCar(TeslaMateValue value)
{
var car = _settings.Cars.First(c => c.Id == value.CarId);

Expand Down Expand Up @@ -188,6 +188,13 @@ private void UpdateCar(TeslaMateValue value)
if (!string.IsNullOrWhiteSpace(value.Value))
{
car.CarState.ChargerActualCurrent = Convert.ToInt32(value.Value);
if (car.CarState.ChargerActualCurrent < 5 &&
car.CarState.LastSetAmp == car.CarState.ChargerActualCurrent - 1 &&
car.CarState.LastSetAmp > 0)
{
_logger.LogWarning("CarId {carId}: Reducing {actualCurrent} from {originalValue} to {newValue} due to error in TeslaApi", car.Id, nameof(car.CarState.ChargerActualCurrent), car.CarState.ChargerActualCurrent, car.CarState.LastSetAmp);
car.CarState.ChargerActualCurrent = car.CarState.LastSetAmp;
}
}
else
{
Expand Down
1 change: 1 addition & 0 deletions SmartTeslaAmpSetter/Shared/ConfigPropertyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class ConfigPropertyResolver : DefaultContractResolver
nameof(Car.CarConfiguration.MinimumAmpere),
nameof(Car.CarConfiguration.MaximumAmpere),
nameof(Car.CarConfiguration.UsableEnergy),
nameof(Car.CarConfiguration.ShouldBeManaged),
nameof(Car.Id),
};

Expand Down
1 change: 1 addition & 0 deletions SmartTeslaAmpSetter/Shared/Dtos/CarBasicConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public CarBasicConfiguration(int carId, string? carName)
public int MaximumAmpere { get; set; }
public int MinimumAmpere { get; set; }
public int UsableEnergy { get; set; }
public bool? ShouldBeManaged { get; set; }
}
12 changes: 12 additions & 0 deletions SmartTeslaAmpSetter/Shared/Dtos/Settings/CarConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ public class CarConfiguration
private int _maximumAmpere;
private int _minimumAmpere;
private int _usableEnergy;
private bool? _shouldBeManaged;

public CarConfiguration()
{
UpdatedSincLastWrite = true;
_shouldBeManaged = true;
}

[JsonIgnore]
Expand Down Expand Up @@ -79,4 +81,14 @@ public int UsableEnergy
UpdatedSincLastWrite = true;
}
}

public bool? ShouldBeManaged
{
get => _shouldBeManaged;
set
{
_shouldBeManaged = value;
UpdatedSincLastWrite = true;
}
}
}

0 comments on commit cdab682

Please sign in to comment.