Add Hourly-Data-Aggregation function
This commit is contained in:
parent
69602e6bd6
commit
7bc70f49f6
|
@ -92,12 +92,13 @@ internal static class Program
|
|||
|
||||
public static async Task Main(String[] args)
|
||||
{
|
||||
//Do not await
|
||||
HourlyDataAggregationManager();
|
||||
InitializeCommunicationToMiddleware();
|
||||
while (true)
|
||||
{
|
||||
//CreateAverage();
|
||||
try
|
||||
{
|
||||
InitializeCommunicationToMiddleware();
|
||||
await Run();
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -105,7 +106,6 @@ internal static class Program
|
|||
e.LogError();
|
||||
}
|
||||
}
|
||||
// ReSharper disable once FunctionNeverReturns
|
||||
}
|
||||
|
||||
private static void InitializeCommunicationToMiddleware()
|
||||
|
@ -636,82 +636,124 @@ internal static class Program
|
|||
return true;
|
||||
}
|
||||
|
||||
private static void CreateAverage()
|
||||
|
||||
private static async Task HourlyDataAggregationManager()
|
||||
{
|
||||
string myDirectory = "LogDirectoryNew";
|
||||
List<Dictionary<string, string>> csvDataList = new List<Dictionary<string, string>>();
|
||||
DateTime currentDateTime = DateTime.Now;
|
||||
DateTime nextRoundedHour = currentDateTime.AddHours(1).AddMinutes(-currentDateTime.Minute).AddSeconds(-currentDateTime.Second);
|
||||
|
||||
// Calculate the time until the next rounded hour
|
||||
TimeSpan timeUntilNextHour = nextRoundedHour - currentDateTime;
|
||||
|
||||
// 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 " + timeUntilNextHour.TotalMinutes + " minutes...");
|
||||
|
||||
// Wait until the next rounded hour
|
||||
await Task.Delay(timeUntilNextHour);
|
||||
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
CreateHourlyAverage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("An error has occured when calculating hourly aggregated data, exception is:\n" + e);
|
||||
}
|
||||
await Task.Delay(TimeSpan.FromHours(1));
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateHourlyAverage()
|
||||
{
|
||||
string myDirectory = "LogDirectory";
|
||||
|
||||
// Get all CSV files in the specified directory
|
||||
string[] csvFiles = Directory.GetFiles(myDirectory, "*.csv");
|
||||
|
||||
List<Double> socList = new List<Double>();
|
||||
List<Double> pvPowerList = new List<Double>();
|
||||
List<Double> batteryPowerList = new List<Double>();
|
||||
|
||||
Int64 currentTimestamp = DateTime.Now.ToUnixTime();
|
||||
Double socAverage=0;
|
||||
Double pvPowerAverage=0;
|
||||
Double batteryPowerAverage=0;
|
||||
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------");
|
||||
Console.WriteLine("File timestamp should start after "+DateTime.Now.AddHours(-1));
|
||||
foreach (var csvFile in csvFiles)
|
||||
{
|
||||
using (var reader = new StreamReader(csvFile))
|
||||
|
||||
if (csvFile == "LogDirectory/log.csv")
|
||||
{
|
||||
// Read the CSV file and store data in dictionary
|
||||
Dictionary<string, string> csvData = new Dictionary<string, string>();
|
||||
continue;
|
||||
}
|
||||
Int64 fileTimestamp = Int64.Parse(Path.GetFileNameWithoutExtension(csvFile).Replace("log_", ""));
|
||||
Int64 oneHourBefore = DateTime.Now.AddHours(-1).ToUnixTime();
|
||||
|
||||
while (!reader.EndOfStream)
|
||||
|
||||
if (fileTimestamp >= oneHourBefore && fileTimestamp <= currentTimestamp)
|
||||
{
|
||||
Console.WriteLine("Check file created at "+DateTimeOffset.FromUnixTimeSeconds(fileTimestamp).DateTime);
|
||||
using (var reader = new StreamReader(csvFile))
|
||||
{
|
||||
var line = reader.ReadLine();
|
||||
var values = line?.Split(';');
|
||||
|
||||
// Assuming there are always three columns (variable name and its value)
|
||||
if (values is { Length: 3 })
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
String variableName = values[0].Trim();
|
||||
String variableValue = values[1].Trim();
|
||||
var line = reader.ReadLine();
|
||||
var values = line?.Split(';');
|
||||
|
||||
// Check if variableValue is a valid number
|
||||
if (IsSoc(variableName))
|
||||
// Assuming there are always three columns (variable name and its value)
|
||||
if (values is { Length: 3 })
|
||||
{
|
||||
// Add to the dictionary only if variableValue is a number
|
||||
socList.Add(double.TryParse(variableValue, out double v)? v: 0);
|
||||
}
|
||||
if (IsPvPower(variableName))
|
||||
{
|
||||
// Add to the dictionary only if variableValue is a number
|
||||
pvPowerList.Add(double.TryParse(variableValue, out double v)? v: 0);
|
||||
}
|
||||
if (IsBatteryPower(variableName))
|
||||
{
|
||||
// Add to the dictionary only if variableValue is a number
|
||||
batteryPowerList.Add(double.TryParse(variableValue, out double v)? v: 0);
|
||||
String variableName = values[0].Trim();
|
||||
String variableValue = values[1].Trim();
|
||||
|
||||
// Check if variableValue is a valid number
|
||||
if (IsSoc(variableName))
|
||||
{
|
||||
if (socAverage == 0){socAverage = double.TryParse(variableValue, out double v) ? v : 0;}
|
||||
else{socAverage = (socAverage + (double.TryParse(variableValue, out double v) ? v : 0)) / 2;}
|
||||
}
|
||||
|
||||
if (IsPvPower(variableName))
|
||||
{
|
||||
if (pvPowerAverage == 0){pvPowerAverage = double.TryParse(variableValue, out double v) ? v : 0;}
|
||||
else{pvPowerAverage = (pvPowerAverage + (double.TryParse(variableValue, out double v) ? v : 0)) / 2;}
|
||||
}
|
||||
|
||||
if (IsBatteryPower(variableName))
|
||||
{
|
||||
if (batteryPowerAverage == 0){batteryPowerAverage = double.TryParse(variableValue, out double v) ? v : 0;}
|
||||
else{batteryPowerAverage = (batteryPowerAverage + (double.TryParse(variableValue, out double v) ? v : 0)) / 2;}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle cases where variableValue is not a valid number
|
||||
// Console.WriteLine($"Invalid numeric value for variable {variableName}: {variableValue}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle cases where variableValue is not a valid number
|
||||
// Console.WriteLine($"Invalid numeric value for variable {variableName}: {variableValue}");
|
||||
// Handle invalid CSV format
|
||||
//Console.WriteLine($"Invalid format in file: {csvFile}");
|
||||
//break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle invalid CSV format
|
||||
//Console.WriteLine($"Invalid format in file: {csvFile}");
|
||||
//break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double socAverage = CalculateAverage(socList);
|
||||
double pvPowerAverage = CalculateAverage(pvPowerList);
|
||||
double batteryPowerAverage = CalculateAverage(batteryPowerList);
|
||||
|
||||
// Print the stored CSV data for verification
|
||||
|
||||
Console.WriteLine($"SOC: {socAverage}");
|
||||
Console.WriteLine($"PvPower: {pvPowerAverage}");
|
||||
Console.WriteLine($"Battery: {batteryPowerAverage}");
|
||||
|
||||
Console.WriteLine("----------");
|
||||
|
||||
Console.WriteLine("CSV data reading and storage completed.");
|
||||
//Create a new file to folder "Hourly Aggregated Data and push it to S3"
|
||||
Console.WriteLine("-----------------------------------------------------------------------------------------------------------------");
|
||||
|
||||
}
|
||||
|
||||
// Custom method to check if a string is numeric
|
||||
|
@ -737,11 +779,4 @@ internal static class Program
|
|||
status.Config.ForceCalibrationCharge = config.ForceCalibrationCharge;
|
||||
}
|
||||
|
||||
// Method to calculate average for a variableValue in a dictionary
|
||||
static double CalculateAverage( List<Double> data)
|
||||
{
|
||||
// Calculate and return the moving average
|
||||
double movingAverage = data.Average();
|
||||
return movingAverage;
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ export const getChartOptions = (chartInfo: chartInfoInterface): ApexOptions => {
|
|||
// Return the formatted date and time based on the provided options
|
||||
return ` ${hour}:${minute}`;
|
||||
};
|
||||
|
||||
const chartOptions: ApexOptions = {
|
||||
chart: {
|
||||
id: 'area-datetime',
|
||||
|
|
|
@ -25,6 +25,7 @@ import { chartDataInterface, overviewInterface } from 'src/interfaces/Chart';
|
|||
import { fetchData } from 'src/content/dashboards/Installations/fetchData';
|
||||
import Button from '@mui/material/Button';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { ApexOptions } from 'apexcharts';
|
||||
|
||||
const prefixes = ['', 'k', 'M', 'G', 'T'];
|
||||
const MAX_NUMBER = 9999999;
|
||||
|
@ -314,6 +315,80 @@ function Overview(props: OverviewProps) {
|
|||
times$.next(times);
|
||||
};
|
||||
|
||||
const series = [
|
||||
{
|
||||
name: 'Inflation',
|
||||
data: [2.3, 3.1, 4.0, 10.1, 4.0, 3.6, 3.2, 2.3, 1.4, 0.8, 0.5, 0.2]
|
||||
}
|
||||
];
|
||||
|
||||
const state: ApexOptions = {
|
||||
chart: {
|
||||
height: 350,
|
||||
type: 'bar'
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
borderRadius: 10,
|
||||
dataLabels: {
|
||||
position: 'top' // top, center, bottom
|
||||
}
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter: function (val) {
|
||||
return val + '%';
|
||||
},
|
||||
offsetY: -20,
|
||||
style: {
|
||||
fontSize: '12px',
|
||||
colors: ['#304758']
|
||||
}
|
||||
},
|
||||
|
||||
xaxis: {
|
||||
categories: [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec'
|
||||
],
|
||||
position: 'bottom',
|
||||
axisBorder: {
|
||||
show: false
|
||||
},
|
||||
axisTicks: {
|
||||
show: false
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
axisBorder: {
|
||||
show: false
|
||||
},
|
||||
axisTicks: {
|
||||
show: false
|
||||
},
|
||||
labels: {
|
||||
show: false,
|
||||
formatter: function (val) {
|
||||
return val + '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const renderGraphs = () => {
|
||||
return (
|
||||
<Container maxWidth="xl">
|
||||
|
@ -399,19 +474,27 @@ function Overview(props: OverviewProps) {
|
|||
}}
|
||||
></Box>
|
||||
</Box>
|
||||
|
||||
<ReactApexChart
|
||||
options={{
|
||||
...getChartOptions(chartOverview.soc),
|
||||
chart: {
|
||||
events: {
|
||||
beforeZoom: handleBeforeZoom
|
||||
}
|
||||
}
|
||||
}}
|
||||
series={chartData.soc}
|
||||
type="area"
|
||||
options={state}
|
||||
series={series}
|
||||
type="bar"
|
||||
height={350}
|
||||
/>
|
||||
|
||||
{/*<ReactApexChart*/}
|
||||
{/* options={{*/}
|
||||
{/* ...getChartOptions(chartOverview.soc),*/}
|
||||
{/* chart: {*/}
|
||||
{/* events: {*/}
|
||||
{/* beforeZoom: handleBeforeZoom*/}
|
||||
{/* }*/}
|
||||
{/* }*/}
|
||||
{/* }}*/}
|
||||
{/* series={chartData.soc}*/}
|
||||
{/* type="area"*/}
|
||||
{/* height={350}*/}
|
||||
{/*/>*/}
|
||||
</Card>
|
||||
</Grid>
|
||||
<Grid item md={6} xs={12}>
|
||||
|
|
Loading…
Reference in New Issue