diff --git a/csharp/App/SaliMax/src/AggregationService/Aggregator.cs b/csharp/App/SaliMax/src/AggregationService/Aggregator.cs index 4fca504a3..afeef3886 100644 --- a/csharp/App/SaliMax/src/AggregationService/Aggregator.cs +++ b/csharp/App/SaliMax/src/AggregationService/Aggregator.cs @@ -30,7 +30,7 @@ public static class Aggregator { try { - AggregatedData hourlyAggregatedData = CreateAverage("LogDirectory",DateTime.Now.AddHours(-1).ToUnixTime(),DateTime.Now.ToUnixTime()); + AggregatedData hourlyAggregatedData = CreateHourlyData("LogDirectory",DateTime.Now.AddHours(-1).ToUnixTime(),DateTime.Now.ToUnixTime()); hourlyAggregatedData.Save("HourlyData"); } catch (Exception e) @@ -64,7 +64,7 @@ public static class Aggregator try { var currentTime = DateTime.Now; - AggregatedData dailyAggregatedData = CreateAverage("HourlyData",currentTime.AddDays(-1).ToUnixTime(),currentTime.ToUnixTime()); + AggregatedData dailyAggregatedData = CreateDailyData("HourlyData",currentTime.AddDays(-1).ToUnixTime(),currentTime.ToUnixTime()); dailyAggregatedData.Save("DailyData"); if (await dailyAggregatedData.PushToS3()) { @@ -95,13 +95,153 @@ public static class Aggregator } } - - private static AggregatedData CreateAverage(String myDirectory, Int64 afterTimestamp, Int64 beforeTimestamp) + // this for test + private static AggregatedData CreateHourlyData(String myDirectory, Int64 afterTimestamp, Int64 beforeTimestamp) + { + // Get all CSV files in the specified directory + var csvFiles = Directory.GetFiles(myDirectory, "*.csv"); + var batterySoc = new List(); + var pvPowerAverage = new List(); + var gridPowerImport = new List(); + var gridPowerExport = new List(); + var batteryDischargePower = new List(); + var batteryChargePower = new List(); + + + Console.WriteLine("-----------------------------------------------------------------------------------------------------------------"); + Console.WriteLine("File timestamp should start after "+ afterTimestamp); + + foreach (var csvFile in csvFiles) + { + if (csvFile == "LogDirectory/log.csv") + { + continue; + } + + if (IsFileWithinTimeRange(csvFile, afterTimestamp, beforeTimestamp)) + { + using var reader = new StreamReader(csvFile); + + while (!reader.EndOfStream) + { + + var line = reader.ReadLine(); + var lines = line?.Split(';'); + + // Assuming there are always three columns (variable name and its value) + if (lines is { Length: 3 }) + { + var variableName = lines[0].Trim(); + + if (TryParse(lines[1].Trim(), out var value)) + { + switch (variableName) + { + case "/Battery/Soc": + batterySoc.Add(value); + break; + + case "/PvOnDc/DcWh" : + pvPowerAverage.Add(value); + break; + + case "/Battery/Dc/Power": + + if (value < 0) + { + batteryDischargePower.Add(value); + } + else + { + batteryChargePower.Add(value); + + } + break; + + case "/GridMeter/ActivePowerExportT2": + // we are using different register to check which value from the grid meter we need to use + gridPowerExport.Add(value); + break; + + case "/GridMeter/ActivePowerImportT2": + gridPowerImport.Add(value); + break; + // Add more cases as needed + default: + // Code to execute when variableName doesn't match any condition + break; + } + + } + else + { + //Handle cases where variableValue is not a valid number + // Console.WriteLine( + // $"Invalid numeric value for variable {variableName}:{lines[1].Trim()}"); + } + } + else + { + // Handle invalid column format + //Console.WriteLine("Invalid format in column"); + } + } + } + } + + //Average Power (Watts)= Sum of Power Readings/Number of Readings + + //Then, you can use the average power in the energy formula: + // + //Energy (kWh)= (Average Power / 3600) × Time (1 seconds) + // + // Dividing the Average power readings by 3600 converts the result from watt-seconds to kilowatt-hours. + + var dischargingEnergy = (batteryDischargePower.Any() ? batteryDischargePower.Average() : 0.0) / 3600 ; + var chargingEnergy = (batteryChargePower.Any() ? batteryChargePower.Average() : 0.0) / 3600 ; + + + var dMaxSoc = batterySoc.Any() ? batterySoc.Max() : 0.0; + var dMinSoc = batterySoc.Any() ? batterySoc.Min() : 0.0; + var dSumGridExportPower = gridPowerExport.Any() ? (gridPowerExport.Max() - gridPowerExport.Min()) / 1000 : 0.0; + var dSumGridImportPower = gridPowerImport.Any() ? (gridPowerImport.Max() - gridPowerImport.Min()) / 1000 : 0.0; + var dSumPvPower = pvPowerAverage.Any() ? pvPowerAverage.Average() /1000 : 0.0; + + AggregatedData aggregatedData = new AggregatedData + { + MaxSoc = dMaxSoc, + MinSoc = dMinSoc, + SumDischargingBatteryPower = dischargingEnergy, + SumChargingBatteryPower = chargingEnergy, + SumGridExportPower = dSumGridExportPower, // divide it + SumGridImportPower = dSumGridImportPower, // divide it + SumPvPower = dSumPvPower + }; + + // Print the stored CSV data for verification + Console.WriteLine($"Max SOC: {aggregatedData.MaxSoc}"); + Console.WriteLine($"Min SOC: {aggregatedData.MinSoc}"); + + Console.WriteLine($"ChargingBatteryPower: {aggregatedData.SumDischargingBatteryPower}"); + Console.WriteLine($"DischargingBatteryBattery: {aggregatedData.SumChargingBatteryPower}"); + + Console.WriteLine($"SumGridExportPower: {aggregatedData.SumGridExportPower}"); + Console.WriteLine($"SumGridImportPower: {aggregatedData.SumGridImportPower}"); + + Console.WriteLine($"Min SOC: {aggregatedData.MinSoc}"); + + + Console.WriteLine("CSV data reading and storage completed."); + Console.WriteLine("-----------------------------------------------------------------------------------------------------------------"); + + return aggregatedData; + } + + private static AggregatedData CreateDailyData(String myDirectory, Int64 afterTimestamp, Int64 beforeTimestamp) { // Get all CSV files in the specified directory var csvFiles = Directory.GetFiles(myDirectory, "*.csv"); var batterySoc = new List(); - var batteryAvgSoc = new List(); // this is only used for the daily data. var pvPowerAverage = new List(); var gridPowerImport = new List(); var gridPowerExport = new List(); @@ -138,40 +278,27 @@ public static class Aggregator { switch (variableName) { - case "/Battery/Soc" or "/MinSoc" or "/MaxSoc": + case "/MinSoc" or "/MaxSoc": batterySoc.Add(value); break; - case "/PvOnDc/DcWh" or "/SumPvPower": + case "/SumPvPower": pvPowerAverage.Add(value); break; - case "/Battery/Dc/Power" or "/SumDischargingBatteryPower" or "/SumChargingBatteryPower": - - //Average Power (Watts)= Sum of Power Readings/Number of Readings - - //Then, you can use the average power in the energy formula: - // - //Energy (kWh)= (Average Power / 3600) × Time (seconds) - // - // Dividing the Average power readings by 3600 converts the result from watt-seconds to kilowatt-hours. - if (value < 0) - { - batteryDischargePower.Add(value); - } - else - { - batteryChargePower.Add(value); - - } + case "/SumDischargingBatteryPower" : + batteryDischargePower.Add(value); + break; + + case "/SumChargingBatteryPower" : + batteryChargePower.Add(value); break; - case "/GridMeter/ActivePowerExportT2" or "/SumGridExportPower": - // we are using different register to check which value from the grid meter we need to use + case "/SumGridExportPower": gridPowerExport.Add(value); break; - case "/GridMeter/ActivePowerImportT2" or "/SumGridImportPower": + case "/SumGridImportPower": gridPowerImport.Add(value); break; // Add more cases as needed @@ -203,8 +330,8 @@ public static class Aggregator MinSoc = batterySoc.Any() ? batterySoc.Min() : 0.0, SumDischargingBatteryPower = batteryDischargePower.Any() ? batteryDischargePower.Average(): 0.0, SumChargingBatteryPower = batteryChargePower.Any() ? batteryChargePower.Average() : 0.0, - SumGridExportPower = gridPowerExport.Any() ? gridPowerExport.Average() : 0.0, - SumGridImportPower = gridPowerImport.Any() ? gridPowerImport.Average() : 0.0, + SumGridExportPower = gridPowerExport.Any() ? gridPowerExport.Average() : 0.0, + SumGridImportPower = gridPowerImport.Any() ? gridPowerImport.Average() : 0.0, SumPvPower = pvPowerAverage.Any() ? pvPowerAverage.Average() : 0.0, }; @@ -227,7 +354,6 @@ public static class Aggregator return aggregatedData; } - // Custom method to check if a string is numeric private static Boolean GetVariable(String value, String path) {