a minimum of 5 A are applied on DcDc to avoid ossiclation problem

This commit is contained in:
atef 2025-08-04 10:42:24 +02:00
parent e1a5aa3b2f
commit 2513187d89
1 changed files with 137 additions and 27 deletions

View File

@ -1,17 +1,11 @@
#define Amax
#undef Amax
#undef GridLimit
using System.Diagnostics;
using System.IO.Compression;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Reflection.Metadata;
using System.Security;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Flurl.Http;
using InnovEnergy.App.SodiStoreMax;
using InnovEnergy.App.SodiStoreMax.Devices;
using InnovEnergy.App.SodiStoreMax.Ess;
using InnovEnergy.App.SodiStoreMax.MiddlewareClasses;
@ -32,13 +26,11 @@ using InnovEnergy.Lib.Protocols.Modbus.Channels;
using InnovEnergy.Lib.Units;
using InnovEnergy.Lib.Utils;
using InnovEnergy.App.SodiStoreMax.DataTypes;
using InnovEnergy.Lib.Devices.Doepke;
using Newtonsoft.Json;
using static InnovEnergy.App.SodiStoreMax.AggregationService.Aggregator;
using static InnovEnergy.App.SodiStoreMax.MiddlewareClasses.MiddlewareAgent;
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig;
using Controller = InnovEnergy.App.SodiStoreMax.System.Controller;
using DeviceState = InnovEnergy.App.SodiStoreMax.Devices.DeviceState;
// ReSharper disable PossibleLossOfFraction
@ -481,8 +473,8 @@ internal static class Program
maxBatteryDischargingCurrentLivebyDcDc = devicesConfig.DcDc.MaxBatteryDischargingCurrent/r.Battery.Devices.Count;
}
maxBatteryChargingCurrentLiveByDcDc = 5 + (maxBatteryChargingCurrentLiveByDcDc * r.Battery.AvailableChBatteries); // Adapt the current to the number of available battery
maxBatteryDischargingCurrentLivebyDcDc = 5 + (maxBatteryDischargingCurrentLivebyDcDc * r.Battery.AvailableDischBatteries); // Adapt the current to the number of available battery
maxBatteryChargingCurrentLiveByDcDc = (maxBatteryChargingCurrentLiveByDcDc * r.Battery.AvailableChBatteries); // Adapt the current to the amount of available battery
maxBatteryDischargingCurrentLivebyDcDc = (maxBatteryDischargingCurrentLivebyDcDc * r.Battery.AvailableDischBatteries); // Adapt the current to the amount of available battery
(r.Battery?.AvailableChBatteries)?.WriteLine(" Available Charging Batteries");
(r.Battery?.AvailableDischBatteries)?.WriteLine(" Available Discharging Batteries");
@ -499,6 +491,17 @@ internal static class Program
maxBatteryChargingCurrentLiveByDcDc = 0;
maxBatteryDischargingCurrentLivebyDcDc = 0;
}
// This random value 5 is applied when the current is limited to 0. This will create an oscillation between discharging and charging
if (maxBatteryChargingCurrentLiveByDcDc == 0)
{
maxBatteryChargingCurrentLiveByDcDc = 5 / dcCount;
}
else if (maxBatteryDischargingCurrentLivebyDcDc == 0)
{
maxBatteryDischargingCurrentLivebyDcDc = 5 / dcCount;
}
inverters.ForEach(d => d.Control.Dc.MaxVoltage = devicesConfig.AcDc.MaxDcLinkVoltage);
inverters.ForEach(d => d.Control.Dc.MinVoltage = devicesConfig.AcDc.MinDcLinkVoltage);
inverters.ForEach(d => d.Control.Dc.ReferenceVoltage = devicesConfig.AcDc.ReferenceDcLinkVoltage);
@ -775,16 +778,6 @@ 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
}
}
@ -793,13 +786,12 @@ internal static class Program
currentDict = (Dictionary<String, Object>)currentDict[key];
}
}
}
private static async Task<Boolean> UploadCsv(StatusRecord status, DateTime timeStamp)
{
var csv = status.ToCsv();
Dictionary<string, object> jsonData = new Dictionary<string, object>();
var jsonData = new Dictionary<String, Object>();
foreach (var line in csv.Split('\n'))
{
@ -828,7 +820,7 @@ internal static class Program
return await ConcatinatingAndCompressingFiles(timeStamp, s3Config);
}
private static async Task<Boolean> ConcatinatingAndCompressingFiles(DateTime timeStamp, S3Config s3Config)
/* private static async Task<Boolean> ConcatinatingAndCompressingFiles(DateTime timeStamp, S3Config s3Config)
{
if (_fileCounter >= NbrOfFileToConcatenate)
{
@ -837,9 +829,7 @@ internal static class Program
var logFileConcatenator = new LogFileConcatenator();
var s3Path = timeStamp.ToUnixTime() + ".json";
s3Path.WriteLine("");
var jsonToSend = logFileConcatenator.ConcatenateFiles(NbrOfFileToConcatenate);
var jsonToSend = logFileConcatenator.ConcatenateFiles(NbrOfFileToConcatenate);
var request = s3Config.CreatePutRequest(s3Path);
//Use this for no compression
@ -870,6 +860,126 @@ internal static class Program
_fileCounter++;
return true;
}*/
private static async Task<Boolean> ConcatinatingAndCompressingFiles(DateTime timeStamp, S3Config s3Config)
{
if (_fileCounter >= NbrOfFileToConcatenate)
{
_fileCounter = 0;
var logFileConcatenator = new LogFileConcatenator();
var jsontoSend = logFileConcatenator.ConcatenateFiles(NbrOfFileToConcatenate);
var fileNameWithoutExtension = timeStamp.ToUnixTime().ToString(); // used for both S3 and local
var s3Path = fileNameWithoutExtension + ".json";
var request = s3Config.CreatePutRequest(s3Path);
var compressedBytes = CompresseBytes(jsontoSend);
var base64String = Convert.ToBase64String(compressedBytes);
var stringContent = new StringContent(base64String, Encoding.UTF8, "application/base64");
var uploadSucceeded = false;
try
{
var response = await request.PutAsync(stringContent);
if (response.StatusCode != 200)
{
Console.WriteLine("ERROR: PUT");
var error = await response.GetStringAsync();
Console.WriteLine(error);
await SaveToLocalCompressedFallback(compressedBytes, fileNameWithoutExtension);
Heartbit();
return false;
}
uploadSucceeded = true;
Console.WriteLine("✅ File uploaded to S3 successfully.");
Console.WriteLine("----------------------------------------Sending Heartbit----------------------------------------");
Heartbit();
await ResendLocalFailedFilesAsync(s3Config); // retry any pending failed files
}
catch (Exception ex)
{
Console.WriteLine("Upload exception: " + ex.Message);
if (!uploadSucceeded)
{
await SaveToLocalCompressedFallback(compressedBytes, fileNameWithoutExtension);
}
Heartbit();
return false;
}
}
_fileCounter++;
return true;
}
private static async Task SaveToLocalCompressedFallback(Byte[] compressedData, String fileNameWithoutExtension)
{
try
{
var fallbackDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FailedUploads");
Directory.CreateDirectory(fallbackDir);
var fileName = fileNameWithoutExtension + ".json"; // Save as .json, but still compressed
var fullPath = Path.Combine(fallbackDir, fileName);
await File.WriteAllBytesAsync(fullPath, compressedData); // Compressed data
Console.WriteLine($"Saved compressed failed upload to: {fullPath}");
}
catch (Exception ex)
{
Console.WriteLine("Failed to save compressed file locally: " + ex.Message);
}
}
private static async Task ResendLocalFailedFilesAsync(S3Config s3Config)
{
var fallbackDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FailedUploads");
if (!Directory.Exists(fallbackDir))
return;
var files = Directory.GetFiles(fallbackDir, "*.json");
foreach (var filePath in files)
{
var fileName = Path.GetFileName(filePath); // e.g., "1720023600.json"
var s3Key = fileName; // same name for S3
try
{
byte[] compressedBytes = await File.ReadAllBytesAsync(filePath);
var base64String = Convert.ToBase64String(compressedBytes);
var stringContent = new StringContent(base64String, Encoding.UTF8, "application/base64");
var request = s3Config.CreatePutRequest(s3Key);
var response = await request.PutAsync(stringContent);
if (response.StatusCode == 200)
{
File.Delete(filePath);
Console.WriteLine($"✅ Successfully resent and deleted: {fileName}");
}
else
{
Console.WriteLine($"❌ Failed to resend {fileName}, status: {response.StatusCode}");
}
}
catch (Exception ex)
{
Console.WriteLine($"⚠️ Exception while resending {fileName}: {ex.Message}");
}
}
}
private static void Heartbit()