From cf060cc387d048ef28e9873a22f6f21b16a6897b Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Fri, 17 Apr 2026 08:55:00 +0200 Subject: [PATCH] Completato fix metodo AutoODL (da testare!) --- MP.Core/Utils.cs | 1 + MP.Data/Controllers/MpIocController.cs | 226 ++++++++++++- MP.IOC/Controllers/IOBController.cs | 31 ++ MP.IOC/Data/MpDataService.cs | 434 ++++++++++++++++++++++++- MP.IOC/MP.IOC.csproj | 2 +- MP.IOC/Resources/ChangeLog.html | 2 +- MP.IOC/Resources/VersNum.txt | 2 +- MP.IOC/Resources/manifest.xml | 2 +- 8 files changed, 693 insertions(+), 7 deletions(-) diff --git a/MP.Core/Utils.cs b/MP.Core/Utils.cs index e2923703..21ff1646 100644 --- a/MP.Core/Utils.cs +++ b/MP.Core/Utils.cs @@ -78,6 +78,7 @@ namespace MP.Core public const string redisTipoArt = redisBaseAddr + "Cache:TipoArt"; + public const string redisVetoSplitOdl = redisBaseAddr + "Cache:VetoOdlMacc"; public const string redisVocabolario = redisBaseAddr + "Cache:Vocabolario"; public const string redisXdlData = redisBaseAddr + "Cache:XDL:"; diff --git a/MP.Data/Controllers/MpIocController.cs b/MP.Data/Controllers/MpIocController.cs index 1f8099cf..192249ff 100644 --- a/MP.Data/Controllers/MpIocController.cs +++ b/MP.Data/Controllers/MpIocController.cs @@ -96,6 +96,140 @@ namespace MP.Data.Controllers return dbResult; } + /// + /// Apre in automatico un nuovo PODL/ODL chiudendo l'attuale (aperto) + /// + /// Idx ODL corrente + /// Matricola operatore + /// idx macchina da confermare + /// TempoCiclo richiesto in attrezzaggio + /// # pz pallet + /// note ODL + /// bool per avvio nuovo ODL (def: true) + /// Qty da produrre, deve essere >0 + /// KeyRich esterno, se vuoto uso vecchia, se KIT sovrascritto con KeyKit + /// + public async Task AutoStartOdlAsync(int idxOdl, int MatrOpr, string idxMacchina, decimal tCRich, int pzPallet, string note, bool startNewOdl, int qtyRich, string keyRich) + { + bool answ = false; + try + { + using (var dbCtx = new MoonProContext(_configuration)) + { + var IdxOdl = new SqlParameter("@idxOdl ", idxOdl); + var MatrApp = new SqlParameter("@MatrApp ", MatrOpr); + var IdxMacchina = new SqlParameter("@idxMacchina", idxMacchina); + var TCRich = new SqlParameter("@TCRichAttr", tCRich); + var PzPallet = new SqlParameter("@PzPallet", pzPallet); + var Note = new SqlParameter("@Note", note); + var StartNewOdl = new SqlParameter("@StartNewOdl", startNewOdl); + var QtyRich = new SqlParameter("@QtyRich", qtyRich); + var KeyRichiesta = new SqlParameter("@KeyRichiesta", keyRich); + + var result = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_ODL_AutoStart @idxOdl, @MatrApp, @idxMacchina, @TCRichAttr, @PzPallet, @Note, @StartNewOdl, @QtyRich, @KeyRichiesta", IdxOdl, MatrApp, IdxMacchina, TCRich, PzPallet, Note, StartNewOdl, QtyRich, KeyRichiesta); + + // indico eseguito! + answ = result > 0; + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in ConfermaProdMacchina:{Environment.NewLine}{exc}"); + } + return answ; + } + + /// + /// Effettua conferma prod macchina dell'intero periodo da confermare (ultima conferma - dtEvent) + /// + /// idx macchina da confermare + /// 0=periodo, 1 = giorno, 2 = turno + /// qta pezzi BUONI da confermare + /// qta pezzi SCARTO da confermare + /// DataOra in cui registrare approvazione + /// Matricola operatore + /// + public async Task ConfermaProdMacchinaAsync(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzScarto, DateTime DataOraApp, int MatrOpr) + { + bool answ = false; + try + { + var rigaProd = await StatoProdMacchinaAsync(idxMacchina, DateTime.Now); + using (var dbCtx = new MoonProContext(_configuration)) + { + var IdxMacchina = new SqlParameter("@idxMacchina", idxMacchina); + var MatrApp = new SqlParameter("@MatrApp ", MatrOpr); + var DataFrom = new SqlParameter("@dataFrom ", rigaProd.DataFrom); + var DataTo = new SqlParameter("@dataTo", DataOraApp); + var PezziConf = new SqlParameter("@pezziConf", numPzConfermati); + var PezziScar = new SqlParameter("@pezziScar", numPzScarto); + var TipoConf = new SqlParameter("@TipoConf", modoConfProd); + var DtOraApp = new SqlParameter("@DataOraApp", DataOraApp); + var TestConferma = new SqlParameter("@TestConferma", true); + + var result = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_ConfermaProduzCompleta @idxMacchina, @MatrApp, @dataFrom, @dataTo, @pezziConf, @pezziScar, @TipoConf, @DataOraApp, @TestConferma ", IdxMacchina, MatrApp, DataFrom, DataTo, PezziConf, PezziScar, TipoConf, DtOraApp, TestConferma); + + // indico eseguito! + answ = result > 0; + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in ConfermaProdMacchina:{Environment.NewLine}{exc}"); + } + return answ; + } + + /// + /// Effettua conferma prod macchina dell'intero periodo da confermare (ultima conferma - dtEvent) + /// + /// idx macchina da confermare + /// 0=periodo, 1 = giorno, 2 = turno + /// qta pezzi BUONI da confermare + /// qta pezzi LASCIATI da confermare + /// qta pezzi SCARTO da confermare + /// DataOra in cui registrare approvazione + /// Matricola operatore + /// + public async Task ConfermaProdMacchinaFullAsync(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzLasciati, int numPzScarto, DateTime DataOraApp, int MatrOpr) + { + bool answ = false; + try + { + var rigaProd = await StatoProdMacchinaAsync(idxMacchina, DateTime.Now); + using (var dbCtx = new MoonProContext(_configuration)) + { + var IdxMacchina = new SqlParameter("@idxMacchina", idxMacchina); + var MatrApp = new SqlParameter("@MatrApp ", MatrOpr); + var DataFrom = new SqlParameter("@dataFrom ", rigaProd.DataFrom); + var DataTo = new SqlParameter("@dataTo", DataOraApp); + var PezziConf = new SqlParameter("@pezziConf", numPzConfermati); + var PezziLasc = new SqlParameter("@pezziLasciati", numPzLasciati); + var PezziScar = new SqlParameter("@pezziScar", numPzScarto); + var TipoConf = new SqlParameter("@TipoConf", modoConfProd); + var DtOraApp = new SqlParameter("@DataOraApp", DataOraApp); + var TestConferma = new SqlParameter("@TestConferma", true); + var Force = new SqlParameter("@Force", false); + + var result = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_ConfermaProduzCompletaFull @idxMacchina, @MatrApp, @dataFrom, @dataTo, @pezziConf, @pezziLasciati, @pezziScar, @TipoConf, @DataOraApp, @TestConferma,@Force", IdxMacchina, MatrApp, DataFrom, DataTo, PezziConf, PezziLasc, PezziScar, TipoConf, DtOraApp, TestConferma, Force); + + // indico eseguito! + answ = result > 0; + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in ConfermaProdMacchinaAsync:{Environment.NewLine}{exc}"); + } + return answ; + } + /// /// Record ConfFlux dato macchina (oppure tutti se vuoto) /// @@ -326,6 +460,65 @@ namespace MP.Data.Controllers } return fatto; } + /// + /// Fix ODL per macchine SLAVE + /// + /// + /// + /// + /// + public bool OdlFixMachineSlave(string idxMacchina, int numDayPrev, int doInsert) + { + bool fatto = false; + using (var dbCtx = new MoonProContext(_configuration)) + { + try + { + var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); + var NumDayPrev = new SqlParameter("@NumDayPrev", numDayPrev); + var DoInsert = new SqlParameter("@DoInsert", doInsert); + var result = dbCtx + .Database + .ExecuteSqlRaw("EXEC stp_ODL_fixMachineSlave @IdxMacchina, @NumDayPrev, @DoInsert", IdxMacc, NumDayPrev, DoInsert); + fatto = result != 0; + } + catch (Exception exc) + { + Log.Error($"Eccezione durante OdlFixMachineSlave{Environment.NewLine}{exc}"); + } + } + return fatto; + } + + /// + /// Fix ODL per macchine SLAVE Async + /// + /// + /// + /// + /// + public async Task OdlFixMachineSlaveAsync(string idxMacchina, int numDayPrev, int doInsert) + { + bool fatto = false; + using (var dbCtx = new MoonProContext(_configuration)) + { + try + { + var IdxMacc = new SqlParameter("@IdxMacchina", idxMacchina); + var NumDayPrev = new SqlParameter("@NumDayPrev", numDayPrev); + var DoInsert = new SqlParameter("@DoInsert", doInsert); + var result = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_ODL_fixMachineSlave @IdxMacchina, @NumDayPrev, @DoInsert", IdxMacc, NumDayPrev, DoInsert); + fatto = result != 0; + } + catch (Exception exc) + { + Log.Error($"Eccezione durante OdlFixMachineSlaveAsync{Environment.NewLine}{exc}"); + } + } + return fatto; + } /// /// Chiamata x stored recupero FluxLog x macchina (first) @@ -1130,7 +1323,38 @@ namespace MP.Data.Controllers } catch (Exception exc) { - Log.Error($"Eccezione in RicalcMse:{Environment.NewLine}{exc}"); + Log.Error($"Eccezione in RecalcMse:{Environment.NewLine}{exc}"); + } + return answ; + } + /// + /// Effettua ricalcolo MSE x macchina indicata + /// + /// idx macchina da confermare + /// Num massimo secondi di "vecchiaia" del dato + /// + public async Task RecalcMseAsync(string idxMacchina, int maxAgeSec) + { + bool answ = false; + try + { + var rigaProd = await StatoProdMacchinaAsync(idxMacchina, DateTime.Now); + using (var dbCtx = new MoonProContext(_configuration)) + { + var MaxAgeSec = new SqlParameter("@maxAgeSec ", maxAgeSec); + var IdxMacchina = new SqlParameter("@idxMacchina", idxMacchina); + + var result = await dbCtx + .Database + .ExecuteSqlRawAsync("EXEC stp_MSE_recalc @maxAgeSec, @idxMacchina ", MaxAgeSec, IdxMacchina); + + // indico eseguito! + answ = result > 0; + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in RecalcMseAsync:{Environment.NewLine}{exc}"); } return answ; } diff --git a/MP.IOC/Controllers/IOBController.cs b/MP.IOC/Controllers/IOBController.cs index 5fa06060..7c491fe7 100644 --- a/MP.IOC/Controllers/IOBController.cs +++ b/MP.IOC/Controllers/IOBController.cs @@ -326,6 +326,37 @@ namespace MP.IOC.Controllers } } + /// + /// Chiude ODL precedente ed avvia uno nuovo (duplicandolo e sitemando quantità RIMANENTE), + /// e CONFERMA produzione... + /// + /// GET: IOB/forceSplitOdl/SIMUL_03 + /// + /// + /// Esito chiamata (OK/vuoto) + + [HttpGet("forceSplitOdl/{id}")] + public async Task ForceSplitOdl(string id) + { + if (string.IsNullOrEmpty(id)) return BadRequest("Missing ID"); + + // Multi: gestione carattere "|" trasformato in "#" + id = id.Replace("|", "#"); + + string answ = ""; + + try + { + answ = await DService.AutoStartOdlAsync(id, true, true, 100, 0, ""); + } + catch (Exception exc) + { + Log.Error($"Errore in ForceSplitOdl{Environment.NewLine}{exc}"); + return StatusCode(StatusCodes.Status500InternalServerError, "NO"); + } + return Ok(answ); + } + /// /// Recupera ArtNum dato CodXdl (per impianti che accettano solo INT in scrittura): /// GET: IOB/getArtNum/SIMUL_03?CodXdl=ABC123 diff --git a/MP.IOC/Data/MpDataService.cs b/MP.IOC/Data/MpDataService.cs index 62e209a8..cd6126f5 100644 --- a/MP.IOC/Data/MpDataService.cs +++ b/MP.IOC/Data/MpDataService.cs @@ -246,6 +246,70 @@ namespace MP.IOC.Data return answ; } + /// + /// Aggiunge un set di task x macchina all'elenco di quelli salvati (in modalità upsert) + /// + /// + /// + /// + /// + public async Task AddTask4MacListAsync(string idxMacchina, Dictionary taskDict) + { + bool answ = false; + bool needSaveParams = false; + var currHash = Utils.RedKeyTask2ExeMacc(idxMacchina, MpIoNS); + var currSavedParHash = Utils.RedKeySavedTask2ExeMacc(idxMacchina, MpIoNS); + Dictionary currTask = new Dictionary(); + Dictionary savedTask = new Dictionary(); + + // leggo valori attuali... + currTask = await mTaskMacchinaAsync(idxMacchina); + // verifico processing dei ricevuti + foreach (var item in taskDict) + { + if (currTask.ContainsKey($"{item.Key}")) + { + currTask[$"{item.Key}"] = item.Value; + } + else + { + currTask.Add($"{item.Key}", item.Value); + } + Log.Trace($"Task ADD | hash: {currHash} | idxMacchina: {idxMacchina} | taskKey: {item.Key} | taskVal: {item.Value}"); + + // verifico in base al tipo di tName se fare backup... + switch (item.Key) + { + case Enums.taskType.setArt: + case Enums.taskType.setComm: + case Enums.taskType.setPzComm: + case Enums.taskType.setProg: + // leggo tName SALVATI attuali... + savedTask = mSavedTaskMacchina(idxMacchina); + savedTask[item.Key.ToString()] = item.Value; + needSaveParams = true; + break; + + case Enums.taskType.endProd: + // salvo un DICT vuoto x resettare + savedTask = new Dictionary(); + needSaveParams = true; + break; + + default: + break; + } + } + // salvo! + answ = await RedisSetHashDictAsync(currHash, currTask); + + if (needSaveParams) + { + answ = await RedisSetHashDictAsync(currSavedParHash, savedTask); + } + return answ; + } + /// /// Insert record allarme /// @@ -549,6 +613,308 @@ namespace MP.IOC.Data return answ; } + /// + /// Effettua split ODL + /// + /// macchina + /// effettuare conferma qty + /// imposta la qty prox ODL da ODL che si chiude + /// matricola operatore + /// Round Step quantità prox ODL (corrente come riferimento) + /// Cod ext da associare all'ODL + /// + public async Task AutoStartOdlAsync(string idxMacchina, bool doConfirm, bool qtyFromLast, int matrOpr, int roundStep = 100, string keyRichiesta = "") + { + string answ = "KO"; + DateTime adesso = DateTime.Now; + + // verifico NON CI SIA un veto a NUOVI split... + string redKey = $"{Utils.redisVetoSplitOdl}:{idxMacchina}"; + var rawData = await redisDb.StringGetAsync(redKey); + if (rawData.HasValue) + { + Log.Info($"VETO ATTIVO | Richiesto forceSplitOdl per impianto {idxMacchina} | impossibile procedere"); + } + else + { + // registro VETO x altri split... 5 minuti + await redisDb.StringSetAsync(redKey, $"Inizio SPLIT-ODL {adesso}", TimeSpan.FromMinutes(5)); + // setup dati da config + bool confRett = false; + int modoConfProd = -1; + bool slaveConfirmPzProd = false; + var configData = await ConfigGetAllAsync(); + if (configData != null) + { + var currRec = configData.FirstOrDefault(x => x.Chiave == "confRett"); + if (currRec != null) + { + bool.TryParse(currRec.Valore, out confRett); + } + currRec = configData.FirstOrDefault(x => x.Chiave == "modoConfProd"); + if (currRec != null) + { + int.TryParse(currRec.Valore, out modoConfProd); + } + currRec = configData.FirstOrDefault(x => x.Chiave == "SlaveConfirmPzProd"); + if (currRec != null) + { + bool.TryParse(currRec.Valore, out slaveConfirmPzProd); + } + } + // calcolo la qta da gestire + int qtyConf = 0; + int qtyNew = 0; + int qtyScarto = 0; + if (doConfirm) + { + try + { + var rigaProd = await IocDbController.PezziProdMacchinaAsync(idxMacchina); + var statoProd = await IocDbController.StatoProdMacchinaAsync(idxMacchina, adesso); + qtyConf = rigaProd.pezziNonConfermati; + qtyScarto = statoProd.Pz2RecScarto; + // calcolo nuovi pezzi da confermare + if (qtyFromLast) + { + roundStep = roundStep == 0 ? 1 : roundStep; + double ratio = (double)qtyConf / roundStep; + qtyNew = (int)Math.Round(Math.Ceiling(ratio) * roundStep, 0); + } + } + catch (Exception exc) + { + Log.Error($"AutoStartOdlAsync | Errore recupero pezzi da confermare | idxMacchina {idxMacchina}{Environment.NewLine}{exc}"); + } + } + + // chiamo metodo redis/db... + try + { + // recupero ODL corrente + var currData = await IocDbController.OdlCurrByMaccAsync(idxMacchina); + if (currData != null && currData.IdxOdl > 0) + { + // preparo var x master/slave + bool isMachMaster = await IobIsMasterAsync(idxMacchina); + List slaveList = new(); + if (isMachMaster) + { + List allSlaveList = await IocDbController.Macchine2SlaveAsync(); + slaveList = allSlaveList.Where(x => x.IdxMacchina == idxMacchina).ToList(); + } + + // registro un evento di inizio attrezzaggio (idxTipoEv = 2) + int idxEvento = 2; + Log.Info($"Invio evento ODL-SPLIT per macchina {idxMacchina} | ev: {idxEvento} | art: {currData.CodArticolo} | qty conf: {qtyConf} | sty sca: {qtyScarto} | new qty: {qtyNew}"); + + // creo evento + EventListModel newRecEv = new EventListModel() + { + CodArticolo = currData.CodArticolo, + IdxMacchina = idxMacchina, + IdxTipo = idxEvento, + InizioStato = adesso, + MatrOpr = matrOpr, + pallet = "", + Value = "ODL-SPLIT" + }; + inputComandoMapo resCmd = await scriviRigaEventoBarcodeAsync(newRecEv); + + // era 100, messo 50... + int wTime = 50; + + // eventuale conferma produzione + if (doConfirm) + { + await Task.Delay(wTime); + adesso = DateTime.Now; + // chiamo conferma produzione... + try + { + string chiamata = confRett ? "confermaProdMacchinaFull" : "confermaProdMacchina"; + Log.Info($"Chiamata a {chiamata} con parametri {currData.IdxMacchina} |{matrOpr} | {DateTime.Now.AddDays(-10)} | {DateTime.Now} | {qtyConf} | 0 | {qtyScarto} | {DateTime.Now} | false"); + string idxMacchinaSel = currData.IdxMacchina; + bool fatto = false; + if (confRett) + { + // confermo al netto dei pezzi lasciati... + fatto = await IocDbController.ConfermaProdMacchinaFullAsync(idxMacchinaSel, modoConfProd, qtyConf, 0, qtyScarto, adesso, matrOpr); + if (slaveConfirmPzProd) + { + foreach (var machine in slaveList) + { + await IocDbController.ConfermaProdMacchinaFullAsync(machine.IdxMacchinaSlave, modoConfProd, qtyConf, 0, qtyScarto, adesso, matrOpr); + } + } + } + else + { + fatto = await IocDbController.ConfermaProdMacchinaAsync(idxMacchinaSel, modoConfProd, qtyConf, qtyScarto, adesso, matrOpr); + if (slaveConfirmPzProd) + { + foreach (var machine in slaveList) + { + await IocDbController.ConfermaProdMacchinaAsync(idxMacchinaSel, modoConfProd, qtyConf, qtyScarto, adesso, matrOpr); + } + } + } + if (!fatto) + { + Log.Error($"ERRORE in chiamata {chiamata}"); + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in ConfermaProduzione{Environment.NewLine}{exc}"); + } + } + // 2025.02.19 portato da 100 a 1000 ms attesa x evitare che ODL sia avviato PRIMA della conferma + // attendo 1000 msec x chiudere ODL + await Task.Delay(1000); + // chiamo splitOdl + await IocDbController.AutoStartOdlAsync(currData.IdxOdl, 0, idxMacchina, currData.TCRichAttr, currData.PzPallet, $"Nuovo ODL da forceSplitOdl.autoStart", true, qtyNew, keyRichiesta); + + // elimino eventuale ODL precedente... + string currKey = $"{Utils.redisOdlCurrByMac}:{idxMacchina}"; + await redisDb.KeyDeleteAsync(currKey); + + // ricalcola ODL macchina + var newOdl = await GetCurrOdlAsync(idxMacchina); + // attendo 1000 msec + await Task.Delay(1000); + + adesso = DateTime.Now; + // registro fine ODL (idxTipoEv = 1) + idxEvento = 1; + Log.Info($"Invio evento FINE ODL-SPLIT | idx: {idxMacchina} | ev: {idxEvento} | art: {currData.CodArticolo}"); + // costruisco nuovo evento + newRecEv = new EventListModel() + { + CodArticolo = currData.CodArticolo, + IdxMacchina = idxMacchina, + IdxTipo = idxEvento, + InizioStato = adesso, + MatrOpr = matrOpr, + pallet = "", + Value = "ODL-START" + }; + resCmd = await scriviRigaEventoBarcodeAsync(newRecEv); + // invio eventi setup a macchina.... + string setArtVal = $"{currData.CodArticolo}"; + string setPzCommVal = $"{qtyNew}"; + string setCommVal = $"ODL{newOdl}"; + if (!string.IsNullOrEmpty(keyRichiesta)) + { + setCommVal = $"{keyRichiesta} ODL{newOdl}"; + } + try + { + // invio task caricamento dati ODL + Dictionary updDict = new Dictionary(); + updDict.Add(taskType.setArt, setArtVal); + updDict.Add(taskType.setComm, setCommVal); + updDict.Add(taskType.setPzComm, setPzCommVal); +#if false + addTask4Machine(idxMacchina, taskType.setArt, setArtVal); + addTask4Machine(idxMacchina, taskType.setComm, setCommVal); + addTask4Machine(idxMacchina, taskType.setPzComm, setPzCommVal); + + updateMachineParameter(idxMacchina, "setArt", setArtVal); + updateMachineParameter(idxMacchina, "setComm", setCommVal); + updateMachineParameter(idxMacchina, "setPzComm", setPzCommVal); +#endif + // recupero set attuale parametri + var currMachPar = await MachineParamListAsync(idxMacchina); + List list2upd = new(); + // aggiorno i valori interessati tra quelli nel dizionario + foreach (var item in updDict) + { + var cRec = currMachPar.FirstOrDefault(x => x.uid == $"{item.Key}"); + if (cRec != null) + { + list2upd.Add(cRec); + } + } + // aggiungo task di setParameters x la commessa... + updDict.Add(taskType.setParameter, setCommVal); + // salvo + await AddTask4MacListAsync(idxMacchina, updDict); + await MachineParamUpsertAsync(idxMacchina, list2upd); + } + catch + { } + // chiamo refresh MSE + await IocDbController.RecalcMseAsync(idxMacchina, 0); + // resetto stato macchina... + var kStatoMacc = $"{Utils.redisStatoMacch}:{idxMacchina}"; + await redisDb.KeyDeleteAsync(kStatoMacc); + answ = "OK"; + Log.Info($"Effettuato reset e ricalcoli x split ODL per macchina {idxMacchina}"); + // se è una master richiamo fix x child... + if (isMachMaster) + { + Dictionary updDict = new Dictionary(); + string ts = ""; + string outData = ""; + await IocDbController.OdlFixMachineSlaveAsync(idxMacchina, 30, 1); + foreach (var machine in slaveList) + { + // invio chiusura attrezzaggio + ts = string.Format("{0:yyMMdd}T{0:HHmmss.fff}Z", DateTime.Now); + outData = $"TS:{ts}|MATR:{matrOpr}|ODL:{newOdl}"; + + updDict.Clear(); + updDict.Add(taskType.setArt, setArtVal); + updDict.Add(taskType.setComm, setCommVal); + updDict.Add(taskType.setPzComm, setPzCommVal); + + +#if false + addTask4Machine(machine.IdxMacchinaSlave, taskType.fixStopSetup, outData); + addTask4Machine(machine.IdxMacchinaSlave, taskType.forceResetPzCount, outData); + // invio task caricamento dati ODL + addTask4Machine(machine.IdxMacchinaSlave, taskType.setArt, setArtVal); + addTask4Machine(machine.IdxMacchinaSlave, taskType.setComm, setCommVal); + addTask4Machine(machine.IdxMacchinaSlave, taskType.setPzComm, setPzCommVal); + + updateMachineParameter(machine.IdxMacchinaSlave, "setArt", setArtVal); + updateMachineParameter(machine.IdxMacchinaSlave, "setComm", setCommVal); + updateMachineParameter(machine.IdxMacchinaSlave, "setPzComm", setPzCommVal); +#endif + + // recupero set attuale parametri + var currMachPar = await MachineParamListAsync(machine.IdxMacchinaSlave); + List list2upd = new(); + // aggiorno i valori interessati tra quelli nel dizionario + foreach (var item in updDict) + { + var cRec = currMachPar.FirstOrDefault(x => x.uid == $"{item.Key}"); + if (cRec != null) + { + list2upd.Add(cRec); + } + } + // aggiungo task di setParameters x la commessa... + updDict.Add(taskType.fixStopSetup, outData); + updDict.Add(taskType.forceResetPzCount, outData); + updDict.Add(taskType.setParameter, setCommVal); + // salvo + await AddTask4MacListAsync(machine.IdxMacchinaSlave, updDict); + await MachineParamUpsertAsync(machine.IdxMacchinaSlave, list2upd); + } + } + } + } + catch (Exception exc) + { + Log.Error($"Eccezione in forceSplitOdl{Environment.NewLine}{exc}"); + } + } + return answ; + } + + public string CalcRecipe(RecipeModel currRecipe) { return mongoController.CalcRecipe(currRecipe); @@ -1379,6 +1745,31 @@ namespace MP.IOC.Data return val != null && (val == "1" || val.ToLower() == "true"); } + /// + /// Restituisce il valore booleano se la macchina sia master + /// + /// + /// + public async Task IobIsMasterAsync(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, "Master"); + + // 2. Se non c'è in cache, carichiamo/resettiamo tutto + if (val == null) + { + //var data = ResetDatiMacchina(idxMacchina); + var data = await ResetDatiMacchinaAsync(idxMacchina); + data.TryGetValue("Master", out val); + } + + // 3. Parsing sicuro + return val != null && (val == "1" || val.ToLower() == "true"); + } + /// /// /// idxMacc odl da cercare @@ -2042,10 +2433,24 @@ namespace MP.IOC.Data } catch (Exception exc) { - Log.Info(string.Format("Errore in mTaskMacchina | idxMacchina {2}:{0}{1}", Environment.NewLine, exc, idxMacchina)); + Log.Error(string.Format("Errore in mTaskMacchina | idxMacchina {2}:{0}{1}", Environment.NewLine, exc, idxMacchina)); } return answ; } + /// + /// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato + /// + /// + /// + public async Task> mTaskMacchinaAsync(string idxMacchina) + { + // hard coded dimensione vettore DatiMacchine + Dictionary answ = new Dictionary(); + // ORA recupero da memoria redis... + var currHash = Utils.RedKeyTask2ExeMacc(idxMacchina, MpIoNS); + answ = await RedisGetHashDictAsync(currHash); + return answ; + } /// /// Generazione autoOdl @@ -4650,6 +5055,32 @@ namespace MP.IOC.Data return answ; } + /// + /// Scrive una riga di evento manuale (barcode) nel db + check cambio stato DiarioDiBordo + /// + /// codice macchina + /// + private async Task scriviRigaEventoBarcodeAsync(EventListModel newRec) + { + bool inserito = false; + try + { + // inserisco evento + inserito = await IocDbController.EvListInsertAsync(newRec); + // faccio controllo per eventuale cambio stato da tab transizioni... + checkCambiaStatoBatch(tipoInputEvento.barcode, 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; + } + /// /// Restituisce il valore booleano se la macchina sia abilitata all'inserimento COMPLETO nel /// Signal Log @@ -4751,7 +5182,6 @@ namespace MP.IOC.Data { answ = currRec.Valore; } - return answ; } diff --git a/MP.IOC/MP.IOC.csproj b/MP.IOC/MP.IOC.csproj index e4ed4b17..7b98492d 100644 --- a/MP.IOC/MP.IOC.csproj +++ b/MP.IOC/MP.IOC.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 6.16.2604.1618 + 6.16.2604.1708 diff --git a/MP.IOC/Resources/ChangeLog.html b/MP.IOC/Resources/ChangeLog.html index 1ea573fb..a0b1750d 100644 --- a/MP.IOC/Resources/ChangeLog.html +++ b/MP.IOC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MP-IOC -

Versione: 6.16.2604.1618

+

Versione: 6.16.2604.1708


Note di rilascio:
  • diff --git a/MP.IOC/Resources/VersNum.txt b/MP.IOC/Resources/VersNum.txt index 139563a9..23fac1d1 100644 --- a/MP.IOC/Resources/VersNum.txt +++ b/MP.IOC/Resources/VersNum.txt @@ -1 +1 @@ -6.16.2604.1618 +6.16.2604.1708 diff --git a/MP.IOC/Resources/manifest.xml b/MP.IOC/Resources/manifest.xml index fc43241b..588db0e5 100644 --- a/MP.IOC/Resources/manifest.xml +++ b/MP.IOC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 6.16.2604.1618 + 6.16.2604.1708 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