Merge branch 'Release/UpdateIoC_01'

This commit is contained in:
Samuele Locatelli
2026-04-28 09:06:49 +02:00
7 changed files with 86 additions and 77 deletions
+30 -13
View File
@@ -1060,24 +1060,40 @@ namespace MP.Data.Controllers
{
bool fatto = false;
using var dbCtx = new MoonProContext(_configuration);
using var transaction = await dbCtx.Database.BeginTransactionAsync();
// 1. Transazione minima: SOLO INSERT + COMMIT
await using var tx = await dbCtx.Database.BeginTransactionAsync();
try
{
dbCtx.DbSetRemRebLog.Add(newRec);
fatto = await dbCtx.SaveChangesAsync() > 0;
var param = new SqlParameter("@num2keep", num2keep);
await dbCtx.Database.ExecuteSqlRawAsync("EXEC dbo.stp_RRL_KeepLatest @num2keep", param);
await transaction.CommitAsync();
return true;
await tx.CommitAsync(); // 🔑 Commit prima della pulizia
}
catch
{
await transaction.RollbackAsync();
await tx.RollbackAsync();
throw;
}
// 2. Cleanup "smart" fuori transazione
if (fatto)
{
try
{
var param = new SqlParameter("@num2keep", num2keep);
await dbCtx.Database.ExecuteSqlRawAsync(
"EXEC dbo.stp_RRL_KeepLatest @num2keep, @multiplier", param,
new SqlParameter("@multiplier", 1.3f)); // Fisso o leggo da config
}
catch (Exception ex)
{
// Log dell'errore, ma NON rilanciare: il record è già salvo
Log.Error(ex, "Failed to execute RRL cleanup for {Machine}", newRec.IdxMacchina);
}
}
return fatto;
}
/// <summary>
@@ -1119,10 +1135,11 @@ namespace MP.Data.Controllers
{
using var dbCtx = new MoonProContext(_configuration);
var Num2keep = new SqlParameter("@num2keep", num2keep);
var dbResult = await dbCtx
.Database
.ExecuteSqlRawAsync("exec dbo.stp_RRL_KeepLatest @num2keep", Num2keep);
var pNum2Keep = new SqlParameter("@num2keep", num2keep);
// La SP gestisce già la logica di soglia (1.5x), ma la specifico x sicurezza
var pThresh = new SqlParameter("@threshMult", 1.5);
var dbResult = await dbCtx.Database.ExecuteSqlRawAsync(
"EXEC dbo.stp_RRL_KeepLatest @num2keep, @threshMult", pNum2Keep, pThresh);
return dbResult != 0;
}
-2
View File
@@ -1156,7 +1156,6 @@ namespace MP.IOC.Controllers
// recupero IP del client remoto, se vuoto IOC
string agent = Request.Headers["User-Agent"].ToString() ?? "IOC";
agent = string.IsNullOrWhiteSpace(agent) ? "IOC" : agent;
//var ipv4 = HttpContext.Connection.RemoteIpAddress?.ToString();
var ipv4 = HttpContext.Connection.RemoteIpAddress?.MapToIPv4().ToString();
// chiamo registrazione reboot
@@ -1187,7 +1186,6 @@ namespace MP.IOC.Controllers
Log.Error($"Errore in sendReboot{Environment.NewLine}{exc}");
return StatusCode(StatusCodes.Status500InternalServerError, "NO");
}
return Ok(answ);
}
/// <summary>
+52 -58
View File
@@ -2945,6 +2945,25 @@ namespace MP.IOC.Data
return answ;
}
/// <summary>
/// Formato dataora standard x parsing
/// </summary>
private string dtFormat = "yyyyMMddHHmmssfff";
/// <summary>
/// Provider CultureInfo x parse valori (es dataora)
/// </summary>
private CultureInfo ciProvider = CultureInfo.InvariantCulture;
/// <summary>
/// Helper standardizzazione valore dataora ricevuto da IOB remoti
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private string dtFormStd(string? s)
{
return s?.Length > 17 ? s[..17] : s?.PadRight(17, '0') ?? string.Empty;
}
/// <summary>
/// Processa input da IOB eventualmente registrando i segnali inviati
/// </summary>
@@ -2968,68 +2987,41 @@ namespace MP.IOC.Data
}
else
{
// 2017.09.14 trimmo eventualmente lo zero finale dalle date SE supera i millisecondi...
dtEve = dtEve.Length > 17 ? dtEve.Substring(0, 17) : dtEve;
dtCurr = dtCurr.Length > 17 ? dtCurr.Substring(0, 17) : dtCurr;
DateTime dataOraEvento = DateTime.Now;
DateTime dtEvento, dtCorrente;
// controllo: se ho valori dt x evento e orario DIVERSI per acquisitore IOB calcolo
// dataOraEvento corretto
if (dtEve != dtCurr)
// fix formato dataora in ingresso
string stdEve = dtFormStd(dtEve);
string stdCurr = dtFormStd(dtCurr);
// 2. Se le stringhe normalizzate coincidono, skip dei calcoli
if (stdEve != stdCurr)
{
// delta è un calcolo MOLTO approssimativo della differenza temporale...
Int64 delta = 0;
try
// 3. Parsing sicuro
if (DateTime.TryParseExact(stdEve, dtFormat, ciProvider, DateTimeStyles.None, out DateTime dtEvento) &&
DateTime.TryParseExact(stdCurr, dtFormat, ciProvider, DateTimeStyles.None, out DateTime dtCorrente))
{
// se ho meno decimali x evento rispetto dtCorrente...
if (dtEve.Length < dtCurr.Length)
TimeSpan diff = dtCorrente - dtEvento;
double ms = Math.Abs(diff.TotalMilliseconds);
// 4. Classificazione delta con switch expression (più leggibile e performante)
string deltaClass = ms switch
{
Log.Info($"ProcessInputAsync: fix valore dtEve: {dtEve} | dtCurr: {dtCurr}");
dtEve = dtEve.PadRight(dtCurr.Length, '0');
}
delta = Convert.ToInt64(dtCurr) - Convert.ToInt64(dtEve);
// log della classe del delta (1-10, 10-100, 100-1k, 1k-10k, > 10k ms)
string deltaClass = "";
// faccio SEMPRE calcolo esatto sennò sbaglia...
CultureInfo provider = CultureInfo.InvariantCulture;
string format = "yyyyMMddHHmmssfff";
dtEvento = DateTime.ParseExact(dtEve, format, provider);
dtCorrente = DateTime.ParseExact(dtCurr, format, provider);
Int64 tiks = dtCorrente.Ticks - dtEvento.Ticks;
TimeSpan ts = new TimeSpan(tiks);
double ms = Math.Abs(ts.TotalMilliseconds);
// calcolo ESATTO dataora evento
dataOraEvento = dataOraEvento.AddTicks(-tiks);
if (ms <= 10)
{
deltaClass = "delta 0-10 ms";
}
else if (ms <= 100)
{
deltaClass = "delta 10-100 ms";
}
else if (ms <= 1000)
{
deltaClass = "delta 100-1000 ms";
}
else if (ms <= 10000)
{
deltaClass = "delta 1-10 sec";
}
else
{
deltaClass = "delta > 10 sec";
}
// se ho deltaClass loggo
if (deltaClass != "")
{
Log.Debug("Correzione " + deltaClass);
}
<= 10 => "0-10 ms",
<= 100 => "10-100 ms",
<= 1000 => "100-1000 ms",
<= 10000 => "1-10 sec",
_ => "> 10 sec"
};
Log.Debug($"Correzione delta {deltaClass}");
// 5. Correzione data/ora server: sottrao lo scarto calcolato
dataOraEvento = dataOraEvento.Subtract(diff);
}
catch (Exception exc)
else
{
Log.Error($"Errore calcolo ms evento/ora corrente da device remoto | dtEve: {dtEve} | dtCurr: {dtCurr}{Environment.NewLine}{exc}");
Log.Error($"Errore parsing date: {stdEve} | {stdCurr}");
}
}
// inizio processing vero e proprio INPUT...
@@ -4563,8 +4555,10 @@ namespace MP.IOC.Data
int.TryParse(datiMacc.ContainsKey("BitFilt") ? datiMacc["BitFilt"] : "0", out BitFilt);
int.TryParse(datiMacc.ContainsKey("BSR") ? datiMacc["BSR"] : "0", out BSR);
Boolean.TryParse(datiMacc.ContainsKey("ExplodeBit") ? datiMacc["ExplodeBit"] : "false", out ExplodeBit);
int.TryParse(datiMacc.ContainsKey("NumBit") ? datiMacc["NumBit"] : "0", out NumBit); // non usato (x ora)
// recupero valore
// non usato (x ora)
int.TryParse(datiMacc.ContainsKey("NumBit") ? datiMacc["NumBit"] : "0", out NumBit);
// recupero valore
valINT = int.Parse(valore, NumberStyles.HexNumber);
// filtro
newValInt = MP.Core.Utils.bMaskInt(valINT, BitFilt);
+1 -1
View File
@@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Version>8.16.2604.2718</Version>
<Version>8.16.2604.2808</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo MP-IOC </i>
<h4>Versione: 8.16.2604.2718</h4>
<h4>Versione: 8.16.2604.2808</h4>
<br /> Note di rilascio:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
8.16.2604.2718
8.16.2604.2808
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>8.16.2604.2718</version>
<version>8.16.2604.2808</version>
<url>https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/MP.IOC.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>