Merge branch 'Release/AggiuntaMetodiIoc_02'
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
namespace MP.Core.DTO
|
||||
{
|
||||
public class EvJsonPayloadDto
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
public List<EvDataDto> eventList { get; set; } = new();
|
||||
|
||||
#endregion Public Properties
|
||||
}
|
||||
}
|
||||
+11
-4
@@ -11,6 +11,7 @@ namespace MP.Core
|
||||
public const string redisAKVKey = redisBaseAddr + "Cache:AKV";
|
||||
|
||||
public const string redisAnagGruppi = redisBaseAddr + "Cache:AnagGruppi";
|
||||
public const string redisAnagStati = redisBaseAddr + "Cache:AnagStati";
|
||||
|
||||
public const string redisArtByDossier = redisBaseAddr + "Cache:ArtByDossier";
|
||||
|
||||
@@ -20,11 +21,16 @@ namespace MP.Core
|
||||
|
||||
public const string redisConfKey = redisBaseAddr + "Cache:Config";
|
||||
|
||||
public const string redisDecNumArtKey = redisBaseAddr + "Cache:DecNumArt";
|
||||
|
||||
public const string redisDossByMac = redisBaseAddr + "Cache:DossByMac";
|
||||
public const string redisDossByMacLast = redisBaseAddr + "Cache:DossByMacLast";
|
||||
|
||||
public const string redisEventList = redisBaseAddr + "Cache:EventList";
|
||||
|
||||
public const string redisFluxByMac = redisBaseAddr + "Cache:FluxByMac";
|
||||
public const string redisFluxByMacFirst = redisBaseAddr + "Cache:FluxByMacFirst";
|
||||
public const string redisConfFlux = redisBaseAddr + "Cache:ConfFlux";
|
||||
|
||||
public const string redisFluxLogFilt = redisBaseAddr + "Cache:FluxLogFilt";
|
||||
|
||||
@@ -216,21 +222,22 @@ namespace MP.Core
|
||||
/// <param name="idxMacchina"></param>
|
||||
/// <param name="baseAddr">Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy)</param>
|
||||
/// <returns></returns>
|
||||
public static RedisKey RedKeyIobMemMap(string idxMacchina, string baseAddr = null)
|
||||
public static RedisKey RedKeyIobConfYaml(string idxMacchina, string baseAddr = null)
|
||||
{
|
||||
var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':');
|
||||
return (RedisKey)$"{prefix}:MemMap:{idxMacchina}";
|
||||
return (RedisKey)$"{prefix}:IOB:{idxMacchina}:ConfYaml";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hash dati MemMap di un IOB
|
||||
/// </summary>
|
||||
/// <param name="idxMacchina"></param>
|
||||
/// <param name="baseAddr">Chiave override per i valori in caso di dati che accedono al dominio dati di un altra app (es: baseAddr x IO legacy)</param>
|
||||
/// <returns></returns>
|
||||
public static RedisKey RedKeyIobConfYaml(string idxMacchina, string baseAddr = null)
|
||||
public static RedisKey RedKeyIobMemMap(string idxMacchina, string baseAddr = null)
|
||||
{
|
||||
var prefix = (baseAddr ?? redisBaseAddr).TrimEnd(':');
|
||||
return (RedisKey)$"{prefix}:IOB:{idxMacchina}:ConfYaml";
|
||||
return (RedisKey)$"{prefix}:MemMap:{idxMacchina}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using MP.Data.DbModels;
|
||||
using MP.Data.DbModels.Anag;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -55,6 +56,45 @@ namespace MP.Data.Controllers
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restituisce l'anagrafica STATI per intero
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<AnagStatiModel>> AnagStatiGetAllAsync()
|
||||
{
|
||||
List<AnagStatiModel> dbResult = new List<AnagStatiModel>();
|
||||
using (var dbCtx = new MoonProContext(_configuration))
|
||||
{
|
||||
dbResult = await dbCtx
|
||||
.DbSetAnagStati
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record ConfFlux dato macchina (oppure tutti se vuoto)
|
||||
/// </summary>
|
||||
/// <param name="idxMacc"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<ConfFluxModel>> ConfFluxFiltAsync(string idxMacc)
|
||||
{
|
||||
List<ConfFluxModel> dbResult = new();
|
||||
using (var dbCtx = new MoonPro_FluxContext(_configuration))
|
||||
{
|
||||
var query = dbCtx.DbSetConfFlux
|
||||
.AsNoTracking()
|
||||
.AsQueryable();
|
||||
|
||||
if (!string.IsNullOrEmpty(idxMacc))
|
||||
query = query.Where(x => x.IdxMacchina == idxMacc);
|
||||
|
||||
dbResult = await query.ToListAsync();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco da tabella Config
|
||||
/// </summary>
|
||||
@@ -65,10 +105,10 @@ namespace MP.Data.Controllers
|
||||
using (var dbCtx = new MoonProContext(_configuration))
|
||||
{
|
||||
dbResult = dbCtx
|
||||
.DbSetConfig
|
||||
.AsNoTracking()
|
||||
.OrderBy(x => x.Chiave)
|
||||
.ToList();
|
||||
.DbSetConfig
|
||||
.AsNoTracking()
|
||||
.OrderBy(x => x.Chiave)
|
||||
.ToList();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
@@ -115,6 +155,24 @@ namespace MP.Data.Controllers
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Intera tab dati macchina
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<DatiMacchineModel>> DatiMacchineGetAllAsync()
|
||||
{
|
||||
List<DatiMacchineModel> dbResult = new List<DatiMacchineModel>();
|
||||
using (var dbCtx = new MoonProContext(_configuration))
|
||||
{
|
||||
dbResult = await dbCtx
|
||||
.DbSetDatiMacchine
|
||||
.AsNoTracking()
|
||||
.OrderBy(x => x.IdxMacchina)
|
||||
.ToListAsync();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserimento record in DDB
|
||||
/// </summary>
|
||||
@@ -149,11 +207,54 @@ namespace MP.Data.Controllers
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco tabella decodifica articoli / codice decimale
|
||||
/// </summary>
|
||||
/// <param name="codArt">Vuoto = tutti / Singolo CodArt</param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<DecNumArticoliModel>> DecNumArtGetFiltAsync(string codArt = "")
|
||||
{
|
||||
List<DecNumArticoliModel> dbResult = new List<DecNumArticoliModel>();
|
||||
using (var dbCtx = new MoonProContext(_configuration))
|
||||
{
|
||||
var query = dbCtx.DbSetDecNumArt
|
||||
.AsNoTracking()
|
||||
.AsQueryable();
|
||||
|
||||
if (!string.IsNullOrEmpty(codArt))
|
||||
query = query.Where(x => x.CodArticolo == codArt);
|
||||
|
||||
dbResult = await query.ToListAsync();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_configuration = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stored x recuperare ultimi dossier macchina
|
||||
/// </summary>
|
||||
/// <param name="idxMacc"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<DossierModel>> DossGetLastByMaccAsync(string idxMacc)
|
||||
{
|
||||
List<DossierModel> dbResult = new();
|
||||
using (var dbCtx = new MoonPro_FluxContext(_configuration))
|
||||
{
|
||||
var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc);
|
||||
|
||||
dbResult = await dbCtx
|
||||
.DbSetDossiers
|
||||
.FromSqlRaw("exec dbo.stp_DOSS_getLastByMacch @idxMacchina", IdxMacchina)
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggiunta record EventList
|
||||
/// </summary>
|
||||
@@ -204,6 +305,29 @@ namespace MP.Data.Controllers
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Chiamata x stored recupero FluxLog x macchina (first)
|
||||
/// </summary>
|
||||
/// <param name="idxMacc"></param>
|
||||
/// <param name="numMax"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<FluxLogModel>> FluxLogFirstByMaccAsync(string idxMacc, int numMax)
|
||||
{
|
||||
List<FluxLogModel> dbResult = new();
|
||||
using (var dbCtx = new MoonPro_FluxContext(_configuration))
|
||||
{
|
||||
var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc);
|
||||
var NumMax = new SqlParameter("@numMax", numMax);
|
||||
|
||||
dbResult = await dbCtx
|
||||
.DbSetFluxLog
|
||||
.FromSqlRaw("exec dbo.stp_FL_getFirstByMacc @IdxMacchina, @numMax", IdxMacchina, NumMax)
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco ultimi n record flux log dato macchina e flusso (ordinato x data registrazione)
|
||||
/// </summary>
|
||||
@@ -279,6 +403,28 @@ namespace MP.Data.Controllers
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stored x eseguire Snapshot FluxLog (= Dossier) dato periodo
|
||||
/// </summary>
|
||||
/// <param name="idxMacc"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> FluxLogTakeSnapshotLastAsync(string idxMacc, DateTime dataInizio, DateTime dataFine)
|
||||
{
|
||||
bool fatto = false;
|
||||
using (var dbCtx = new MoonPro_FluxContext(_configuration))
|
||||
{
|
||||
var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacc);
|
||||
var DataInizio = new SqlParameter("@DtMin", dataInizio);
|
||||
var DataFine = new SqlParameter("@DtMax", dataFine);
|
||||
|
||||
var result = await dbCtx
|
||||
.Database
|
||||
.ExecuteSqlRawAsync("EXEC stp_FL_TakeSnapshotLast @IdxMacchina, @DtMin, @DtMax", IdxMacchina, DataInizio, DataFine);
|
||||
fatto = result > 0;
|
||||
}
|
||||
return fatto;
|
||||
}
|
||||
|
||||
public bool KeepAliveUpsert(string IdxMacc, DateTime OraServer, DateTime OraMacc)
|
||||
{
|
||||
bool fatto = false;
|
||||
@@ -379,6 +525,24 @@ namespace MP.Data.Controllers
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Intera tabella relazione master/slave in machine (gestione setup master --> slave)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<Macchine2SlaveModel>> Macchine2SlaveAsync()
|
||||
{
|
||||
List<Macchine2SlaveModel> dbResult = new List<Macchine2SlaveModel>();
|
||||
using (var dbCtx = new MoonProContext(_configuration))
|
||||
{
|
||||
dbResult = await dbCtx
|
||||
.DbSetM2S
|
||||
.AsNoTracking()
|
||||
.OrderBy(x => x.IdxMacchina)
|
||||
.ToListAsync();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco Record Macchine
|
||||
/// </summary>
|
||||
@@ -589,18 +753,18 @@ namespace MP.Data.Controllers
|
||||
/// Elenco da tabella MappaStatoExplModel
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<MappaStatoExplModel> MseGetAll(int maxAge = 2000)
|
||||
public async Task<List<MappaStatoExplModel>> MseGetAllAsync(int maxAge = 2000)
|
||||
{
|
||||
List<MappaStatoExplModel> dbResult = new List<MappaStatoExplModel>();
|
||||
using (var dbCtx = new MoonProContext(_configuration))
|
||||
{
|
||||
var maxAgeSec = new SqlParameter("@maxAgeSec", maxAge);
|
||||
|
||||
dbResult = dbCtx
|
||||
.DbSetMSE
|
||||
.FromSqlRaw("EXEC stp_MSE_getData @maxAgeSec", maxAgeSec)
|
||||
.AsNoTracking()
|
||||
.ToList();
|
||||
dbResult = await dbCtx
|
||||
.DbSetMSE
|
||||
.FromSqlRaw("EXEC stp_MSE_getData @maxAgeSec", maxAgeSec)
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
@@ -1273,6 +1437,27 @@ namespace MP.Data.Controllers
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Vista v_MSFD x singola macchina (da stored) - singolo record
|
||||
/// </summary>
|
||||
/// <param name="idxMacc"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<VMSFDModel>> VMSFDGetByMaccAsync(string idxMacc)
|
||||
{
|
||||
List<VMSFDModel> dbResult = new List<VMSFDModel>();
|
||||
using (var dbCtx = new MoonProContext(_configuration))
|
||||
{
|
||||
var IdxMacchina = new SqlParameter("@pIdxMacchina", idxMacc);
|
||||
|
||||
dbResult = await dbCtx
|
||||
.DbSetMSFD
|
||||
.FromSqlRaw("exec dbo.stp_MSFD_getMacc @pIdxMacchina", IdxMacchina)
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Vista v_MSFD delle machine MULTI filtrato x macchina (da stored)
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace MP.Data.DbModels.Anag
|
||||
{
|
||||
[Table("AlarmLog")]
|
||||
public class DecNumArticoliModel
|
||||
{
|
||||
[Key]
|
||||
public string CodArticolo { get; set; } = "";
|
||||
public int NumART { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
|
||||
#nullable disable
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace MP.Data.DbModels
|
||||
{
|
||||
[Table("ConfFlux")]
|
||||
public partial class ConfFluxModel
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[MaxLength(50)]
|
||||
public string IdxMacchina { get; set; }
|
||||
|
||||
[MaxLength(50)]
|
||||
public string CodFlux { get; set; }
|
||||
|
||||
public bool EnabDoss { get; set; }
|
||||
|
||||
#endregion Public Properties
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using MP.Data.DbModels;
|
||||
using MP.Data.DbModels.Anag;
|
||||
using NLog;
|
||||
|
||||
#nullable disable
|
||||
@@ -45,6 +46,8 @@ namespace MP.Data
|
||||
public virtual DbSet<AnagStatiModel> DbSetAnagStati { get; set; }
|
||||
public virtual DbSet<AnagTagsModel> DbSetAnagTags { get; set; }
|
||||
public virtual DbSet<AnagArticoliModel> DbSetArticoli { get; set; }
|
||||
public virtual DbSet<DecNumArticoliModel> DbSetDecNumArt { get; set; }
|
||||
|
||||
public virtual DbSet<ConfigModel> DbSetConfig { get; set; }
|
||||
public virtual DbSet<ElencoConfermeProdModel> DbSetElConfProd { get; set; }
|
||||
public virtual DbSet<LinkMenuModel> DbSetLinkMenu { get; set; }
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using MP.Core.DTO;
|
||||
using MP.Data.DbModels;
|
||||
using MP.Data.DTO;
|
||||
using NLog;
|
||||
using System;
|
||||
|
||||
#nullable disable
|
||||
// <Auto-Generated>
|
||||
@@ -54,6 +52,8 @@ namespace MP.Data
|
||||
public virtual DbSet<FluxLogModel> DbSetFluxLog { get; set; }
|
||||
public virtual DbSet<DossierModel> DbSetDossiers { get; set; }
|
||||
public virtual DbSet<ParetoFluxLogDTO> DbSetParetoFluxLog { get; set; }
|
||||
public virtual DbSet<ConfFluxModel> DbSetConfFlux { get; set; }
|
||||
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
|
||||
@@ -320,6 +320,10 @@ namespace MP.Data.Services
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco da tabella MappaStatoExplModel
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<MappaStatoExplModel>> MseGetAll(bool forceDb = false)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
@@ -327,10 +331,10 @@ namespace MP.Data.Services
|
||||
sw.Start();
|
||||
List<MappaStatoExplModel>? result = new List<MappaStatoExplModel>();
|
||||
// cerco in _redisConn...
|
||||
RedisValue rawData = redisDb.StringGet(Constants.redisMseKey);
|
||||
RedisValue rawData = await redisDb.StringGetAsync(Constants.redisMseKey);
|
||||
if (rawData.HasValue && !forceDb)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<MappaStatoExplModel>>($"{rawData}");
|
||||
result = JsonConvert.DeserializeObject<List<MappaStatoExplModel>>($"{rawData}") ?? new();
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace MP.IOC.Controllers
|
||||
[HttpGet("addOptPar/{id}")]
|
||||
public async Task<IActionResult> AddOptPar(string id, string pName, string pValue)
|
||||
{
|
||||
DService.ScriviKeepAlive(id, DateTime.Now);
|
||||
await DService.ScriviKeepAliveAsync(id, DateTime.Now);
|
||||
try
|
||||
{
|
||||
DService.AddOptPar4Machine(id, pName, pValue);
|
||||
@@ -88,21 +88,85 @@ namespace MP.IOC.Controllers
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("enabled/{id}")]
|
||||
public IActionResult Enabled(string id)
|
||||
public async Task<IActionResult> Enabled(string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID");
|
||||
|
||||
if (DService.IobInsEnab(id))
|
||||
try
|
||||
{
|
||||
return Ok("OK");
|
||||
// Il metodo ora restituisce direttamente il booleano logico
|
||||
bool isEnabled = await DService.IobInsEnabAsync(id);
|
||||
|
||||
return isEnabled
|
||||
? Ok("OK")
|
||||
: UnprocessableEntity("NO");
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
//return StatusCode(503, "NO");
|
||||
return UnprocessableEntity("NO");
|
||||
Log.Error(ex, "Errore durante la verifica abilitazione per {Id}", id);
|
||||
return StatusCode(500, "Errore interno del server");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processa una chiamata POST per l'invio di un array Json di oggetti input (EVENTI)
|
||||
/// POST: IOB/evListJson/SIMUL_03
|
||||
/// </summary>
|
||||
/// <param name="id">ID dell'IOB</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("evListJson/{id}")]
|
||||
public async Task<IActionResult> EvListJson(string id, [FromBody] string content = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID");
|
||||
string answ = "-";
|
||||
try
|
||||
{
|
||||
// se ho dati...
|
||||
if (content != "")
|
||||
{
|
||||
answ = await processEvListJsonAsync(id, content);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"Errore in EvListJson - no content");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "NO");
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Errore in EvListJson{Environment.NewLine}{exc}");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "NO");
|
||||
}
|
||||
return Ok(answ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sistema Dossier/Snapshot giornalieri x impianto indicato, andando a generare 1 Dossier
|
||||
/// giornaliero x ogni giornata dall'ultimo registrato alla data corrente
|
||||
/// es: http://url_site/MP/IO/IOB/fixDailyDossier/SIMUL_03
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("fixDailyDossier/{id}")]
|
||||
public async Task<IActionResult> FixDailyDossier(string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID");
|
||||
// Multi: gestione carattere "|" trasformato in "#"
|
||||
id = id.Replace("|", "#");
|
||||
|
||||
string answ = "";
|
||||
try
|
||||
{
|
||||
answ = await DService.FixDailyDossierAsync(id);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Errore in FixDailyDossier{Environment.NewLine}{exc}");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "NO");
|
||||
}
|
||||
return Ok(answ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sistema ODL giornalieri x impianto indicato, andando a generare 1 ODL giornaliero x ogni
|
||||
/// giornata dall'ultimo ODL aperto alla data corrente
|
||||
@@ -262,6 +326,36 @@ namespace MP.IOC.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera ArtNum dato CodXdl (per impianti che accettano solo INT in scrittura):
|
||||
/// GET: IOB/getArtNum/SIMUL_03?CodXdl=ABC123
|
||||
/// </summary>
|
||||
/// <param name="id">IdxMacchina (NON considerato)</param>
|
||||
/// <param name="CodArt">CodXdl richiesto, se vuoto restituisce TUTTI i valori in tabella di decodifica</param>
|
||||
/// <returns>Json contenente le righe delle codifiche attive Articolo/Numero</returns>
|
||||
[HttpGet("getArtNum/{id}")]
|
||||
public async Task<IActionResult> GetArtNum(string id, string CodArt = "")
|
||||
{
|
||||
// in realtà ID macchina non conterebbe...
|
||||
if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID");
|
||||
// Multi: gestione carattere "|" trasformato in "#"
|
||||
id = id.Replace("|", "#");
|
||||
string answ = "";
|
||||
try
|
||||
{
|
||||
await DService.ScriviKeepAliveAsync(id, DateTime.Now);
|
||||
// leggo da REDIS eventuale elenco task x macchina...
|
||||
Dictionary<string, int> valori = await DService.GetArtNumAsync(CodArt);
|
||||
answ = JsonConvert.SerializeObject(valori);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Errore in GetArtNum{Environment.NewLine}{exc}");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "NO");
|
||||
}
|
||||
return Ok(answ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera COUNTER x macchina:
|
||||
/// GET: IOB/getCounter/SIMUL_03
|
||||
@@ -425,6 +519,51 @@ namespace MP.IOC.Controllers
|
||||
return Ok(answ.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restituisce il valore dello stato di IDLE della macchina, quindi SOLO SE NON é in lavoro
|
||||
/// e già convertito in minuti...
|
||||
/// GET: IOB/getIdlePeriod/SIMUL_01
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("getIdlePeriod/{id}")]
|
||||
public async Task<IActionResult> GetIdlePeriod(string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID");
|
||||
// Multi: gestione carattere "|" trasformato in "#"
|
||||
id = id.Replace("|", "#");
|
||||
int answ = 0;
|
||||
|
||||
// chiamo metodo x avere stato macchina...
|
||||
try
|
||||
{
|
||||
await DService.ScriviKeepAliveAsync(id, DateTime.Now);
|
||||
var mseData = await DService.MseGetAllAsync();
|
||||
if (mseData.Count > 0)
|
||||
{
|
||||
var currRec = mseData.FirstOrDefault(x => x.IdxMacchina == id);
|
||||
if (currRec != null)
|
||||
{
|
||||
// recupero da redis elenco stati
|
||||
var anagStati = await DService.AnagStatiGetAllAsync();
|
||||
var currStato = anagStati.FirstOrDefault(x => x.IdxStato == currRec.IdxStato);
|
||||
// calcolo SE sia idle... OVVERO SEMAFORO NON VERDE!!!
|
||||
if (currStato != null && currStato.Semaforo != "sVe")
|
||||
{
|
||||
// calcolo durata...
|
||||
answ = (int)(currRec.Durata ?? 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Errore in GetIdlePeriod{Environment.NewLine}{exc}");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "NO");
|
||||
}
|
||||
return Ok(answ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera TASK richiesto x macchina:
|
||||
/// GET: IOB/getOptPar/SIMUL_03
|
||||
@@ -440,7 +579,7 @@ namespace MP.IOC.Controllers
|
||||
id = id.Replace("|", "#");
|
||||
string answ = "";
|
||||
// scrivo keep alive!!! (se necessario, altrimenti è in cache...)
|
||||
DService.ScriviKeepAlive(id, DateTime.Now);
|
||||
await DService.ScriviKeepAliveAsync(id, DateTime.Now);
|
||||
try
|
||||
{
|
||||
// leggo da REDIS eventuale elenco task x macchina...
|
||||
@@ -468,7 +607,7 @@ namespace MP.IOC.Controllers
|
||||
string answ = "";
|
||||
try
|
||||
{
|
||||
DService.ScriviKeepAlive(id, DateTime.Now);
|
||||
await DService.ScriviKeepAliveAsync(id, DateTime.Now);
|
||||
// leggo da REDIS eventuale elenco task x macchina...
|
||||
Dictionary<string, string> valori = await DService.GetTask2ExeMacchinaAsync(id);
|
||||
answ = JsonConvert.SerializeObject(valori);
|
||||
@@ -481,6 +620,35 @@ namespace MP.IOC.Controllers
|
||||
return Ok(answ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera codice numerico ODL/PODL dato CodXdl, in pratica la parte finale SENZA ODL/PODL
|
||||
/// Funzione per impianti che accettano solo INT in scrittura:
|
||||
/// GET: IOB/getXdlNum/SIMUL_03?CodXdl=ODL00000123
|
||||
/// </summary>
|
||||
/// <param name="id">IdxMacchina (NON considerato)</param>
|
||||
/// <param name="CodXdl">
|
||||
/// CodXdl richiesto, se vuoto restituisce TUTTI i valori in tabella di decodifica
|
||||
/// </param>
|
||||
/// <returns>SINGOLO VALORE calcolato on the fly</returns>
|
||||
[HttpGet("getXdlNum/{id}")]
|
||||
public async Task<IActionResult> GetXdlNum(string id, string CodXdl = "")
|
||||
{
|
||||
// in realtà ID macchina non conta e lo ignoriamo...
|
||||
string answ = "";
|
||||
await DService.ScriviKeepAliveAsync(id, DateTime.Now);
|
||||
try
|
||||
{
|
||||
// sostituisco PODL/ODL con "" e lascio zero iniziali (conversione INT in IOB)
|
||||
answ = CodXdl.Replace("PODL", "").Replace("ODL", "");
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Errore in GetXdlNum{Environment.NewLine}{exc}");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "NO");
|
||||
}
|
||||
return Ok(answ);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metodo di dichiarazione "improprio" tramite get call totalmetne definita da URL
|
||||
/// GET: IOB/input/SIMUL_03?valore=3&dtEve=20181206180600000&dtCurr=20181206180600000&cnt=999
|
||||
@@ -505,12 +673,12 @@ namespace MP.IOC.Controllers
|
||||
DateTime dataOraEvento = DateTime.Now;
|
||||
try
|
||||
{
|
||||
answ = DService.processInput(id, valore, dtEve, dtCurr, cnt);
|
||||
answ = await DService.ProcessInputAsync(id, valore, dtEve, dtCurr, cnt);
|
||||
return Ok(answ);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Errore in processInput{Environment.NewLine}{exc}");
|
||||
Log.Error($"Errore in ProcessInputAsync{Environment.NewLine}{exc}");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, "NO");
|
||||
}
|
||||
}
|
||||
@@ -1017,6 +1185,47 @@ namespace MP.IOC.Controllers
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Processing effettivo EvListJson
|
||||
/// </summary>
|
||||
/// <param name="idxMacc"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> processEvListJsonAsync(string idxMacc, string content)
|
||||
{
|
||||
string answ = "";
|
||||
int insDone = 0;
|
||||
|
||||
// procedo a deserializzare in blocco l'oggetto...
|
||||
EvJsonPayloadDto receivedData = JsonConvert.DeserializeObject<EvJsonPayloadDto>(content) ?? new();
|
||||
|
||||
// se ho qualcosa da processare...
|
||||
if (receivedData != null)
|
||||
{
|
||||
// per ogni valore --> processo!
|
||||
try
|
||||
{
|
||||
foreach (var item in receivedData.eventList)
|
||||
{
|
||||
// formato datetime come yyyyMMddHHmmssfff -->es: 20181223180600000
|
||||
answ = await DService.ProcessInputAsync(idxMacc, item.valore, item.dtEve.ToString("yyyyMMddHHmmssfff"), item.dtCurr.ToString("yyyyMMddHHmmssfff"), item.cnt.ToString());
|
||||
insDone++;
|
||||
}
|
||||
// se vuoto --> OK!
|
||||
if (string.IsNullOrEmpty(answ))
|
||||
{
|
||||
answ = $"OK {insDone} processed";
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Errore in fase invio valori inputJson{Environment.NewLine}{exc}");
|
||||
answ = "NO";
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettivo processing FLogJson
|
||||
/// </summary>
|
||||
|
||||
+541
-15
@@ -1,8 +1,10 @@
|
||||
using MP.Core.Conf;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MP.Core.Conf;
|
||||
using MP.Core.DTO;
|
||||
using MP.Core.Objects;
|
||||
using MP.Data;
|
||||
using MP.Data.DbModels;
|
||||
using MP.Data.DbModels.Anag;
|
||||
using MP.Data.MgModels;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
@@ -293,6 +295,30 @@ namespace MP.IOC.Data
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restituisce l'anagrafica STATI per intero
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<AnagStatiModel>> AnagStatiGetAllAsync()
|
||||
{
|
||||
List<AnagStatiModel> dbResult = new List<AnagStatiModel>();
|
||||
// cerco in redis...
|
||||
var currKey = Utils.redisAnagStati;
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
dbResult = JsonConvert.DeserializeObject<List<AnagStatiModel>>($"{rawData}") ?? new();
|
||||
}
|
||||
else
|
||||
{
|
||||
dbResult = await IocDbController.AnagStatiGetAllAsync();
|
||||
// serializzo e salvo...
|
||||
rawData = JsonConvert.SerializeObject(dbResult);
|
||||
await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache));
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
public async Task<List<ListValuesModel>> AnagTipoArtLV()
|
||||
{
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
@@ -500,10 +526,10 @@ namespace MP.IOC.Data
|
||||
/// <param name="dtEve">data-ora evento (server)</param>
|
||||
/// <param name="contatore">sequenza dati inviati</param>
|
||||
/// <returns></returns>
|
||||
public inputComandoMapo checkMicroStato(string idxMacchina, string valore, DateTime dtEve, string contatore)
|
||||
public async Task<inputComandoMapo> CheckMicroStatoAsync(string idxMacchina, string valore, DateTime dtEve, string contatore)
|
||||
{
|
||||
// recupero SE IMPIEGATO REDIS i valori del Dictionary della macchina...
|
||||
Dictionary<string, string> datiMacc = mDatiMacchine(idxMacchina);
|
||||
Dictionary<string, string> datiMacc = await mDatiMacchineAsync(idxMacchina);
|
||||
|
||||
// processing
|
||||
inputComandoMapo answ = new inputComandoMapo();
|
||||
@@ -515,7 +541,7 @@ namespace MP.IOC.Data
|
||||
string CodArticolo = datiMacc["CodArticolo"];
|
||||
if (string.IsNullOrEmpty(CodArticolo))
|
||||
{
|
||||
var allDatiMacch = IocDbController.DatiMacchineGetAll();
|
||||
var allDatiMacch = await IocDbController.DatiMacchineGetAllAsync();
|
||||
var recMacc = allDatiMacch.FirstOrDefault(x => x.IdxMacchina == idxMacchina);
|
||||
if (recMacc != null)
|
||||
{
|
||||
@@ -570,7 +596,7 @@ namespace MP.IOC.Data
|
||||
InizioStato = dtEve,
|
||||
Value = valore
|
||||
};
|
||||
IocDbController.MicroStatoMacchinaUpsert(newRec);
|
||||
await IocDbController.MicroStatoMacchinaUpsertAsync(newRec);
|
||||
if (idxTipoEv > 0)
|
||||
{
|
||||
try
|
||||
@@ -589,7 +615,7 @@ namespace MP.IOC.Data
|
||||
Value = valEsteso
|
||||
};
|
||||
// salva e processa
|
||||
answ = scriviRigaEvento(newRecEv);
|
||||
answ = await scriviRigaEventoAsync(newRecEv);
|
||||
//currTask = scriviRigaEvento(idxMacchina, idxTipoEv, codArticolo, valEsteso, 0, "-", dtEve, DateTime.Now);
|
||||
// forzo RESET dati macchina...
|
||||
ResetDatiMacchina(idxMacchina);
|
||||
@@ -687,6 +713,27 @@ namespace MP.IOC.Data
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<List<DecNumArticoliModel>> DecNumArtGetFiltAsync(string codArt = "")
|
||||
{
|
||||
List<DecNumArticoliModel> result = new();
|
||||
string tag = string.IsNullOrEmpty(codArt) ? "ALL" : codArt;
|
||||
string currKey = $"{Utils.redisDecNumArtKey}:{tag}";
|
||||
// cerco in redis dato valore sel macchina...
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<DecNumArticoliModel>>($"{rawData}") ?? new();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await IocDbController.DecNumArtGetFiltAsync(codArt);
|
||||
// serializzo e salvo...
|
||||
rawData = JsonConvert.SerializeObject(result);
|
||||
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose del connettore ai dati
|
||||
/// </summary>
|
||||
@@ -899,6 +946,80 @@ namespace MP.IOC.Data
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Task completo sistemazione dossier quotidiani mancanti
|
||||
/// </summary>
|
||||
/// <param name="idxMacc"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> FixDailyDossierAsync(string idxMacc)
|
||||
{
|
||||
string answ = "";
|
||||
// verifico se si possa processare, ovvero tab ConfFlux x macchina sia valorizzata...
|
||||
var confDataMach = await ConfFluxMach(idxMacc);
|
||||
if (confDataMach.Count > 0)
|
||||
{
|
||||
// determino ultima data da processare (inizio oggi, a mezzanotte)
|
||||
DateTime dtTo = DateTime.Today;
|
||||
DateTime dtFrom = dtTo;
|
||||
// determino data di partenza, prima da dossier esistenti
|
||||
var listaDoss = await DossierLastByMachAsync(idxMacc);
|
||||
if (listaDoss.Count > 0)
|
||||
{
|
||||
// primo giorno DOPO ultima registrazione
|
||||
dtFrom = listaDoss.OrderByDescending(x => x).FirstOrDefault().AddDays(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...o da fluxLog acquisiti...
|
||||
var listaFL = await FluxLogFirstByMachAsync(idxMacc);
|
||||
if (listaFL.Count > 0)
|
||||
{
|
||||
// giorno successivo a prima registrazione
|
||||
dtFrom = listaFL.OrderBy(x => x).FirstOrDefault().AddDays(1);
|
||||
}
|
||||
}
|
||||
string caller = $"takeFlogSnapshot({idxMacc})";
|
||||
DateTime dtStart = dtFrom.Date;
|
||||
DateTime dtEnd = dtFrom;
|
||||
// max 10 dossier alla volta (se non configurato diversamente)
|
||||
int maxAdd = 1;
|
||||
string confVal = await tryGetConfig("IO_numDossMaxCreate");
|
||||
if (!string.IsNullOrEmpty(confVal))
|
||||
{
|
||||
int.TryParse(confVal, out maxAdd);
|
||||
}
|
||||
|
||||
if (dtStart < dtTo)
|
||||
{
|
||||
// verifico di avere almeno 1 dossier da produrre ciclo fino ad esaurire le
|
||||
// date da processare
|
||||
while (dtStart < dtTo && maxAdd > 0)
|
||||
{
|
||||
// sistemo end
|
||||
dtEnd = dtStart.AddDays(1);
|
||||
// effettuo chiamata registrazione snapshot!
|
||||
answ = await FluxLogSaveSnapshotAsync(idxMacc, dtStart, dtEnd, caller);
|
||||
// incremento START...
|
||||
dtStart = dtEnd;
|
||||
// riduco il numero di chiamate ammesse x singolo task
|
||||
maxAdd--;
|
||||
}
|
||||
// reset cache dossier...
|
||||
await DossierLastByMachResetAsync(idxMacc);
|
||||
answ = "OK";
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warn("FixDailyDossierAsync | NO more to add");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warn("FixDailyDossierAsync | NO ConfFluxData");
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
public async Task<bool> FlushRedisCache()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
@@ -1161,8 +1282,32 @@ namespace MP.IOC.Data
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restituisce il valore booleano se la macchina sia abilitata all'input
|
||||
/// </summary>
|
||||
/// <param name="IdxOdl">id odl da cercare</param>
|
||||
/// <param name="idxMacchina"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> IobInsEnabAsync(string idxMacchina)
|
||||
{
|
||||
var key = Utils.RedKeyDatiMacc(idxMacchina, MpIoNS);
|
||||
|
||||
// 1. Tentativo ottimizzato: leggiamo solo il campo che ci serve
|
||||
// Supponendo che tu usi StackExchange.Redis direttamente o un wrapper
|
||||
string? val = await redisDb.HashGetAsync(key, "insEnabled");
|
||||
|
||||
// 2. Se non c'è in cache, carichiamo/resettiamo tutto
|
||||
if (val == null)
|
||||
{
|
||||
var data = await ResetDatiMacchinaAsync(idxMacchina);
|
||||
data.TryGetValue("insEnabled", out val);
|
||||
}
|
||||
|
||||
// 3. Parsing sicuro
|
||||
return val != null && (val == "1" || val.ToLower() == "true");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="IdxOdl">idxMacc odl da cercare</param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<AnagGiacenzeModel>> ListGiacenze(int IdxOdl)
|
||||
{
|
||||
@@ -1229,6 +1374,40 @@ namespace MP.IOC.Data
|
||||
Log.Debug($"Macchine2SlaveGetAll | Read from {readType}: {ts.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// Elenco completo valori Macchine 2 Slave
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<Macchine2SlaveModel>> Macchine2SlaveGetAllAsync()
|
||||
{
|
||||
List<Macchine2SlaveModel>? result = new List<Macchine2SlaveModel>();
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
string readType = "DB";
|
||||
string currKey = $"{Utils.redisBaseAddr}:M2STab";
|
||||
// cerco in redis dato valore sel macchina...
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<Macchine2SlaveModel>>($"{rawData}");
|
||||
readType = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await IocDbController.Macchine2SlaveAsync();
|
||||
// serializzo e salvo...
|
||||
rawData = JsonConvert.SerializeObject(result);
|
||||
await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache));
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<Macchine2SlaveModel>();
|
||||
}
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Debug($"Macchine2SlaveGetAllAsync | Read from {readType}: {ts.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco di tutte le macchine gestite
|
||||
@@ -1338,7 +1517,7 @@ namespace MP.IOC.Data
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco id Macchine che abbiano dati FLuxLog, nel periodo indicato
|
||||
/// Elenco idxMacc Macchine che abbiano dati FLuxLog, nel periodo indicato
|
||||
/// </summary>
|
||||
/// <param name="dtStart"></param>
|
||||
/// <param name="dtEnd"></param>
|
||||
@@ -1596,6 +1775,33 @@ namespace MP.IOC.Data
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restitusice elenco KVP dei campi DatiMacchine + StatoMacchine per l'impianto indicato
|
||||
/// </summary>
|
||||
/// <param name="idxMacchina"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<Dictionary<string, string>> mDatiMacchineAsync(string idxMacchina)
|
||||
{
|
||||
// hard coded dimensione vettore DatiMacchine
|
||||
Dictionary<string, string> answ = new Dictionary<string, string>();
|
||||
// ORA recupero da memoria redis...
|
||||
try
|
||||
{
|
||||
var currHash = Utils.RedKeyDatiMacc(idxMacchina, MpIoNS);
|
||||
answ = await RedisGetHashDictAsync(currHash);
|
||||
// se è vuoto... leggo da DB e popolo!
|
||||
if (answ.Count == 0)
|
||||
{
|
||||
answ = ResetDatiMacchina(idxMacchina);
|
||||
}
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Errore in compilazione dati Macchine x Redis - idxMacchina {idxMacchina}:{Environment.NewLine}{exc}");
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato
|
||||
/// </summary>
|
||||
@@ -1640,6 +1846,39 @@ namespace MP.IOC.Data
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco da tabella MappaStatoExplModel
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<MappaStatoExplModel>> MseGetAllAsync(bool forceDb = false)
|
||||
{
|
||||
Stopwatch sw = new Stopwatch();
|
||||
string source = "DB";
|
||||
sw.Start();
|
||||
List<MappaStatoExplModel>? result = new List<MappaStatoExplModel>();
|
||||
// cerco in _redisConn...
|
||||
RedisValue rawData = await redisDb.StringGetAsync(Constants.redisMseKey);
|
||||
if (rawData.HasValue && !forceDb)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<MappaStatoExplModel>>($"{rawData}") ?? new();
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await IocDbController.MseGetAllAsync(maxAge);
|
||||
// serializzp e salvo...
|
||||
rawData = JsonConvert.SerializeObject(result);
|
||||
await redisDb.StringSetAsync(Constants.redisMseKey, rawData, getRandTOut(redisShortTimeCache / 2));
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<MappaStatoExplModel>();
|
||||
}
|
||||
sw.Stop();
|
||||
Log.Debug($"MseGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restitusice elenco KVP
|
||||
/// currKey: IdxMacchina
|
||||
@@ -2232,7 +2471,7 @@ namespace MP.IOC.Data
|
||||
/// <param name="dtCurr"></param>
|
||||
/// <param name="contatore"></param>
|
||||
/// <returns></returns>
|
||||
public string processInput(string idxMacchina, string valore, string dtEve, string dtCurr, string contatore)
|
||||
public async Task<string> ProcessInputAsync(string idxMacchina, string valore, string dtEve, string dtCurr, string contatore)
|
||||
{
|
||||
string answ = "";
|
||||
// 2018.10.26 controllo dtEve e dtCurr
|
||||
@@ -2263,7 +2502,7 @@ namespace MP.IOC.Data
|
||||
// se ho meno decimali x evento rispetto dtCorrente...
|
||||
if (dtEve.Length < dtCurr.Length)
|
||||
{
|
||||
Log.Info($"processInput: fix valore dtEve: {dtEve} | dtCurr: {dtCurr}");
|
||||
Log.Info($"ProcessInputAsync: fix valore dtEve: {dtEve} | dtCurr: {dtCurr}");
|
||||
dtEve = dtEve.PadRight(dtCurr.Length, '0');
|
||||
}
|
||||
delta = Convert.ToInt64(dtCurr) - Convert.ToInt64(dtEve);
|
||||
@@ -2320,13 +2559,13 @@ namespace MP.IOC.Data
|
||||
{
|
||||
int cntVal = 0;
|
||||
int.TryParse(contatore, out cntVal);
|
||||
saveSigLog(idxMacchina, valore, dataOraEvento, cntVal);
|
||||
await saveSigLogAsync(idxMacchina, valore, dataOraEvento, cntVal);
|
||||
}
|
||||
// continuo col resto
|
||||
try
|
||||
{
|
||||
// scrivo keep alive!!! (se necessario, altrimenti è in cache...)
|
||||
ScriviKeepAlive(idxMacchina, DateTime.Now);
|
||||
await ScriviKeepAliveAsync(idxMacchina, DateTime.Now);
|
||||
// verifico se sia una macchina MULTI ed in tal caso calcolo i
|
||||
// SUB-systems e CHIAMERO' alla fine pure loro....
|
||||
if (isMulti(idxMacchina))
|
||||
@@ -2339,14 +2578,14 @@ namespace MP.IOC.Data
|
||||
newVal = preProcInput(item.Key, valore);
|
||||
// ora processo e salvo il valore del microstato...
|
||||
// INTERNAMENTE gestisce i casi DB/REDIS secondo necessità
|
||||
checkMicroStato(item.Key, newVal, dataOraEvento, contatore);
|
||||
await CheckMicroStatoAsync(item.Key, newVal, dataOraEvento, contatore);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ora processo e salvo il valore del microstato... INTERNAMENTE
|
||||
// gestisce i casi DB/REDIS secondo necessità
|
||||
checkMicroStato(idxMacchina, valore, dataOraEvento, contatore);
|
||||
await CheckMicroStatoAsync(idxMacchina, valore, dataOraEvento, contatore);
|
||||
}
|
||||
// registro in risposta che è andato tutto bene...
|
||||
answ = "OK";
|
||||
@@ -2836,11 +3075,15 @@ namespace MP.IOC.Data
|
||||
return answ;
|
||||
}
|
||||
|
||||
public async Task<bool> RedisSetHashDictAsync(RedisKey redKey, Dictionary<string, string> valori)
|
||||
public async Task<bool> RedisSetHashDictAsync(RedisKey redKey, Dictionary<string, string> valori, double expireSeconds = -1.0)
|
||||
{
|
||||
bool answ = false;
|
||||
HashEntry[] redHash = valori.Select(x => new HashEntry(x.Key, x.Value)).ToArray();
|
||||
await redisDb.HashSetAsync(redKey, redHash);
|
||||
if (expireSeconds > 0.0)
|
||||
{
|
||||
redisDb.KeyExpire(redKey, DateTime.Now.AddSeconds(expireSeconds));
|
||||
}
|
||||
answ = true;
|
||||
return answ;
|
||||
}
|
||||
@@ -3266,6 +3509,27 @@ namespace MP.IOC.Data
|
||||
return IocDbController.SignalLogInsert(newRec);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// salva il segnale di "microstato" (segnale) ASYNC
|
||||
/// </summary>
|
||||
/// <param name="idxMacchina">idx macchina</param>
|
||||
/// <param name="valore">valore ingresso</param>
|
||||
/// <param name="dtEve">data-ora evento (server)</param>
|
||||
/// <param name="contatore">contatore sequenza dati inviati</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> saveSigLogAsync(string idxMacchina, string valore, DateTime dtEve, int contatore)
|
||||
{
|
||||
SignalLogModel newRec = new SignalLogModel()
|
||||
{
|
||||
IdxMacchina = idxMacchina,
|
||||
DtCurr = DateTime.Now,
|
||||
DtEve = dtEve,
|
||||
Contatore = contatore,
|
||||
Valore = valore
|
||||
};
|
||||
return await IocDbController.SignalLogInsertAsync(newRec);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// scrive un evento di keepalive sulla tabella
|
||||
/// </summary>
|
||||
@@ -3593,6 +3857,28 @@ namespace MP.IOC.Data
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
/// <summary>
|
||||
/// Recupera ArtNum dato CodArt (per impianti che accettano solo INT in scrittura)
|
||||
/// </summary>
|
||||
/// <param name="CodArt">
|
||||
/// CodArt richiesto, se vuoto restituisce TUTTI i valori in tabella di decodifica
|
||||
/// </param>
|
||||
/// <returns>Dizionario contenente le righe delle codifiche attive Articolo/Numero</returns>
|
||||
internal async Task<Dictionary<string, int>> GetArtNumAsync(string codArt)
|
||||
{
|
||||
Dictionary<string, int> answ = new Dictionary<string, int>();
|
||||
var currData = await DecNumArtGetFiltAsync(codArt);
|
||||
foreach (var item in currData)
|
||||
{
|
||||
answ.Add(item.CodArticolo, item.NumART);
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
#endregion Internal Methods
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected Random rand = new Random();
|
||||
@@ -3628,6 +3914,11 @@ namespace MP.IOC.Data
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
/// <summary>
|
||||
/// MS max age x dato MSE
|
||||
/// </summary>
|
||||
private int maxAge = 2000;
|
||||
|
||||
private string MpIoNS = "";
|
||||
|
||||
/// <summary>
|
||||
@@ -3725,6 +4016,144 @@ namespace MP.IOC.Data
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restituisce l'elenco codici flusso (da confFlux) x una macchina (se presenti) Impiegata
|
||||
/// anche cache redis
|
||||
/// </summary>
|
||||
/// <param name="idxMacchina"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<List<string>> ConfFluxMach(string idxMacchina)
|
||||
{
|
||||
List<string> resultList = new List<string>();
|
||||
string tag = string.IsNullOrEmpty(idxMacchina) ? "ALL" : idxMacchina;
|
||||
var currKey = $"{Utils.redisConfFlux}:{tag}";
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
resultList = JsonConvert.DeserializeObject<List<string>>($"{rawData}") ?? new();
|
||||
}
|
||||
else
|
||||
{
|
||||
var dbData = await IocDbController.ConfFluxFiltAsync(idxMacchina);
|
||||
resultList = dbData
|
||||
.Select(x => x.CodFlux)
|
||||
.ToList();
|
||||
// serializzo e salvo...
|
||||
rawData = JsonConvert.SerializeObject(resultList);
|
||||
await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache));
|
||||
}
|
||||
if (resultList == null)
|
||||
{
|
||||
resultList = new();
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restituisce l'elenco delle date dei dossier x una macchina (se presenti) Impiegata anche
|
||||
/// cache redis
|
||||
/// </summary>
|
||||
/// <param name="idxMacchina"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<List<DateTime>> DossierLastByMachAsync(string idxMacchina)
|
||||
{
|
||||
List<DateTime> resultList = new List<DateTime>();
|
||||
|
||||
var currKey = $"{Utils.redisDossByMacLast}:{idxMacchina}";
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
resultList = JsonConvert.DeserializeObject<List<DateTime>>($"{rawData}") ?? new();
|
||||
}
|
||||
else
|
||||
{
|
||||
var dbData = await IocDbController.DossGetLastByMaccAsync(idxMacchina);
|
||||
resultList = dbData
|
||||
.Select(x => x.DtRif)
|
||||
.ToList();
|
||||
// serializzo e salvo...
|
||||
rawData = JsonConvert.SerializeObject(resultList);
|
||||
await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache));
|
||||
}
|
||||
if (resultList == null)
|
||||
{
|
||||
resultList = new List<DateTime>();
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Svuota la cache redis x l'elenco delle righe di confFlux x una macchina (se presenti)
|
||||
/// </summary>
|
||||
/// <param name="idxMacchina"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<bool> DossierLastByMachResetAsync(string idxMacchina)
|
||||
{
|
||||
bool answ = false;
|
||||
var currKey = $"{Utils.redisDossByMacLast}:{idxMacchina}";
|
||||
await redisDb.KeyDeleteAsync(currKey);
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restituisce l'elenco delle data-ora di confFlux x una macchina (se presenti) Impiegata
|
||||
/// anche cache redis
|
||||
/// </summary>
|
||||
/// <param name="idxMacchina"></param>
|
||||
/// <param name="numMax">num record da recuperare</param>
|
||||
/// <returns></returns>
|
||||
private async Task<List<DateTime>> FluxLogFirstByMachAsync(string idxMacchina, int numMax = 10)
|
||||
{
|
||||
List<DateTime> resultList = new List<DateTime>();
|
||||
|
||||
var currKey = $"{Utils.redisFluxByMacFirst}:{idxMacchina}";
|
||||
RedisValue rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
resultList = JsonConvert.DeserializeObject<List<DateTime>>($"{rawData}") ?? new();
|
||||
}
|
||||
else
|
||||
{
|
||||
var dbData = await IocDbController.FluxLogFirstByMaccAsync(idxMacchina, numMax);
|
||||
resultList = dbData
|
||||
.Select(x => x.dtEvento)
|
||||
.ToList();
|
||||
// serializzo e salvo...
|
||||
rawData = JsonConvert.SerializeObject(resultList);
|
||||
await redisDb.StringSetAsync(currKey, rawData, getRandTOut(redisLongTimeCache));
|
||||
}
|
||||
if (resultList == null)
|
||||
{
|
||||
resultList = new List<DateTime>();
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua vera chiamata x salvataggio snapshot dati FluxLog
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="maxSec"></param>
|
||||
/// <param name="caller"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<string> FluxLogSaveSnapshotAsync(string id, DateTime dtStart, DateTime dtEnd, string caller)
|
||||
{
|
||||
string answ = "";
|
||||
DateTime dataOraEvento = DateTime.Now;
|
||||
Log.Debug($"{caller} | Richiesta snapshot dati FluxLog macchina: id: {id} | periodo: {dtStart} - {dtEnd}");
|
||||
try
|
||||
{
|
||||
bool fatto = await IocDbController.FluxLogTakeSnapshotLastAsync(id, dtStart, dtEnd);
|
||||
answ = fatto ? "OK" : "KO";
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Errore in {caller}{Environment.NewLine}{exc}");
|
||||
answ = "NO";
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupero info ODL corrente da dati prod macchina
|
||||
/// </summary>
|
||||
@@ -3904,6 +4333,77 @@ namespace MP.IOC.Data
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restitusice elenco KVP dei campi DatiMacchine + StatoMacchine per l'impianto indicato
|
||||
/// </summary>
|
||||
/// <param name="idxMacc"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<Dictionary<string, string>> ResetDatiMacchinaAsync(string idxMacc)
|
||||
{
|
||||
var currHash = Utils.RedKeyDatiMacc(idxMacc, MpIoNS);
|
||||
// inizio con un bel reset...
|
||||
RedisFlushPattern($"{currHash}");
|
||||
Dictionary<string, string>? result = new Dictionary<string, string>();
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
string readType = "DB";
|
||||
var dbResults = await IocDbController.VMSFDGetByMaccAsync(idxMacc);
|
||||
// converto in formato dizionario...
|
||||
if (dbResults != null && dbResults.Count > 0)
|
||||
{
|
||||
var rowResult = dbResults[0];
|
||||
// salvo 1:1 i valori... STATO
|
||||
result.Add("IdxMicroStato", $"{rowResult.IdxMicroStato}");
|
||||
result.Add("IdxStato", $"{rowResult.IdxStato}");
|
||||
result.Add("CodArticolo", $"{rowResult.CodArticolo}");
|
||||
result.Add("insEnabled", $"{rowResult.InsEnabled}");
|
||||
result.Add("sLogEnabled", $"{rowResult.SLogEnabled}");
|
||||
result.Add("pallet", $"{rowResult.Pallet}");
|
||||
result.Add("CodArticolo_A", $"{rowResult.CodArticoloA}");
|
||||
result.Add("CodArticolo_B", $"{rowResult.CodArticoloB}");
|
||||
result.Add("TempoCicloBase", $"{rowResult.TempoCicloBase}");
|
||||
result.Add("PzPalletProd", $"{rowResult.PzPalletProd}");
|
||||
result.Add("MatrOpr", $"{rowResult.MatrOpr}");
|
||||
result.Add("lastVal", $"{rowResult.LastVal}");
|
||||
result.Add("TCBase", $"{rowResult.TempoCicloBase}");
|
||||
|
||||
//...e SETUP
|
||||
result.Add("CodMacc", $"{rowResult.Codmacchina}");
|
||||
result.Add("IdxFamIn", $"{rowResult.IdxFamigliaIngresso}");
|
||||
result.Add("Multi", $"{rowResult.Multi}");
|
||||
result.Add("BitFilt", $"{rowResult.BitFilt}");
|
||||
result.Add("MaxVal", $"{rowResult.MaxVal}");
|
||||
result.Add("BSR", $"{rowResult.Bsr}");
|
||||
result.Add("ExplodeBit", $"{rowResult.ExplodeBit}");
|
||||
result.Add("NumBit", $"{rowResult.NumBit}");
|
||||
result.Add("IdxFamMacc", $"{rowResult.IdxFamiglia}");
|
||||
result.Add("simplePallet", $"{rowResult.SimplePallet}");
|
||||
result.Add("palletChange", $"{rowResult.PalletChange}");
|
||||
}
|
||||
// cerco info Master/slave...
|
||||
var m2sTab = await Macchine2SlaveGetAllAsync();
|
||||
string isMaster = m2sTab.Where(x => x.IdxMacchina == idxMacc).Count() > 0 ? "1" : "0";
|
||||
string isSlave = m2sTab.Where(x => x.IdxMacchinaSlave == idxMacc).Count() > 0 ? "1" : "0";
|
||||
result.Add("Master", isMaster);
|
||||
result.Add("Slave", isSlave);
|
||||
|
||||
// durata cache in secondi dal valore insEnabled...
|
||||
double numSecCache = 60 * ((result["insEnabled"].ToLower() == "true") ? redisShortTimeCache / 4 : redisShortTimeCache);
|
||||
// ...e salvo...
|
||||
await RedisSetHashDictAsync(currHash, result, numSecCache);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
result = new Dictionary<string, string>();
|
||||
}
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Debug($"GetCurrMSFDMacc | Read from {readType}: {ts.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Resetta (rileggendo) i dati della State Machine ingressi nel formato
|
||||
/// currKey: cState_nVal (current MICRO-STATE + "_" + new Value)
|
||||
@@ -3967,6 +4467,32 @@ namespace MP.IOC.Data
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scrive una riga di evento nel db + check cambio stato DiarioDiBordo
|
||||
/// </summary>
|
||||
/// <param name="newRec">codice macchina</param>
|
||||
/// <returns></returns>
|
||||
private async Task<inputComandoMapo> scriviRigaEventoAsync(EventListModel newRec)
|
||||
{
|
||||
bool inserito = false;
|
||||
try
|
||||
{
|
||||
// inserisco evento
|
||||
inserito = await IocDbController.EvListInsertAsync(newRec);
|
||||
// faccio controllo per eventuale cambio stato da tab transizioni...
|
||||
checkCambiaStatoBatch(tipoInputEvento.hw, newRec.IdxMacchina, newRec.InizioStato ?? DateTime.Now, newRec.IdxTipo, newRec.CodArticolo, newRec.Value, newRec.MatrOpr, newRec.pallet);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Errore in scriviRigaEvento | IdxMacchina {newRec.IdxMacchina} | IdxTipo {newRec.IdxTipo} | codArticolo {newRec.CodArticolo} | Value {newRec.Value} | MatrOpr {newRec.MatrOpr} | Pallet {newRec.pallet} | dTime {newRec.InizioStato}{Environment.NewLine}{exc}");
|
||||
}
|
||||
// formatto output
|
||||
inputComandoMapo answ = new inputComandoMapo();
|
||||
answ.outValue = inserito.ToString();
|
||||
answ.needStatusRefresh = true;
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restituisce il valore booleano se la macchina sia abilitata all'inserimento COMPLETO nel
|
||||
/// Signal Log
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>6.16.2604.1517</Version>
|
||||
<Version>6.16.2604.1608</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<i>Modulo MP-IOC </i>
|
||||
<h4>Versione: 6.16.2604.1517</h4>
|
||||
<h4>Versione: 6.16.2604.1608</h4>
|
||||
<br /> Note di rilascio:
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1 +1 @@
|
||||
6.16.2604.1517
|
||||
6.16.2604.1608
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<item>
|
||||
<version>6.16.2604.1517</version>
|
||||
<version>6.16.2604.1608</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>
|
||||
|
||||
Reference in New Issue
Block a user