using System; using System.Collections.Generic; using InnovEnergy.App.SinexcelCommunication.ESS; namespace InnovEnergy.App.SinexcelCommunication.AggregationService; public class HourlyAccumulator { public DateTime HourStart { get; set; } public double StartSelfGeneratedElectricity { get; set; } public double StartElectricityPurchased { get; set; } public double StartElectricityFed { get; set; } public double StartBatteryChargeEnergy { get; set; } public double StartBatteryDischargeEnergy { get; set; } public double StartLoadPowerConsumption { get; set; } public double LastSelfGeneratedElectricity { get; set; } public double LastElectricityPurchased { get; set; } public double LastElectricityFed { get; set; } public double LastBatteryChargeEnergy { get; set; } public double LastBatteryDischargeEnergy { get; set; } public double LastLoadPowerConsumption { get; set; } } public static class EnergyAggregation { private static HourlyAccumulator? _currentHourAccumulator; private static DateTime? _lastDailySaveDate; public static HourlyEnergyData? ProcessHourlyData(StatusRecord statusRecord, DateTime timestamp) { var r = statusRecord.InverterRecord; var hourStart = new DateTime(timestamp.Year, timestamp.Month, timestamp.Day, timestamp.Hour, 0, 0); // First call if (_currentHourAccumulator == null) { _currentHourAccumulator = new HourlyAccumulator { HourStart = hourStart, StartSelfGeneratedElectricity = r.SelfGeneratedElectricity, StartElectricityPurchased = r.ElectricityPurchased, StartElectricityFed = r.ElectricityFed, StartBatteryChargeEnergy = r.BatteryChargeEnergy, StartBatteryDischargeEnergy = r.BatteryDischargeEnergy, StartLoadPowerConsumption = r.LoadPowerConsumption, LastSelfGeneratedElectricity = r.SelfGeneratedElectricity, LastElectricityPurchased = r.ElectricityPurchased, LastElectricityFed = r.ElectricityFed, LastBatteryChargeEnergy = r.BatteryChargeEnergy, LastBatteryDischargeEnergy = r.BatteryDischargeEnergy, LastLoadPowerConsumption = r.LoadPowerConsumption }; return null; } // Still same hour → just update last values if (_currentHourAccumulator.HourStart == hourStart) { _currentHourAccumulator.LastSelfGeneratedElectricity = r.SelfGeneratedElectricity; _currentHourAccumulator.LastElectricityPurchased = r.ElectricityPurchased; _currentHourAccumulator.LastElectricityFed = r.ElectricityFed; _currentHourAccumulator.LastBatteryChargeEnergy = r.BatteryChargeEnergy; _currentHourAccumulator.LastBatteryDischargeEnergy = r.BatteryDischargeEnergy; _currentHourAccumulator.LastLoadPowerConsumption = r.LoadPowerConsumption; return null; } // Hour changed → finalize previous hour var completedHour = new HourlyEnergyData { Timestamp = _currentHourAccumulator.HourStart, SelfGeneratedElectricity = SafeDiff( _currentHourAccumulator.LastSelfGeneratedElectricity, _currentHourAccumulator.StartSelfGeneratedElectricity), ElectricityPurchased = SafeDiff( _currentHourAccumulator.LastElectricityPurchased, _currentHourAccumulator.StartElectricityPurchased), ElectricityFed = SafeDiff( _currentHourAccumulator.LastElectricityFed, _currentHourAccumulator.StartElectricityFed), BatteryChargeEnergy = SafeDiff( _currentHourAccumulator.LastBatteryChargeEnergy, _currentHourAccumulator.StartBatteryChargeEnergy), BatteryDischargeEnergy = SafeDiff( _currentHourAccumulator.LastBatteryDischargeEnergy, _currentHourAccumulator.StartBatteryDischargeEnergy), LoadPowerConsumption = SafeDiff( _currentHourAccumulator.LastLoadPowerConsumption, _currentHourAccumulator.StartLoadPowerConsumption) }; // Start new hour with current sample _currentHourAccumulator = new HourlyAccumulator { HourStart = hourStart, StartSelfGeneratedElectricity = r.SelfGeneratedElectricity, StartElectricityPurchased = r.ElectricityPurchased, StartElectricityFed = r.ElectricityFed, StartBatteryChargeEnergy = r.BatteryChargeEnergy, StartBatteryDischargeEnergy = r.BatteryDischargeEnergy, StartLoadPowerConsumption = r.LoadPowerConsumption, LastSelfGeneratedElectricity = r.SelfGeneratedElectricity, LastElectricityPurchased = r.ElectricityPurchased, LastElectricityFed = r.ElectricityFed, LastBatteryChargeEnergy = r.BatteryChargeEnergy, LastBatteryDischargeEnergy = r.BatteryDischargeEnergy, LastLoadPowerConsumption = r.LoadPowerConsumption }; return completedHour; } public static DailyEnergyData? TryCreateDailyData(StatusRecord statusRecord, DateTime timestamp) { if (timestamp is { Hour: 23, Minute: 59 }) { if (_lastDailySaveDate != timestamp.Date) { _lastDailySaveDate = timestamp.Date; var r = statusRecord.InverterRecord; return new DailyEnergyData { Timestamp = timestamp, DailySelfGeneratedElectricity = r.DailySelfGeneratedElectricity, DailyElectricityPurchased = r.DailyElectricityPurchased, DailyElectricityFed = r.DailyElectricityFed, BatteryDailyChargeEnergy = r.BatteryDailyChargeEnergy, BatteryDailyDischargeEnergy = r.BatteryDailyDischargeEnergy, DailyLoadPowerConsumption = r.DailyLoadPowerConsumption }; } } return null; } private static double SafeDiff(double endValue, double startValue) { var diff = endValue - startValue; return diff < 0 ? 0 : diff; } }