Innovenergy_trunk/csharp/App/SodiStoreMax/src/AggregationService/Aggregator.cs

334 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using InnovEnergy.App.SodiStoreMax.Ess;
using InnovEnergy.Lib.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using static System.Double;
namespace InnovEnergy.App.SodiStoreMax.AggregationService;
public static class Aggregator
{
public static async Task HourlyDataAggregationManager()
{
var currentDateTime = DateTime.Now;
var nextRoundedHour = currentDateTime.AddHours(1).AddMinutes(-currentDateTime.Minute).AddSeconds(-currentDateTime.Second);
// Calculate the time until the next rounded hour
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);
while (true)
{
try
{
AggregatedData hourlyAggregatedData = CreateHourlyData("JsonLogDirectory",DateTime.Now.AddHours(-1).ToUnixTime(),DateTime.Now.ToUnixTime());
hourlyAggregatedData.Save("HourlyData");
}
catch (Exception e)
{
Console.WriteLine("An error has occured when calculating hourly aggregated data, exception is:\n" + e);
}
await Task.Delay(TimeSpan.FromHours(1));
}
}
public static async Task DailyDataAggregationManager()
{
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
{
var currentTime = DateTime.Now;
AggregatedData dailyAggregatedData = CreateDailyData("HourlyData",currentTime.AddDays(-1).ToUnixTime(),currentTime.ToUnixTime());
dailyAggregatedData.Save("DailyData");
if (await dailyAggregatedData.PushToS3())
{
DeleteHourlyData("HourlyData",currentTime.ToUnixTime());
//AggregatedData.DeleteDailyData("DailyData");
}
}
catch (Exception e)
{
Console.WriteLine("An error has occured when calculating daily aggregated data, exception is:\n" + e);
}
await Task.Delay(TimeSpan.FromDays(1));
}
}
private static void DeleteHourlyData(String myDirectory, Int64 beforeTimestamp)
{
var jsonFiles = Directory.GetFiles(myDirectory, "*.json");
//Console.WriteLine("Delete data before"+beforeTimestamp);
foreach (var jsonFile in jsonFiles)
{
if (IsFileWithinTimeRange(jsonFile, 0, beforeTimestamp))
{
File.Delete(jsonFile);
//Console.WriteLine($"Deleted hourly data file: {jsonFile}");
}
}
}
private static AggregatedData CreateHourlyData(String myDirectory, Int64 afterTimestamp, Int64 beforeTimestamp)
{
// Get all json files in the specified directory
var jsonFiles = Directory.GetFiles(myDirectory, "*.json");
var batterySoc = new List<Double>();
var pvPowerSum = new List<Double>();
var gridPowerImport = new List<Double>();
var gridPowerExport = new List<Double>();
var batteryDischargePower = new List<Double>();
var batteryChargePower = new List<Double>();
foreach (var jsonFile in jsonFiles)
{
if (jsonFile == "JsonLogDirectory/log.json")
{
continue;
}
if (IsFileWithinTimeRange(jsonFile, afterTimestamp, beforeTimestamp))
{
try
{
// Read and parse JSON
var jsonData = File.ReadAllText(jsonFile);
// Step 2: Find the first '{' character and trim everything before it
int startIndex = jsonData.IndexOf('{');
if (startIndex != -1)
{
jsonData = jsonData.Substring(startIndex); // Trim everything before '{'
}
var jsonObject = JObject.Parse(jsonData);
if (jsonObject["Battery"] != null && jsonObject["Battery"]["Soc"] != null)
{
batterySoc.Add((double)jsonObject["Battery"]["Soc"]);
}
if (jsonObject["PvOnDc"] != null && jsonObject["PvOnDc"]["DcWh"] != null)
{
pvPowerSum.Add((double)jsonObject["PvOnDc"]["DcWh"]);
}
if (jsonObject["Battery"] != null && jsonObject["Battery"]["Power"] != null)
{
double batteryPower = (double)jsonObject["Battery"]["Power"];
if (batteryPower < 0)
batteryDischargePower.Add(batteryPower);
else
batteryChargePower.Add(batteryPower);
}
if (jsonObject["GridMeter"] != null && jsonObject["GridMeter"]["ActivePowerExportT3"] != null)
{
gridPowerExport.Add((double)jsonObject["GridMeter"]["ActivePowerExportT3"]);
}
if (jsonObject["GridMeter"] != null && jsonObject["GridMeter"]["ActivePowerImportT3"] != null)
{
gridPowerImport.Add((double)jsonObject["GridMeter"]["ActivePowerImportT3"]);
}
}
catch (Exception e)
{
Console.WriteLine($"Failed to parse JSON file {jsonFile}: {e.Message}");
}
}
}
//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.
//Console.WriteLine("MAX IS "+gridPowerExport.Max());
// Console.WriteLine("MIN IS "+gridPowerExport.Min());
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(): 0.0;
var dSumGridImportPower = gridPowerImport.Any() ? gridPowerImport.Max() - gridPowerImport.Min(): 0.0;
var dSumPvPower = pvPowerSum.Any() ? pvPowerSum.Max() : 0.0;
AggregatedData aggregatedData = new AggregatedData
{
MaxSoc = dMaxSoc,
MinSoc = dMinSoc,
DischargingBatteryPower = dischargingEnergy,
ChargingBatteryPower = chargingEnergy,
GridExportPower = dSumGridExportPower,
GridImportPower = dSumGridImportPower,
PvPower = dSumPvPower,
HeatingPower = 0
};
// Print the stored JSON data for verification
Console.WriteLine($"Max SOC: {aggregatedData.MaxSoc}");
Console.WriteLine($"Min SOC: {aggregatedData.MinSoc}");
Console.WriteLine($"DischargingBatteryBattery: {aggregatedData.DischargingBatteryPower}");
Console.WriteLine($"ChargingBatteryPower: {aggregatedData.ChargingBatteryPower}");
Console.WriteLine($"SumGridExportPower: {aggregatedData.GridExportPower}");
Console.WriteLine($"SumGridImportPower: {aggregatedData.GridImportPower}");
Console.WriteLine($"Min SOC: {aggregatedData.MinSoc}");
Console.WriteLine("JSON data reading and storage completed.");
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------");
return aggregatedData;
}
private static AggregatedData CreateDailyData(String myDirectory, Int64 afterTimestamp, Int64 beforeTimestamp)
{
// Get all JSON files in the specified directory
var jsonFiles = Directory.GetFiles(myDirectory, "*.json");
var batterySoc = new List<Double>();
var pvPower = new List<Double>();
var gridPowerImport = new List<Double>();
var gridPowerExport = new List<Double>();
var batteryDischargePower = new List<Double>();
var batteryChargePower = new List<Double>();
var heatingPowerAvg = new List<Double>();
foreach (var jsonFile in jsonFiles)
{
if (jsonFile == "JsonLogDirectory/log.json")
{
continue;
}
if (IsFileWithinTimeRange(jsonFile, afterTimestamp, beforeTimestamp))
{
try
{
var jsonData = File.ReadAllText(jsonFile);
// Parse JSON into a Dictionary
var jsonDict = JsonConvert.DeserializeObject<Dictionary<string, Double>>(jsonData);
// Process values
foreach (var (variableName, value) in jsonDict)
{
switch (variableName)
{
case "MinSoc":
case "MaxSoc":
batterySoc.Add(value);
break;
case "PvPower":
pvPower.Add(value);
break;
case "DischargingBatteryPower":
batteryDischargePower.Add(value);
break;
case "ChargingBatteryPower":
batteryChargePower.Add(value);
break;
case "GridExportPower":
gridPowerExport.Add(value);
break;
case "GridImportPower":
gridPowerImport.Add(value);
break;
}
}
}
catch (Exception e)
{
Console.WriteLine($"Failed to parse JSON file {jsonFile}: {e.Message}");
}
}
}
AggregatedData aggregatedData = new AggregatedData
{
MaxSoc = batterySoc.Any() ? batterySoc.Max() : 0.0,
MinSoc = batterySoc.Any() ? batterySoc.Min() : 0.0,
DischargingBatteryPower = batteryDischargePower.Any() ? batteryDischargePower.Average(): 0.0,
ChargingBatteryPower = batteryChargePower.Any() ? batteryChargePower.Average() : 0.0,
GridExportPower = gridPowerExport.Any() ? gridPowerExport.Sum() : 0.0,
GridImportPower = gridPowerImport.Any() ? gridPowerImport.Sum() : 0.0,
PvPower = pvPower.Any() ? pvPower.Last() : 0.0,
HeatingPower = heatingPowerAvg.Any() ? heatingPowerAvg.Average() : 0.0,
};
// Print the stored JSON data for verification
Console.WriteLine($"Pv Power: {aggregatedData.PvPower}");
Console.WriteLine($"Heating Power: {aggregatedData.HeatingPower}");
Console.WriteLine($"Max SOC: {aggregatedData.MaxSoc}");
Console.WriteLine($"Min SOC: {aggregatedData.MinSoc}");
Console.WriteLine($"ChargingBatteryPower: {aggregatedData.DischargingBatteryPower}");
Console.WriteLine($"DischargingBatteryBattery: {aggregatedData.ChargingBatteryPower}");
Console.WriteLine($"SumGridExportPower: {aggregatedData.GridExportPower}");
Console.WriteLine($"SumGridImportPower: {aggregatedData.GridImportPower}");
Console.WriteLine("JSON data reading and storage completed.");
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------");
return aggregatedData;
}
// Custom method to check if a string is numeric
private static Boolean GetVariable(String value, String path)
{
return value == path;
}
private static Boolean IsFileWithinTimeRange(string filePath, long startTime, long endTime)
{
var fileTimestamp = long.TryParse(Path.GetFileNameWithoutExtension(filePath).Replace("log_", ""), out var fileTimestamp1) ? fileTimestamp1 : -1;
return fileTimestamp >= startTime && fileTimestamp < endTime;
}
}