using MapoSDK; using Newtonsoft.Json; using SteamWare; using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Globalization; using System.Reflection; namespace MapoDb { /// /// classe gestione operazioni su DB tramite MapoDb /// public class DataLayer { #region area table adapters // Table adapter x DS_Applicazione public DS_applicazioneTableAdapters.AnagraficaGruppiTableAdapter taAG; public DS_applicazioneTableAdapters.MacchineTableAdapter taMacchine; public DS_applicazioneTableAdapters.StatoMacchineTableAdapter taStatoMacchine; public DS_applicazioneTableAdapters.AnagraficaEventiTableAdapter taAnagEventi; public DS_applicazioneTableAdapters.AnagraficaStatiTableAdapter taAnagStati; public DS_applicazioneTableAdapters.KeepAliveTableAdapter taKeepAlive; public DS_applicazioneTableAdapters.DiarioDiBordoTableAdapter taStati; public DS_applicazioneTableAdapters.EventListTableAdapter taEventi; public DS_applicazioneTableAdapters.AnagraficaOperatoriTableAdapter taOp; public DS_applicazioneTableAdapters.AnagraficaOperatori2insTableAdapter taOp2ins; public DS_applicazioneTableAdapters.TransizioneIngressiTableAdapter taTranIngr; public DS_applicazioneTableAdapters.RemoteRebootLogTableAdapter taRemReb; public DS_applicazioneTableAdapters.SignalLogTableAdapter taSigLog; public DS_applicazioneTableAdapters.FluxLogTableAdapter taFL; // Table adapter x DS_ProdTempi public DS_ProdTempiTableAdapters.AnagArticoliTableAdapter taAnagArt; public DS_ProdTempiTableAdapters.ODLTableAdapter taODL; public DS_ProdTempiTableAdapters.DatiMacchineTableAdapter taDatiMacchine; public DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaTableAdapter taDatiProdMacch; public DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaPeriodoTableAdapter taDatiProdMacchPer; public DS_ProdTempiTableAdapters.stp_repDonati_getLastStatoDurataMacchinaTableAdapter taDatiStatoMacch; public DS_ProdTempiTableAdapters.PostazioniMapoTableAdapter taPostazioni; #if false public DS_ProdTempiTableAdapters.DatiConfermatiTableAdapter taDatiConfermati; #endif public DS_ProdTempiTableAdapters.stp_PzProd_getByMacchinaTableAdapter taPzProd2conf; public DS_ProdTempiTableAdapters.TempiCicloRilevatiTableAdapter taTempiCicloRilevati; public DS_ProdTempiTableAdapters.DatiProduzioneTableAdapter taDatiProd; public DS_ProdTempiTableAdapters.stp_TempoByIdxMaccPeriodClassTableAdapter taTempoByClass; public DS_ProdTempiTableAdapters.TurniMacchinaTableAdapter taTurniMacc; public DS_ProdTempiTableAdapters.CalendFesteFerieTableAdapter taCalFF; public DS_ProdTempiTableAdapters.MappaStatoExplTableAdapter taMSE; public DS_ProdTempiTableAdapters.PromesseODLTableAdapter taPODL; public DS_ProdTempiTableAdapters.RegistroControlliTableAdapter taRC; public DS_ProdTempiTableAdapters.RegistroScartiTableAdapter taRS; public DS_ProdTempiTableAdapters.StatoProdTableAdapter taStatoProd; // table adapter x utility public DS_UtilityTableAdapters.v_selArticoliTableAdapter taSelArt; public DS_UtilityTableAdapters.v_selMacchineTableAdapter taSelMacc; public DS_UtilityTableAdapters.v_selODLTableAdapter taSelOdlFree; public DS_UtilityTableAdapters.CommentiTableAdapter taComm; // table adapter x planner public DS_PlanTableAdapters.MachineParamsTableAdapter taMacParams; public DS_PlanTableAdapters.CalStopTableAdapter taPlanCalStop; public DS_PlanTableAdapters.CalDispTableAdapter taPlanCalDisp; public DS_PlanTableAdapters.RichiesteTableAdapter taPlanRichieste; public DS_PlanTableAdapters.PromesseOUTTableAdapter taPromOut; // tablet adapter x IS public DS_IntServTableAdapters.IstanzeKITTableAdapter taIstK; public DS_IntServTableAdapters.ProduzioneAs400TableAdapter taAs400; public DS_IntServTableAdapters.TKS_SearchTableAdapter taTKS; public DS_IntServTableAdapters.TransitoDatiTableAdapter taIS_TrDati; public DS_IntServTableAdapters.WipSetupKitTableAdapter taWKS; /// /// init dei table adapters /// protected void initTA() { // istanzio oggetto taAG = new DS_applicazioneTableAdapters.AnagraficaGruppiTableAdapter(); taMacchine = new DS_applicazioneTableAdapters.MacchineTableAdapter(); taStatoMacchine = new DS_applicazioneTableAdapters.StatoMacchineTableAdapter(); taAnagEventi = new DS_applicazioneTableAdapters.AnagraficaEventiTableAdapter(); taAnagStati = new DS_applicazioneTableAdapters.AnagraficaStatiTableAdapter(); taKeepAlive = new DS_applicazioneTableAdapters.KeepAliveTableAdapter(); taStati = new DS_applicazioneTableAdapters.DiarioDiBordoTableAdapter(); taEventi = new DS_applicazioneTableAdapters.EventListTableAdapter(); taOp = new DS_applicazioneTableAdapters.AnagraficaOperatoriTableAdapter(); taOp2ins = new DS_applicazioneTableAdapters.AnagraficaOperatori2insTableAdapter(); taTranIngr = new DS_applicazioneTableAdapters.TransizioneIngressiTableAdapter(); taRemReb = new DS_applicazioneTableAdapters.RemoteRebootLogTableAdapter(); taSigLog = new DS_applicazioneTableAdapters.SignalLogTableAdapter(); taFL = new DS_applicazioneTableAdapters.FluxLogTableAdapter(); taAnagArt = new DS_ProdTempiTableAdapters.AnagArticoliTableAdapter(); taODL = new DS_ProdTempiTableAdapters.ODLTableAdapter(); taDatiMacchine = new DS_ProdTempiTableAdapters.DatiMacchineTableAdapter(); taDatiProdMacch = new DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaTableAdapter(); taDatiProdMacchPer = new DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaPeriodoTableAdapter(); taDatiStatoMacch = new DS_ProdTempiTableAdapters.stp_repDonati_getLastStatoDurataMacchinaTableAdapter(); taPostazioni = new DS_ProdTempiTableAdapters.PostazioniMapoTableAdapter(); taTurniMacc = new DS_ProdTempiTableAdapters.TurniMacchinaTableAdapter(); #if false taDatiConfermati = new DS_ProdTempiTableAdapters.DatiConfermatiTableAdapter(); #endif taPzProd2conf = new DS_ProdTempiTableAdapters.stp_PzProd_getByMacchinaTableAdapter(); taTempiCicloRilevati = new DS_ProdTempiTableAdapters.TempiCicloRilevatiTableAdapter(); taDatiProd = new DS_ProdTempiTableAdapters.DatiProduzioneTableAdapter(); taTempoByClass = new DS_ProdTempiTableAdapters.stp_TempoByIdxMaccPeriodClassTableAdapter(); taCalFF = new DS_ProdTempiTableAdapters.CalendFesteFerieTableAdapter(); taMSE = new DS_ProdTempiTableAdapters.MappaStatoExplTableAdapter(); taPODL = new DS_ProdTempiTableAdapters.PromesseODLTableAdapter(); taRC = new DS_ProdTempiTableAdapters.RegistroControlliTableAdapter(); taRS = new DS_ProdTempiTableAdapters.RegistroScartiTableAdapter(); taStatoProd = new DS_ProdTempiTableAdapters.StatoProdTableAdapter(); taSelArt = new DS_UtilityTableAdapters.v_selArticoliTableAdapter(); taSelMacc = new DS_UtilityTableAdapters.v_selMacchineTableAdapter(); taSelOdlFree = new DS_UtilityTableAdapters.v_selODLTableAdapter(); taComm = new DS_UtilityTableAdapters.CommentiTableAdapter(); taMacParams = new DS_PlanTableAdapters.MachineParamsTableAdapter(); taPlanCalStop = new DS_PlanTableAdapters.CalStopTableAdapter(); taPlanCalDisp = new DS_PlanTableAdapters.CalDispTableAdapter(); taPlanRichieste = new DS_PlanTableAdapters.RichiesteTableAdapter(); taPromOut = new DS_PlanTableAdapters.PromesseOUTTableAdapter(); taIstK = new DS_IntServTableAdapters.IstanzeKITTableAdapter(); taAs400 = new DS_IntServTableAdapters.ProduzioneAs400TableAdapter(); taTKS = new DS_IntServTableAdapters.TKS_SearchTableAdapter(); taIS_TrDati = new DS_IntServTableAdapters.TransitoDatiTableAdapter(); 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 connectionStringES3 = memLayer.ML.confReadString("MoonProConnectionStringES3"); // connections del db taAG.Connection.ConnectionString = connectionString; taMacchine.Connection.ConnectionString = connectionString; taStatoMacchine.Connection.ConnectionString = connectionString; taAnagEventi.Connection.ConnectionString = connectionString; taAnagStati.Connection.ConnectionString = connectionString; taKeepAlive.Connection.ConnectionString = connectionString; taStati.Connection.ConnectionString = connectionString; taEventi.Connection.ConnectionString = connectionString; taOp.Connection.ConnectionString = connectionString; taOp2ins.Connection.ConnectionString = connectionString; taTranIngr.Connection.ConnectionString = connectionString; taRemReb.Connection.ConnectionString = connectionString; taSigLog.Connection.ConnectionString = connectionString; taFL.Connection.ConnectionString = connectionString; taAnagArt.Connection.ConnectionString = connectionString; taODL.Connection.ConnectionString = connectionString; taDatiMacchine.Connection.ConnectionString = connectionString; taDatiProdMacch.Connection.ConnectionString = connectionString; taDatiProdMacchPer.Connection.ConnectionString = connectionString; taDatiStatoMacch.Connection.ConnectionString = connectionString; taPostazioni.Connection.ConnectionString = connectionString; taTurniMacc.Connection.ConnectionString = connectionString; #if false taDatiConfermati.Connection.ConnectionString = connectionString; #endif taPzProd2conf.Connection.ConnectionString = connectionString; taTempiCicloRilevati.Connection.ConnectionString = connectionString; taDatiProd.Connection.ConnectionString = connectionString; taTempoByClass.Connection.ConnectionString = connectionString; taCalFF.Connection.ConnectionString = connectionString; taMSE.Connection.ConnectionString = connectionString; taPODL.Connection.ConnectionString = connectionString; taRC.Connection.ConnectionString = connectionString; taRS.Connection.ConnectionString = connectionString; taStatoProd.Connection.ConnectionString = connectionString; taSelArt.Connection.ConnectionString = connectionString; taSelMacc.Connection.ConnectionString = connectionString; taSelOdlFree.Connection.ConnectionString = connectionString; taComm.Connection.ConnectionString = connectionString; // area planner taMacParams.Connection.ConnectionString = connectionStringES3; taPlanCalStop.Connection.ConnectionString = connectionStringES3; taPlanCalDisp.Connection.ConnectionString = connectionStringES3; taPlanRichieste.Connection.ConnectionString = connectionStringES3; taPromOut.Connection.ConnectionString = connectionStringES3; // area IS taIS_TrDati.Connection.ConnectionString = connectionStringIS; taIstK.Connection.ConnectionString = connectionStringIS; taAs400.Connection.ConnectionString = connectionStringIS; taWKS.Connection.ConnectionString = connectionStringIS; taTKS.Connection.ConnectionString = connectionStringIS; } #endregion #region Inizializzazione protected DataLayer() { initTA(); setupConnectionStringBase(); // aggiunta x gestione timeout esteso (ove necessario)! fixCommandTimeout(); } /// /// sistemazione timeout comandi nei tableadapter /// private void fixCommandTimeout() { SetAllCommandTimeouts(taComm, memLayer.ML.CRI("sqlLongCommandTimeout")); } 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; } } /// /// oggetto static per fare chiamate sul magazzino /// public static DataLayer obj = new DataLayer(); #endregion #region utility interne /// /// 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}")); } } 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; } 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; } #endregion #region utility public esposte /// /// 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 = DataLayer.obj.taPzProd2conf.GetData(idxMacchina.ToString())[0]; // chiamo stored stp_ConfermaProduzCompleta(idxMacchina,MatrApp,dataFrom,dataTo,pezziConf) taPzProd2conf.stp_ConfermaProduzCompleta(idxMacchina, MatrOpr, rigaProd.DataFrom, DataOraApp, numPzConfermati, numPzScarto, modoConfProd, DataOraApp, true); //taPzProd2conf.stp_ConfermaProduzCompleta(idxMacchina, MatrOpr, rigaProd.DataFrom, rigaProd.DataTo, numPzConfermati, numPzScarto, modoConfProd, DateTime.Now, true); // indico eseguito! answ = true; } catch (Exception exc) { logger.lg.scriviLog(string.Format("Errore in conferma prod macchina:{0}{1}", Environment.NewLine, exc)); } return answ; } /// /// 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; } /// /// 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; } /// /// MatrOpr in sessione /// public static int MatrOpr { get { int idx = 0; try { idx = memLayer.ML.IntSessionObj("MatrOpr"); } catch { } return idx; } set { memLayer.ML.setSessionVal("MatrOpr", value); } } /// /// Cognome Nome da MatrOpr in sessione /// public static string CognomeNomeOpr { get { // cerco operatore... string answ = ""; try { DS_applicazione.AnagraficaOperatoriRow oper = DataLayer.obj.taOp.getByMatrOpr(MatrOpr)[0]; answ = string.Format("{0} {1}", oper.Cognome, oper.Nome); } catch { } return answ; } } /// /// Processa input da IOB eventualmente registrando i segnali inviati /// /// /// /// /// /// /// public static 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 != "" && DataLayer.sLogEnab(idxMacchina)) { connDb.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 (DataLayer.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à connDb.checkMicroStato(item.Key, newVal, dataOraEvento, contatore); } } else { // ora processo e salvo il valore del microstato... INTERNAMENTE gestisce i casi DB/REDIS secondo necessità connDb.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 != "" && MapoDb.obj.sLogEnabled(idxMacchina)) { MapoDb.obj.saveSigLog(idxMacchina, valore, dataOraEvento, contatore); } // continuo col resto try { // scrivo keep alive!!! (se encessario, altrimenti è in cache...) MapoDb.obj.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 (MapoDb.obj.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... MapoDb.obj.checkMicroStato(item.Key, newVal, dataOraEvento, contatore); } } else { // ora processo e salvo il valore del microstato... MapoDb.obj.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.ERROR); answ = errore; } } else { string errore = "Errore: mancano parametri macchina/valore"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } } return answ; } /// /// Calcola l'effettivo valore da passare alla macchina a stati INGRESSI data conf Macchine2FamigliaIngressi /// /// /// /// private static 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(DataLayer.mDatiMacchinaVal(idxMacchina, "BitFilt"), out BitFilt); int.TryParse(DataLayer.mDatiMacchinaVal(idxMacchina, "BSR"), out BSR); Boolean.TryParse(DataLayer.mDatiMacchinaVal(idxMacchina, "ExplodeBit"), out ExplodeBit); int.TryParse(DataLayer.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; } /// /// Processa registrazione FL da IOB /// /// /// /// /// /// /// /// public static 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 != "") { 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.ERROR); answ = errore; } } else { string errore = "Errore: mancano parametri macchina/valore"; logger.lg.scriviLog(errore, tipoLog.ERROR); 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 static 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 static 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; } /// /// Processa registrazione di un counter x una data macchina IOB /// /// /// contapezzi /// public static string saveCounter(string idxMacchina, string counter) { if (counter == null) { throw new ArgumentNullException(nameof(counter)); } // registro conteggio impiego chiamate REDIS if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("saveCounter"); } string answ = ""; // inizio processing vero e proprio INPUT... if (idxMacchina != null && counter != null) { if (idxMacchina != "" && counter != "") { int newCounter = -1; int.TryParse(counter, out newCounter); // se il conteggio è >= 0 SALVO come nuovo conteggio... if (newCounter >= 0) { // salvo in Redis nell'area CURR_VAL TUTTI i valori live memLayer.ML.setRSV(pzCountHash(idxMacchina), counter); } // registro in risposta che è andato tutto bene... answ = "OK"; } else { string errore = "Errore: parametri macchina/counter vuoti"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } } else { string errore = "Errore: mancano parametri macchina/counter"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } return answ; } /// /// Processa registrazione EVENTO CONTEGGIO PEZZI x una data macchina IOB /// /// Macchina /// Pezzi da registrare /// public static string saveCaricoPezzi(string idxMacchina, string qty) { // default: 0, non registrato come cautela... string answ = "0"; if (qty == null) { throw new ArgumentNullException(nameof(qty)); } // 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; MapoDb.obj.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"; logger.lg.scriviLog(errore, tipoLog.ERROR); answ = errore; } return answ; } /// /// Salvataggio su della mappa di memoria dell'IOB x ulteriori impieghi /// /// /// /// public static 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; } /// /// GET elenco parametri correnti x IOB /// /// /// public static 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 static 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; } /// /// SET elenco parametri correnti x IOB /// /// /// /// public static 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; } /// /// Effettua UPSERT elenco parametri correnti x IOB (se c'è UPDATE, se manca ADD) /// /// /// /// public static 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; } /// /// Rimuove Key dell'ODL corrente x una data macchina IOB /// /// /// public static string emptyCurrODL(string idxMacchina) { string answ = ""; try { memLayer.ML.redDelKey(currODLHash(idxMacchina)); answ = "OK"; } catch { answ = "KO"; } return answ; } /// /// Processa registrazione ODL corrente x macchina /// /// /// cod ODL in produzione, se "" --> non c'è... /// public static 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 != "") { memLayer.ML.setRSV(currODLHash(idxMacchina), currODL, memLayer.ML.CRI("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; } #region definizioni hash x REDIS /// /// 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 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 OPT PARAMETERS x la macchina specificata /// /// /// public static string optParHash(string idxMacchina) { return mHash(string.Format("OptPar:{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 dati COUNTER x la macchina specificata /// /// /// public static string pzCountHash(string idxMacchina) { return mHash(string.Format("PzCount:{0}", idxMacchina)); } /// /// Hash dati MemoryMap x la macchina specificata /// /// /// public static string memMapHash(string idxMacchina) { return mHash(string.Format("MemMap:{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 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 Current StatoMacchina x la macchina specificata /// /// /// public static string currStatoMaccHash(string idxMacchina) { return mHash(string.Format("CurrStatoMacc:{0}", idxMacchina)); } /// /// Hash dati tabella AnagStati macchina /// /// public static string currAnagStatiMacc() { return mHash(string.Format("Anag:StatiMacc")); } /// /// Hash dati LIVE x la macchina specificata /// /// /// public static string LiveCurrValHash(string idxMacchina) { return mHash(string.Format("LIVE:{0}:CURR_VAL", idxMacchina)); } /// /// 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 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 Macchine Multi SM Ingressi /// /// Macchina PRINCIPALE /// public static string hMSMI(string IdxMacchina) { return mHash(string.Format("hMSMI:{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 MSE /// /// public static string hMSE { get { return mHash(string.Format("hMSE_DATA")); } } #endregion #region gestione MSE /// /// 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); } } #endregion #region gestione task macchina /// /// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato /// /// /// public static 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; } /// /// Aggiunge un task all'elenco di quelli salvati (in modalità upsert) /// /// /// /// /// public static 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; } /// /// RIMUOVE un task dall'elenco di quelli salvati /// /// /// /// public static 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; } #endregion #region gestione OPT PARAMETERS macchina /// /// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato /// /// /// public static 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; } /// /// Aggiunge un PARAMETRO OPZIONALE all'elenco di quelli salvati (in modalità upsert) /// /// /// /// /// public static 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; } /// /// RIMUOVE un PARAMETRO OPZIONALE dall'elenco di quelli salvati /// /// /// /// public static 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; } #endregion #region gestione attrezzaggi public static string forceSplitOdl(string idxMacchina) { string answ = "KO"; 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}", tipoLog.INFO); inputComando resCmd = MapoDb.obj.scriviRigaEventoBarcode(idxMacchina, idxEvento, currData[0].CodArticolo, "ODL-SPLIT", 0, "", adesso.AddMinutes(-1), adesso); // chiamo splitOdl MapoDb.obj.taODL.splitODL(currData[0].IdxODL, 0, idxMacchina, currData[0].TCRichAttr, currData[0].PzPallet, $"Nuovo ODL da forceSplitOdl", true); // 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 = MapoDb.obj.scriviRigaEventoBarcode(idxMacchina, idxEvento, currData[0].CodArticolo, "ODL-START"); // chiamo refresh MSE obj.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); } } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in forceSplitOdl{Environment.NewLine}{exc}", tipoLog.EXCEPTION); } return answ; } #endregion #region gestione stato macchina /// /// Restituisce il valore dell'intera RIGA stato macchina corrente (da redis o da DB se non trovata...) /// /// /// public static 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 { answTab = MapoDb.obj.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 = MapoDb.obj.currStatoMaccTab(idxMacchina); } return answTab; } /// /// Elenco stati macchina /// /// public static 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 { answTab = MapoDb.obj.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 = MapoDb.obj.taAnagSt.GetData(); } return answTab; } #endregion #region gestione dati macchina /// /// Restitusice elenco KVP dei campi DatiMacchine + StatoMacchine per l'impianto indicato /// /// /// public static 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; } /// /// Resetta (rileggendo) i dati della macchina /// /// /// public static 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); // se ho righe... DS_applicazione.MSFDDataTable tab = new DS_applicazione.MSFDDataTable(); DS_applicazione.MSFDRow rigaMSFD; if (tabMSFD.Rows.Count > 0) { try { rigaMSFD = tabMSFD[0]; } catch { rigaMSFD = tab.NewMSFDRow(); } } else { rigaMSFD = tab.NewMSFDRow(); } // 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); } // 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 = (answ["insEnabled"].ToLower() == "true") ? tOutShort : tOutLong; // salvo in redis! memLayer.ML.redSaveHashDict(currHash, answ, redDtMacTOut); return answ; } /// /// Restituisce il valore booleano se la macchina sia abilitata all'input /// /// /// public static 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 = MapoDb.obj.insEnabled(idxMacchina); } } return answ; } /// /// Restituisce il valore dell'intera RIGA ODL corrente (da redis o da DB se non trovata...) /// /// /// public static 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 { answTab = MapoDb.obj.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 { answTab = MapoDb.obj.currODLTab(idxMacchina); } return answTab; } /// /// Restituisce il valore dell'ODL corrente (ODL deve esserci per gestione contapezzi, senza ODL NO invio/gestione ODL) /// /// /// public static string currODL(string idxMacchina) { string answ = ""; string rCall = ""; if (memLayer.ML.CRB("IOB_RedEnab")) { saveCallRec("hasODL"); try { rCall = memLayer.ML.getRSV(currODLHash(idxMacchina)); if (rCall != null && rCall != "") { answ = rCall; } else { answ = MapoDb.obj.currODL(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 static 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 (_idxOdl != null && _idxOdl != "") { answ = _idxOdl; } else { answ = MapoDb.obj.currODL(idxMacchina); // salvo in redis... saveCurrODL(idxMacchina, answ); memLayer.ML.setRSV(rKey, answ, 3); } } else { answ = currODL(idxMacchina); } return answ; } /// /// Restituisce il valore booleano se la macchina sia abilitata all'inserimento COMPLETO nel Signal Log /// /// /// public static 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 = MapoDb.obj.sLogEnabled(idxMacchina); } return answ; } /// /// Restituisce il contapezzi come CONTEGGIO da TCRilevati per la macchina /// /// /// public static 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 odlFound = false; int taSP_ms_ant = memLayer.ML.cdvi("taStatoProd_ms_anticipo"); DateTime dataRif = DateTime.Now.AddMilliseconds(-taSP_ms_ant); odlFound = getStatoProd(idxMacchina, ref datiProdAct, dataRif); // se NON avesse recuperato --> aspetto taSP_ms_ant e poi RICHIAMO procedura... int maxTry = 3; while (!odlFound && maxTry > 0) { logger.lg.scriviLog(string.Format("[pzCounterTC] Impossibile recuperare dati ODL x idxMacchina {0}", idxMacchina), tipoLog.ERROR); // sleep... System.Threading.Thread.Sleep(taSP_ms_ant); // riprovo lettura... odlFound = getStatoProd(idxMacchina, ref datiProdAct, dataRif); maxTry--; } // ora proseguo SE ho trovato i dati... if (odlFound) { // ...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.ERROR); } return answ; } /// /// Recupero dati stato prod da macchina... /// /// /// /// /// private static bool getStatoProd(string idxMacchina, ref DS_ProdTempi.StatoProdDataTable datiProdAct, DateTime dataRif) { bool answ = false; try { // recupero con stored NUOVA... datiProdAct = DataLayer.obj.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(string.Format("pzCounterTC: Non trovato currODL x idxMacchina {0} | IdxOdl {1} | pzTot {2} | dataRif {3}", idxMacchina, datiProdAct[0].IdxOdl, datiProdAct[0].PzTotODL, dataRif), tipoLog.WARNING); } } else { logger.lg.scriviLog("pzCounterTC: Non trovate righe in currODL x idxMacchina " + idxMacchina + ": datiProdAct vuota", tipoLog.WARNING); } } catch (Exception exc) { logger.lg.scriviLog(string.Format("[pzCounterTC] Eccezione in pzCounterTC x idxMacchina {0}{1}{2}", idxMacchina, Environment.NewLine, exc), tipoLog.EXCEPTION); } return answ; } /// /// Restituisce il contapezzi salvato per la macchina /// /// /// public static 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 valore booleano se la macchina sia di tipo MULTI (con più state machine x INGRESSI) /// /// /// public static 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 = MapoDb.obj.isMulti(idxMacchina); } return answ; } #endregion #region gestione State Machine Ingressi /// /// Recupera (da DB) i dati della State Machine multi ingressi nel formato /// key: IdxMacchina /// value: IdxFamigliaIngresso /// /// /// public static 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 = MapoDb.obj.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; } /// /// Restitusice elenco KVP /// key: IdxMacchina /// value: IdxFamigliaIngresso /// /// /// public static 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; } /// /// Resetta (rileggendo) i dati della State Machine multi ingressi nel formato /// key: IdxMacchina /// value: IdxFamigliaIngresso /// /// /// public static 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 = MapoDb.obj.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; } /// /// 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 static 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; } /// /// 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 static 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 = MapoDb.obj.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; } /// /// Restituisce il valore SPECIFICATO per la state machine ingressi /// value: iTipoEv_nState (IdxTipoEv da trasmettere + New MICRO-STATE) /// /// /// /// /// public static 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); } /// /// Restituisce valore di una singola chiave del dizionario DatiMacchina /// /// /// /// public static string mDatiMacchinaVal(string idxMacchina, string chiave) { string answ = ""; try { answ = mDatiMacchine(idxMacchina)[chiave]; } catch { } return answ; } #endregion #endregion } } #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