using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Globalization; using System.Reflection; using System.Threading; using MapoSDK; using Newtonsoft.Json; using SteamWare; namespace MapoDb { /// /// classe gestione operazioni su DB tramite MapoDb /// public class DataLayer { #region Protected Fields /// /// indica conferma con rettifica (evento 121) /// protected bool confRett = memLayer.ML.CRB("confRett"); #endregion Protected Fields #region Public Fields /// /// Oggetto MapoDb impiegato da DataLayer x i suoi accessi ai dati /// public MapoDb MapoDbObj = new MapoDb(); // Table adapter vari... public DS_applicazioneTableAdapters.AnagraficaGruppiTableAdapter taAG; public DS_ProdTempiTableAdapters.AnagArticoliTableAdapter taAnagArt; public DS_applicazioneTableAdapters.AnagraficaEventiTableAdapter taAnagEventi; public DS_applicazioneTableAdapters.AnagraficaStatiTableAdapter taAnagStati; public DS_ArcaTableAdapters.GiacenzeTableAdapter taArcaGiac; public DS_IntServTableAdapters.ProduzioneAs400TableAdapter taAs400; public DS_ProdTempiTableAdapters.CalendFesteFerieTableAdapter taCalFF; public DS_UtilityTableAdapters.CommentiTableAdapter taComm; public DS_ProdTempiTableAdapters.DatiConfermatiTableAdapter taDatiConf; public DS_ProdTempiTableAdapters.DatiMacchineTableAdapter taDatiMacchine; public DS_ProdTempiTableAdapters.DatiProduzioneTableAdapter taDatiProd; public DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaTableAdapter taDatiProdMacch; public DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaPeriodoTableAdapter taDatiProdMacchPer; public DS_ProdTempiTableAdapters.stp_repDonati_getLastStatoDurataMacchinaTableAdapter taDatiStatoMacch; public DS_applicazioneTableAdapters.EventListTableAdapter taEventi; public DS_applicazioneTableAdapters.FluxLogTableAdapter taFL; public DS_IntServTableAdapters.TransitoDatiTableAdapter taIS_TrDati; public DS_IntServTableAdapters.IstanzeKITTableAdapter taIstK; public DS_applicazioneTableAdapters.KeepAliveTableAdapter taKeepAlive; public DS_ProdTempiTableAdapters.Macchine2SlaveTableAdapter taM2S; public DS_applicazioneTableAdapters.MacchineTableAdapter taMacchine; public DS_PlanTableAdapters.MachineParamsTableAdapter taMacParams; public DS_MAGTableAdapters.ElencoLottiTableAdapter taMagELotti; public DS_ProdTempiTableAdapters.MappaStatoExplTableAdapter taMSE; public DS_ProdTempiTableAdapters.ODLTableAdapter taODL; public DS_applicazioneTableAdapters.AnagraficaOperatoriTableAdapter taOp; public DS_applicazioneTableAdapters.AnagraficaOperatori2insTableAdapter taOp2ins; public DS_PlanTableAdapters.CalDispTableAdapter taPlanCalDisp; public DS_PlanTableAdapters.CalStopTableAdapter taPlanCalStop; public DS_PlanTableAdapters.RichiesteTableAdapter taPlanRichieste; public DS_ProdTempiTableAdapters.PromesseODLTableAdapter taPODL; public DS_ProdTempiTableAdapters.PostazioniMapoTableAdapter taPostazioni; public DS_PlanTableAdapters.PromesseOUTTableAdapter taPromOut; public DS_ProdTempiTableAdapters.stp_PzProd_getByMacchinaTableAdapter taPzProd2conf; public DS_ProdTempiTableAdapters.RegistroControlliTableAdapter taRC; public DS_applicazioneTableAdapters.RemoteRebootLogTableAdapter taRemReb; public DS_ProdTempiTableAdapters.RegistroScartiTableAdapter taRS; public DS_UtilityTableAdapters.v_selArticoliTableAdapter taSelArt; public DS_UtilityTableAdapters.v_selMacchineTableAdapter taSelMacc; public DS_UtilityTableAdapters.v_selODLTableAdapter taSelOdlFree; public DS_applicazioneTableAdapters.SignalLogTableAdapter taSigLog; public DS_SheetTechTableAdapters.ST_ActualRowTableAdapter taSTAR; public DS_applicazioneTableAdapters.DiarioDiBordoTableAdapter taStati; public DS_applicazioneTableAdapters.StatoMacchineTableAdapter taStatoMacchine; public DS_ProdTempiTableAdapters.StatoProdTableAdapter taStatoProd; public DS_SheetTechTableAdapters.ST_CheckTableAdapter taSTChk; public DS_ProdTempiTableAdapters.TempiCicloRilevatiTableAdapter taTempiCicloRilevati; public DS_ProdTempiTableAdapters.stp_TempoByIdxMaccPeriodClassTableAdapter taTempoByClass; public DS_IntServTableAdapters.TKS_SearchTableAdapter taTKS; public DS_applicazioneTableAdapters.TransizioneIngressiTableAdapter taTranIngr; public DS_ProdTempiTableAdapters.TurniMacchinaTableAdapter taTurniMacc; public DS_IntServTableAdapters.WipSetupKitTableAdapter taWKS; #endregion Public Fields #region Public Constructors /// /// Init classe /// public DataLayer() { initTA(); setupConnectionStringBase(); // aggiunta x gestione timeout esteso (ove necessario)! fixCommandTimeout(); // init oggetto MapoDb MapoDbObj = new MapoDb(); } #endregion Public Constructors #region Public Properties /// /// Hash dati MSE /// /// public static string hMSE { get { return mHash(string.Format("hMSE_DATA")); } } /// /// Cognome Nome da MatrOpr in sessione /// public string CognomeNomeOpr { get { // cerco operatore... string answ = ""; try { DS_applicazione.AnagraficaOperatoriRow oper = taOp.getByMatrOpr(MatrOpr)[0]; answ = string.Format("{0} {1}", oper.Cognome, oper.Nome); } catch { } return answ; } } /// /// Dati MSE serializzati in REDIS (get/set) /// public string currMSE { get { string answ = ""; logger.lg.scriviLog("Richiesta MSE da REDIS"); answ = memLayer.ML.getRSV(hMSE); return answ; } set { int MSE_cacheDuration = memLayer.ML.CRI("MSE_cacheDuration"); memLayer.ML.setRSV(hMSE, value, MSE_cacheDuration); } } /// /// MatrOpr in sessione /// public int MatrOpr { get { int idx = 0; try { idx = memLayer.ML.IntSessionObj("MatrOpr"); } catch { } return idx; } set { memLayer.ML.setSessionVal("MatrOpr", value); } } #endregion Public Properties #region Private Methods private static T ConvertDataRowToGenericType(DataRow row) where T : class, new() { Type entityType = typeof(T); T objEntity = new T(); foreach (DataColumn column in row.Table.Columns) { object value = row[column.ColumnName]; if (value == DBNull.Value) value = null; PropertyInfo property = entityType.GetProperty(column.ColumnName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public); try { if (property != null && property.CanWrite) property.SetValue(objEntity, value, null); } catch (Exception ex) { throw ex; } } return objEntity; } /// /// registra su REDIS eventuale superamento numero limite di call x il metodo in oggetto /// /// private static void saveCallRec(string callCountKey) { // conto la richiesta nel contatore REDIS long nCall = memLayer.ML.setRCntI(mHash($"COUNT:pCall:{callCountKey}")); //... se == nCall2Log scrivo su log e resetto long nCall2Log = memLayer.ML.cdvi("nCall2Log"); if (nCall >= nCall2Log) { // loggo logger.lg.scriviLog($"{callCountKey}: {nCall} call received", tipoLog.INFO); // resetto! memLayer.ML.resetRCnt(mHash($"COUNT:pCall:{callCountKey}")); } } /// /// verifica se sia necessario inserire un cambio di stato impianto in modalità batch /// /// /// /// /// /// /// /// /// private void checkCambiaStatoBatch(tipoInputEvento tipoInput, string IdxMacchina, DateTime InizioStato, int IdxTipo, string CodArt, string Value, int MatrOpr, string pallet) { int _logLevel = memLayer.ML.CRI("_logLevel"); DS_applicazione.TransizioneStatiDataTable tabTransStati; DS_applicazione.TransizioneStatiRow rigaTransStati; switch (tipoInput) { case tipoInputEvento.barcode: // effettuo cambio stato INDIPENDENTEMENTE da stato precedente try { tabTransStati = MapoDbObj.taTranSt.GetUserForcedTransitions(IdxMacchina, IdxTipo); if (tabTransStati != null) { if (tabTransStati.Count > 0) { rigaTransStati = tabTransStati[0]; // solo se cambia stato... if (rigaTransStati.IdxStato != rigaTransStati.next_IdxStato) { MapoDbObj.taDiario.InsStatoBatch(IdxMacchina, InizioStato, rigaTransStati.next_IdxStato, CodArt, Value, MatrOpr, pallet); // aggiorno MSE taMSE.forceRecalc(0, IdxMacchina); } } else { if (_logLevel > 6) { logger.lg.scriviLog($"Non trovata riga per: BARCODE | IdxMacchina: {IdxMacchina} | IdxTipo: {IdxTipo} | CodArt: {CodArt} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}", tipoLog.INFO); } } } } catch (Exception exc) { // non dovrebbe succedere... input utente da barcode dovrebbero TUTTI essere inseriti in tab transizione con famiglia 1... logger.lg.scriviLog($"Errore controllo transizione stato x evento barcode: BARCODE | IdxMacchina: {IdxMacchina} | IdxTipo: {IdxTipo} | CodArt: {CodArt} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } break; case tipoInputEvento.hw: // verifico se ci sia necessità di cambio stato try { tabTransStati = MapoDbObj.taTranSt.GetHwTransitions(IdxMacchina, IdxTipo); if (tabTransStati != null) { if (tabTransStati.Count > 0) { rigaTransStati = tabTransStati[0]; if (rigaTransStati != null) { // solo se cambia stato... if (rigaTransStati.IdxStato != rigaTransStati.next_IdxStato) { MapoDbObj.taDiario.InsStatoBatch(IdxMacchina, InizioStato, rigaTransStati.next_IdxStato, CodArt, Value, MatrOpr, pallet); } } } else { if (_logLevel > 6) { logger.lg.scriviLog($"Non trovata riga per: HW | IdxMacchina: {IdxMacchina} | IdxTipo: {IdxTipo} | CodArt: {CodArt} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}", tipoLog.INFO); } } } } catch (Exception exc) { // non trovo riga [0]... NON scrivo! logger.lg.scriviLog($"Errore controllo transizione stato x evento barcode: HW | IdxMacchina: {IdxMacchina} | IdxTipo: {IdxTipo} | CodArt: {CodArt} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } break; } } /// /// sistemazione timeout comandi nei tableadapter /// private void fixCommandTimeout() { SetAllCommandTimeouts(taComm, memLayer.ML.CRI("sqlLongCommandTimeout")); } /// /// Recupero dati stato prod da macchina... /// /// /// /// /// private bool getStatoProd(string idxMacchina, ref DS_ProdTempi.StatoProdDataTable datiProdAct, DateTime dataRif) { bool answ = false; try { // recupero con stored NUOVA... //2020.01.31 NUOVO oggetto (NON singleton) DataLayer man = new DataLayer(); datiProdAct = man.taStatoProd.GetData(idxMacchina, dataRif); if (datiProdAct.Rows.Count > 0) { // solo SE ho idxODL (altrimenti loggo errore) if (datiProdAct[0].IdxOdl > 0) { answ = true; } else { // verifico se ho già questo errore attivo IN REDIS (altrimenti reinvio) logger.lg.scriviLog($"pzCounterTC: Non trovato currODL x idxMacchina {idxMacchina} ", $"idxMacchina {idxMacchina} | IdxOdl {datiProdAct[0].IdxOdl} | pzTot {datiProdAct[0].PzTotODL} | dataRif {dataRif}", tipoLog.WARNING); } } else { logger.lg.scriviLog($"pzCounterTC: Non trovate righe in currODL {idxMacchina}", $"Non trovate righe in currODL x idxMacchina {idxMacchina}: datiProdAct vuota", tipoLog.WARNING); } } catch (Exception exc) { logger.lg.scriviLog($"[pzCounterTC] Eccezione in pzCounterTC x idxMacchina {idxMacchina}", $"[pzCounterTC] Eccezione in pzCounterTC x idxMacchina {idxMacchina}{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } return answ; } /// /// Calcola l'effettivo valore da passare alla macchina a stati INGRESSI data conf Macchine2FamigliaIngressi /// /// /// /// private string preProcInput(string idxMacchina, string valore) { string newVal = ""; try { // variabili int valINT = 0; int BitFilt = 0; int BSR = 0; bool ExplodeBit = false; int NumBit = 0; int newValInt = 0; // recupero parametri... int.TryParse(mDatiMacchinaVal(idxMacchina, "BitFilt"), out BitFilt); int.TryParse(mDatiMacchinaVal(idxMacchina, "BSR"), out BSR); Boolean.TryParse(mDatiMacchinaVal(idxMacchina, "ExplodeBit"), out ExplodeBit); int.TryParse(mDatiMacchinaVal(idxMacchina, "NumBit"), out NumBit); // non usato (x ora) // recupero valore valINT = int.Parse(valore, NumberStyles.HexNumber); // filtro newValInt = utility.bMaskInt(valINT, BitFilt); // effettuo eventuale BitShiftRight if (BSR > 0) { newValInt = newValInt >> BSR; } // effettuo eventuale esplosione in BIT esclusivi if (ExplodeBit) { newValInt = Convert.ToInt32(1 << newValInt); } // riconverto a STRING HEX!!! newVal = newValInt.ToString("X"); } catch { newVal = valore; } return newVal; } private void SetAllCommandTimeouts(object adapter, int timeout) { var commands = adapter.GetType().InvokeMember( "CommandCollection", BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, adapter, new object[0]); var sqlCommand = (SqlCommand[])commands; foreach (var cmd in sqlCommand) { cmd.CommandTimeout = timeout; } } /// /// cerca codice in anagrafica macchine ed eventualmente inserisce nuova macchina /// /// private void verificaIdxMacchina(string IdxMacchina) { bool needDB = false; if (!memLayer.ML.CRB("disable_verificaIdxMacchina")) { if (memLayer.ML.CRB("IOB_RedEnab")) { try { // esecuzione in REDIS...cerco status macchina... if (mDatiMacchine(IdxMacchina).Count == 0) { needDB = true; } } catch { } } // ...oppure segno richiesta DB... else { needDB = true; } if (needDB) { // 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione NUOVO oggetto if (memLayer.ML.CRB("disable_singleton")) { taMacchine = new DS_applicazioneTableAdapters.MacchineTableAdapter(); MapoDbObj.taMSM = new DS_applicazioneTableAdapters.MicroStatoMacchinaTableAdapter(); } // verifico esistenza macchina if (taMacchine.GetByIdx(IdxMacchina).Rows.Count == 0) { // inserisco nuova macchina... taMacchine.Insert(IdxMacchina, "9999", IdxMacchina, "Macchina non codificata", "-", "http://", "nd", "col", 0, 0); } // verifico ci sia un microstato macchina... if (MapoDbObj.taMSM.getByIdxMacchina(IdxMacchina).Rows.Count == 0) { // inserisco nuovo stato... MapoDbObj.taMSM.Insert(IdxMacchina, 0, DateTime.Now, "00"); } } } } #endregion Private Methods #region Protected Methods /// /// init dei table adapters /// protected void initTA() { // istanzio oggetto taAG = new DS_applicazioneTableAdapters.AnagraficaGruppiTableAdapter(); taAnagArt = new DS_ProdTempiTableAdapters.AnagArticoliTableAdapter(); taAnagEventi = new DS_applicazioneTableAdapters.AnagraficaEventiTableAdapter(); taAnagStati = new DS_applicazioneTableAdapters.AnagraficaStatiTableAdapter(); taAs400 = new DS_IntServTableAdapters.ProduzioneAs400TableAdapter(); taArcaGiac = new DS_ArcaTableAdapters.GiacenzeTableAdapter(); taCalFF = new DS_ProdTempiTableAdapters.CalendFesteFerieTableAdapter(); taComm = new DS_UtilityTableAdapters.CommentiTableAdapter(); taDatiConf = new DS_ProdTempiTableAdapters.DatiConfermatiTableAdapter(); taDatiMacchine = new DS_ProdTempiTableAdapters.DatiMacchineTableAdapter(); taDatiProd = new DS_ProdTempiTableAdapters.DatiProduzioneTableAdapter(); taDatiProdMacch = new DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaTableAdapter(); taDatiProdMacchPer = new DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaPeriodoTableAdapter(); taDatiStatoMacch = new DS_ProdTempiTableAdapters.stp_repDonati_getLastStatoDurataMacchinaTableAdapter(); taEventi = new DS_applicazioneTableAdapters.EventListTableAdapter(); taFL = new DS_applicazioneTableAdapters.FluxLogTableAdapter(); taIS_TrDati = new DS_IntServTableAdapters.TransitoDatiTableAdapter(); taIstK = new DS_IntServTableAdapters.IstanzeKITTableAdapter(); taKeepAlive = new DS_applicazioneTableAdapters.KeepAliveTableAdapter(); taM2S = new DS_ProdTempiTableAdapters.Macchine2SlaveTableAdapter(); taMacchine = new DS_applicazioneTableAdapters.MacchineTableAdapter(); taMacParams = new DS_PlanTableAdapters.MachineParamsTableAdapter(); taMagELotti = new DS_MAGTableAdapters.ElencoLottiTableAdapter(); taMSE = new DS_ProdTempiTableAdapters.MappaStatoExplTableAdapter(); taODL = new DS_ProdTempiTableAdapters.ODLTableAdapter(); taOp = new DS_applicazioneTableAdapters.AnagraficaOperatoriTableAdapter(); taOp2ins = new DS_applicazioneTableAdapters.AnagraficaOperatori2insTableAdapter(); taPlanCalDisp = new DS_PlanTableAdapters.CalDispTableAdapter(); taPlanCalStop = new DS_PlanTableAdapters.CalStopTableAdapter(); taPlanRichieste = new DS_PlanTableAdapters.RichiesteTableAdapter(); taPODL = new DS_ProdTempiTableAdapters.PromesseODLTableAdapter(); taPostazioni = new DS_ProdTempiTableAdapters.PostazioniMapoTableAdapter(); taPromOut = new DS_PlanTableAdapters.PromesseOUTTableAdapter(); taPzProd2conf = new DS_ProdTempiTableAdapters.stp_PzProd_getByMacchinaTableAdapter(); taRC = new DS_ProdTempiTableAdapters.RegistroControlliTableAdapter(); taRemReb = new DS_applicazioneTableAdapters.RemoteRebootLogTableAdapter(); taRS = new DS_ProdTempiTableAdapters.RegistroScartiTableAdapter(); taSelArt = new DS_UtilityTableAdapters.v_selArticoliTableAdapter(); taSelMacc = new DS_UtilityTableAdapters.v_selMacchineTableAdapter(); taSelOdlFree = new DS_UtilityTableAdapters.v_selODLTableAdapter(); taSigLog = new DS_applicazioneTableAdapters.SignalLogTableAdapter(); taSTAR = new DS_SheetTechTableAdapters.ST_ActualRowTableAdapter(); taStati = new DS_applicazioneTableAdapters.DiarioDiBordoTableAdapter(); taStatoMacchine = new DS_applicazioneTableAdapters.StatoMacchineTableAdapter(); taStatoProd = new DS_ProdTempiTableAdapters.StatoProdTableAdapter(); taSTChk = new DS_SheetTechTableAdapters.ST_CheckTableAdapter(); taTempiCicloRilevati = new DS_ProdTempiTableAdapters.TempiCicloRilevatiTableAdapter(); taTempoByClass = new DS_ProdTempiTableAdapters.stp_TempoByIdxMaccPeriodClassTableAdapter(); taTKS = new DS_IntServTableAdapters.TKS_SearchTableAdapter(); taTranIngr = new DS_applicazioneTableAdapters.TransizioneIngressiTableAdapter(); taTurniMacc = new DS_ProdTempiTableAdapters.TurniMacchinaTableAdapter(); taWKS = new DS_IntServTableAdapters.WipSetupKitTableAdapter(); } /// /// effettua setup dei connection strings da web.config delal singola applicazione /// protected virtual void setupConnectionStringBase() { string connectionString = memLayer.ML.confReadString("MoonProConnectionString"); string connectionStringIS = memLayer.ML.confReadString("MoonProConnectionStringIS"); string connectionStringArca = memLayer.ML.confReadString("MoonProConnectionStringArca"); string connectionStringES3 = memLayer.ML.confReadString("MoonProConnectionStringES3"); string connectionStringMAG = memLayer.ML.confReadString("MoonProConnectionStringMAG"); // connections del db taAG.Connection.ConnectionString = connectionString; taAnagArt.Connection.ConnectionString = connectionString; taAnagEventi.Connection.ConnectionString = connectionString; taAnagStati.Connection.ConnectionString = connectionString; taAs400.Connection.ConnectionString = connectionStringIS; taArcaGiac.Connection.ConnectionString = connectionStringArca; taCalFF.Connection.ConnectionString = connectionString; taComm.Connection.ConnectionString = connectionString; taDatiConf.Connection.ConnectionString = connectionString; taDatiMacchine.Connection.ConnectionString = connectionString; taDatiProd.Connection.ConnectionString = connectionString; taDatiProdMacch.Connection.ConnectionString = connectionString; taDatiProdMacchPer.Connection.ConnectionString = connectionString; taDatiStatoMacch.Connection.ConnectionString = connectionString; taEventi.Connection.ConnectionString = connectionString; taFL.Connection.ConnectionString = connectionString; taIS_TrDati.Connection.ConnectionString = connectionStringIS; taIstK.Connection.ConnectionString = connectionStringIS; taKeepAlive.Connection.ConnectionString = connectionString; taM2S.Connection.ConnectionString = connectionString; taMacchine.Connection.ConnectionString = connectionString; taMacParams.Connection.ConnectionString = connectionStringES3; taMagELotti.Connection.ConnectionString = connectionStringMAG; taMSE.Connection.ConnectionString = connectionString; taODL.Connection.ConnectionString = connectionString; taOp.Connection.ConnectionString = connectionString; taOp2ins.Connection.ConnectionString = connectionString; taPlanCalDisp.Connection.ConnectionString = connectionStringES3; taPlanCalStop.Connection.ConnectionString = connectionStringES3; taPlanRichieste.Connection.ConnectionString = connectionStringES3; taPODL.Connection.ConnectionString = connectionString; taPostazioni.Connection.ConnectionString = connectionString; taPromOut.Connection.ConnectionString = connectionStringES3; taPzProd2conf.Connection.ConnectionString = connectionString; taRC.Connection.ConnectionString = connectionString; taRemReb.Connection.ConnectionString = connectionString; taRS.Connection.ConnectionString = connectionString; taSelArt.Connection.ConnectionString = connectionString; taSelMacc.Connection.ConnectionString = connectionString; taSelOdlFree.Connection.ConnectionString = connectionString; taSigLog.Connection.ConnectionString = connectionString; taSTAR.Connection.ConnectionString = connectionString; taStati.Connection.ConnectionString = connectionString; taStatoMacchine.Connection.ConnectionString = connectionString; taStatoProd.Connection.ConnectionString = connectionString; taSTChk.Connection.ConnectionString = connectionString; taTempiCicloRilevati.Connection.ConnectionString = connectionString; taTempoByClass.Connection.ConnectionString = connectionString; taTKS.Connection.ConnectionString = connectionStringIS; taTranIngr.Connection.ConnectionString = connectionString; taTurniMacc.Connection.ConnectionString = connectionString; taWKS.Connection.ConnectionString = connectionStringIS; } #endregion Protected Methods #region Public Methods /// /// Hash dati tabella AnagStati macchina /// /// public static string currAnagStatiMacc() { return mHash(string.Format("Anag:StatiMacc")); } /// /// Hash dati Current ODL x la macchina specificata /// /// /// public static string currODLHash(string idxMacchina) { return mHash(string.Format("CurrODL:{0}", idxMacchina)); } /// /// Hash dati Current ODL ROW x la macchina specificata /// /// /// public static string currOdlRowHash(string idxMacchina) { return mHash(string.Format("CurrOdlRow:{0}", idxMacchina)); } /// /// Hash dati CurrentParameters x la macchina specificata /// /// /// public static string currParametersHash(string idxMacchina) { return mHash(string.Format("CurrentParameters:{0}", idxMacchina)); } /// /// Hash dati Current StatoMacchina x la macchina specificata /// /// /// public static string currStatoMaccHash(string idxMacchina) { return mHash(string.Format("CurrStatoMacc:{0}", idxMacchina)); } public static List DataTableToList(DataTable dt) where T : class, new() { List lstItems = new List(); if (dt != null && dt.Rows.Count > 0) foreach (DataRow row in dt.Rows) lstItems.Add(ConvertDataRowToGenericType(row)); else lstItems = null; return lstItems; } /// /// Hash dati STATUS x la macchina specificata /// /// /// public static string dtMaccHash(string idxMacchina) { return mHash(string.Format("DtMac:{0}", idxMacchina)); } /// /// Hash dati EXE TASK x la macchina specificata /// /// /// public static string exeTaskHash(string idxMacchina) { return mHash(string.Format("ExeTask:{0}", idxMacchina)); } /// /// Hash dati relativi all'associazione macchina <--> IOB /// /// Macchina PRINCIPALE /// public static string hM2IOB(string IdxMacchina) { return mHash(string.Format("hM2IOB:{0}", IdxMacchina)); } /// /// Hash dati Macchine Multi SM Ingressi /// /// Macchina PRINCIPALE /// public static string hMSMI(string IdxMacchina) { return mHash(string.Format("hMSMI:{0}", IdxMacchina)); } /// /// Hash dati STATE MACHINE INGRESSI x la FAMIGLIA INGRESSI specificata (per completare poi manca singolo micro stato corrente + valore letto x definire chiave) /// /// /// public static string hSMI(int idxFamIn) { return mHash(string.Format("hSMI:{0}", idxFamIn)); } /// /// Hash dati BUFFER x la macchina specificata /// /// /// /// public static string LiveBufferHash(string idxMacchina, string bufferName) { return mHash(string.Format("LIVE:{0}:{1}", idxMacchina, bufferName)); } /// /// Hash dati LIVE x la macchina specificata /// /// /// public static string LiveCurrValHash(string idxMacchina) { return mHash(string.Format("LIVE:{0}:CURR_VAL", idxMacchina)); } /// /// Hash dati MemoryMap x la macchina specificata /// /// /// public static string memMapHash(string idxMacchina) { return mHash(string.Format("MemMap:{0}", idxMacchina)); } /// /// Hash Redis contenente i dati MP di una specifico TYPE (es StatusMacchina, StateMachineIngressi, ...) /// /// /// public static string mHash(string dataType) { return memLayer.ML.redHash(dataType); } /// /// Hash dati OPT PARAMETERS x la macchina specificata /// /// /// public static string optParHash(string idxMacchina) { return mHash(string.Format("OptPar:{0}", idxMacchina)); } /// /// Hash dati COUNTER x la macchina specificata /// /// /// public static string pzCountHash(string idxMacchina) { return mHash(string.Format("PzCount:{0}", idxMacchina)); } /// /// Hash dati STATUS x la macchina specificata. /// - dati ODL /// - dati articolo /// - dati produzione corrente /// /// /// public static string stMaccHash(string idxMacchina) { return mHash(string.Format("StMac:{0}", idxMacchina)); } /// /// Hash x VETO dello SPLIT ODL la macchina specificata /// /// /// public static string vetoSplitOdlMaccHash(string idxMacchina) { return mHash($"VetoOdlMacc:{idxMacchina}"); } /// /// Aggiunge un PARAMETRO OPZIONALE all'elenco di quelli salvati (in modalità upsert) /// /// /// /// /// public bool addOptPar4Machine(string idxMacchina, string taskKey, string taskVal) { bool answ = false; string currHash = optParHash(idxMacchina); try { // leggo task attuali... var currVal = mOptParMacchina(idxMacchina); currVal[taskKey] = taskVal; answ = memLayer.ML.redSaveHashDict(currHash, currVal); } catch { } return answ; } /// /// Aggiunge un task all'elenco di quelli salvati (in modalità upsert) /// /// /// /// /// public bool addTask4Machine(string idxMacchina, taskType taskKey, string taskVal) { bool answ = false; string currHash = exeTaskHash(idxMacchina); try { // leggo task attuali... var currTask = mTaskMacchina(idxMacchina); currTask[taskKey.ToString()] = taskVal; answ = memLayer.ML.redSaveHashDict(currHash, currTask); logger.lg.scriviLog($"Task ADD - idxMacchina: {idxMacchina} | taskKey: {taskKey.ToString()} | taskVal: {taskVal}"); } catch { } return answ; } /// /// Elenco stati macchina /// /// public DS_applicazione.AnagraficaStatiDataTable AnagraficaStati() { DS_applicazione.AnagraficaStatiDataTable answTab = null; // cerco in cache... string rCall = ""; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("hasAnagStati"); try { rCall = memLayer.ML.getRSV(currAnagStatiMacc()); if (!string.IsNullOrEmpty(rCall)) { answTab = JsonConvert.DeserializeObject(rCall); } else { //2020.01.31 nuovo obj x evitare concorrenza MapoDb man = new MapoDb(); answTab = man.taAnagSt.GetData(); //answTab = MapoDbObj.taAnagSt.GetData(); // salvo in redis... rCall = JsonConvert.SerializeObject(answTab); int anagrCacheDur = memLayer.ML.CRI("anagrCacheDur"); memLayer.ML.setRSV(currAnagStatiMacc(), rCall, anagrCacheDur); } } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in recupero currODLRow{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } } else { answTab = MapoDbObj.taAnagSt.GetData(); } return answTab; } /// /// controlla se da il segnale di "microstato" deriva un evento da generare - modalità OFFLINE /// /// idx macchina /// valore ingresso /// data-ora evento (server) /// sequenza dati inviati /// public inputComandoMapo checkMicroStato(string idxMacchina, string valore, DateTime dtEve, string contatore) { int _logLevel = memLayer.ML.CRI("_logLevel"); // recupero SE IMPIEGATO REDIS i valori del Dictionary della macchina... Dictionary datiMacc = mDatiMacchine(idxMacchina); if (_logLevel > 6) { logger.lg.scriviLog(string.Format("[ChkMiSt]{2}---------------------------{2}Richiesta verifica INPUT per Macchina {0}, seriale {1}", idxMacchina, valore, Environment.NewLine), tipoLog.INFO); } // formatto output inputComandoMapo answ = new inputComandoMapo(); DS_applicazione.TransizioneIngressiDataTable TabTransIn; DS_applicazione.TransizioneIngressiRow rigaTransIn = null; // verifico se esista la macchina altrimenti la creo... REDIS compliant verificaIdxMacchina(idxMacchina); string CodArticolo = ""; if (memLayer.ML.CRB("IOB_RedEnab")) { try { // esecuzione in REDIS CodArticolo = datiMacc["CodArticolo"]; } catch { } } // ...oppure dritto su DB else { // esecuzione in DB... // recupero CodArticolo corretto try { // 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione NUOVO oggetto if (memLayer.ML.CRB("disable_singleton")) { // 2017.07.10 forzo init x errori "sovrapposizioni" taDatiMacchine = new DS_ProdTempiTableAdapters.DatiMacchineTableAdapter(); } CodArticolo = taDatiMacchine.getByIdx(idxMacchina)[0].CodArticolo_A; } catch (Exception exc) { logger.lg.scriviLog(string.Format("[ChkMiSt_4a] - Eccezione in recupero CodArticolo:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); } } // recupero next microstato int? valINT = 0; try { valINT = int.Parse(valore, System.Globalization.NumberStyles.HexNumber); // esecuzione in REDIS... if (memLayer.ML.CRB("IOB_RedEnab")) { try { int idxFamIn = Convert.ToInt32(datiMacc["IdxFamIn"]); int idxMicroStato = Convert.ToInt32(datiMacc["IdxMicroStato"]); int valIOB = Convert.ToInt32(valINT); int idxTipoEv = 0; int next_idxMS = idxMicroStato; // verifico esistenza tab SMI... string fiHASH = DataLayer.hSMI(idxFamIn); string todoSMI = ""; bool trovato = memLayer.ML.redHashPresentSz(fiHASH); if (!trovato) { // ricarico tabella! KeyValuePair[] valori = mTabSMI(idxFamIn); } // recupero singolo valore (stringa) x chiave todoSMI = valoreSMI(idxFamIn, idxMicroStato, valIOB); // solo se ho trovato un risultato nella tab SMI della famiglia macchina... if (todoSMI != "") { // splitto e salvo valori OUT... string[] valori = todoSMI.Split('_'); idxTipoEv = Convert.ToInt32(valori[0]); next_idxMS = Convert.ToInt32(valori[1]); // creo la riga tipizzatya dai dati di redis x procedere... DS_applicazione.TransizioneIngressiDataTable tab = new DS_applicazione.TransizioneIngressiDataTable(); rigaTransIn = tab.NewTransizioneIngressiRow(); rigaTransIn.IdxFamigliaIngresso = idxFamIn; rigaTransIn.IdxMicroStato = idxMicroStato; rigaTransIn.ValoreIngresso = valIOB; rigaTransIn.IdxTipoEvento = idxTipoEv; rigaTransIn.next_IdxMicroStato = next_idxMS; } } catch { } } // ...oppure dritto su DB else { // 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione NUOVO oggetto if (memLayer.ML.CRB("disable_singleton")) { // 2017.06.09 forzo init x errori "sovrapposizioni" MapoDbObj.taTransIngr = new DS_applicazioneTableAdapters.TransizioneIngressiTableAdapter(); } TabTransIn = MapoDbObj.taTransIngr.getByIdxMacchinaValore(idxMacchina, valINT); if (TabTransIn.Rows.Count > 0) { rigaTransIn = TabTransIn[0]; } } } catch (Exception exc) { logger.lg.scriviLog(string.Format("[ChkMiSt_5a] - - Eccezione in recupero riga Trans ingressi per idxMacchina {3} e valore {2}:{0}{1}", Environment.NewLine, exc, valINT, idxMacchina), tipoLog.EXCEPTION); } // effettuo update vari SU DB!!! if (rigaTransIn != null) { try { if (_logLevel > 5) { logger.lg.scriviLog(string.Format("[ChkMiSt_6a] - Salvo Update Microstato:{0}macchina: {1} | valore seriale: {2} | next micro stato: {3}", Environment.NewLine, idxMacchina, valINT, rigaTransIn.next_IdxMicroStato), tipoLog.INFO); } // 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione NUOVO oggetto if (memLayer.ML.CRB("disable_singleton")) { // 2017.06.09 forzo init x errori "sovrapposizioni" MapoDbObj.taMSM = new DS_applicazioneTableAdapters.MicroStatoMacchinaTableAdapter(); } // salvo nuovo microstato... MapoDbObj.taMSM.updateQuery(rigaTransIn.next_IdxMicroStato, dtEve, valore, idxMacchina); // controllo se c'è evento if (rigaTransIn.IdxTipoEvento > 0) { if (_logLevel > 5) { logger.lg.scriviLog(string.Format("[ChkMiSt_7a] - Salvo evento:{0}macchina: {1} | tipoEvento: {2} | CodArticolo: {3} | contatore: {4} | valore: {5}", Environment.NewLine, idxMacchina, rigaTransIn.IdxTipoEvento, CodArticolo, contatore, valore), tipoLog.INFO); } string valEsteso = string.Format("[{0}] {1}", contatore.PadLeft(3, '0'), valore); // aggiunto contatore! answ = scriviRigaEvento(idxMacchina, rigaTransIn.IdxTipoEvento, CodArticolo, valEsteso, 0, "-", dtEve, DateTime.Now); // 2017.09.12 SE era in modalità redis RICARICA dati macchina... if (memLayer.ML.CRB("IOB_RedEnab")) { resetDatiMacchina(idxMacchina); } if (_logLevel > 5) { logger.lg.scriviLog(string.Format("[ChkMiSt_a] - Macchina {0} | seriale(INT) {1} | valEsteso {3} | answ {4}{2}---------------------------{2}", idxMacchina, valINT, Environment.NewLine, valEsteso, answ), tipoLog.INFO); } } } catch (Exception exc) { logger.lg.scriviLog(string.Format("[ChkMiSt_8a] - Eccezione:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); } } return answ; } /// /// controlla se da il segnale di "microstato" deriva un evento da generare - modalità OFFLINE /// /// idx macchina /// valore ingresso /// data-ora evento (server) /// public inputComandoMapo checkMicroStato(string idxMacchina, string valore, DateTime dtEve) { if (memLayer.ML.CRI("_logLevel") > 6) { logger.lg.scriviLog(string.Format("{2}---------------------------{2}Richiesta verifica INPUT per Macchina {0}, seriale {1}", idxMacchina, valore, Environment.NewLine), tipoLog.INFO); } // formatto output inputComandoMapo answ = new inputComandoMapo(); DS_applicazione.TransizioneIngressiDataTable TabTransIn; DS_applicazione.TransizioneIngressiRow rigaTransIn = null; // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(idxMacchina); string CodArticolo = ""; // recupero CodArticolo corretto try { // 2017.07.10 forzo init x errori "sovrapposizioni" taDatiMacchine = new DS_ProdTempiTableAdapters.DatiMacchineTableAdapter(); CodArticolo = taDatiMacchine.getByIdx(idxMacchina)[0].CodArticolo_A; } catch (Exception exc) { logger.lg.scriviLog(string.Format("[ChkMiSt_4b] - Eccezione in recupero CodArticolo:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); } // recupero next microstato //int? valINT = Convert.ToInt32(valore); int? valINT = 0; try { // 2017.06.09 forzo init x errori "sovrapposizioni" MapoDbObj.taTransIngr = new DS_applicazioneTableAdapters.TransizioneIngressiTableAdapter(); valINT = int.Parse(valore, System.Globalization.NumberStyles.HexNumber); TabTransIn = MapoDbObj.taTransIngr.getByIdxMacchinaValore(idxMacchina, valINT); if (TabTransIn.Rows.Count > 0) { rigaTransIn = TabTransIn[0]; } } catch (Exception exc) { logger.lg.scriviLog(string.Format("[ChkMiSt_5b] - Eccezione in recupero riga Trans ingressi per idxMacchina {3} e valore {2}:{0}{1}", Environment.NewLine, exc, valINT, idxMacchina), tipoLog.EXCEPTION); } int _logLevel = memLayer.ML.CRI("_logLevel"); // effettuo update vari if (rigaTransIn != null) { try { if (_logLevel > 5) { logger.lg.scriviLog(string.Format("[ChkMiSt_6b] - Salvo Update Microstato:{0}macchina: {1} | valore seriale: {2} | next micro stato: {3}", Environment.NewLine, idxMacchina, valINT, rigaTransIn.next_IdxMicroStato), tipoLog.INFO); } // salvo nuovo microstato... MapoDbObj.taMSM.updateQuery(rigaTransIn.next_IdxMicroStato, dtEve, valore, idxMacchina); // controllo se c'è evento if (rigaTransIn.IdxTipoEvento > 0) { if (_logLevel > 5) { logger.lg.scriviLog(string.Format("[ChkMiSt_7b] - Salvo evento:{0}macchina: {1} | tipoEvento: {2} | CodArticolo: {3}", Environment.NewLine, idxMacchina, rigaTransIn.IdxTipoEvento, CodArticolo), tipoLog.INFO); } answ = scriviRigaEvento(idxMacchina, rigaTransIn.IdxTipoEvento, CodArticolo, valore, 0, "-", dtEve, DateTime.Now); if (_logLevel > 5) { logger.lg.scriviLog(string.Format("[ChkMiSt_b] -Macchina {0}, seriale(INT) {1}{2}---------------------------{2}", idxMacchina, valINT, Environment.NewLine), tipoLog.INFO); } } } catch (Exception exc) { logger.lg.scriviLog(string.Format("[ChkMiSt_8b] - Eccezione:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); } } return answ; } /// /// controlla se da il segnale di "microstato" deriva un evento da generare /// /// /// /// public inputComandoMapo checkMicroStato(string idxMacchina, string valore) { // wrapper ad ora corrente... return checkMicroStato(idxMacchina, valore, DateTime.Now); } /// /// Effettua conferma prod macchina dell'intero periodo da confermare (ultima conferma --> adesso) /// /// 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 /// public bool confermaProdMacchina(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzScarto, DateTime DataOraApp) { bool answ = false; try { DS_ProdTempi.stp_PzProd_getByMacchinaRow rigaProd = taPzProd2conf.GetData(idxMacchina.ToString())[0]; taPzProd2conf.stp_ConfermaProduzCompleta(idxMacchina, MatrOpr, rigaProd.DataFrom, DataOraApp, numPzConfermati, numPzScarto, modoConfProd, DataOraApp, true); // indico eseguito! answ = true; } catch (Exception exc) { logger.lg.scriviLog($"Errore in conferma prod macchina:{Environment.NewLine}{exc}"); } return answ; } /// /// Effettua conferma prod macchina dell'intero periodo da confermare (ultima conferma --> adesso) /// /// idx macchina da confermare /// 0=periodo, 1 = giorno, 2 = turno /// qta pezzi BUONI da confermare /// qta pezzi LASCIATI alla macchina da confermare (2 eventi 121 rettifica neg/pos) /// qta pezzi SCARTO da confermare /// DataOra in cui registrare approvazione /// public bool confermaProdMacchinaFull(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzLasciati, int numPzScarto, DateTime DataOraApp) { bool answ = false; try { DS_ProdTempi.stp_PzProd_getByMacchinaRow rigaProd = taPzProd2conf.GetData(idxMacchina.ToString())[0]; taPzProd2conf.stp_ConfermaProduzCompletaFull(idxMacchina, MatrOpr, rigaProd.DataFrom, DataOraApp, numPzConfermati, numPzLasciati, numPzScarto, modoConfProd, DataOraApp, true); // indico eseguito! answ = true; } catch (Exception exc) { logger.lg.scriviLog($"Errore in conferma prod macchina con rett ev121:{Environment.NewLine}{exc}"); } return answ; } /// /// Restituisce il valore dell'ODL corrente (ODL deve esserci per gestione contapezzi, senza ODL NO invio/gestione ODL) /// /// /// public string currODL(string idxMacchina) { string answ = ""; string rCall = ""; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("hasODL"); try { rCall = memLayer.ML.getRSV(currODLHash(idxMacchina)); if (!string.IsNullOrEmpty(rCall)) { answ = rCall; } else { answ = getCurrODL(idxMacchina); // salvo in redis... saveCurrODL(idxMacchina, answ); } } catch { } } return answ; } /// /// Restituisce il valore dell'ODL corrente (ODL deve esserci per gestione contapezzi, senza ODL NO invio/gestione ODL) /// /// /// indica se forzare lettura da db (true) o meno /// public string currODL(string idxMacchina, bool forceDb) { string answ = ""; // faccio comunque verifica se sia stato letto da poco il valore... x cui anche a fronte di richiesta lettura da DB per 3 sec tengo buono valore in cache redis... string rKey = memLayer.ML.redHash($"ODL:{idxMacchina}"); string _idxOdl = memLayer.ML.getRSV(rKey); if (forceDb) { if (!string.IsNullOrEmpty(_idxOdl)) { answ = _idxOdl; } else { answ = getCurrODL(idxMacchina); // salvo in redis... saveCurrODL(idxMacchina, answ); memLayer.ML.setRSV(rKey, answ, 3); } } else { answ = currODL(idxMacchina); } return answ; } /// /// Restituisce il valore dell'intera RIGA ODL corrente (da redis o da DB se non trovata...) /// /// /// public DS_ProdTempi.ODLDataTable currODLRowTab(string idxMacchina) { DS_ProdTempi.ODLDataTable answTab = null; string rCall = ""; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("hasODL_row"); try { rCall = memLayer.ML.getRSV(currOdlRowHash(idxMacchina)); if (!string.IsNullOrEmpty(rCall)) { answTab = JsonConvert.DeserializeObject(rCall); } else { // istanzio un NUOVO oggetto lettura MapoDb connDb = new MapoDb(); answTab = connDb.currODLTab(idxMacchina); // salvo in redis... rCall = JsonConvert.SerializeObject(answTab); int currOdlRowCacheDur = memLayer.ML.CRI("currOdlRowCacheDur"); memLayer.ML.setRSV(currOdlRowHash(idxMacchina), rCall, currOdlRowCacheDur); } } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in recupero currODLRow{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } } else { // istanzio un NUOVO oggetto lettura MapoDb connDb = new MapoDb(); answTab = connDb.currODLTab(idxMacchina); } return answTab; } /// /// Restituisce il valore dell'intera RIGA stato macchina corrente (da redis o da DB se non trovata...) /// /// /// public DS_applicazione.StatoMacchineDataTable currSMTab(string idxMacchina) { DS_applicazione.StatoMacchineDataTable answTab = null; string rCall = ""; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("hasStatoMacc"); try { rCall = memLayer.ML.getRSV(currStatoMaccHash(idxMacchina)); if (!string.IsNullOrEmpty(rCall)) { answTab = JsonConvert.DeserializeObject(rCall); } else { // 2020.01.31 uso nuovo oggetto connessione MapoDb man = new MapoDb(); answTab = man.currStatoMaccTab(idxMacchina); //answTab = MapoDbObj.currStatoMaccTab(idxMacchina); // salvo in redis... rCall = JsonConvert.SerializeObject(answTab); int currStatoMaccCacheDur = memLayer.ML.CRI("currStatoMaccCacheDur"); memLayer.ML.setRSV(currStatoMaccHash(idxMacchina), rCall, currStatoMaccCacheDur); } } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in recupero currODLRow{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } } else { answTab = MapoDbObj.currStatoMaccTab(idxMacchina); } return answTab; } /// /// Rimuove Key dell'ODL corrente x una data macchina IOB /// /// /// public string emptyCurrODL(string idxMacchina) { string answ = ""; try { memLayer.ML.redDelKey(currODLHash(idxMacchina)); answ = "OK"; } catch { answ = "KO"; } return answ; } /// /// effettua enroll del device /// /// /// /// /// /// /// public bool enrollDevice(string UserAuthKey, string IPv4, string DeviceName, string Description, int matricola) { bool fatto = false; // in primis testo se dipendente ed authKey sono validi.. if (taOp.getByMatrAuthKey(matricola, UserAuthKey).Rows.Count > 0) { // salvo matrOpr MatrOpr = matricola; /************************************************ * Gestione riconoscimento devices * * - cerco IP del device, testo se è rete interna (A) o extranet/internet (B) cercando substring "localNet" da web.config * (A): device interni: c'è un DHCP, e "dhcpLeaseTime" deve essere pari a lease time--- * - verifico se IP già in uso da un tempo < "dhcpLeaseTime" --> in questo caso segnalo errore e rimbalzo (NON permetto di registrare device a nuovo utente... sospetto uso "improprio" del device * - se tempo > dhcpLeaseTime allora può aver cambiato IP: aggiorno IP e descrizione del device e proseguo * (B): all'esterno vedo tutta una subnet NATtata con unico IP, non è + discriminante * - le timbrature "da esterno" devono essere confermate (instrodurre "tipo timbratura" x cui interne sono autoconfermate, esterne sono "grayed" (da confermare, da admin o ad esempio se si accende secondo device utente entro 5/10 min) * - le timbrature ext DOVREBBERO chiedere location (jScript?) e inviarla, visibile in conferma * * * **********************************************/ // calcolo il secret... DateTime adesso = DateTime.Now; string Dominio = memLayer.ML.CRS("dominio"); string UsrName = memLayer.ML.CRS("user"); // recupero dati da matricola... try { DataLayer_AnagGen.UTENTERow rigaUt = user_std.UtSn.rigaUtenteDaMatricola(matricola.ToString()); if (rigaUt != null) { Dominio = rigaUt.DOMINIO; UsrName = rigaUt.USER_NAME; } else { logger.lg.scriviLog(string.Format("non sono riuscito a recuperare RIGA utente per matricola {0}", matricola), tipoLog.ERROR); } } catch { logger.lg.scriviLog(string.Format("Eccezione! non sono riuscito a recuperare utente per matricola {0}", matricola), tipoLog.ERROR); Dominio = memLayer.ML.CRS("dominio"); UsrName = memLayer.ML.CRS("user"); } string Secret = authProxy.getSecret(Dominio, UsrName, matricola, DeviceName, adesso); string devSecret = SteamCrypto.EncryptString(Secret, memLayer.ML.CRS("cookieName")); try { // creo device + cookie! fatto = authProxy.createNewCookie(Dominio, UsrName, matricola, DeviceName, Description, IPv4, memLayer.ML.CRS("cookieName"), DateTime.Now.AddDays(memLayer.ML.CRI("cookieDayExpire"))); // loggo! logger.lg.scriviLog(string.Format("Effettuato enroll nuovo device: utente {0}\\{1} | matricola {2} | DeviceName {3} | Descrizione {4} | IP {5} | nome cookcie {6} | valido sino a {7:yyyy/MM/dd}", Dominio, UsrName, matricola, DeviceName, Description, IPv4, memLayer.ML.CRS("cookieName"), DateTime.Now.AddDays(memLayer.ML.CRI("cookieDayExpire")))); } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore enroll nuovo device:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); } } return fatto; } /// /// Effettua split ODL /// /// /// public string forceSplitOdl(string idxMacchina, bool doConfirm, bool qtyFromLast, int roundStep = 100) { string answ = "KO"; // verifico NON CI SIA un veto a NUOVI split... 2 min di default... string redKey = vetoSplitOdlMaccHash(idxMacchina); string rawData = memLayer.ML.getRSV(redKey); if (string.IsNullOrEmpty(rawData)) { // registro VETO x altri split... 5 minuti memLayer.ML.setRSV(redKey, $"Inizio SPLIT-ODL {DateTime.Now}", 300); // calcolo la qta da gestire int qtyConf = 0; int qtyNew = 0; if (doConfirm) { DS_ProdTempi.stp_PzProd_getByMacchinaRow rigaProd; try { rigaProd = taPzProd2conf.GetData(idxMacchina)[0]; qtyConf = rigaProd.pezziNonConfermati; // 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) { logger.lg.scriviLog(string.Format("Errore recupero pezzi da confermare per la macchina {0}{1}{2}", idxMacchina, Environment.NewLine, exc), tipoLog.ERROR); } } // proseguo DS_ProdTempi.ODLDataTable currData = null; DateTime adesso = DateTime.Now; // chiamo metodo redis/db... try { // recupero ODL corrente currData = currODLRowTab(idxMacchina); if (currData.Count > 0) { // registro un evento di inizio attrezzaggio (idxTipoEv = 2) int idxEvento = 2; logger.lg.scriviLog($"Invio evento ODL-SPLIT per macchina {idxMacchina}, evento {idxEvento}, articolo {currData[0].CodArticolo}, qty confermata {qtyConf}, nuova qty {qtyNew}", tipoLog.INFO); inputComandoMapo resCmd = scriviRigaEventoBarcode(idxMacchina, idxEvento, currData[0].CodArticolo, "ODL-SPLIT", 0, "", adesso, adesso); if (doConfirm) { // attendo 100 msec Thread.Sleep(100); adesso = DateTime.Now; // chiamo conferma produzione... try { string chiamata = confRett ? "confermaProdMacchinaFull" : "confermaProdMacchina"; logger.lg.scriviLog($"Chiamata a {chiamata} con parametri {currData[0].IdxMacchina} |{MatrOpr} | {DateTime.Now.AddDays(-10)} | {DateTime.Now} | {qtyConf} | 0 | 1 | {DateTime.Now} | false", tipoLog.INFO); string idxMacchinaSel = currData[0].IdxMacchina; bool fatto = false; if (confRett) { // confermo al netto dei pezzi lasciati... fatto = confermaProdMacchinaFull(idxMacchinaSel, memLayer.ML.CRI("modoConfProd"), qtyConf, 0, 0, adesso); } else { fatto = confermaProdMacchina(idxMacchinaSel, memLayer.ML.CRI("modoConfProd"), qtyConf, 0, adesso); } if (!fatto) { logger.lg.scriviLog($"ERRORE in chiamata {chiamata}", tipoLog.ERROR); } } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in ConfermaProduzione{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } } // attendo 100 msec Thread.Sleep(100); // chiamo splitOdl MapoDbObj.taODL.splitODL(currData[0].IdxODL, 0, idxMacchina, currData[0].TCRichAttr, currData[0].PzPallet, $"Nuovo ODL da forceSplitOdl", true, qtyNew); // elimino eventuale ODL precedente... string rKey = memLayer.ML.redHash($"ODL:{idxMacchina}"); memLayer.ML.setRSV(rKey, ""); // ricalcola ODL macchina var newOdl = currODL(idxMacchina, true); // attendo 1000 msec Thread.Sleep(1000); adesso = DateTime.Now; // registro fine ODL (idxTipoEv = 1) idxEvento = 1; logger.lg.scriviLog($"Invio evento FINE ODL-SPLIT per macchina {idxMacchina}, evento {idxEvento}, articolo {currData[0].CodArticolo}", tipoLog.INFO); resCmd = scriviRigaEventoBarcode(idxMacchina, idxEvento, currData[0].CodArticolo, "ODL-START"); // chiamo refresh MSE taMSE.forceRecalc(0, idxMacchina); // resetto stato macchina... memLayer.ML.redDelKey(currStatoMaccHash(idxMacchina)); answ = "OK"; logger.lg.scriviLog($"Effettuato reset e ricalcoli x split ODL per macchina {idxMacchina}", tipoLog.INFO); // se è una master richiamo fix x child... if (isMaster(idxMacchina)) { taODL.fixMachineSlave(idxMacchina, 30, 1); } } } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in forceSplitOdl{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } } else { logger.lg.scriviLog($"VETO ATTIVO | Richiesto forceSplitOdl per impianto {idxMacchina} | impossibile procedere"); } return answ; } /// /// GET elenco parametri correnti x IOB /// /// /// public List getCurrObjItems(string idxMacchina) { string serVal = memLayer.ML.getRSV(currParametersHash(idxMacchina)); List actValues = new List(); if (serVal != null) { try { actValues = JsonConvert.DeserializeObject>(serVal); // ordino! actValues.Sort((a, b) => (a.name.CompareTo(b.name))); } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in deserializzazione getIobCurrParam{Environment.NewLine}{exc}"); } } return actValues; } /// /// GET elenco parametri che richiedono una WRITE x IOB /// /// /// public List getCurrObjItemsPendigWrite(string idxMacchina) { string serVal = memLayer.ML.getRSV(currParametersHash(idxMacchina)); List actValues = new List(); List writeValues = new List(); if (serVal != null) { try { actValues = JsonConvert.DeserializeObject>(serVal); // cerco e rimuovo parametri sola lettura o SENZA richieste scrittura foreach (var item in actValues) { if (item.writable && !string.IsNullOrEmpty(item.reqValue)) { writeValues.Add(item); } } } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in deserializzazione getIobCurrParam{Environment.NewLine}{exc}"); } } return writeValues; } /// /// restituisce valore dell'ODL attivo (iniziato e NON concluso) /// /// /// public string getCurrODL(string idxMacchina) { string answ = ""; // recupero con stored NUOVA... DS_ProdTempi.ODLDataTable tabOdl = taODL.getByMacchina(idxMacchina); if (tabOdl.Rows.Count > 0) { // solo SE ho idxODL (altrimenti loggo errore) if (tabOdl[0].IdxODL > 0) { answ = tabOdl[0].IdxODL.ToString(); answ = answ == "" ? "0" : answ; } else { answ = "0"; logger.lg.scriviLog("[currODL] Errore in currODL x idxMacchina " + idxMacchina + ": IdxODL = 0"); } } else { // se è empty --> 0!!! answ = "0"; } // ultimo controllo su idxOdl... answ = answ == "" ? "0" : answ; // restituisco! return answ; } /// /// restituisce una tabella con tutte le transizioni degli ingressi per una data macchina /// /// /// public DS_applicazione.TransizioneIngressiDataTable getMatriceIngressi(string idxMacchina) { DS_applicazione.TransizioneIngressiDataTable answ; try { answ = taTranIngr.getMatriceByIdxMacchina(idxMacchina); } catch { answ = null; } return answ; } /// /// Recupera (da DB) i dati della State Machine multi ingressi nel formato /// key: IdxMacchina /// value: IdxFamigliaIngresso /// /// /// public KeyValuePair[] getMSMI_DB(string idxMacchina) { DS_applicazione.MSFDDataTable tabMSMI = new DS_applicazione.MSFDDataTable(); // 2017.09.13: inserisco gestione singleton condizionale if (memLayer.ML.CRB("disable_singleton")) { // instanzio un nuovo oggetto MapoDb MapoDb connDb = new MapoDb(); tabMSMI = connDb.taMSFD.getMulti(idxMacchina); } else { // leggo DB da singleton tabMSMI = MapoDbObj.taMSFD.getMulti(idxMacchina); } KeyValuePair[] answ = new KeyValuePair[tabMSMI.Count]; // salvo tutti i valori StateMachineIngressi... int i = 0; foreach (var item in tabMSMI) { answ[i] = new KeyValuePair(item.IdxMacchina, item.IdxFamigliaIngresso.ToString()); i++; } return answ; } /// /// restituisce il TempoCiclo effettivo (tecnico) della macchina /// /// /// public decimal getTcEffMacchina(string idxMacchina) { decimal tc = 0; try { DS_ProdTempi.stp_repDonati_getDatiProdMacchinaPeriodoRow riga = taDatiProdMacchPer.GetData(idxMacchina, DateTime.Now.AddMinutes(-30), DateTime.Now)[0]; if (riga.TCEffRT > 0) { tc = riga.TCEffRT; } else { tc = riga.TCAssegnato; } } catch { } // imposto a 99'TC if (tc == 0) { tc = 99.9M; // scrivo log per indicare mancato caricamento dati tc dichiarato e conseguente errore sul timer - 2/11/2012 EN&CV logger.lg.scriviLog(string.Format("Impostato TC Tempo Ciclo a 99' (99.9M) causa mancato inserimento tempo ciclo dichiarato")); } return tc; } /// /// Restituisce il valore booleano se la macchina sia abilitata all'input /// /// /// public bool insEnab(string idxMacchina) { bool answ = false; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("insEnabled"); try { answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "insEnabled")); } catch { } } // ...oppure dritto su DB else { if (memLayer.ML.CRB("disable_singleton")) { // instanzio un nuovo oggetto MapoDb MapoDb connDb = new MapoDb(); answ = connDb.insEnabled(idxMacchina); } else { // leggo DB da singleton answ = MapoDbObj.insEnabled(idxMacchina); } } return answ; } /// /// Restituisce il valore booleano se la macchina sia di tipo MASTER (imposta ODL x gli slave) /// /// /// public bool isMaster(string idxMacchina) { bool answ = false; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("isMaster"); try { answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "Master") == "1"); } catch { } } // ...oppure dritto su DB else { answ = MapoDbObj.isMaster(idxMacchina); } return answ; } /// /// Restituisce il valore booleano se la macchina sia di tipo MULTI (con più state machine x INGRESSI) /// /// /// public bool isMulti(string idxMacchina) { bool answ = false; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("isMulti"); try { answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "Multi") == "1"); } catch { } } // ...oppure dritto su DB else { answ = MapoDbObj.isMulti(idxMacchina); } return answ; } /// /// Restituisce il valore booleano se la macchina sia di tipo SLAVE (ODL impostato da MASTER) /// /// /// public bool isSlave(string idxMacchina) { bool answ = false; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("isSlave"); try { answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "Slave") == "1"); } catch { } } // ...oppure dritto su DB else { answ = MapoDbObj.isMulti(idxMacchina); } return answ; } /// /// Restituisce valore di una singola chiave del dizionario DatiMacchina /// /// /// /// public string mDatiMacchinaVal(string idxMacchina, string chiave) { string answ = ""; try { answ = mDatiMacchine(idxMacchina)[chiave]; } catch { } return answ; } /// /// Restitusice elenco KVP dei campi DatiMacchine + StatoMacchine per l'impianto indicato /// /// /// public Dictionary mDatiMacchine(string idxMacchina) { // hard coded dimensione vettore DatiMacchine Dictionary answ = new Dictionary(); // ORA recupero da memoria redis... try { string currHash = dtMaccHash(idxMacchina); answ = memLayer.ML.redGetHashDict(currHash); // se è vuoto... leggo da DB e popolo! if (answ.Count == 0) { answ = resetDatiMacchina(idxMacchina); } } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in compilazione dati Macchine x Redis - 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 Dictionary mOptParMacchina(string idxMacchina) { // hard coded dimensione vettore DatiMacchine Dictionary answ = new Dictionary(); // ORA recupero da memoria redis... try { string currHash = optParHash(idxMacchina); answ = memLayer.ML.redGetHashDict(currHash); } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in compilazione dati OPT PARAM x Redis - idxMacchina {2}:{0}{1}", Environment.NewLine, exc, idxMacchina)); } return answ; } /// /// Restitusice elenco KVP /// key: IdxMacchina /// value: IdxFamigliaIngresso /// /// /// public KeyValuePair[] mTabMSMI(string idxMacchina) { // hard coded dimensione vettore DatiMacchine KeyValuePair[] answ = new KeyValuePair[1]; // iniziualizzo con un valore... 0/0 answ[0] = new KeyValuePair("0", "0"); // ORA recupero da memoria redis... try { string currHash = hMSMI(idxMacchina); answ = memLayer.ML.redGetHash(currHash); // se è vuoto... leggo da DB e popolo! if (answ.Length == 0) { answ = resetMSMI(idxMacchina); } } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in compilazione Tabella Multi State Machine Ingressi x Redis:{0}{1}", Environment.NewLine, exc)); } return answ; } /// /// Restitusice elenco KVP dei campi della State Machine ingressi nel formato /// key: cState_nVal (current MICRO-STATE + "_" + new Value) /// value: iTipoEv_nState (IdxTipoEv da trasmettere + New MICRO-STATE /// /// /// public KeyValuePair[] mTabSMI(int idxFamIn) { // hard coded dimensione vettore DatiMacchine KeyValuePair[] answ = new KeyValuePair[1]; // iniziualizzo con un valore... 0/0 answ[0] = new KeyValuePair("0", "0"); // ORA recupero da memoria redis... try { string currHash = hSMI(idxFamIn); answ = memLayer.ML.redGetHash(currHash); // se è vuoto... leggo da DB e popolo! if (answ.Length == 0) { answ = resetSMI(idxFamIn); } } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in compilazione State Machine Ingressi x Redis:{0}{1}", Environment.NewLine, exc)); } return answ; } /// /// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato /// /// /// public Dictionary mTaskMacchina(string idxMacchina) { // hard coded dimensione vettore DatiMacchine Dictionary answ = new Dictionary(); // ORA recupero da memoria redis... try { string currHash = exeTaskHash(idxMacchina); answ = memLayer.ML.redGetHashDict(currHash); } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in compilazione dati EXE TASK x Redis - idxMacchina {2}:{0}{1}", Environment.NewLine, exc, idxMacchina)); } return answ; } /// /// Processa registrazione FL da IOB /// /// /// /// /// /// /// /// public string processFluxLog(string idxMacchina, string flux, string valore, string dtEve, string dtCurr, int contatore) { // instanzio un nuovo oggetto MapoDb MapoDb connDb = new MapoDb(); // scrivo keep alive!!! (se necessario, altrimenti è in cache...) connDb.scriviKeepAlive(idxMacchina, DateTime.Now); // 2017.09.14 trimmo eventualmente lo zero finale dalle date SE supera i millisecondi... dtEve = dtEve.Length > 17 ? dtEve.Substring(0, 17) : dtEve; dtCurr = dtCurr.Length > 17 ? dtCurr.Substring(0, 17) : dtCurr; // registro conteggio impiego chiamate REDIS if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("processFluxLog"); } string answ = ""; DateTime dataOraEvento = DateTime.Now; DateTime dtEvento, dtCorrente; // controllo: se ho valori dt x evento e orario DIVERSI per acquisitore IOB calcolo dataOraEvento corretto if (dtEve != dtCurr) { Int64 delta = 0; try { // se ho meno decimali x evento rispetto dtCorrente... if (dtEve.Length < dtCurr.Length) { dtEve = dtEve.PadRight(dtCurr.Length, '0'); } delta = Convert.ToInt64(dtCurr) - Convert.ToInt64(dtEve); // se meno di 60'000 ms ... if (delta < 59999) { dataOraEvento = dataOraEvento.AddMilliseconds(-delta); } else { // in questo caso elimino i MS dalle stringhe e converto i datetime.... CultureInfo provider = CultureInfo.InvariantCulture; string format = "yyyyMMddHHmmssfff"; dtEvento = DateTime.ParseExact(dtEve, format, provider); dtCorrente = DateTime.ParseExact(dtCurr, format, provider); Int64 tiks = dtCorrente.Ticks - dtEvento.Ticks; dataOraEvento = dataOraEvento.AddTicks(-tiks); } } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore calcolo ms evento/ora corrente da device remoto:{0}dtEve : {1}{0}dtCurr: {2}{0}{3}", Environment.NewLine, dtEve, dtCurr, exc), tipoLog.EXCEPTION); } } // inizio processing vero e proprio INPUT... if (idxMacchina != null && valore != null) { if (idxMacchina != "" && valore != "") { // 2020.01.31 nuovo OBJ DataLayer man = new DataLayer(); man.taFL.InsNew(idxMacchina, dataOraEvento, flux, valore, contatore); //DataLayer.obj.taFL.InsNew(idxMacchina, dataOraEvento, flux, valore, contatore); // registro in risposta che è andato tutto bene... answ = "OK"; } else { string errore = "Errore: parametri macchina/valore vuoti"; logger.lg.scriviLog(errore, tipoLog.INFO); answ = errore; } } else { string errore = "Errore: mancano parametri macchina/valore"; logger.lg.scriviLog(errore, tipoLog.INFO); answ = errore; } return answ; } /// /// Processa input da IOB eventualmente registrando i segnali inviati /// /// /// /// /// /// /// public string processInput(string idxMacchina, string valore, string dtEve, string dtCurr, string contatore) { string answ = ""; // 2018.10.26 controllo dtEve e dtCurr if (dtEve == null || dtCurr == null) { logger.lg.scriviLog(string.Format("procInput: valori nulli date: idxMacchina: {0} | valore: {1} | dtEve: {2} | dtCurr:{3}", idxMacchina, valore, dtEve, dtCurr)); } else if (dtEve.Length < 17 || dtCurr.Length < 17) { logger.lg.scriviLog(string.Format("procInput: valori data non corretti: idxMacchina: {0} | valore: {1} | dtEve: {2} | dtCurr:{3}", idxMacchina, valore, dtEve, dtCurr)); } else { // 2017.09.14 trimmo eventualmente lo zero finale dalle date SE supera i millisecondi... dtEve = dtEve.Length > 17 ? dtEve.Substring(0, 17) : dtEve; dtCurr = dtCurr.Length > 17 ? dtCurr.Substring(0, 17) : dtCurr; // registro conteggio impiego chiamate REDIS if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("processInput"); } DateTime dataOraEvento = DateTime.Now; DateTime dtEvento, dtCorrente; // controllo: se ho valori dt x evento e orario DIVERSI per acquisitore IOB calcolo dataOraEvento corretto if (dtEve != dtCurr) { // delta è un calcolo MOLTO approssimativo della differenza temporale... Int64 delta = 0; try { // se ho meno decimali x evento rispetto dtCorrente... if (dtEve.Length < dtCurr.Length) { logger.lg.scriviLog(string.Format("processInput: fix valore dtEve: {0} vs dtCurr: {1}", dtEve, dtCurr), tipoLog.INFO); dtEve = dtEve.PadRight(dtCurr.Length, '0'); } delta = Convert.ToInt64(dtCurr) - Convert.ToInt64(dtEve); // log della classe del delta (1-10, 10-100, 100-1k, 1k-10k, > 10k ms) string deltaClass = ""; // faccio SEMPRE calcolo esatto sennò sbaglia... CultureInfo provider = CultureInfo.InvariantCulture; string format = "yyyyMMddHHmmssfff"; dtEvento = DateTime.ParseExact(dtEve, format, provider); dtCorrente = DateTime.ParseExact(dtCurr, format, provider); Int64 tiks = dtCorrente.Ticks - dtEvento.Ticks; TimeSpan ts = new TimeSpan(tiks); double ms = Math.Abs(ts.TotalMilliseconds); // calcolo ESATTO dataora evento dataOraEvento = dataOraEvento.AddTicks(-tiks); if (ms <= 10) { deltaClass = "delta 0-10 ms"; } else if (ms <= 100) { deltaClass = "delta 10-100 ms"; } else if (ms <= 1000) { deltaClass = "delta 100-1000 ms"; } else if (ms <= 10000) { deltaClass = "delta 1-10 sec"; } else { deltaClass = "delta > 10 sec"; } // se ho deltaClass loggo if (deltaClass != "") { logger.lg.scriviLog("Correzione " + deltaClass); } } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore calcolo ms evento/ora corrente da device remoto:{0}dtEve : {1}{0}dtCurr: {2}{0}{3}", Environment.NewLine, dtEve, dtCurr, exc), tipoLog.EXCEPTION); } } // inizio processing vero e proprio INPUT... if (idxMacchina != null && valore != null) { if (idxMacchina != "" && valore != "") { // 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione NUOVO oggetto if (memLayer.ML.CRB("disable_singleton")) { // instanzio un nuovo oggetto MapoDb MapoDb connDb = new MapoDb(); // se abilitato registro evento sul DB if (idxMacchina != "" && sLogEnab(idxMacchina)) { saveSigLog(idxMacchina, valore, dataOraEvento, contatore); } // continuo col resto try { // scrivo keep alive!!! (se necessario, altrimenti è in cache...) connDb.scriviKeepAlive(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)) { // inizio preprocessing string newVal = ""; // processo OGNI macchina a stati dell'impianto... (KEY: IdxMacchina / IdxMacchina#qualcosa, Val = IdxFamIn) foreach (var item in mTabMSMI(idxMacchina)) { 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); } } else { // ora processo e salvo il valore del microstato... INTERNAMENTE gestisce i casi DB/REDIS secondo necessità checkMicroStato(idxMacchina, valore, dataOraEvento, contatore); } // registro in risposta che è andato tutto bene... answ = "OK"; } catch (Exception exc) { if (memLayer.ML.CRI("_logLevel") > 5) { string errore = string.Format("Errore: {0}{1}", Environment.NewLine, exc); logger.lg.scriviLog(errore, tipoLog.EXCEPTION); answ = errore; } } } else { // se abilitato registro evento sul DB if (idxMacchina != "" && MapoDbObj.sLogEnabled(idxMacchina)) { saveSigLog(idxMacchina, valore, dataOraEvento, contatore); } // continuo col resto try { // scrivo keep alive!!! (se encessario, altrimenti è in cache...) MapoDbObj.scriviKeepAlive(idxMacchina, DateTime.Now); // verifico se sia una macchina MULTI ed in tal caso calcolo i SUB-systems e CHIAMERO' alla fine pure loro.... if (MapoDbObj.isMulti(idxMacchina)) { // inizio preprocessing string newVal = ""; // processo OGNI macchina a stati dell'impianto... (KEY: IdxMacchina / IdxMacchina#qualcosa, Val = IdxFamIn) foreach (var item in getMSMI_DB(idxMacchina)) { newVal = preProcInput(item.Key, valore); // ora processo e salvo il valore del microstato... checkMicroStato(item.Key, newVal, dataOraEvento, contatore); } } else { // ora processo e salvo il valore del microstato... checkMicroStato(idxMacchina, valore, dataOraEvento, contatore); } answ = "OK"; // registro in risposta che è andato tutto bene... } catch (Exception exc) { if (memLayer.ML.CRI("_logLevel") > 5) { string errore = string.Format("Errore: {0}{1}", Environment.NewLine, exc); logger.lg.scriviLog(errore, tipoLog.EXCEPTION); answ = errore; } } } } else { string errore = "Errore: parametri macchina/valore vuoti"; logger.lg.scriviLog(errore, tipoLog.INFO); answ = errore; } } else { string errore = "Errore: mancano parametri macchina/valore"; logger.lg.scriviLog(errore, tipoLog.INFO); answ = errore; } } return answ; } /// /// Processa registrazione di uno stream di dati LIVE da IOB /// /// /// Dati live nel formato di lista di KVP chiave/valore1 /// public string processLiveJson(string idxMacchina, liveIOB liveData) { if (liveData == null) { throw new ArgumentNullException(nameof(liveData)); } // registro conteggio impiego chiamate REDIS if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("processLiveJson"); } string answ = ""; DateTime dataOraEvento = DateTime.Now; // inizio processing vero e proprio INPUT... if (!string.IsNullOrEmpty(idxMacchina) && liveData != null) { // SE ho dei segnali... if (liveData.dataList.Count > 0) { // salvo in Redis nell'area CURR_VAL TUTTI i valori live memLayer.ML.redSaveHashList(LiveCurrValHash(idxMacchina), liveData.dataList); // accodo in buffer ULTIMI valori con dataora uno ad uno... KeyValuePair[] newData = new KeyValuePair[1]; foreach (var item in liveData.dataList) { // accodo update valori... newData[0] = new KeyValuePair(dataOraEvento.ToString(), item.Value); memLayer.ML.redSaveHash(LiveBufferHash(idxMacchina, item.Key), newData); } } else { string errore = "Errore: formato liveData errato (split #)"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } // registro in risposta che è andato tutto bene... answ = "OK"; } else { string errore = "Errore: mancano parametri macchina/liveData come Json"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } return answ; } /// /// Processa registrazione di uno stream di dati LIVE da IOB /// /// /// Dati live nel formato chiave1|valore1#chiave2|valore2#chiave3|valore3 /// public string processLiveRec(string idxMacchina, string liveData) { if (liveData == null) { throw new ArgumentNullException(nameof(liveData)); } // registro conteggio impiego chiamate REDIS if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("processLiveRec"); } string answ = ""; DateTime dataOraEvento = DateTime.Now; // inizio processing vero e proprio INPUT... if (idxMacchina != null && liveData != null) { if (idxMacchina != "" && liveData != "") { // prendo il vettore LiveData e lo splitto per variabili inviate string[] liveSignals = liveData.Split('|'); // SE ho dei segnali... if (liveSignals.Length > 0) { KeyValuePair[] liveSet = new KeyValuePair[liveSignals.Length]; string[] kvp; int i = 0; foreach (string liveKVP in liveSignals) { // ogni variabile la splitto come chiave/valore kvp = liveKVP.Split(':'); liveSet[i] = new KeyValuePair(kvp[0], kvp[1]); i++; } // salvo in Redis nell'area CURR_VAL TUTTI i valori live memLayer.ML.redSaveHash(LiveCurrValHash(idxMacchina), liveSet); // accodo in buffer ULTIMI valori con dataora uno ad uno... KeyValuePair[] newData = new KeyValuePair[1]; foreach (var item in liveSet) { // accodo update valori... newData[0] = new KeyValuePair(dataOraEvento.ToString(), item.Value); memLayer.ML.redSaveHash(LiveBufferHash(idxMacchina, item.Key), newData); } } else { string errore = "Errore: formato liveData errato (split #)"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } // registro in risposta che è andato tutto bene... answ = "OK"; } else { string errore = "Errore: parametri macchina/liveData vuoti"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } } else { string errore = "Errore: mancano parametri macchina/liveData"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } return answ; } /// /// Restituisce il contapezzi salvato per la macchina /// /// /// public int pzCounter(string idxMacchina) { int answ = -1; string rCall = ""; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("getCounter"); try { rCall = memLayer.ML.getRSV(pzCountHash(idxMacchina)); if (rCall != "" && rCall != null) { int.TryParse(rCall, out answ); } else { answ = pzCounterTC(idxMacchina); // salvo in redis... saveCounter(idxMacchina, answ.ToString()); } } catch { } } return answ; } /// /// Restituisce il contapezzi come CONTEGGIO da TCRilevati per la macchina /// /// /// public int pzCounterTC(string idxMacchina) { int answ = -1; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("getCounterTC"); } // variabile x controllo dati recuperati DS_ProdTempi.StatoProdDataTable datiProdAct = null; bool okDatiProd = false; int taSP_ms_ant = memLayer.ML.cdvi("taStatoProd_ms_anticipo"); DateTime dataRif = DateTime.Now.AddMilliseconds(-taSP_ms_ant); okDatiProd = getStatoProd(idxMacchina, ref datiProdAct, dataRif); // se NON avesse recuperato --> aspetto taSP_ms_ant e poi RICHIAMO procedura... int maxTry = 3; while (!okDatiProd && maxTry > 0) { logger.lg.scriviLog(string.Format("[pzCounterTC] Impossibile recuperare dati ODL x idxMacchina {0}", idxMacchina), tipoLog.WARNING); // sleep... Thread.Sleep(taSP_ms_ant * 2); // riprovo lettura... okDatiProd = getStatoProd(idxMacchina, ref datiProdAct, dataRif); maxTry--; } // ora proseguo SE ho trovato i dati... if (okDatiProd) { if (datiProdAct != null) { if (datiProdAct.Count > 0) { if (!datiProdAct[0].IsPzTotODLNull()) { // ...a questo punto recupero DAVVERO i dati (o almeno ci provo...) try { // controllo answ = datiProdAct[0].PzTotODL; } catch (Exception exc) { logger.lg.scriviLog(string.Format("[pzCounterTC] Eccezione in recupero PzTotODL x idxMacchina {0}{1}{2}", idxMacchina, Environment.NewLine, exc), tipoLog.EXCEPTION); } } } } } else { logger.lg.scriviLog(string.Format("[pzCounterTC] Dati ODL x idxMacchina {0} non recuperati dopo tentativi reiterati...", idxMacchina), tipoLog.WARNING); } return answ; } /// /// RIMUOVE un PARAMETRO OPZIONALE dall'elenco di quelli salvati /// /// /// /// public bool remOptPar4Machine(string idxMacchina, string taskKey) { bool answ = false; string currHash = optParHash(idxMacchina); try { // leggo task attuali... var currVal = mOptParMacchina(idxMacchina); currVal.Remove(taskKey); memLayer.ML.redDelKey(currHash); answ = memLayer.ML.redSaveHashDict(currHash, currVal); } catch { } return answ; } /// /// RIMUOVE un task dall'elenco di quelli salvati /// /// /// /// public bool remTask4Machine(string idxMacchina, taskType taskKey) { bool answ = false; string currHash = exeTaskHash(idxMacchina); try { // leggo task attuali... var currTask = mTaskMacchina(idxMacchina); currTask.Remove(taskKey.ToString()); memLayer.ML.redDelKey(currHash); answ = memLayer.ML.redSaveHashDict(currHash, currTask); logger.lg.scriviLog($"Task REM - idxMacchina: {idxMacchina} | taskKey: {taskKey.ToString()}"); } catch { } return answ; } /// /// Resetta (rileggendo) i dati della macchina /// /// /// public Dictionary resetDatiMacchina(string idxMacchina) { string currHash = dtMaccHash(idxMacchina); // inizio con un bel reset... memLayer.ML.redFlushKey(currHash); Dictionary answ = new Dictionary(); DS_applicazione.MSFDDataTable tabMSFD = new DS_applicazione.MSFDDataTable(); // 2018.01.08 SEMPRE senza singleton: instanzio un nuovo oggetto MapoDb MapoDb connDb = new MapoDb(); tabMSFD = connDb.taMSFD.getByIdxMacc(idxMacchina); bool trovato = false; // se ho righe... DS_applicazione.MSFDDataTable tab = new DS_applicazione.MSFDDataTable(); DS_applicazione.MSFDRow rigaMSFD; if (tabMSFD.Rows.Count > 0) { try { rigaMSFD = tabMSFD[0]; trovato = true; } catch { rigaMSFD = tab.NewMSFDRow(); } } else { rigaMSFD = tab.NewMSFDRow(); } if (trovato) { // ora provo a compilare... try { // salvo 1:1 i valori... STATO answ.Add("IdxMicroStato", rigaMSFD.IdxMicroStato.ToString()); answ.Add("IdxStato", rigaMSFD.IdxStato.ToString()); answ.Add("CodArticolo", rigaMSFD.CodArticolo); answ.Add("insEnabled", rigaMSFD.insEnabled.ToString()); answ.Add("sLogEnabled", rigaMSFD.sLogEnabled.ToString()); answ.Add("pallet", rigaMSFD.pallet); answ.Add("CodArticolo_A", rigaMSFD.CodArticolo_A); answ.Add("CodArticolo_B", rigaMSFD.CodArticolo_B); answ.Add("TempoCicloBase", rigaMSFD.TempoCicloBase.ToString()); answ.Add("PzPalletProd", rigaMSFD.PzPalletProd.ToString()); answ.Add("MatrOpr", rigaMSFD.MatrOpr.ToString()); answ.Add("lastVal", rigaMSFD.lastVal); answ.Add("TCBase", rigaMSFD.TempoCicloBase.ToString()); //...e SETUP answ.Add("CodMacc", rigaMSFD.codmacchina); answ.Add("IdxFamIn", rigaMSFD.IdxFamigliaIngresso.ToString()); answ.Add("Multi", rigaMSFD.Multi.ToString()); answ.Add("BitFilt", rigaMSFD.BitFilt.ToString()); answ.Add("MaxVal", rigaMSFD.MaxVal.ToString()); answ.Add("BSR", rigaMSFD.BSR.ToString()); answ.Add("ExplodeBit", rigaMSFD.ExplodeBit.ToString()); answ.Add("NumBit", rigaMSFD.NumBit.ToString()); answ.Add("IdxFamMacc", rigaMSFD.IdxFamiglia.ToString()); answ.Add("simplePallet", rigaMSFD.simplePallet.ToString()); answ.Add("palletChange", rigaMSFD.palletChange.ToString()); } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in compilazione dati MSFD:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION); } // cerco dati master/slave... string isMaster = connDb.taM2S.getByMaster(idxMacchina).Count > 0 ? "1" : "0"; string isSlave = connDb.taM2S.getBySlave(idxMacchina).Count > 0 ? "1" : "0"; answ.Add("Master", isMaster); answ.Add("Slave", isSlave); // verifico il timeout che cambia a seconda che sia vero o falso insEnabled... int tOutShort = memLayer.ML.cdvi("TmOut.MS.S"); int tOutLong = memLayer.ML.cdvi("TmOut.MS.L"); int redDtMacTOut = tOutLong; try { redDtMacTOut = (answ["insEnabled"].ToLower() == "true") ? tOutShort : tOutLong; } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in calcolo timeout dati macchina: idxMacchina{idxMacchina} | TShort: {tOutShort} | TLong {tOutLong}{Environment.NewLine}{exc}"); } // salvo in redis! memLayer.ML.redSaveHashDict(currHash, answ, redDtMacTOut); } else { logger.lg.scriviLog("Errore in chiamata stp_MSFD_getMacc (connDb.taMSFD.getByIdxMacc(idxMacchina))"); } return answ; } /// /// Resetta (rileggendo) i dati della State Machine multi ingressi nel formato /// key: IdxMacchina /// value: IdxFamigliaIngresso /// /// /// public KeyValuePair[] resetMSMI(string idxMacchina) { string currHash = hMSMI(idxMacchina); DS_applicazione.MSFDDataTable tabMSMI = new DS_applicazione.MSFDDataTable(); // 2017.09.13: inserisco gestione singleton condizionale if (memLayer.ML.CRB("disable_singleton")) { // instanzio un nuovo oggetto MapoDb MapoDb connDb = new MapoDb(); tabMSMI = connDb.taMSFD.getMulti(idxMacchina); } else { // leggo DB da singleton tabMSMI = MapoDbObj.taMSFD.getMulti(idxMacchina); } KeyValuePair[] answ = new KeyValuePair[tabMSMI.Count]; // salvo tutti i valori StateMachineIngressi... int i = 0; foreach (var item in tabMSMI) { answ[i] = new KeyValuePair(item.IdxMacchina, item.IdxFamigliaIngresso.ToString()); i++; } // verifico il timeout (default 60 sec...) int tOut = (memLayer.ML.cdvi("TmOut.MSMI") <= 0) ? 60 : memLayer.ML.cdvi("TmOut.MSMI"); // salvo in redis! memLayer.ML.redSaveHash(currHash, answ, tOut); return answ; } /// /// Resetta (rileggendo) i dati della State Machine ingressi nel formato /// key: cState_nVal (current MICRO-STATE + "_" + new Value) /// value: iTipoEv_nState (IdxTipoEv da trasmettere + New MICRO-STATE) /// /// /// public KeyValuePair[] resetSMI(int idxFamIn) { string currHash = hSMI(idxFamIn); DS_applicazione.TransizioneIngressiDataTable tabSMI = new DS_applicazione.TransizioneIngressiDataTable(); // 2017.09.13: inserisco gestione singleton condizionale if (memLayer.ML.CRB("disable_singleton")) { // instanzio un nuovo oggetto MapoDb MapoDb connDb = new MapoDb(); tabSMI = connDb.taTransIngr.getByIdxFamIng(idxFamIn); } else { // leggo DB da singleton tabSMI = MapoDbObj.taTransIngr.getByIdxFamIng(idxFamIn); } KeyValuePair[] answ = new KeyValuePair[tabSMI.Count]; // salvo tutti i valori StateMachineIngressi... int i = 0; string key = ""; string val = ""; foreach (var item in tabSMI) { key = string.Format("{0}_{1}", item.IdxMicroStato, item.ValoreIngresso); val = string.Format("{0}_{1}", item.IdxTipoEvento, item.next_IdxMicroStato); answ[i] = new KeyValuePair(key, val); i++; } // verifico il timeout (default 60 sec...) int tOut = (memLayer.ML.cdvi("TmOut.SMI") <= 0) ? 60 : memLayer.ML.cdvi("TmOut.SMI"); // salvo in redis! memLayer.ML.redSaveHash(currHash, answ, tOut); return answ; } /// /// rigenera la tab diario di bordo x la macchian richiesta nell'intervallo definito /// /// /// /// public void rigeneraDiarioDiBordo(string IdxMacchina, DateTime dataInizio, DateTime dataFine) { // elimino da diario di bordo i valori nell'intervallo... MapoDbObj.taDiario.DeleteByMacchinaPeriodo(IdxMacchina, dataInizio, dataFine); // seleziono le righe eventi interessate e le processo 1 ad 1... DS_applicazione.EventListDataTable tabEventi = MapoDbObj.taEvList.GetByMacchinaPeriodo(IdxMacchina, dataInizio, dataFine); foreach (DS_applicazione.EventListRow rigaEv in tabEventi) { if (rigaEv.IdxTipo <= 12) // è barcode { checkCambiaStatoBatch(tipoInputEvento.barcode, IdxMacchina, rigaEv.InizioStato, rigaEv.IdxTipo, rigaEv.CodArticolo, rigaEv.Value, rigaEv.MatrOpr, rigaEv.pallet); } else // è hw { checkCambiaStatoBatch(tipoInputEvento.hw, IdxMacchina, rigaEv.InizioStato, rigaEv.IdxTipo, rigaEv.CodArticolo, rigaEv.Value, rigaEv.MatrOpr, rigaEv.pallet); } } } /// /// Processa registrazione EVENTO CONTEGGIO PEZZI x una data macchina IOB /// /// Macchina /// Pezzi da registrare /// public string saveCaricoPezzi(string idxMacchina, string qty) { // default: 0, non registrato come cautela... string answ = "0"; // controllo per proseguire if (!string.IsNullOrEmpty(idxMacchina) && !string.IsNullOrEmpty(qty)) { int numPzIncr = -1; int.TryParse(qty, out numPzIncr); // se il conteggio è >= 0 SALVO evento... if (numPzIncr >= 0) { // recupero ODL corrente var currData = currODLRowTab(idxMacchina); // registro evento 120 --> contapezzi in blocco !!!HARD CODED!!! !!!FIXME!!! int idxEvento = 120; // istanziato un NUOVO oggetto x scrivere... scriviRigaEventoBarcode(idxMacchina, idxEvento, currData[0].CodArticolo, qty); } // registro in risposta che è andato tutto bene... ovvero la qty richiesta... answ = qty; } else { string errore = $"Errore: mancano parametri macchina/incremento: idxMacchina {idxMacchina} | qty {qty}"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } return answ; } /// /// Processa registrazione di un counter x una data macchina IOB /// /// /// contapezzi /// public string saveCounter(string idxMacchina, string counter) { // registro conteggio impiego chiamate REDIS if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("saveCounter"); } string answ = "0"; // inizio processing vero e proprio INPUT... if (!string.IsNullOrEmpty(idxMacchina)) { if (!string.IsNullOrEmpty(counter)) { int newCounter = -1; int.TryParse(counter, out newCounter); // se il conteggio è >= 0 SALVO come nuovo conteggio... if (newCounter >= 0) { string redKey = pzCountHash(idxMacchina); // verifico SE ci sia chiave in redis (ALTRIMENTI rileggo da DB) string redVal = memLayer.ML.getRSV(redKey); if (!string.IsNullOrEmpty(redVal)) { // salvo in Redis nell'area corretta il valore richiesto memLayer.ML.setRSV(redKey, counter); // imposto risposta... answ = counter; } else { // rileggo da DB e salvo e poi restituisco questo... int currCount = pzCounterTC(idxMacchina); memLayer.ML.setRSV(redKey, currCount.ToString()); // imposto risposta... answ = currCount.ToString(); } } } else { string errore = "Errore: parametro counter vuoto"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } } else { string errore = "Errore: parametro macchina vuoto"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } return answ; } /// /// Processa registrazione ODL corrente x macchina /// /// /// cod ODL in produzione, se "" --> non c'è... /// public string saveCurrODL(string idxMacchina, string currODL) { if (currODL == null) { throw new ArgumentNullException(nameof(currODL)); } // registro conteggio impiego chiamate REDIS if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("saveCurrODL"); } string answ = ""; // inizio processing vero e proprio INPUT... if (idxMacchina != null && currODL != null) { if (idxMacchina != "" && currODL != "") { int currOdlCacheDur = memLayer.ML.CRI("currOdlCacheDur"); // se ODL fosse 0 USO DURATA CACHE 1/4... if (currODL == "0") { currOdlCacheDur = currOdlCacheDur / 4; } memLayer.ML.setRSV(currODLHash(idxMacchina), currODL, currOdlCacheDur); // registro in risposta che è andato tutto bene... answ = "OK"; } else { string errore = string.Format("Errore: parametri macchina/currODL vuoti ({0}/{1})", idxMacchina, currODL); logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } } else { string errore = "Errore: mancano parametri macchina/currODL"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } return answ; } /// /// salva il segnale di "microstato" /// /// idx macchina /// valore ingresso /// data-ora evento (server) /// sequenza dati inviati /// public void saveSigLog(string idxMacchina, string valore, DateTime dtEve, string contatore) { int cont = 0; try { cont = Convert.ToInt32(contatore); } catch { } // 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione NUOVO oggetto if (memLayer.ML.CRB("disable_singleton")) { // 2017.06.09 forzo init x errori "sovrapposizioni" taSigLog = new DS_applicazioneTableAdapters.SignalLogTableAdapter(); } taSigLog.Insert(DateTime.Now, idxMacchina, valore, dtEve, cont); } /// /// scrive una riga di evento nel db /// /// codice macchina /// idx evento /// Codice Articolo /// valore /// matricola operatore /// pallet (vuoto se nd) /// data-ora dell'evento /// data-ora corrente dell'invio /// public inputComandoMapo scriviRigaEvento(string IdxMacchina, int IdxTipo, string CodArticolo, string Value, int MatrOpr, string pallet, DateTime eventTime, DateTime currentTime) { int inserito = 0; // 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione NUOVO oggetto if (memLayer.ML.CRB("disable_singleton")) { // 2017.06.09 forzo init x errori "sovrapposizioni" MapoDbObj.taEvList = new DS_applicazioneTableAdapters.EventListTableAdapter(); } try { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); // calcolo dataOra reale (evento + delta(ora server - ora remota) DateTime dataOra = eventTime.Add(DateTime.Now - currentTime); // inserisco evento inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet); // faccio controllo per eventuale cambio stato da tab transizioni... checkCambiaStatoBatch(tipoInputEvento.hw, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet); } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} MatrOpr {5}{0} Pallet {6}{0} eventTime {7}{0} currentTime {8}{0} eccezione: {0}{9}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value, MatrOpr, pallet, eventTime, currentTime, exc), tipoLog.EXCEPTION); } // formatto output inputComandoMapo answ = new inputComandoMapo(); answ.outValue = inserito.ToString(); answ.needStatusRefresh = true; return answ; } /// /// scrive una riga di evento nel db /// /// codice macchina /// idx evento /// Codice Articolo /// valore /// matricola operatore /// pallet (vuoto se nd) /// public inputComandoMapo scriviRigaEvento(string IdxMacchina, int IdxTipo, string CodArticolo, string Value, int MatrOpr, string pallet) { int inserito = 0; // 2017.06.09 forzo init x errori "sovrapposizioni" MapoDbObj.taEvList = new DS_applicazioneTableAdapters.EventListTableAdapter(); try { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); DateTime dataOra = DateTime.Now; // inserisco evento inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet); // faccio controllo per eventuale cambio stato da tab transizioni... checkCambiaStatoBatch(tipoInputEvento.hw, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet); } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} MatrOpr {5}{0} Pallet {6}{0} eccezione:{0}{7}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value, MatrOpr, pallet, exc), tipoLog.EXCEPTION); } // formatto output inputComandoMapo answ = new inputComandoMapo(); answ.outValue = inserito.ToString(); answ.needStatusRefresh = true; return answ; } /// /// scrive una riga di evento nel db SENZA passare operatore e pallet (mette a 0 e "-") /// /// codice macchina /// idx evento /// Codice Articolo /// valore /// public inputComandoMapo scriviRigaEvento(string IdxMacchina, int IdxTipo, string CodArticolo, string Value) { int inserito = 0; try { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); DateTime dataOra = DateTime.Now; // inserisco evento inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, 0, "-"); // faccio controllo per eventuale cambio stato da tab transizioni... checkCambiaStatoBatch(tipoInputEvento.hw, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, 0, "-"); } catch { logger.lg.scriviLog(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} eccezione: {0}{5}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value), tipoLog.EXCEPTION); } // formatto output inputComandoMapo answ = new inputComandoMapo(); answ.outValue = inserito.ToString(); answ.needStatusRefresh = true; return answ; } /// /// scrive una riga di evento inviato da Barcode nel db /// /// codice macchina /// idx evento /// Codice Articolo /// valore /// matricola operatore /// pallet (vuoto se nd) /// data-ora dell'evento /// data-ora corrente dell'invio /// public inputComandoMapo scriviRigaEventoBarcode(string IdxMacchina, int IdxTipo, string CodArticolo, string Value, int MatrOpr, string pallet, DateTime eventTime, DateTime currentTime) { int inserito = 0; // calcolo dataOra reale (evento + delta(ora server - ora remota) DateTime dataOra = eventTime.Add(DateTime.Now - currentTime); try { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); // inserisco evento inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet); } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} MatrOpr {5}{0} Pallet {6}{0} eventTime {7}{0} currentTime {8}{0} eccezione: {0}{9}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value, MatrOpr, pallet, eventTime, currentTime, exc), tipoLog.EXCEPTION); } try { // faccio controllo per eventuale cambio stato da tab transizioni... checkCambiaStatoBatch(tipoInputEvento.barcode, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet); } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in checkCambiaStatoBatch(8) | tipoInputEvento: {tipoInputEvento.barcode} | IdxMacchina: {IdxMacchina} | dataOra: {dataOra} | IdxTipo: {IdxTipo} | CodArticolo: {CodArticolo} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}{Environment.NewLine}{exc}"); } // formatto output inputComandoMapo answ = new inputComandoMapo(); answ.outValue = inserito.ToString(); answ.needStatusRefresh = true; return answ; } /// /// scrive una riga di evento inviato da Barcode nel db /// /// codice macchina /// idx evento /// Codice Articolo /// valore /// matricola operatore /// pallet (vuoto se nd) /// public inputComandoMapo scriviRigaEventoBarcode(string IdxMacchina, int IdxTipo, string CodArticolo, string Value, int MatrOpr, string pallet) { int inserito = 0; DateTime dataOra = DateTime.Now; try { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); // inserisco evento inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet); } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} MatrOpr {5}{0} Pallet {6}{0} eccezione: {0}{7}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value, MatrOpr, pallet, exc), tipoLog.EXCEPTION); } try { // faccio controllo per eventuale cambio stato da tab transizioni... checkCambiaStatoBatch(tipoInputEvento.barcode, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet); } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in checkCambiaStatoBatch(6) | tipoInputEvento: {tipoInputEvento.barcode} | IdxMacchina: {IdxMacchina} | dataOra: {dataOra} | IdxTipo: {IdxTipo} | CodArticolo: {CodArticolo} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}{Environment.NewLine}{exc}"); } // formatto output inputComandoMapo answ = new inputComandoMapo(); answ.outValue = inserito.ToString(); answ.needStatusRefresh = true; return answ; } /// /// scrive una riga di evento inviato da Barcode nel db SENZA operatore e pallet (mette a 0 e "-") /// /// codice macchina /// idx evento /// Codice Articolo /// valore /// public inputComandoMapo scriviRigaEventoBarcode(string IdxMacchina, int IdxTipo, string CodArticolo, string Value) { int inserito = 0; DateTime dataOra = DateTime.Now; try { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); // inserisco evento inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, 0, "-"); } catch { logger.lg.scriviLog(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} eccezione: {0}{5}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value), tipoLog.EXCEPTION); } try { // faccio controllo per eventuale cambio stato da tab transizioni... checkCambiaStatoBatch(tipoInputEvento.barcode, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, 0, "-"); } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in checkCambiaStatoBatch(4) | tipoInputEvento: {tipoInputEvento.barcode} | IdxMacchina: {IdxMacchina} | dataOra: {dataOra} | IdxTipo: {IdxTipo} | CodArticolo: {CodArticolo} | Value: {Value} | MatrOpr: 0 | pallet: -{Environment.NewLine}{exc}"); } // formatto output inputComandoMapo answ = new inputComandoMapo(); answ.outValue = inserito.ToString(); answ.needStatusRefresh = true; return answ; } public int scriviRigaEventoSimulata(DateTime dataOra, string IdxMacchina, int IdxTipo, string CodArticolo, string Value, int MatrOpr, string pallet) { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); // inserisco evento int inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet); return inserito; } public int scriviRigaEventoSimulata(DateTime dataOra, string IdxMacchina, int IdxTipo, string CodArticolo, string Value) { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); // inserisco evento int inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, 0, "-"); return inserito; } /// /// scrive una riga di stato nel diario di bordo /// /// codice macchina /// idx stato /// Codice Articolo /// valore /// matricola operatore /// pallet (vuoto se nd) /// data-ora dell'evento /// data-ora corrente dell'invio /// public inputComandoMapo scriviRigaStato(string IdxMacchina, int IdxStato, string CodArticolo, string Value, int MatrOpr, string pallet, DateTime eventTime, DateTime currentTime) { int inserito = 0; try { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); // calcolo dataOra reale (evento + delta(ora server - ora remota) DateTime dataOra = eventTime.Add(DateTime.Now - currentTime); // inserisco la nuova riga di stato mentre il trigger aggiorna le tab... inserito = MapoDbObj.taDiario.Insert(IdxMacchina, dataOra, null, IdxStato, null, Value, CodArticolo, null, null, MatrOpr, pallet); } catch { logger.lg.scriviLog(string.Format("Errore in fase di scrittura stato con i seguenti dati:{0} macchina {1}{0} IdxStato {2}{0} CodArticolo {3}{0} Value {4}{0} MatrOpr {5}{0} Pallet {6}{0} eventTime {7}{0} currentTime {8}{0} eccezione: {0}{9}", Environment.NewLine, IdxMacchina, IdxStato, CodArticolo, Value, MatrOpr, pallet, eventTime, currentTime), tipoLog.EXCEPTION); } // formatto output inputComandoMapo answ = new inputComandoMapo(); answ.outValue = inserito.ToString(); answ.needStatusRefresh = true; return answ; } public int scriviRigaStatoSimulata(DateTime dataOra, string IdxMacchina, int IdxStato, string CodArticolo, string Value, int MatrOpr, string pallet) { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); // inserisco la nuova riga di stato mentre il trigger aggiorna le tab... int inserito = MapoDbObj.taDiario.Insert(IdxMacchina, dataOra, null, IdxStato, null, Value, CodArticolo, null, null, MatrOpr, pallet); return inserito; } public int scriviRigaStatoSimulata(DateTime dataOra, string IdxMacchina, int IdxStato, string CodArticolo, string Value) { // verifico se esista la macchina altrimenti la creo... verificaIdxMacchina(IdxMacchina); // inserisco la nuova riga di stato mentre il trigger aggiorna le tab... int inserito = MapoDbObj.taDiario.Insert(IdxMacchina, dataOra, null, IdxStato, null, Value, CodArticolo, null, null, 0, "-"); return inserito; } /// /// invia una mail al destinatario x linkare nuovi devices tramite URL /// /// /// /// /// public bool sendUserAuthEmail(string destinatario, string UserAuthKey, int idxDipendente) { bool fatto = false; string smtpCli = ""; string mittente = ""; string oggetto = ""; string userUrl = ""; string baseUrl = ""; string userWebUrl = ""; string baseWebUrl = ""; string corpo = ""; try { // compongo la stringa smtpCli = memLayer.ML.CRS("_smtpCli"); mittente = memLayer.ML.CRS("_fromEmail"); oggetto = "Link autorizzazione device per GPW"; baseUrl = memLayer.ML.CRS("baseUrl"); baseWebUrl = memLayer.ML.CRS("baseWebUrl"); userUrl = string.Format("{2}jumper.aspx?UserAuthkey={0}&idxDipendente={1}", UserAuthKey, idxDipendente, baseUrl); userWebUrl = string.Format("{2}jumper.aspx?UserAuthkey={0}&idxDipendente={1}", UserAuthKey, idxDipendente, baseWebUrl); corpo = string.Format("Hai ricevuto questa email su richiesta tua o dell'Admin per poter procedere a registrare un (nuovo) devices con GPW:{0}
Per proseguire clicca sul link seguente(rete interna):
{0}{0}{1}{0}{0}

oppure sul link seguente (internet):
{0}{0}{2}{0}{0}

Team GPW Steamware", Environment.NewLine, userUrl, userWebUrl); gestEmail.ge.mandaEmail(mittente, destinatario, oggetto, corpo); fatto = true; } catch { } return fatto; } /// /// Invia email di avviso che ci sono dei TC da confermare /// /// /// public bool sendWarnTcChangeReq(string destinatario) { bool fatto = false; string mittente = ""; string oggetto = ""; string pageUrl = ""; string corpo = ""; try { // compongo la stringa mittente = memLayer.ML.CRS("_fromEmail"); oggetto = memLayer.ML.CRS("oggettoChgTc"); pageUrl = string.Format("{0}{1}", memLayer.ML.CRS("baseUrlAdmin"), memLayer.ML.CRS("pageUrlApprODL")); corpo = string.Format(memLayer.ML.CRS("corpoChgTc"), Environment.NewLine, pageUrl); if (memLayer.ML.CRB("_useAuthSmtp")) { gestEmail.geAuth.mandaEmail(mittente, destinatario, oggetto, corpo); } else { gestEmail.ge.mandaEmail(mittente, destinatario, oggetto, corpo); } fatto = true; } catch { } return fatto; } /// /// SET elenco parametri correnti x IOB /// /// /// /// public bool setCurrObjItems(string idxMacchina, List currValues) { bool answ = false; if (currValues != null) { string serVal = JsonConvert.SerializeObject(currValues); memLayer.ML.setRSV(currParametersHash(idxMacchina), serVal); } return answ; } /// /// Salvataggio su della mappa di memoria dell'IOB x ulteriori impieghi /// /// /// /// public bool setIobMemMap(string idxMacchina, plcMemMap currMemMap) { bool answ = false; // se ho un area memoria valida... if (currMemMap != null) { // salvo! string serVal = JsonConvert.SerializeObject(currMemMap); memLayer.ML.setRSV(memMapHash(idxMacchina), serVal); } return answ; } /// /// Restituisce il valore booleano se la macchina sia abilitata all'inserimento COMPLETO nel Signal Log /// /// /// public bool sLogEnab(string idxMacchina) { bool answ = false; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("sLogEnabled"); try { answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "sLogEnabled")); } catch { } } // ...oppure dritto su DB else { answ = MapoDbObj.sLogEnabled(idxMacchina); } return answ; } /// /// Aggiornamento parametro per macchina /// /// /// Parametro macchina come definito in file json /// /// public bool updateMachineParameter(string idxMacchina, string Original_uid, string reqValue) { bool answ = false; // recupero items... List dcList = getCurrObjItems(idxMacchina); List list2Update = new List(); // cerco quello da aggiornare objItem trovato = dcList.Find(obj => obj.uid == Original_uid); // se non trova --> crea ed aggiunge... if(trovato==null) { dcList.Add(new objItem() { uid = Original_uid }); trovato = dcList.Find(obj => obj.uid == Original_uid); } // se trovato procedo if (trovato != null) { // aggiorno valore richiesto + dt richiesta trovato.reqValue = reqValue; trovato.lastRequest = DateTime.Now; list2Update.Add(trovato); upsertCurrObjItems(idxMacchina, list2Update); // accodo in task 2 exe la richiesta di processing addTask4Machine(idxMacchina, taskType.setParameter, trovato.uid); answ = true; } return answ; } /// /// Effettua UPSERT elenco parametri correnti x IOB (se c'è UPDATE, se manca ADD) /// /// /// /// public bool upsertCurrObjItems(string idxMacchina, List innovations) { bool answ = false; if (innovations != null) { // leggo i valori attuali... List actValues = getCurrObjItems(idxMacchina); // per ogni valore passatomi faccio insert o update foreach (var item in actValues) { // cerco nelle innovazioni SE CI SIA un valore act objItem trovato = innovations.Find(obj => obj.uid == item.uid); // se non trovato... if (trovato == null) { // aggiungo innovations.Add(item); } } // serializzo e salvo string serVal = JsonConvert.SerializeObject(innovations); memLayer.ML.setRSV(currParametersHash(idxMacchina), serVal); } return answ; } /// /// Restituisce il valore SPECIFICATO per la state machine ingressi /// value: iTipoEv_nState (IdxTipoEv da trasmettere + New MICRO-STATE) /// /// /// /// /// public string valoreSMI(int idxFamIn, int idxMicroStato, int valoreIn) { string currHash = hSMI(idxFamIn); string field = string.Format("{0}_{1}", idxMicroStato, valoreIn); return memLayer.ML.redGetHashField(currHash, field); } #endregion Public Methods } } #if false /// /// Elenco task ammessi (x IOB-WIN da eseguire...) /// public enum taskType { /// /// Task nullo / fake /// nihil, /// /// Rimanda a PLC eventuale segnale NON in setup (MA NON RESETTA) /// fixStopSetup, /// /// Indica al PLC di forzare il reset del contapezzi /// forceResetPzCount, /// /// Indica al PLC di forzare il NUOVO valore di contapezzi (impostato come value) /// forceSetPzCount, /// /// Imposta Articolo su PLC /// setArt, /// /// Imposta Commessa su PLC /// setComm, /// /// Set Programma CNC su PLC /// setProg, /// /// Indica al PLC iniziato setup (e secondo casi ferma contapezzi /resetta) /// startSetup, /// /// Indica al PLC finito setup (e secondo casi ferma contapezzi /resetta) /// stopSetup, /// /// Richiesta invio watchdog a PLC /// sendWatchDogMes2Plc } public enum tipoSelettore { articoli } #endif