From b13ff6efbef3303be042b24bb1e3e62ab423b430 Mon Sep 17 00:00:00 2001 From: Noe Date: Fri, 15 Dec 2023 14:55:23 +0100 Subject: [PATCH] Updated aggregation service --- .../src/AggregationService/Aggregator.cs | 97 ++++++++++++------- .../src/AggregationService/HourlyData.cs | 96 ++++++------------ csharp/App/SaliMax/src/Program.cs | 1 + 3 files changed, 95 insertions(+), 99 deletions(-) diff --git a/csharp/App/SaliMax/src/AggregationService/Aggregator.cs b/csharp/App/SaliMax/src/AggregationService/Aggregator.cs index 09b803969..8226b890e 100644 --- a/csharp/App/SaliMax/src/AggregationService/Aggregator.cs +++ b/csharp/App/SaliMax/src/AggregationService/Aggregator.cs @@ -15,11 +15,12 @@ public static class Aggregator var timeUntilNextHour = nextRoundedHour - currentDateTime; // Output the current and next rounded hour times + Console.WriteLine("------------------------------------------HourlyDataAggregationManager-------------------------------------------"); Console.WriteLine("Current Date and Time: " + currentDateTime); Console.WriteLine("Next Rounded Hour: " + nextRoundedHour); - // Output the time until the next rounded hour Console.WriteLine("Waiting for " + timeUntilNextHour.TotalMinutes + " minutes..."); + Console.WriteLine("-----------------------------------------------------------------------------------------------------------------"); // Wait until the next rounded hour await Task.Delay(timeUntilNextHour); @@ -28,7 +29,8 @@ public static class Aggregator { try { - CreateHourlyAverage(); + AggregatedData hourlyAggregatedData=CreateAverage("LogDirectory",DateTime.Now.AddHours(-1).ToUnixTime(),DateTime.Now.ToUnixTime()); + hourlyAggregatedData.Save("HourlyData"); } catch (Exception e) { @@ -38,22 +40,50 @@ public static class Aggregator } } - private static void CreateHourlyAverage() + public static async Task DailyDataAggregationManager() { - var myDirectory = "LogDirectory"; + var currentDateTime = DateTime.Now; + var nextRoundedHour = currentDateTime.AddDays(1).AddHours(-currentDateTime.Hour).AddMinutes(-currentDateTime.Minute).AddSeconds(-currentDateTime.Second); + // Calculate the time until the next rounded hour + var timeUntilNextDay = nextRoundedHour - currentDateTime; + Console.WriteLine("------------------------------------------DailyDataAggregationManager-------------------------------------------"); + // Output the current and next rounded hour times + Console.WriteLine("Current Date and Time: " + currentDateTime); + Console.WriteLine("Next Rounded Hour: " + nextRoundedHour); + // Output the time until the next rounded hour + Console.WriteLine("Waiting for " + timeUntilNextDay.TotalHours + " hours..."); + Console.WriteLine("-----------------------------------------------------------------------------------------------------------------"); + + + // Wait until the next rounded hour + await Task.Delay(timeUntilNextDay); + + while (true) + { + try + { + AggregatedData dailyAggregatedData=CreateAverage("HourlyData",DateTime.Now.AddDays(-1).ToUnixTime(),DateTime.Now.ToUnixTime()); + dailyAggregatedData.Save("DailyData"); + } + catch (Exception e) + { + Console.WriteLine("An error has occured when calculating daily aggregated data, exception is:\n" + e); + } + await Task.Delay(TimeSpan.FromHours(1)); + } + } + + private static AggregatedData CreateAverage(string myDirectory,long afterTimestamp,long beforeTimestamp) + { // Get all CSV files in the specified directory var csvFiles = Directory.GetFiles(myDirectory, "*.csv"); - - var currentTimestamp = DateTime.Now.ToUnixTime(); - var oneHourBefore = DateTime.Now.AddHours(-1).ToUnixTime(); - var socAverage = new List(); var pvPowerAverage = new List(); var batteryPowerAverage = new List(); Console.WriteLine("-----------------------------------------------------------------------------------------------------------------"); - Console.WriteLine("File timestamp should start after "+ DateTime.Now.AddHours(-1)); + Console.WriteLine("File timestamp should start after "+ afterTimestamp); foreach (var csvFile in csvFiles) { @@ -62,7 +92,7 @@ public static class Aggregator continue; } - if (IsFileWithinTimeRange(csvFile, oneHourBefore, currentTimestamp)) + if (IsFileWithinTimeRange(csvFile, afterTimestamp, beforeTimestamp)) { using var reader = new StreamReader(csvFile); @@ -71,6 +101,7 @@ public static class Aggregator var line = reader.ReadLine(); var lines = line?.Split(';'); + // Assuming there are always three columns (variable name and its value) if (lines is { Length: 3 }) @@ -81,18 +112,15 @@ public static class Aggregator { switch (variableName) { - case var _ when GetVariable(variableName,"/Battery/Soc"): - // Code to execute when variableName matches IsSoc condition + case var _ when variableName is "/Battery/Soc" or "/AvgSoc" : socAverage.Add(value); break; - case var _ when GetVariable(variableName, "/PvOnDc/Dc/Power"): - // Code to execute when variableName matches IsPvPower condition + case var _ when variableName is "/PvOnDc/Dc/Power" or "/AvgPvPower": pvPowerAverage.Add(value); break; - case var _ when GetVariable(variableName, "/Battery/Dc/Power"): - // Code to execute when variableName matches IsBatteryPower condition + case var _ when variableName is "/Battery/Dc/Power" or "/BatteryPowerAverage": batteryPowerAverage.Add(value); break; @@ -105,37 +133,38 @@ public static class Aggregator } else { - // Handle cases where variableValue is not a valid number - Console.WriteLine( - $"Invalid numeric value for variable {variableName}:{lines[1].Trim()}"); + //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"); + //Console.WriteLine("Invalid format in column"); } } } } - - // Calculate the average of values - var avgSoc = socAverage.Any() ? socAverage.Average() : 0.0; - var avgPvPower = pvPowerAverage.Any() ? pvPowerAverage.Average() : 0.0; - var avgBatteryPower = batteryPowerAverage.Any() ? batteryPowerAverage.Average() : 0.0; - + + AggregatedData aggregatedData = new AggregatedData + { + AvgSoc = socAverage.Any() ? socAverage.Average() : 0.0, + AvgPvPower = pvPowerAverage.Any() ? pvPowerAverage.Average() : 0.0, + BatteryPowerAverage = batteryPowerAverage.Any() ? batteryPowerAverage.Average() : 0.0 + }; + // Print the stored CSV data for verification - - Console.WriteLine($"SOC: {avgSoc}"); - Console.WriteLine($"PvPower: {avgPvPower}"); - Console.WriteLine($"Battery: {avgBatteryPower}"); - + Console.WriteLine($"SOC: {aggregatedData.AvgSoc}"); + Console.WriteLine($"PvPower: {aggregatedData.AvgPvPower}"); + Console.WriteLine($"Battery: {aggregatedData.BatteryPowerAverage}"); Console.WriteLine("CSV data reading and storage completed."); - //Create a new file to folder "Hourly Aggregated Data and push it to S3" Console.WriteLine("-----------------------------------------------------------------------------------------------------------------"); - + + return aggregatedData; } - + + // Custom method to check if a string is numeric private static Boolean GetVariable(String value, String path) { diff --git a/csharp/App/SaliMax/src/AggregationService/HourlyData.cs b/csharp/App/SaliMax/src/AggregationService/HourlyData.cs index a47db1c74..447159d30 100644 --- a/csharp/App/SaliMax/src/AggregationService/HourlyData.cs +++ b/csharp/App/SaliMax/src/AggregationService/HourlyData.cs @@ -1,5 +1,6 @@ using System.Text.Json; using InnovEnergy.App.SaliMax.Devices; +using InnovEnergy.Lib.Units; using InnovEnergy.Lib.Utils; using static System.Text.Json.JsonSerializer; @@ -7,49 +8,31 @@ namespace InnovEnergy.App.SaliMax.AggregationService; // shut up trim warnings #pragma warning disable IL2026 -public class HourlyData //TODO: let IE choose from config files (Json) and connect to GUI +public class AggregatedData { - private static String DefaultHDataPath => Path.Combine(Environment.CurrentDirectory, "HourlyData/config.json"); - private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true }; - public required Double MinSoc { get; set; } - public required Double MaxChargeBatteryVoltage { get; set; } - public required Double MinDischargeBatteryVoltage { get; set; } - private static String? LastSavedData { get; set; } - - #if DEBUG - public static HourlyData Default => new() - { - MinSoc = 20, - MaxChargeBatteryVoltage = 0, - MinDischargeBatteryVoltage = 0 - - }; - #else - public static HourlyData Default => new() - { - MinSoc = 20, - MaxChargeBatteryVoltage = 0, - MinDischargeBatteryVoltage = 0 + public required Double AvgSoc { get; set; } + public required Double AvgPvPower { get; set; } + public required Double BatteryPowerAverage { get; set; } - }; - #endif - - public void Save(String? path = null) + public void Save(String directory) { - var dataFilePath = path ?? DefaultHDataPath; + var date = DateTime.Now.ToUnixTime(); + var defaultHDataPath = Environment.CurrentDirectory + "/"+directory+"/"; + var dataFilePath = defaultHDataPath+date+".csv"; + + if (!Directory.Exists(defaultHDataPath)) + { + Directory.CreateDirectory(defaultHDataPath); + Console.WriteLine("Directory created successfully."); + } + Console.WriteLine("data file path is "+dataFilePath); try { - var jsonString = Serialize(this, JsonOptions); - - if (LastSavedData == jsonString) - return; - - LastSavedData = jsonString; - - File.WriteAllText(dataFilePath, jsonString); + var csvString = Units.ToCsv(this); + File.WriteAllText(dataFilePath, csvString); } catch (Exception e) { @@ -58,35 +41,18 @@ public class HourlyData //TODO: let IE choose from config files (Json) and conne } } - public static HourlyData Load(String? path = null) - { - var dataFilePath = path ?? DefaultHDataPath; - try - { - var jsonString = File.ReadAllText(dataFilePath); - return Deserialize(jsonString)!; - } - catch (Exception e) - { - $"Failed to read config file {dataFilePath}, using default config\n{e}".WriteLine(); - return Default; - } - } + // public static HourlyData? Load(String dataFilePath) + // { + // try + // { + // var csvString = File.ReadAllText(dataFilePath); + // return Deserialize(jsonString)!; + // } + // catch (Exception e) + // { + // $"Failed to read config file {dataFilePath}, using default config\n{e}".WriteLine(); + // return null; + // } + // } - - public static async Task LoadAsync(String? path = null) - { - var dataFilePath = path ?? DefaultHDataPath; - try - { - var jsonString = await File.ReadAllTextAsync(dataFilePath); - return Deserialize(jsonString)!; - } - catch (Exception e) - { - Console.WriteLine($"Couldn't read config file {dataFilePath}, using default config"); - e.Message.WriteLine(); - return Default; - } - } } \ No newline at end of file diff --git a/csharp/App/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs index 513e07140..611f8d8e8 100644 --- a/csharp/App/SaliMax/src/Program.cs +++ b/csharp/App/SaliMax/src/Program.cs @@ -82,6 +82,7 @@ internal static class Program { //Do not await Aggregator.HourlyDataAggregationManager().ContinueWith(t=>t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted).SupressAwaitWarning(); + Aggregator.DailyDataAggregationManager().ContinueWith(t=>t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted).SupressAwaitWarning(); MiddlewareAgent.InitializeCommunicationToMiddleware(); while (true) {