diff --git a/MP.Core/Utils.cs b/MP.Core/Utils.cs index 6f8d33c6..4310cc6b 100644 --- a/MP.Core/Utils.cs +++ b/MP.Core/Utils.cs @@ -62,9 +62,12 @@ namespace MP.Core public const string redisPOdlList = redisXdlData + "POdlList"; + public const string redisPzCount = redisBaseAddr + "Cache:PzCount"; + public const string redisRecipeConf = redisBaseAddr + "Cache:Recipe:Conf"; public const string redisStatoCom = redisBaseAddr + "Cache:StatoCom"; + public const string redisStatoProd = redisBaseAddr + "Cache:StatoProd"; public const string redisStatsDbMaint = redisBaseAddr + "Stats:DbMaint"; diff --git a/MP.Data/Controllers/MpIocController.cs b/MP.Data/Controllers/MpIocController.cs index 17a9d49e..e6eaea32 100644 --- a/MP.Data/Controllers/MpIocController.cs +++ b/MP.Data/Controllers/MpIocController.cs @@ -25,7 +25,6 @@ namespace MP.Data.Controllers #region Public Methods - /// /// Elenco da tabella Config /// @@ -91,7 +90,6 @@ namespace MP.Data.Controllers _configuration = null; } - /// /// Aggiunta record EventList /// @@ -177,7 +175,6 @@ namespace MP.Data.Controllers return fatto; } - public List ListLinkFilt(string tipoLink) { List dbResult = new List(); @@ -274,6 +271,26 @@ namespace MP.Data.Controllers return dbResult; } + /// + /// Stato prod macchina + /// + /// + /// + public PzProdModel PezziProdMacchina(string idxMacchina) + { + PzProdModel dbResult = new PzProdModel(); + using (var dbCtx = new MoonProContext(_configuration)) + { + var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); + dbResult = dbCtx + .DbSetPzProd + .FromSqlRaw("EXEC stp_PzProd_getByMacchina @IdxMacchina", IdxMacchina) + .AsNoTracking() + .FirstOrDefault(); + } + return dbResult; + } + /// /// Annulla modifiche su una specifica entity (cancel update) /// @@ -320,20 +337,25 @@ namespace MP.Data.Controllers } /// - /// Stato prod macchina + /// Stato prod macchina (completo) /// /// + /// /// - public PzProdModel PezziProdMacchina(string idxMacchina) + public StatoProdModel StatoProdMacchina(string idxMacchina, DateTime dtReq) { - PzProdModel dbResult = new PzProdModel(); + StatoProdModel dbResult = new StatoProdModel(); using (var dbCtx = new MoonProContext(_configuration)) { var IdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina); - dbResult = dbCtx - .DbSetPzProd - .FromSqlRaw("EXEC stp_PzProd_getByMacchina @IdxMacchina", IdxMacchina) + var DataOra = new SqlParameter("@DataOra ", dtReq); + var rawData = dbCtx + .DbSetStatoProd + .FromSqlRaw("EXEC stp_StatoProd_getByMacchina @IdxMacchina, @DataOra ", IdxMacchina, DataOra) .AsNoTracking() + .AsEnumerable() + .ToList(); + dbResult = rawData .FirstOrDefault(); } return dbResult; @@ -378,6 +400,7 @@ namespace MP.Data.Controllers } return dbResult; } + /// /// Vista v_MSFD delle machine MULTI filtrato x macchina (da stored) /// diff --git a/MP.Data/Services/TabDataService.cs b/MP.Data/Services/TabDataService.cs index 0aa47c54..ef43d8e2 100644 --- a/MP.Data/Services/TabDataService.cs +++ b/MP.Data/Services/TabDataService.cs @@ -2498,7 +2498,7 @@ namespace MP.Data.Services int answ = -1; saveCallRec("getCounterTC"); DateTime dataRif = DateTime.Now; - var datiProd = await StatoProdMacchina(idxMacchina, dataRif); + var datiProd = await StatoProdMacchinaAsync(idxMacchina, dataRif); if (datiProd != null) { answ = datiProd.PzTotODL; @@ -3434,7 +3434,7 @@ namespace MP.Data.Services /// /// /// - public async Task StatoProdMacchina(string idxMacchina, DateTime dtReq) + public async Task StatoProdMacchinaAsync(string idxMacchina, DateTime dtReq) { int rndWait = rnd.Next(0, 2); await Task.Delay(rndWait); @@ -3445,9 +3445,6 @@ namespace MP.Data.Services StatoProdModel? result = new StatoProdModel(); // cerco in _redisConn... string currKey = $"{redisBaseKey}:StatoProd:{idxMacchina}:{dtReq:HHmm}"; -#if false - RedisValue rawData = redisDb.StringGet(currKey); -#endif RedisValue rawData = await _redisDb.StringGetAsync(currKey); //if (!string.IsNullOrEmpty($"{rawData}")) if (rawData.HasValue) @@ -3460,9 +3457,6 @@ namespace MP.Data.Services result = dbTabController.StatoProdMacchina(idxMacchina, dtReq); // serializzo e salvo... rawData = JsonConvert.SerializeObject(result); -#if false - redisDb.StringSet(currKey, rawData, UltraFastCache); -#endif await _redisDb.StringSetAsync(currKey, rawData, UltraFastCache); } if (result == null) @@ -3470,10 +3464,7 @@ namespace MP.Data.Services result = new StatoProdModel(); } sw.Stop(); -#if false - Log.Debug($"StatoProdMacchina | {source} | {sw.Elapsed.TotalMilliseconds}ms"); -#endif - string callName = $"StatoProdMacchina.{source}"; + string callName = $"StatoProdMacchinaAsync.{source}"; int numRec = esCollect.RecordCall(callName, sw.Elapsed.TotalMilliseconds); if (numRec >= nRecLog || true) { diff --git a/MP.IOC/Controllers/IOBController.cs b/MP.IOC/Controllers/IOBController.cs index c1239fab..22a5d776 100644 --- a/MP.IOC/Controllers/IOBController.cs +++ b/MP.IOC/Controllers/IOBController.cs @@ -23,19 +23,17 @@ namespace MP.IOC.Controllers #region Public Methods /// SALVA x macchina KVP parametro/valore: - /// /// GET: api/IOB/addOptPar/SIMUL_03?pName=PZREQ&pValue=1000 - /// /// [HttpGet("addOptPar/{id}")] - public string addOptPar(string id, string pName, string pValue) + public string AddOptPar(string id, string pName, string pValue) { string answ = ""; DService.ScriviKeepAlive(id, DateTime.Now); try { DService.AddOptPar4Machine(id, pName, pValue); - answ = getOptPar(id); + answ = GetOptPar(id); } catch { } @@ -58,7 +56,7 @@ namespace MP.IOC.Controllers /// /// [HttpGet("enabled/{id}")] - public IActionResult enabled(string id) + public IActionResult Enabled(string id) { if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID"); @@ -68,8 +66,8 @@ namespace MP.IOC.Controllers } else { - return UnprocessableEntity("NO"); // O un altro errore appropriato - //return StatusCode(503, "NO"); // O un altro errore appropriato + //return StatusCode(503, "NO"); + return UnprocessableEntity("NO"); } #if false if (string.IsNullOrEmpty(id)) return Ok("KO"); @@ -88,6 +86,114 @@ namespace MP.IOC.Controllers #endif } + /// + /// Recupera COUNTER x macchina: + /// GET: IOB/getCounter/SIMUL_03 + /// + /// + /// Il conteggio pezzi o un errore strutturato + [HttpGet("getCounter/{id}")] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(int))] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetCounter(string id) + { + if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID"); + + try + { + var pzCount = await DService.pzCounter(id); + return Ok(pzCount); + } + catch (Exception exc) + { + Log.Error(exc, "Errore durante il recupero del counter per la macchina {MachineId}", id); + return StatusCode(StatusCodes.Status500InternalServerError, "Errore interno | GetCounter"); + } + } + + /// + /// Recupera COUNTER x macchina dal CONTEGGIO dei TCRecorded: + /// + /// GET: IOB/getCounterTCRec/5 + /// + /// + /// Il conteggio pezzi o un errore strutturato + [HttpGet("getCounterTCRec/{id}")] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(int))] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task GetCounterTCRec(string id) + { + if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID"); + + // attenzione! poiché nell'URL il carattere "#" viene filtrato ci aspettiamo il + // carattere "|" che poi trasformiamo ora in "#" + id = id.Replace("|", "#"); + try + { + var pzCount = await DService.pzCounterTC(id); + return Ok(pzCount); + } + catch (Exception exc) + { + Log.Error(exc, "Errore durante il recupero del counter TC per la macchina {MachineId}", id); + return StatusCode(StatusCodes.Status500InternalServerError, "Errore interno | GetCounterTCRec"); + } + } + +#if false + /// + /// Recupera COUNTER x macchina: + /// + /// GET: IOB/getCounter/5 + /// + /// + /// + [HttpGet("getCounter/{id}")] + public async Task getCounter(string id) + { + string answ = ""; + try + { + var pzCount = await _tabDService.pzCounter(id); + answ = $"{pzCount}"; + } + catch (Exception exc) + { + Log.Error($"Errore in counter TC (get){Environment.NewLine}{exc}"); + answ = "NO"; + } + return answ; + } + /// + /// Recupera COUNTER x macchina dal CONTEGGIO dei TCRecorded: + /// + /// GET: IOB/getCounterTCRec/5 + /// + /// + /// + [HttpGet("getCounterTCRec/{id}")] + public async Task getCounterTCRec(string id) + { + // attenzione! poiché nell'URL il carattere "#" viene filtrato ci aspettiamo il + // carattere "|" che poi trasformiamo ora in "#" + id = id.Replace("|", "#"); + string answ = ""; + try + { + var pzCountTC = await _tabDService.pzCounterTC(id); + answ = $"{pzCountTC}"; + } + catch (Exception exc) + { + Log.Error($"Errore in counter TC (get){Environment.NewLine}{exc}"); + answ = "NO"; + } + return answ; + } +#endif + /// /// Recupera TASK richiesto x macchina: /// @@ -96,7 +202,7 @@ namespace MP.IOC.Controllers /// /// Json contenente 1..n task da eseguire [HttpGet("getOptPar/{id}")] - public string getOptPar(string id) + public string GetOptPar(string id) { string answ = ""; // scrivo keep alive!!! (se necessario, altrimenti è in cache...) @@ -113,7 +219,7 @@ namespace MP.IOC.Controllers } [HttpGet("version")] - public IActionResult version() + public IActionResult Version() { var version = Assembly .GetExecutingAssembly() @@ -126,15 +232,6 @@ namespace MP.IOC.Controllers #endregion Public Methods - #region Protected Properties - - /// - /// Dataservice x accesso DB - /// - protected MpDataService DService { get; set; } - - #endregion Protected Properties - #region Private Fields private static IConfiguration _configuration = null!; @@ -143,6 +240,15 @@ namespace MP.IOC.Controllers #endregion Private Fields + #region Private Properties + + /// + /// Dataservice x accesso DB + /// + private MpDataService DService { get; set; } + + #endregion Private Properties + ///// AGGIUNGE TASK richiesto x macchina: ///// ///// GET: IOB/addTask2Exe/3010?taskName=startSetup&taskVal=T190406101512 @@ -706,52 +812,6 @@ namespace MP.IOC.Controllers // return answ; //} - ///// - ///// Recupera COUNTER x macchina: - ///// - ///// GET: IOB/getCounter/5 - ///// - ///// - ///// - //public string getCounter(string id) - //{ - // string answ = ""; - // try - // { - // DataLayer DataLayerObj = new DataLayer(); - // answ = DataLayerObj.pzCounter(id).ToString(); - // } - // catch (Exception exc) - // { - // logger.lg.scriviLog(string.Format("Errore in counter (get){0}{1}", Destination.NewLine, exc)); - // answ = "NO"; - // } - // return answ; - //} - - ///// - ///// Recupera COUNTER x macchina dal CONTEGGIO dei TCRecorded: - ///// - ///// GET: IOB/getCounterTCRec/5 - ///// - ///// - ///// - //public string getCounterTCRec(string id) - //{ - // string answ = ""; - // try - // { - // DataLayer DataLayerObj = new DataLayer(); - // answ = DataLayerObj.pzCounterTC(id).ToString(); - // } - // catch (Exception exc) - // { - // logger.lg.scriviLog(string.Format("Errore in counter TC (get){0}{1}", Destination.NewLine, exc)); - // answ = "NO"; - // } - // return answ; - //} - ///// ///// Recupera DATI correnti x macchina: ///// diff --git a/MP.IOC/Data/MpDataService.cs b/MP.IOC/Data/MpDataService.cs index 714c40a0..005c1417 100644 --- a/MP.IOC/Data/MpDataService.cs +++ b/MP.IOC/Data/MpDataService.cs @@ -1476,6 +1476,53 @@ namespace MP.IOC.Data return dbResult; } + /// + /// Restituisce il contapezzi salvato per la macchina + /// + /// + /// + public async Task pzCounter(string idxMacchina) + { + int answ = -1; + try + { + string currKey = $"{Utils.redisPzCount}:{idxMacchina}"; + RedisValue rawData = redisDb.StringGet(currKey); + if (rawData.HasValue) + { + int.TryParse(rawData, out answ); + } + else + { + answ = await pzCounterTC(idxMacchina); + // salvo in _redisConn... + await redisDb.StringSetAsync(currKey, answ.ToString()); + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in pzCounter{Environment.NewLine}{exc}"); + } + return answ; + } + + /// + /// Restituisce il contapezzi come CONTEGGIO da TCRilevati per la macchina + /// + /// + /// + public async Task pzCounterTC(string idxMacchina) + { + int answ = -1; + DateTime dataRif = DateTime.Now; + var datiProd = await StatoProdMacchinaAsync(idxMacchina, dataRif); + if (datiProd != null) + { + answ = datiProd.PzTotODL; + } + return answ; + } + /// /// Ricerca ricetta su MongoDB dato PODL /// @@ -1738,18 +1785,6 @@ namespace MP.IOC.Data return answ; } - public bool RedisSetKey(string valKey, string redVal) - { - bool answ = redisDb.StringSet(Utils.RedKeyHash(valKey), redVal); - return answ; - } - - public bool RedisSetKey(RedisKey valKey, string redVal, int TTL_sec) - { - bool answ = redisDb.StringSet(Utils.RedKeyHash(valKey), redVal, TimeSpan.FromSeconds(TTL_sec)); - return answ; - } - /// /// Restitusice elenco KVP dei campi DatiMacchine + StatoMacchine per l'impianto indicato /// @@ -1878,7 +1913,7 @@ namespace MP.IOC.Data // se NON presente salvo in REDIS con TTL 10 sec e sul DB... if (!keyPresent) { - RedisSetKey(currKey, adesso.ToString("s"), 10); + redisDb.StringSet(currKey, adesso.ToString("s"), TimeSpan.FromSeconds(10)); try { Log.Trace($"Scrittura keep alive! IdxMacchina: {IdxMacchina}"); @@ -2121,6 +2156,7 @@ namespace MP.IOC.Data #region Private Fields private static IConfiguration _configuration = null!; + private static ILogger _logger = null!; private static Logger Log = LogManager.GetCurrentClassLogger(); @@ -2146,8 +2182,14 @@ namespace MP.IOC.Data private IDatabase redisDb = null!; private int redisLongTimeCache = 5; + private int redisShortTimeCache = 2; + /// + /// Generatore random classe + /// + private Random rnd = new Random(); + #endregion Private Fields #region Private Methods @@ -2175,6 +2217,66 @@ namespace MP.IOC.Data await RedisFlushPatternAsync(pattern); } + /// + /// Stato prod macchina (completo) + /// + /// + /// + /// + private async Task StatoProdMacchinaAsync(string idxMacchina, DateTime dtReq) + { + int rndWait = rnd.Next(0, 2); + await Task.Delay(rndWait); + // setup parametri costanti + string source = "DB"; + StatoProdModel? result = new StatoProdModel(); + // cerco in _redisConn... + string currKey = $"{Utils.redisStatoProd}:{idxMacchina}:{dtReq:HHmm}"; + RedisValue rawData = await redisDb.StringGetAsync(currKey); + //if (!string.IsNullOrEmpty($"{rawData}")) + if (rawData.HasValue) + { + result = JsonConvert.DeserializeObject($"{rawData}"); + source = "REDIS"; + } + else + { + result = IocDbController.StatoProdMacchina(idxMacchina, dtReq); + // serializzo e salvo... + rawData = JsonConvert.SerializeObject(result); + await redisDb.StringSetAsync(currKey, rawData, TimeSpan.FromSeconds(5)); + } + if (result == null) + { + result = new StatoProdModel(); + } + return result; + } + #endregion Private Methods + +#if false + public bool RedisSetKey(string valKey, string redVal) + { + bool answ = redisDb.StringSet(Utils.RedKeyHash(valKey), redVal); + return answ; + } + public async Task RedisSetKeyAsync(string valKey, string redVal) + { + bool answ = await redisDb.StringSetAsync(Utils.RedKeyHash(valKey), redVal); + return answ; + } + + public bool RedisSetKey(RedisKey valKey, string redVal, int TTL_sec) + { + bool answ = redisDb.StringSet(Utils.RedKeyHash(valKey), redVal, TimeSpan.FromSeconds(TTL_sec)); + return answ; + } + public async Task RedisSetKeyAsync(RedisKey valKey, string redVal, int TTL_sec) + { + bool answ = await redisDb.StringSetAsync(Utils.RedKeyHash(valKey), redVal, TimeSpan.FromSeconds(TTL_sec)); + return answ; + } +#endif } } \ No newline at end of file diff --git a/MP.IOC/MP.IOC.csproj b/MP.IOC/MP.IOC.csproj index 3502570b..65e5d325 100644 --- a/MP.IOC/MP.IOC.csproj +++ b/MP.IOC/MP.IOC.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 6.16.2604.1017 + 6.16.2604.1109 diff --git a/MP.IOC/Program.cs b/MP.IOC/Program.cs index aed57589..aabf3b51 100644 --- a/MP.IOC/Program.cs +++ b/MP.IOC/Program.cs @@ -101,6 +101,8 @@ builder.Services.AddSwaggerGen(c => // avvio oggetto shared x redis... var redisMux = ConnectionMultiplexer.Connect(connStringRedis); builder.Services.AddSingleton(redisMux); + +// oggetto principale accesso dati builder.Services.AddSingleton(); logger.Info("Standard service configured"); diff --git a/MP.IOC/Resources/ChangeLog.html b/MP.IOC/Resources/ChangeLog.html index e95de881..12ae1f77 100644 --- a/MP.IOC/Resources/ChangeLog.html +++ b/MP.IOC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MP-IOC -

Versione: 6.16.2604.1017

+

Versione: 6.16.2604.1109


Note di rilascio:
  • diff --git a/MP.IOC/Resources/VersNum.txt b/MP.IOC/Resources/VersNum.txt index 43632be8..4b72e53b 100644 --- a/MP.IOC/Resources/VersNum.txt +++ b/MP.IOC/Resources/VersNum.txt @@ -1 +1 @@ -6.16.2604.1017 +6.16.2604.1109 diff --git a/MP.IOC/Resources/manifest.xml b/MP.IOC/Resources/manifest.xml index 6875b321..012b1f6e 100644 --- a/MP.IOC/Resources/manifest.xml +++ b/MP.IOC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 6.16.2604.1017 + 6.16.2604.1109 https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/MP.IOC.zip https://nexus.steamware.net/repository/SWS/MP-IOC/stable/LAST/ChangeLog.html false