Updated aggregation service

This commit is contained in:
Noe 2023-12-15 14:55:23 +01:00
parent bc9b3b95b9
commit b13ff6efbe
3 changed files with 95 additions and 99 deletions

View File

@ -15,11 +15,12 @@ public static class Aggregator
var timeUntilNextHour = nextRoundedHour - currentDateTime; var timeUntilNextHour = nextRoundedHour - currentDateTime;
// Output the current and next rounded hour times // Output the current and next rounded hour times
Console.WriteLine("------------------------------------------HourlyDataAggregationManager-------------------------------------------");
Console.WriteLine("Current Date and Time: " + currentDateTime); Console.WriteLine("Current Date and Time: " + currentDateTime);
Console.WriteLine("Next Rounded Hour: " + nextRoundedHour); Console.WriteLine("Next Rounded Hour: " + nextRoundedHour);
// Output the time until the next rounded hour // Output the time until the next rounded hour
Console.WriteLine("Waiting for " + timeUntilNextHour.TotalMinutes + " minutes..."); Console.WriteLine("Waiting for " + timeUntilNextHour.TotalMinutes + " minutes...");
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------");
// Wait until the next rounded hour // Wait until the next rounded hour
await Task.Delay(timeUntilNextHour); await Task.Delay(timeUntilNextHour);
@ -28,7 +29,8 @@ public static class Aggregator
{ {
try try
{ {
CreateHourlyAverage(); AggregatedData hourlyAggregatedData=CreateAverage("LogDirectory",DateTime.Now.AddHours(-1).ToUnixTime(),DateTime.Now.ToUnixTime());
hourlyAggregatedData.Save("HourlyData");
} }
catch (Exception e) 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 // Get all CSV files in the specified directory
var csvFiles = Directory.GetFiles(myDirectory, "*.csv"); var csvFiles = Directory.GetFiles(myDirectory, "*.csv");
var currentTimestamp = DateTime.Now.ToUnixTime();
var oneHourBefore = DateTime.Now.AddHours(-1).ToUnixTime();
var socAverage = new List<Double>(); var socAverage = new List<Double>();
var pvPowerAverage = new List<Double>(); var pvPowerAverage = new List<Double>();
var batteryPowerAverage = new List<Double>(); var batteryPowerAverage = new List<Double>();
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------"); 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) foreach (var csvFile in csvFiles)
{ {
@ -62,7 +92,7 @@ public static class Aggregator
continue; continue;
} }
if (IsFileWithinTimeRange(csvFile, oneHourBefore, currentTimestamp)) if (IsFileWithinTimeRange(csvFile, afterTimestamp, beforeTimestamp))
{ {
using var reader = new StreamReader(csvFile); using var reader = new StreamReader(csvFile);
@ -72,6 +102,7 @@ public static class Aggregator
var line = reader.ReadLine(); var line = reader.ReadLine();
var lines = line?.Split(';'); var lines = line?.Split(';');
// Assuming there are always three columns (variable name and its value) // Assuming there are always three columns (variable name and its value)
if (lines is { Length: 3 }) if (lines is { Length: 3 })
{ {
@ -81,18 +112,15 @@ public static class Aggregator
{ {
switch (variableName) switch (variableName)
{ {
case var _ when GetVariable(variableName,"/Battery/Soc"): case var _ when variableName is "/Battery/Soc" or "/AvgSoc" :
// Code to execute when variableName matches IsSoc condition
socAverage.Add(value); socAverage.Add(value);
break; break;
case var _ when GetVariable(variableName, "/PvOnDc/Dc/Power"): case var _ when variableName is "/PvOnDc/Dc/Power" or "/AvgPvPower":
// Code to execute when variableName matches IsPvPower condition
pvPowerAverage.Add(value); pvPowerAverage.Add(value);
break; break;
case var _ when GetVariable(variableName, "/Battery/Dc/Power"): case var _ when variableName is "/Battery/Dc/Power" or "/BatteryPowerAverage":
// Code to execute when variableName matches IsBatteryPower condition
batteryPowerAverage.Add(value); batteryPowerAverage.Add(value);
break; break;
@ -105,37 +133,38 @@ public static class Aggregator
} }
else else
{ {
// Handle cases where variableValue is not a valid number //Handle cases where variableValue is not a valid number
Console.WriteLine( // Console.WriteLine(
$"Invalid numeric value for variable {variableName}:{lines[1].Trim()}"); // $"Invalid numeric value for variable {variableName}:{lines[1].Trim()}");
} }
} }
else else
{ {
// Handle invalid column format // Handle invalid column format
Console.WriteLine("Invalid format in column"); //Console.WriteLine("Invalid format in column");
} }
} }
} }
} }
// Calculate the average of values AggregatedData aggregatedData = new AggregatedData
var avgSoc = socAverage.Any() ? socAverage.Average() : 0.0; {
var avgPvPower = pvPowerAverage.Any() ? pvPowerAverage.Average() : 0.0; AvgSoc = socAverage.Any() ? socAverage.Average() : 0.0,
var avgBatteryPower = batteryPowerAverage.Any() ? batteryPowerAverage.Average() : 0.0; AvgPvPower = pvPowerAverage.Any() ? pvPowerAverage.Average() : 0.0,
BatteryPowerAverage = batteryPowerAverage.Any() ? batteryPowerAverage.Average() : 0.0
};
// Print the stored CSV data for verification // Print the stored CSV data for verification
Console.WriteLine($"SOC: {aggregatedData.AvgSoc}");
Console.WriteLine($"SOC: {avgSoc}"); Console.WriteLine($"PvPower: {aggregatedData.AvgPvPower}");
Console.WriteLine($"PvPower: {avgPvPower}"); Console.WriteLine($"Battery: {aggregatedData.BatteryPowerAverage}");
Console.WriteLine($"Battery: {avgBatteryPower}");
Console.WriteLine("CSV data reading and storage completed."); Console.WriteLine("CSV data reading and storage completed.");
//Create a new file to folder "Hourly Aggregated Data and push it to S3"
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------"); Console.WriteLine("-----------------------------------------------------------------------------------------------------------------");
return aggregatedData;
} }
// Custom method to check if a string is numeric // Custom method to check if a string is numeric
private static Boolean GetVariable(String value, String path) private static Boolean GetVariable(String value, String path)
{ {

View File

@ -1,5 +1,6 @@
using System.Text.Json; using System.Text.Json;
using InnovEnergy.App.SaliMax.Devices; using InnovEnergy.App.SaliMax.Devices;
using InnovEnergy.Lib.Units;
using InnovEnergy.Lib.Utils; using InnovEnergy.Lib.Utils;
using static System.Text.Json.JsonSerializer; using static System.Text.Json.JsonSerializer;
@ -7,49 +8,31 @@ namespace InnovEnergy.App.SaliMax.AggregationService;
// shut up trim warnings // shut up trim warnings
#pragma warning disable IL2026 #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 }; private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true };
public required Double MinSoc { get; set; } public required Double AvgSoc { get; set; }
public required Double MaxChargeBatteryVoltage { get; set; } public required Double AvgPvPower { get; set; }
public required Double MinDischargeBatteryVoltage { get; set; } public required Double BatteryPowerAverage { get; set; }
private static String? LastSavedData { get; set; }
#if DEBUG public void Save(String directory)
public static HourlyData Default => new()
{ {
MinSoc = 20, var date = DateTime.Now.ToUnixTime();
MaxChargeBatteryVoltage = 0, var defaultHDataPath = Environment.CurrentDirectory + "/"+directory+"/";
MinDischargeBatteryVoltage = 0 var dataFilePath = defaultHDataPath+date+".csv";
}; if (!Directory.Exists(defaultHDataPath))
#else {
public static HourlyData Default => new() Directory.CreateDirectory(defaultHDataPath);
{ Console.WriteLine("Directory created successfully.");
MinSoc = 20, }
MaxChargeBatteryVoltage = 0, Console.WriteLine("data file path is "+dataFilePath);
MinDischargeBatteryVoltage = 0
};
#endif
public void Save(String? path = null)
{
var dataFilePath = path ?? DefaultHDataPath;
try try
{ {
var jsonString = Serialize(this, JsonOptions); var csvString = Units.ToCsv(this);
File.WriteAllText(dataFilePath, csvString);
if (LastSavedData == jsonString)
return;
LastSavedData = jsonString;
File.WriteAllText(dataFilePath, jsonString);
} }
catch (Exception e) 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) // public static HourlyData? Load(String dataFilePath)
{ // {
var dataFilePath = path ?? DefaultHDataPath; // try
try // {
{ // var csvString = File.ReadAllText(dataFilePath);
var jsonString = File.ReadAllText(dataFilePath); // return Deserialize<HourlyData>(jsonString)!;
return Deserialize<HourlyData>(jsonString)!; // }
} // catch (Exception e)
catch (Exception e) // {
{ // $"Failed to read config file {dataFilePath}, using default config\n{e}".WriteLine();
$"Failed to read config file {dataFilePath}, using default config\n{e}".WriteLine(); // return null;
return Default; // }
} // }
}
public static async Task<HourlyData> LoadAsync(String? path = null)
{
var dataFilePath = path ?? DefaultHDataPath;
try
{
var jsonString = await File.ReadAllTextAsync(dataFilePath);
return Deserialize<HourlyData>(jsonString)!;
}
catch (Exception e)
{
Console.WriteLine($"Couldn't read config file {dataFilePath}, using default config");
e.Message.WriteLine();
return Default;
}
}
} }

View File

@ -82,6 +82,7 @@ internal static class Program
{ {
//Do not await //Do not await
Aggregator.HourlyDataAggregationManager().ContinueWith(t=>t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted).SupressAwaitWarning(); Aggregator.HourlyDataAggregationManager().ContinueWith(t=>t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted).SupressAwaitWarning();
Aggregator.DailyDataAggregationManager().ContinueWith(t=>t.Exception.WriteLine(), TaskContinuationOptions.OnlyOnFaulted).SupressAwaitWarning();
MiddlewareAgent.InitializeCommunicationToMiddleware(); MiddlewareAgent.InitializeCommunicationToMiddleware();
while (true) while (true)
{ {