Update SodistoreMax code.
Fixed the product to value 3 when sending heartbits. Deleted prints during aggregation Updated backend code to support SodistoreMax
This commit is contained in:
parent
31c06e2815
commit
cf9c96377f
|
|
@ -193,7 +193,8 @@ public class Controller : ControllerBase
|
||||||
|
|
||||||
while (startTimestamp <= endTimestamp)
|
while (startTimestamp <= endTimestamp)
|
||||||
{
|
{
|
||||||
string bucketPath = installation.Product==(int)ProductType.Salimax? "s3://"+installation.S3BucketId + "-3e5b3069-214a-43ee-8d85-57d72000c19d/"+startTimestamp :
|
string bucketPath = installation.Product==(int)ProductType.Salimax || installation.Product==(int)ProductType.SodiStoreMax?
|
||||||
|
"s3://"+installation.S3BucketId + "-3e5b3069-214a-43ee-8d85-57d72000c19d/"+startTimestamp :
|
||||||
"s3://"+installation.S3BucketId + "-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e/"+startTimestamp;
|
"s3://"+installation.S3BucketId + "-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e/"+startTimestamp;
|
||||||
Console.WriteLine("Fetching data for "+startTimestamp);
|
Console.WriteLine("Fetching data for "+startTimestamp);
|
||||||
|
|
||||||
|
|
@ -442,6 +443,20 @@ public class Controller : ControllerBase
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[HttpGet(nameof(GetAllInstallationsFromProduct))]
|
||||||
|
public ActionResult<IEnumerable<Installation>> GetAllInstallationsFromProduct(int product,Token authToken)
|
||||||
|
{
|
||||||
|
var user = Db.GetSession(authToken)?.User;
|
||||||
|
|
||||||
|
if (user is null)
|
||||||
|
return Unauthorized();
|
||||||
|
|
||||||
|
return user
|
||||||
|
.AccessibleInstallations(product)
|
||||||
|
.Select(i => i.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(user).HideWriteKeyIfUserIsNotAdmin(user.UserType))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet(nameof(GetAllInstallations))]
|
[HttpGet(nameof(GetAllInstallations))]
|
||||||
public ActionResult<IEnumerable<Installation>> GetAllInstallations(Token authToken)
|
public ActionResult<IEnumerable<Installation>> GetAllInstallations(Token authToken)
|
||||||
{
|
{
|
||||||
|
|
@ -451,9 +466,8 @@ public class Controller : ControllerBase
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
|
|
||||||
return user
|
return user
|
||||||
.AccessibleInstallations(product:(int)ProductType.Salimax)
|
.AccessibleInstallations(product:(int)ProductType.Salimax)
|
||||||
.Select(i => i.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(user).HideWriteKeyIfUserIsNotAdmin(user.UserType))
|
.ToList();
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet(nameof(GetAllSalidomoInstallations))]
|
[HttpGet(nameof(GetAllSalidomoInstallations))]
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ public enum ProductType
|
||||||
{
|
{
|
||||||
Salimax = 0,
|
Salimax = 0,
|
||||||
Salidomo = 1,
|
Salidomo = 1,
|
||||||
SodioHome =2
|
SodioHome =2,
|
||||||
|
SodiStoreMax=3
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum StatusType
|
public enum StatusType
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ public static class Program
|
||||||
RabbitMqManager.StartRabbitMqConsumer().SupressAwaitWarning();
|
RabbitMqManager.StartRabbitMqConsumer().SupressAwaitWarning();
|
||||||
WebsocketManager.MonitorSalimaxInstallationTable().SupressAwaitWarning();
|
WebsocketManager.MonitorSalimaxInstallationTable().SupressAwaitWarning();
|
||||||
WebsocketManager.MonitorSalidomoInstallationTable().SupressAwaitWarning();
|
WebsocketManager.MonitorSalidomoInstallationTable().SupressAwaitWarning();
|
||||||
|
WebsocketManager.MonitorSodistoreInstallationTable().SupressAwaitWarning();
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
builder.Services.AddProblemDetails(setup =>
|
builder.Services.AddProblemDetails(setup =>
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,39 @@ public static class WebsocketManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Every 1 minute, check the timestamp of the latest received message for every installation.
|
||||||
|
//If the difference between the two timestamps is more than two minutes, we consider this Sodistore installation unavailable.
|
||||||
|
public static async Task MonitorSodistoreInstallationTable()
|
||||||
|
{
|
||||||
|
while (true){
|
||||||
|
Console.WriteLine("TRY TO LOCK FOR MONITOR SODISTORE INSTALLATIONS\n");
|
||||||
|
lock (InstallationConnections){
|
||||||
|
Console.WriteLine("MONITOR SODISTORE INSTALLATIONS\n");
|
||||||
|
foreach (var installationConnection in InstallationConnections)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (installationConnection.Value.Product==(int)ProductType.SodiStoreMax && (DateTime.Now - installationConnection.Value.Timestamp) > TimeSpan.FromMinutes(2))
|
||||||
|
{
|
||||||
|
|
||||||
|
//Console.WriteLine("installationConnection.Value.Timestamp is "+installationConnection.Value.Timestamp);
|
||||||
|
//Console.WriteLine("timestamp now is is "+(DateTime.Now));
|
||||||
|
|
||||||
|
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == (int)ProductType.SodiStoreMax && f.Id == installationConnection.Key);
|
||||||
|
Console.WriteLine("Installation ID is "+installation.Name + " diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
||||||
|
installation.Status = (int)StatusType.Offline;
|
||||||
|
installation.Apply(Db.Update);
|
||||||
|
|
||||||
|
installationConnection.Value.Status = (int)StatusType.Offline;
|
||||||
|
if (installationConnection.Value.Connections.Count > 0){InformWebsocketsForInstallation(installationConnection.Key);}
|
||||||
|
else{Console.WriteLine("NONE IS CONNECTED TO THAT INSTALLATION-------------------------------------------------------------");}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Console.WriteLine("FINISHED WITH UPDATING\n");
|
||||||
|
}
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Inform all the connected websockets regarding installation "installationId"
|
//Inform all the connected websockets regarding installation "installationId"
|
||||||
public static void InformWebsocketsForInstallation(Int64 installationId)
|
public static void InformWebsocketsForInstallation(Int64 installationId)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ public static class Aggregator
|
||||||
dailyAggregatedData.Save("DailyData");
|
dailyAggregatedData.Save("DailyData");
|
||||||
if (await dailyAggregatedData.PushToS3())
|
if (await dailyAggregatedData.PushToS3())
|
||||||
{
|
{
|
||||||
//DeleteHourlyData("HourlyData",currentTime.ToUnixTime());
|
DeleteHourlyData("HourlyData",currentTime.ToUnixTime());
|
||||||
//AggregatedData.DeleteDailyData("DailyData");
|
//AggregatedData.DeleteDailyData("DailyData");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,13 +86,13 @@ public static class Aggregator
|
||||||
private static void DeleteHourlyData(String myDirectory, Int64 beforeTimestamp)
|
private static void DeleteHourlyData(String myDirectory, Int64 beforeTimestamp)
|
||||||
{
|
{
|
||||||
var jsonFiles = Directory.GetFiles(myDirectory, "*.json");
|
var jsonFiles = Directory.GetFiles(myDirectory, "*.json");
|
||||||
Console.WriteLine("Delete data before"+beforeTimestamp);
|
//Console.WriteLine("Delete data before"+beforeTimestamp);
|
||||||
foreach (var jsonFile in jsonFiles)
|
foreach (var jsonFile in jsonFiles)
|
||||||
{
|
{
|
||||||
if (IsFileWithinTimeRange(jsonFile, 0, beforeTimestamp))
|
if (IsFileWithinTimeRange(jsonFile, 0, beforeTimestamp))
|
||||||
{
|
{
|
||||||
File.Delete(jsonFile);
|
File.Delete(jsonFile);
|
||||||
Console.WriteLine($"Deleted hourly data file: {jsonFile}");
|
//Console.WriteLine($"Deleted hourly data file: {jsonFile}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -103,15 +103,11 @@ public static class Aggregator
|
||||||
var jsonFiles = Directory.GetFiles(myDirectory, "*.json");
|
var jsonFiles = Directory.GetFiles(myDirectory, "*.json");
|
||||||
var batterySoc = new List<Double>();
|
var batterySoc = new List<Double>();
|
||||||
var pvPowerSum = new List<Double>();
|
var pvPowerSum = new List<Double>();
|
||||||
var heatingPower = new List<Double>();
|
|
||||||
var gridPowerImport = new List<Double>();
|
var gridPowerImport = new List<Double>();
|
||||||
var gridPowerExport = new List<Double>();
|
var gridPowerExport = new List<Double>();
|
||||||
var batteryDischargePower = new List<Double>();
|
var batteryDischargePower = new List<Double>();
|
||||||
var batteryChargePower = new List<Double>();
|
var batteryChargePower = new List<Double>();
|
||||||
|
|
||||||
|
|
||||||
Console.WriteLine("File timestamp should start after "+ afterTimestamp);
|
|
||||||
|
|
||||||
foreach (var jsonFile in jsonFiles)
|
foreach (var jsonFile in jsonFiles)
|
||||||
{
|
{
|
||||||
if (jsonFile == "JsonLogDirectory/log.json")
|
if (jsonFile == "JsonLogDirectory/log.json")
|
||||||
|
|
@ -136,7 +132,6 @@ public static class Aggregator
|
||||||
|
|
||||||
var jsonObject = JObject.Parse(jsonData);
|
var jsonObject = JObject.Parse(jsonData);
|
||||||
|
|
||||||
//Console.WriteLine(jsonObject);
|
|
||||||
if (jsonObject["Battery"] != null && jsonObject["Battery"]["Soc"] != null)
|
if (jsonObject["Battery"] != null && jsonObject["Battery"]["Soc"] != null)
|
||||||
{
|
{
|
||||||
batterySoc.Add((double)jsonObject["Battery"]["Soc"]);
|
batterySoc.Add((double)jsonObject["Battery"]["Soc"]);
|
||||||
|
|
@ -155,12 +150,10 @@ public static class Aggregator
|
||||||
}
|
}
|
||||||
if (jsonObject["GridMeter"] != null && jsonObject["GridMeter"]["ActivePowerExportT3"] != null)
|
if (jsonObject["GridMeter"] != null && jsonObject["GridMeter"]["ActivePowerExportT3"] != null)
|
||||||
{
|
{
|
||||||
Console.WriteLine("power export is "+jsonObject["GridMeter"]["ActivePowerExportT3"]);
|
|
||||||
gridPowerExport.Add((double)jsonObject["GridMeter"]["ActivePowerExportT3"]);
|
gridPowerExport.Add((double)jsonObject["GridMeter"]["ActivePowerExportT3"]);
|
||||||
}
|
}
|
||||||
if (jsonObject["GridMeter"] != null && jsonObject["GridMeter"]["ActivePowerImportT3"] != null)
|
if (jsonObject["GridMeter"] != null && jsonObject["GridMeter"]["ActivePowerImportT3"] != null)
|
||||||
{
|
{
|
||||||
Console.WriteLine("power import is "+jsonObject["GridMeter"]["ActivePowerImportT3"]);
|
|
||||||
gridPowerImport.Add((double)jsonObject["GridMeter"]["ActivePowerImportT3"]);
|
gridPowerImport.Add((double)jsonObject["GridMeter"]["ActivePowerImportT3"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -235,10 +228,6 @@ public static class Aggregator
|
||||||
var batteryChargePower = new List<Double>();
|
var batteryChargePower = new List<Double>();
|
||||||
var heatingPowerAvg = new List<Double>();
|
var heatingPowerAvg = new List<Double>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Console.WriteLine("File timestamp should start after "+ afterTimestamp);
|
|
||||||
|
|
||||||
foreach (var jsonFile in jsonFiles)
|
foreach (var jsonFile in jsonFiles)
|
||||||
{
|
{
|
||||||
if (jsonFile == "JsonLogDirectory/log.json")
|
if (jsonFile == "JsonLogDirectory/log.json")
|
||||||
|
|
@ -252,7 +241,6 @@ public static class Aggregator
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var jsonData = File.ReadAllText(jsonFile);
|
var jsonData = File.ReadAllText(jsonFile);
|
||||||
//Console.WriteLine("Parse file "+jsonFile);
|
|
||||||
|
|
||||||
// Parse JSON into a Dictionary
|
// Parse JSON into a Dictionary
|
||||||
var jsonDict = JsonConvert.DeserializeObject<Dictionary<string, Double>>(jsonData);
|
var jsonDict = JsonConvert.DeserializeObject<Dictionary<string, Double>>(jsonData);
|
||||||
|
|
@ -287,13 +275,6 @@ public static class Aggregator
|
||||||
gridPowerImport.Add(value);
|
gridPowerImport.Add(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "HeatingPower":
|
|
||||||
heatingPowerAvg.Add(value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Ignore unknown variables
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -302,70 +283,6 @@ public static class Aggregator
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Failed to parse JSON file {jsonFile}: {e.Message}");
|
Console.WriteLine($"Failed to parse JSON file {jsonFile}: {e.Message}");
|
||||||
}
|
}
|
||||||
// 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 "/MinSoc" or "/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;
|
|
||||||
//
|
|
||||||
// case "/HeatingPower":
|
|
||||||
// heatingPowerAvg.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");
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -278,9 +278,6 @@ internal static class Program
|
||||||
var s3Bucket = Config.Load().S3?.Bucket;
|
var s3Bucket = Config.Load().S3?.Bucket;
|
||||||
var subscribedNow = false;
|
var subscribedNow = false;
|
||||||
|
|
||||||
//Every 15 iterations(30 seconds), the installation sends a heartbit message to the queue
|
|
||||||
//_heartBitInterval++;
|
|
||||||
|
|
||||||
//When the controller boots, it tries to subscribe to the queue
|
//When the controller boots, it tries to subscribe to the queue
|
||||||
if (_subscribeToQueueForTheFirstTime == false)
|
if (_subscribeToQueueForTheFirstTime == false)
|
||||||
{
|
{
|
||||||
|
|
@ -297,16 +294,6 @@ internal static class Program
|
||||||
if (s3Bucket != null)
|
if (s3Bucket != null)
|
||||||
RabbitMqManager.InformMiddleware(currentSalimaxState);
|
RabbitMqManager.InformMiddleware(currentSalimaxState);
|
||||||
}
|
}
|
||||||
// else if (_subscribedToQueue && _heartBitInterval >= 30)
|
|
||||||
// {
|
|
||||||
// //Send a heartbit to the backend
|
|
||||||
// Console.WriteLine("----------------------------------------Sending Heartbit----------------------------------------");
|
|
||||||
// _heartBitInterval = 0;
|
|
||||||
// currentSalimaxState.Type = MessageType.Heartbit;
|
|
||||||
//
|
|
||||||
// if (s3Bucket != null)
|
|
||||||
// RabbitMqManager.InformMiddleware(currentSalimaxState);
|
|
||||||
// }
|
|
||||||
|
|
||||||
//If there is an available message from the RabbitMQ Broker, apply the configuration file
|
//If there is an available message from the RabbitMQ Broker, apply the configuration file
|
||||||
Configuration? config = SetConfigurationFile();
|
Configuration? config = SetConfigurationFile();
|
||||||
|
|
@ -498,7 +485,7 @@ internal static class Program
|
||||||
var returnedStatus = new StatusMessage
|
var returnedStatus = new StatusMessage
|
||||||
{
|
{
|
||||||
InstallationId = installationId,
|
InstallationId = installationId,
|
||||||
Product = 0,
|
Product = 3,
|
||||||
Status = _salimaxAlarmState,
|
Status = _salimaxAlarmState,
|
||||||
Type = MessageType.AlarmOrWarning,
|
Type = MessageType.AlarmOrWarning,
|
||||||
Alarms = alarmList,
|
Alarms = alarmList,
|
||||||
|
|
@ -845,6 +832,16 @@ internal static class Program
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// var values = value.Split(','); //in case it is a list
|
||||||
|
// Console.WriteLine("len is ",values.Length);
|
||||||
|
// if (values.Length > 4)
|
||||||
|
// {
|
||||||
|
// foreach (var val in values)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine("value from list is ", val);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
currentDict[key] = value; // Store as string if not a number
|
currentDict[key] = value; // Store as string if not a number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -944,7 +941,7 @@ internal static class Program
|
||||||
var returnedStatus = new StatusMessage
|
var returnedStatus = new StatusMessage
|
||||||
{
|
{
|
||||||
InstallationId = installationId,
|
InstallationId = installationId,
|
||||||
Product = 0, // Salimax is always 0
|
Product = 3, // Salimax is always 0
|
||||||
Status = _salimaxAlarmState,
|
Status = _salimaxAlarmState,
|
||||||
Type = MessageType.Heartbit,
|
Type = MessageType.Heartbit,
|
||||||
Timestamp = nameOfJsonFile
|
Timestamp = nameOfJsonFile
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue