diff --git a/Plugins.SmaEnergymeter/Controllers/CurrentPowerController.cs b/Plugins.SmaEnergymeter/Controllers/CurrentPowerController.cs index 0cfa53a92..07b83b274 100644 --- a/Plugins.SmaEnergymeter/Controllers/CurrentPowerController.cs +++ b/Plugins.SmaEnergymeter/Controllers/CurrentPowerController.cs @@ -18,5 +18,11 @@ public int GetPower() { return _currentPowerService.GetCurrentPower(); } + + [HttpGet] + public SharedValues GetAllValues() + { + return _currentPowerService.GetAllValues(); + } } } diff --git a/Plugins.SmaEnergymeter/Services/CurrentPowerService.cs b/Plugins.SmaEnergymeter/Services/CurrentPowerService.cs index 0fe5c8ce6..1aabbdc4b 100644 --- a/Plugins.SmaEnergymeter/Services/CurrentPowerService.cs +++ b/Plugins.SmaEnergymeter/Services/CurrentPowerService.cs @@ -14,6 +14,12 @@ public CurrentPowerService(ILogger logger, SharedValues sha public int GetCurrentPower() { _logger.LogTrace("{method}()", nameof(GetCurrentPower)); - return _sharedValues.Overage; + return _sharedValues.OverageW; } -} \ No newline at end of file + + public SharedValues GetAllValues() + { + _logger.LogTrace("{method}()", nameof(GetAllValues)); + return _sharedValues; + } +} diff --git a/Plugins.SmaEnergymeter/Services/EnergyMeterService.cs b/Plugins.SmaEnergymeter/Services/EnergyMeterService.cs index 3a67d8830..27afc7f11 100644 --- a/Plugins.SmaEnergymeter/Services/EnergyMeterService.cs +++ b/Plugins.SmaEnergymeter/Services/EnergyMeterService.cs @@ -55,21 +55,37 @@ public void StartLogging() var relevantValues = byteArray.Skip(28).Take(byteArray.Length - 27).ToArray(); var obisValues = ConvertArrayToObisDictionary(relevantValues); - var currentSupply = - Convert.ToDecimal(obisValues.First(v => v.Id == 1 && v.ValueType == ValueMode.Average).Value / 10.0); var currentOverage = Convert.ToDecimal(obisValues.First(v => v.Id == 2 && v.ValueType == ValueMode.Average).Value / 10.0); + var currentSupply = + Convert.ToDecimal(obisValues.First(v => v.Id == 1 && v.ValueType == ValueMode.Average).Value / 10.0); + + + var totalEnergyToGrid = Convert.ToDecimal(obisValues.First(v => v.Id == 2 && v.ValueType == ValueMode.Counter).Value / 3600.0); + var totalEnergyFromGrid = Convert.ToDecimal(obisValues.First(v => v.Id == 1 && v.ValueType == ValueMode.Counter).Value / 3600.0); + + _sharedValues.PowerFromGridW = (int) currentSupply; + _sharedValues.PowerToGridW = (int) currentOverage; + + _sharedValues.TotalEnergyToGridWh = totalEnergyToGrid; + _sharedValues.TotalEnergyFromGridWh = totalEnergyFromGrid; + + _sharedValues.LastValuesFrom = DateTime.UtcNow; + + _logger.LogTrace("current overage: {currentOverage} W", currentOverage); + _logger.LogTrace("current supply: {currentSupply} W", currentSupply); - _logger.LogTrace("current supply: {currentSupply}", currentSupply); - _logger.LogTrace("current overage: {currentOverage}", currentOverage); + _logger.LogTrace("Total energy to grid: {totalEnergyToGrid} W", totalEnergyToGrid); + _logger.LogTrace("Total energy from grid: {totalEnergyFromGrid} W", totalEnergyFromGrid); + if (currentSupply > 0) { - _sharedValues.Overage = (int)-currentSupply; + _sharedValues.OverageW = (int)-currentSupply; } else { - _sharedValues.Overage = (int)currentOverage; + _sharedValues.OverageW = (int)currentOverage; } } } diff --git a/Plugins.SmaEnergymeter/SharedValues.cs b/Plugins.SmaEnergymeter/SharedValues.cs index b0b9a6c79..5c2a2973e 100644 --- a/Plugins.SmaEnergymeter/SharedValues.cs +++ b/Plugins.SmaEnergymeter/SharedValues.cs @@ -2,5 +2,16 @@ public class SharedValues { - public int Overage { get; set; } -} \ No newline at end of file + public int OverageW { get; set; } + + public int PowerToGridW { get; set; } + public int PowerFromGridW { get; set; } + + public decimal TotalEnergyToGridWh { get; set; } + public decimal TotalEnergyFromGridWh { get; set; } + + public decimal TotalEnergyToGridkWh => TotalEnergyToGridWh / 1000; + public decimal TotalEnergyFromGridkWh => TotalEnergyFromGridWh / 1000; + + public DateTime LastValuesFrom { get; set; } +} diff --git a/Plugins.SolarEdge/Services/CurrentValuesService.cs b/Plugins.SolarEdge/Services/CurrentValuesService.cs index 1c6eb3023..8cefd1a82 100644 --- a/Plugins.SolarEdge/Services/CurrentValuesService.cs +++ b/Plugins.SolarEdge/Services/CurrentValuesService.cs @@ -214,7 +214,9 @@ private void AddCloudApiValueToSharedValues(CloudApiValue cloudApiValue) return null; } //If there are already values there and there is no relevant car, call API everytime reset minutes are over. - if (_sharedValues.CloudApiValues.Count > 0 && numberOfRelevantCars < 1 && _sharedValues.CloudApiValues.MaxBy(v => v.Key).Key > DateTime.UtcNow - solarEdgeTooManyRequestsResetTime) + if ((_sharedValues.CloudApiValues.Count > 0) + && numberOfRelevantCars < 1 + && (_sharedValues.CloudApiValues.MaxBy(v => v.Key).Key > (DateTime.UtcNow - solarEdgeTooManyRequestsResetTime))) { _logger.LogDebug("Prevent calling SolarEdge API as relevantCarCount is {relevantCarCount}", numberOfRelevantCars); return null; diff --git a/Plugins.Solax/Plugins.Solax.csproj b/Plugins.Solax/Plugins.Solax.csproj index a85d443ce..be9411f73 100644 --- a/Plugins.Solax/Plugins.Solax.csproj +++ b/Plugins.Solax/Plugins.Solax.csproj @@ -8,7 +8,7 @@ - + diff --git a/TeslaSolarCharger.Model/TeslaSolarCharger.Model.csproj b/TeslaSolarCharger.Model/TeslaSolarCharger.Model.csproj index 3eb5b507b..5d0a1d8c7 100644 --- a/TeslaSolarCharger.Model/TeslaSolarCharger.Model.csproj +++ b/TeslaSolarCharger.Model/TeslaSolarCharger.Model.csproj @@ -7,16 +7,16 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/TeslaSolarCharger.Tests/Services/Server/ChargeTimeCalculationService.cs b/TeslaSolarCharger.Tests/Services/Server/ChargeTimeCalculationService.cs index f64811d91..ee9ec5948 100644 --- a/TeslaSolarCharger.Tests/Services/Server/ChargeTimeCalculationService.cs +++ b/TeslaSolarCharger.Tests/Services/Server/ChargeTimeCalculationService.cs @@ -150,7 +150,8 @@ public async Task Dont_Plan_Charging_If_Min_Soc_Reached(ChargeMode chargeMode) }; var chargeTimeCalculationService = Mock.Create(); - var chargingSlots = await chargeTimeCalculationService.PlanChargingSlots(car, currentDate).ConfigureAwait(false); + // ReSharper disable once UseConfigureAwaitFalse + var chargingSlots = await chargeTimeCalculationService.PlanChargingSlots(car, currentDate); Assert.Empty(chargingSlots); } @@ -210,7 +211,8 @@ public async Task Calculate_Correct_ChargeTimes_Without_Stock_Prices(ChargeMode }; var chargeTimeCalculationService = Mock.Create(); - var chargingSlots = await chargeTimeCalculationService.PlanChargingSlots(car, currentDate).ConfigureAwait(false); + // ReSharper disable once UseConfigureAwaitFalse + var chargingSlots = await chargeTimeCalculationService.PlanChargingSlots(car, currentDate); Assert.Single(chargingSlots); diff --git a/TeslaSolarCharger.Tests/Services/Server/LatestTimeToReachSocUpdateService.cs b/TeslaSolarCharger.Tests/Services/Server/LatestTimeToReachSocUpdateService.cs index 71fbba876..468f96536 100644 --- a/TeslaSolarCharger.Tests/Services/Server/LatestTimeToReachSocUpdateService.cs +++ b/TeslaSolarCharger.Tests/Services/Server/LatestTimeToReachSocUpdateService.cs @@ -1,5 +1,4 @@ -using Autofac; -using System; +using System; using TeslaSolarCharger.Shared.Contracts; using TeslaSolarCharger.Shared.Dtos.Settings; using TeslaSolarCharger.Shared.TimeProviding; @@ -24,13 +23,10 @@ public void Correctly_Updates_LatestTimeToReachSoc(bool shouldIgnoreDate, DateTi LatestTimeToReachSoC = configuredDate, }; - var currentTimeProvider = Mock.Create( - new NamedParameter("dateTime", currentDate)); - Mock.Provide(currentTimeProvider); - - var latestTimeToReachSocUpdateService = Mock.Create(); + _fake.Provide(new FakeDateTimeProvider(currentDate)); + var latestTimeToReachSocUpdateService = _fake.Resolve(); latestTimeToReachSocUpdateService.UpdateCarConfiguration(carConfiguration); - + Assert.Equal(expectedDate, carConfiguration.LatestTimeToReachSoC); } diff --git a/TeslaSolarCharger.Tests/TeslaSolarCharger.Tests.csproj b/TeslaSolarCharger.Tests/TeslaSolarCharger.Tests.csproj index 24510bda8..2e43c3220 100644 --- a/TeslaSolarCharger.Tests/TeslaSolarCharger.Tests.csproj +++ b/TeslaSolarCharger.Tests/TeslaSolarCharger.Tests.csproj @@ -8,15 +8,18 @@ - - - - - - - - - + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/TeslaSolarCharger.Tests/TestBase.cs b/TeslaSolarCharger.Tests/TestBase.cs index 66a197545..d7898f2be 100644 --- a/TeslaSolarCharger.Tests/TestBase.cs +++ b/TeslaSolarCharger.Tests/TestBase.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using Autofac; +using Autofac.Extras.FakeItEasy; using Autofac.Extras.Moq; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; @@ -12,6 +13,8 @@ using Serilog.Events; using TeslaSolarCharger.Model.Contracts; using TeslaSolarCharger.Model.EntityFramework; +using TeslaSolarCharger.Server.MappingExtensions; +using TeslaSolarCharger.Shared.Contracts; using TeslaSolarCharger.Shared.TimeProviding; using Xunit.Abstractions; @@ -24,6 +27,7 @@ public class TestBase : IDisposable protected readonly AutoMock Mock; private readonly TeslaSolarChargerContext _ctx; + protected readonly AutoFake _fake; protected ITeslaSolarChargerContext Context => _ctx; @@ -44,16 +48,28 @@ protected TestBase( {"ConfigFileLocation", "configs"}, {"CarConfigFilename", "carConfig.json"}, }; + var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(configDictionary!) - .Build() + .AddInMemoryCollection(configDictionary!) + .Build() ; - - Mock = AutoMock.GetLoose(cfg => - { - cfg.RegisterType(typeof(FakeDateTimeProvider)); - cfg.RegisterInstance(configuration).As(); - }); + + var currentFakeTime = new DateTime(2023, 2, 2, 8, 0, 0); + + _fake = new AutoFake(); + _fake.Provide(); + _fake.Provide(new FakeDateTimeProvider(currentFakeTime)); + _fake.Provide(configuration); + + Mock = AutoMock.GetLoose( + b => + { + b.Register((_, _) => Context); + b.Register((_, _) => _fake.Resolve()); + b.Register((_, _) => _fake.Resolve()); + b.RegisterType(); + //b.Register((_, _) => _fake.Resolve()); + }); // In-memory database only exists while the connection is open var connection = new SqliteConnection("DataSource=:memory:"); @@ -88,7 +104,7 @@ protected TestBase( //var autoMock = AutoMock.GetLoose(cfg => cfg.RegisterInstance(new TeslaSolarChargerContext(options)).As()); //_ctx = (TeslaSolarChargerContext) autoMock.Create(); - _ctx = (TeslaSolarChargerContext)Mock.Provide(new TeslaSolarChargerContext(options)); + _ctx = _fake.Provide(new TeslaSolarChargerContext(options)); _ctx.Database.EnsureCreated(); //_ctx.InitContextData(); _ctx.SaveChanges(); diff --git a/TeslaSolarCharger/Client/Pages/Index.razor b/TeslaSolarCharger/Client/Pages/Index.razor index 68a6ddaa9..12d13d71a 100644 --- a/TeslaSolarCharger/Client/Pages/Index.razor +++ b/TeslaSolarCharger/Client/Pages/Index.razor @@ -238,7 +238,7 @@ else @if (car.ChargeInformation.Count > 0) {

