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:
Noe 2025-04-29 15:08:06 +02:00
parent 31c06e2815
commit cf9c96377f
6 changed files with 77 additions and 114 deletions

View File

@ -193,7 +193,8 @@ public class Controller : ControllerBase
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;
Console.WriteLine("Fetching data for "+startTimestamp);
@ -442,28 +443,41 @@ 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))]
public ActionResult<IEnumerable<Installation>> GetAllInstallations(Token authToken)
{
var user = Db.GetSession(authToken)?.User;
if (user is null)
return Unauthorized();
return user
.AccessibleInstallations(product:(int)ProductType.Salimax)
.Select(i => i.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(user).HideWriteKeyIfUserIsNotAdmin(user.UserType))
.ToList();
.AccessibleInstallations(product:(int)ProductType.Salimax)
.ToList();
}
[HttpGet(nameof(GetAllSalidomoInstallations))]
public ActionResult<IEnumerable<Installation>> GetAllSalidomoInstallations(Token authToken)
{
var user = Db.GetSession(authToken)?.User;
if (user is null)
return Unauthorized();
return user
.AccessibleInstallations(product:(int)ProductType.Salidomo)
.ToList();
@ -473,10 +487,10 @@ public class Controller : ControllerBase
public ActionResult<IEnumerable<Installation>> GetAllSodioHomeInstallations(Token authToken)
{
var user = Db.GetSession(authToken)?.User;
if (user is null)
return Unauthorized();
return user
.AccessibleInstallations(product:(int)ProductType.SodioHome)
.ToList();

View File

@ -6,7 +6,8 @@ public enum ProductType
{
Salimax = 0,
Salidomo = 1,
SodioHome =2
SodioHome =2,
SodiStoreMax=3
}
public enum StatusType

View File

@ -29,6 +29,7 @@ public static class Program
RabbitMqManager.StartRabbitMqConsumer().SupressAwaitWarning();
WebsocketManager.MonitorSalimaxInstallationTable().SupressAwaitWarning();
WebsocketManager.MonitorSalidomoInstallationTable().SupressAwaitWarning();
WebsocketManager.MonitorSodistoreInstallationTable().SupressAwaitWarning();
builder.Services.AddControllers();
builder.Services.AddProblemDetails(setup =>

View File

@ -78,6 +78,39 @@ public static class WebsocketManager
await Task.Delay(TimeSpan.FromMinutes(1));
}
}
//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"
public static void InformWebsocketsForInstallation(Int64 installationId)

View File

@ -70,7 +70,7 @@ public static class Aggregator
dailyAggregatedData.Save("DailyData");
if (await dailyAggregatedData.PushToS3())
{
//DeleteHourlyData("HourlyData",currentTime.ToUnixTime());
DeleteHourlyData("HourlyData",currentTime.ToUnixTime());
//AggregatedData.DeleteDailyData("DailyData");
}
@ -86,13 +86,13 @@ public static class Aggregator
private static void DeleteHourlyData(String myDirectory, Int64 beforeTimestamp)
{
var jsonFiles = Directory.GetFiles(myDirectory, "*.json");
Console.WriteLine("Delete data before"+beforeTimestamp);
//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}");
//Console.WriteLine($"Deleted hourly data file: {jsonFile}");
}
}
}
@ -103,14 +103,10 @@ public static class Aggregator
var jsonFiles = Directory.GetFiles(myDirectory, "*.json");
var batterySoc = new List<Double>();
var pvPowerSum = new List<Double>();
var heatingPower = new List<Double>();
var gridPowerImport = new List<Double>();
var gridPowerExport = new List<Double>();
var batteryDischargePower = new List<Double>();
var batteryChargePower = new List<Double>();
Console.WriteLine("File timestamp should start after "+ afterTimestamp);
foreach (var jsonFile in jsonFiles)
{
@ -136,7 +132,6 @@ public static class Aggregator
var jsonObject = JObject.Parse(jsonData);
//Console.WriteLine(jsonObject);
if (jsonObject["Battery"] != null && jsonObject["Battery"]["Soc"] != null)
{
batterySoc.Add((double)jsonObject["Battery"]["Soc"]);
@ -155,12 +150,10 @@ public static class Aggregator
}
if (jsonObject["GridMeter"] != null && jsonObject["GridMeter"]["ActivePowerExportT3"] != null)
{
Console.WriteLine("power export is "+jsonObject["GridMeter"]["ActivePowerExportT3"]);
gridPowerExport.Add((double)jsonObject["GridMeter"]["ActivePowerExportT3"]);
}
if (jsonObject["GridMeter"] != null && jsonObject["GridMeter"]["ActivePowerImportT3"] != null)
{
Console.WriteLine("power import is "+jsonObject["GridMeter"]["ActivePowerImportT3"]);
gridPowerImport.Add((double)jsonObject["GridMeter"]["ActivePowerImportT3"]);
}
}
@ -234,10 +227,6 @@ public static class Aggregator
var batteryDischargePower = new List<Double>();
var batteryChargePower = new List<Double>();
var heatingPowerAvg = new List<Double>();
Console.WriteLine("File timestamp should start after "+ afterTimestamp);
foreach (var jsonFile in jsonFiles)
{
@ -252,7 +241,6 @@ public static class Aggregator
try
{
var jsonData = File.ReadAllText(jsonFile);
//Console.WriteLine("Parse file "+jsonFile);
// Parse JSON into a Dictionary
var jsonDict = JsonConvert.DeserializeObject<Dictionary<string, Double>>(jsonData);
@ -286,14 +274,7 @@ public static class Aggregator
case "GridImportPower":
gridPowerImport.Add(value);
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}");
}
// 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");
// }
//}
}
}

View File

@ -277,10 +277,7 @@ internal static class Program
{
var s3Bucket = Config.Load().S3?.Bucket;
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
if (_subscribeToQueueForTheFirstTime == false)
{
@ -297,16 +294,6 @@ internal static class Program
if (s3Bucket != null)
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
Configuration? config = SetConfigurationFile();
@ -498,7 +485,7 @@ internal static class Program
var returnedStatus = new StatusMessage
{
InstallationId = installationId,
Product = 0,
Product = 3,
Status = _salimaxAlarmState,
Type = MessageType.AlarmOrWarning,
Alarms = alarmList,
@ -845,6 +832,16 @@ internal static class Program
}
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
}
}
@ -944,7 +941,7 @@ internal static class Program
var returnedStatus = new StatusMessage
{
InstallationId = installationId,
Product = 0, // Salimax is always 0
Product = 3, // Salimax is always 0
Status = _salimaxAlarmState,
Type = MessageType.Heartbit,
Timestamp = nameOfJsonFile