- Car will @(car.HomeChargePower > 0 ? "stop" : "start") charging when following conditions are met:
+ Car will @((car.State == CarStateEnum.Charging && car.IsHome) ? "stop" : "start") charging when following conditions are met:

    @foreach (var chargeInfo in car.ChargeInformation) { diff --git a/TeslaSolarCharger/Client/TeslaSolarCharger.Client.csproj b/TeslaSolarCharger/Client/TeslaSolarCharger.Client.csproj index 956c3edb9..51506cd18 100644 --- a/TeslaSolarCharger/Client/TeslaSolarCharger.Client.csproj +++ b/TeslaSolarCharger/Client/TeslaSolarCharger.Client.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/TeslaSolarCharger/Server/Services/ApiServices/IndexService.cs b/TeslaSolarCharger/Server/Services/ApiServices/IndexService.cs index 057be24d4..239addb72 100644 --- a/TeslaSolarCharger/Server/Services/ApiServices/IndexService.cs +++ b/TeslaSolarCharger/Server/Services/ApiServices/IndexService.cs @@ -66,6 +66,7 @@ public DtoPvValues GetPvValues() HomeBatterySoc = _settings.HomeBatterySoc, PowerBuffer = powerBuffer, CarCombinedChargingPowerAtHome = _settings.Cars.Select(c => c.CarState.ChargingPowerAtHome).Sum(), + LastUpdated = _settings.LastPvValueUpdate, }; } @@ -136,7 +137,7 @@ private List GenerateChargeInformation(Car enabledCar) }); } - if (enabledCar.CarState.State != CarStateEnum.Charging + if ((!(enabledCar.CarState.State == CarStateEnum.Charging && enabledCar.CarState.IsHomeGeofence == true)) && enabledCar.CarState.EarliestSwitchOn != null && enabledCar.CarState.EarliestSwitchOn > _dateTimeProvider.Now()) { @@ -147,7 +148,7 @@ private List GenerateChargeInformation(Car enabledCar) }); } - if (enabledCar.CarState.State != CarStateEnum.Charging + if ((!(enabledCar.CarState.State == CarStateEnum.Charging && enabledCar.CarState.IsHomeGeofence == true)) && enabledCar.CarState.EarliestSwitchOn == null) { result.Add(new DtoChargeInformation() @@ -157,7 +158,7 @@ private List GenerateChargeInformation(Car enabledCar) }); } - if (enabledCar.CarState.State == CarStateEnum.Charging + if ((enabledCar.CarState.State == CarStateEnum.Charging && enabledCar.CarState.IsHomeGeofence == true) && enabledCar.CarState.EarliestSwitchOff != null && enabledCar.CarState.EarliestSwitchOff > _dateTimeProvider.Now()) { @@ -168,7 +169,7 @@ private List GenerateChargeInformation(Car enabledCar) }); } - if (enabledCar.CarState.State != CarStateEnum.Charging + if ((!(enabledCar.CarState.State == CarStateEnum.Charging && enabledCar.CarState.IsHomeGeofence == true)) && (enabledCar.CarState.SocLimit - enabledCar.CarState.SoC) < (_constants.MinimumSocDifference + 1)) { result.Add(new DtoChargeInformation() diff --git a/TeslaSolarCharger/Server/Services/PvValueService.cs b/TeslaSolarCharger/Server/Services/PvValueService.cs index d810553c8..dc1435e2e 100644 --- a/TeslaSolarCharger/Server/Services/PvValueService.cs +++ b/TeslaSolarCharger/Server/Services/PvValueService.cs @@ -37,7 +37,7 @@ public PvValueService(ILogger logger, ISettings settings, public async Task UpdatePvValues() { _logger.LogTrace("{method}()", nameof(UpdatePvValues)); - _settings.LastPvValueUpdate = _dateTimeProvider.DateTimeOffSetNow(); + var gridRequestUrl = _configurationWrapper.CurrentPowerToGridUrl(); var frontendConfiguration = _configurationWrapper.FrontendConfiguration(); HttpRequestMessage? originGridRequest = default; @@ -184,6 +184,7 @@ public async Task UpdatePvValues() _settings.HomeBatteryPower = homeBatteryPower; } + _settings.LastPvValueUpdate = _dateTimeProvider.DateTimeOffSetNow(); } private async Task GetValueByHttpResponse(HttpResponseMessage? httpResponse, string? jsonPattern, string? xmlPattern, diff --git a/TeslaSolarCharger/Server/TeslaSolarCharger.Server.csproj b/TeslaSolarCharger/Server/TeslaSolarCharger.Server.csproj index 6106e6b48..428938dc9 100644 --- a/TeslaSolarCharger/Server/TeslaSolarCharger.Server.csproj +++ b/TeslaSolarCharger/Server/TeslaSolarCharger.Server.csproj @@ -34,21 +34,21 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - +