using IOB_UT; using MapoSDK; using Newtonsoft.Json; using NLog; using NLog.Config; using NLog.Targets; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; using System.Threading; using System.Windows.Forms; namespace IOB_WIN { public partial class AdapterForm : Form { #region Protected Fields /// /// contatore veloce /// protected int fastCount; /// /// Data-Ora prima apertura FORM... /// protected DateTime firstStart; /// /// Oggetto ultimo inviato stato IOB x REDIS /// protected IobWinStatus lastIobStatus = new IobWinStatus(); /// /// Oggetto ultimo inviato stato MP-IO x REDIS /// protected ServerMpStatus lastSrvStatus = new ServerMpStatus(); /// /// ultimo tentativo riavvio... /// protected DateTime lastStartTry; /// /// contatore normale /// protected int normCount; /// /// Contatore campionamento memoria /// protected int sampleMemCount; /// /// contatore lento /// protected int slowCount; /// /// contatore sync allarmi /// protected int verySlowCount; /// /// Temnpo attesa std in MS /// protected int waitRecMSec = 30000; #endregion Protected Fields #region Public Fields /// /// oggetto logging /// public static Logger lg; /// /// Modello macchina /// public string curModel = ""; /// /// Vendor macchina /// public string curVendor = ""; /// /// configurazione caricata /// public IobConfiguration IOBConf; /// /// Oggetto x gestione dell'adapter GENERICO (x poter usare metodi di ognuno...) /// public IobGeneric iobObj; /// /// tipo di adapter prescelto... /// public tipoAdapter tipoScelto = tipoAdapter.SIMULA; #endregion Public Fields #region Public Constructors /// /// Avvio MainForm /// /// public AdapterForm(string codIOB) { CurrIOB = codIOB; // continuo avvio... InitializeComponent(); myGraphInitForm(); checkEditMes2Plc(); // inizializzo orologi firstStart = DateTime.Now; lastStartTry = DateTime.Now; initDatamonitor(); waitRecMSec = utils.CRI("waitRecMSec"); LogManager.ReconfigExistingLoggers(); lg = LogManager.GetCurrentClassLogger(); displayTaskAndLog("MainForm Starting"); // se abilitato autoload conf leggo file corretto... if (utils.CRB("autoLoadConf")) { try { loadIniFile(defConfFilePath); lgInfo("INI LOADED"); } catch (Exception exc) { displayTaskAndLog(string.Format("Eccezione in autoLoadConf: {0}", exc)); } } if (IOBConf == null || !utils.CRB("autoLoadConf")) { // definisco e avvio tipo adapter generico tipoScelto = tipoAdapter.ND; curVendor = "ACME"; curModel = "NONE"; IOBConf = new IobConfiguration(); loadIobType(); displayTaskAndLog("Waiting for config file selection"); } // cerco tra i parametri opzionali se ho il parametro di int timerIntMs = utils.CRI("timerIntMs"); if (IOBConf.optPar.ContainsKey("timerIntMs")) { // recupero string rawVal = IOBConf.optPar["timerIntMs"]; if (!string.IsNullOrEmpty(rawVal)) { int.TryParse(rawVal, out timerIntMs); lgInfo($"Impostato timerIntMs da IOB.ini: {timerIntMs}"); } } // Start timer periodico comunicazione gather.Interval = timerIntMs; gather.Enabled = true; displayTaskAndLog(string.Format("Main timer set: {0}ms", gather.Interval)); // Start timer periodico interfaccia displTimer.Interval = utils.CRI("timerIntMs"); displTimer.Enabled = true; displayTaskAndLog("Program Running"); // check oggetto not null if (iobObj != null) { try { // verifico server online... if (iobObj.checkServerAlive) { // segnalo reboot (programma)... IobGeneric.callUrl(iobObj.urlReboot, true); } else { displayTaskAndLog("AdapterForm: Server OFFLINE"); } } catch (Exception exc) { lgError(string.Format("AdapterForm: EXCEPTION in fase di chiamata URL di reboot:{0}{1}{2}", iobObj.urlReboot, Environment.NewLine, exc)); } } displayTaskAndLog("Main Form OK"); } #endregion Public Constructors #region Private Delegates private delegate void SafeCallDelegate(string text); #endregion Private Delegates #region Protected Properties /// /// Valore protected comunicazione PLC /// protected bool _commPlcActive { get; set; } = false; /// /// Valore protetto stato comunicazione /// protected int _commSrvActive { get; set; } = 0; /// /// Valore protected semaforo IN /// protected Semaforo _sIN { get; set; } = Semaforo.ND; /// /// Valore protected semaforo OUT /// protected Semaforo _sOUT { get; set; } = Semaforo.ND; /// /// Codice IOB della macchina cui connettersi (x scegliere corretto file di conf...) /// protected string CurrIOB { get; set; } protected int delayShowLogMs { get; set; } = utils.CRI("delayShowLogMs"); /// /// Dictionary dei divieti del datamonitor /// protected Dictionary dMonDisplVetoVeto { get; set; } = new Dictionary(); /// /// array degli oggetti datamonitor da mostrare /// protected Dictionary dMonValues { get; set; } = new Dictionary(); /// /// Veto a NUOVE scritture in COUNTER... /// protected DateTime logCounterVeto { get; set; } = DateTime.Now; /// /// Stringa corrente di log... /// protected string logWatchString { get; set; } = ""; /// /// Veto a NUOVE scritture in logWatch... /// protected DateTime logWatchWriteVeto { get; set; } = DateTime.Now; protected int maxAlQueue { get; set; } protected int maxEvQueue { get; set; } protected int maxFlQueue { get; set; } protected int maxMsQueue { get; set; } protected int qAlLen { get; set; } protected int qEvLen { get; set; } protected int qFlLen { get; set; } protected int qMsLen { get; set; } protected int totQueue { get { return qEvLen + qFlLen + qAlLen + qMsLen; } } #endregion Protected Properties #region Public Properties public int alQueueLen { set { qAlLen = value; lblQueueAlarmLen.Text = qAlLen.ToString(); showQueueData(); // se supero max precedente, ed è > 10... loggo! if (qAlLen > maxAlQueue && qAlLen > 10) { maxAlQueue = qAlLen; lgInfo($"[WARN] Coda FLog di {value} record"); } else { maxAlQueue--; maxAlQueue = maxAlQueue < qAlLen ? qAlLen : maxAlQueue; } } get { return qAlLen; } } /// /// Visualizzazione stato di comunicazione attiva con PLC /// public bool commPlcActive { get { return _commPlcActive; } set { _commPlcActive = value; // se true --> comunica/verde, altrimenti grigio lblCNC.ForeColor = value ? Color.SeaGreen : Color.Black; statusStrip1.Refresh(); } } /// /// Visualizzazione stato di comunicazione attiva con PLC: /// 0 = NO PING /// 1 = PING OK /// 2 = IOB enabled /// public int commSrvActive { get { return _commSrvActive; } set { _commSrvActive = value; switch (value) { case 0: lblSrvUrl.ForeColor = Color.Red; break; case 1: lblSrvUrl.ForeColor = Color.OrangeRed; break; case 2: lblSrvUrl.ForeColor = Color.SeaGreen; break; default: break; } statusStrip1.Refresh(); } } public string counterIob { get { return lblPzCountIob.Text; } set { lblPzCountIob.Text = value; } } public string counterMac { get { return lblPzCountMac.Text; } set { lblPzCountMac.Text = value; } } /// /// Stringa dati monitoraggio mostrata (1 SX)... /// public string dataMonitor_0 { get { return dMonValues[0]; } set { DateTime adesso = DateTime.Now; // salvo nell'array... dMonValues[0] = value; if (dMonDisplVetoVeto[0] < adesso) { // se scaduto veto --> display! lblRawData.Text = value; // update veto! dMonDisplVetoVeto[0] = adesso.AddMilliseconds(delayShowLogMs); } } } /// /// Stringa dati monitoraggio mostrata (1 SX)... /// public string dataMonitor_1 { get { return dMonValues[1]; } set { DateTime adesso = DateTime.Now; // salvo nell'array... dMonValues[1] = value; if (dMonDisplVetoVeto[1] < adesso) { // se scaduto veto --> display! lblOutMessage.Text = value; // update veto! dMonDisplVetoVeto[1] = adesso.AddMilliseconds(delayShowLogMs); } } } /// /// Stringa dati monitoraggio mostrata (2 centro)... /// public string dataMonitor_2 { get { return dMonValues[2]; } set { DateTime adesso = DateTime.Now; // salvo nell'array... dMonValues[2] = value; if (dMonDisplVetoVeto[2] < adesso) { // se scaduto veto --> display! lblOutMessage2.Text = value; // update veto! dMonDisplVetoVeto[2] = adesso.AddMilliseconds(delayShowLogMs); } } } /// /// Stringa dati monitoraggio mostrata (3 dx)... /// public string dataMonitor_3 { get { return dMonValues[3]; } set { DateTime adesso = DateTime.Now; // salvo nell'array... dMonValues[3] = value; if (dMonDisplVetoVeto[3] < adesso) { // se scaduto veto --> display! lblOutMessage3.Text = value; // update veto! dMonDisplVetoVeto[3] = adesso.AddMilliseconds(delayShowLogMs); } } } /// /// label del numero di record processati (libera) /// public string dataProcLabel { get { return lblDataProc.Text; } set { lblDataProc.Text = value; } } /// /// File configurazione default /// public string defConfFilePath { get { return string.Format(@"{0}\{1}.ini", utils.confDir, CurrIOB); } } public bool enableEditMes2Plc { get; set; } public int evQueueLen { set { qEvLen = value; lblQueueLen.Text = qEvLen.ToString(); showQueueData(); // se supero max precedente, ed è > 10... loggo! if (qEvLen > maxEvQueue && qEvLen > 10) { maxEvQueue = qEvLen; lgInfo($"[WARN] Coda EV di {value} record"); } else { maxEvQueue--; maxEvQueue = maxEvQueue < qEvLen ? qEvLen : maxEvQueue; } } get { return qEvLen; } } public int flQueueLen { set { qFlLen = value; lblQueueFLogLen.Text = qFlLen.ToString(); showQueueData(); // se supero max precedente, ed è > 10... loggo! if (qFlLen > maxFlQueue && qFlLen > 10) { maxFlQueue = qFlLen; lgInfo($"[WARN] Coda FLog di {value} record"); } else { maxFlQueue--; maxFlQueue = maxFlQueue < qFlLen ? qFlLen : maxFlQueue; } } get { return qFlLen; } } /// /// Log verboso da configurazione (SOLO CHAIVE "verbose"... /// public bool isVerboseLog { get; set; } = utils.CRB("verbose"); /// /// Logwatcher (in modalità "accodamento in testa" ultimi messaggi...) /// public string logWatcher { get { return lblLogfile.Text; } set { try { logWatchString = limitLine2show($"{value}{Environment.NewLine}{logWatchString}"); DateTime adesso = DateTime.Now; if (logWatchWriteVeto < adesso) { lblLogfile.Text = logWatchString; lblLogfile.Refresh(); logWatchWriteVeto = adesso.AddMilliseconds(delayShowLogMs); } } catch (Exception exc) { lgError($"Errore in esecuzione logWatcher{Environment.NewLine}--> {value}"); if (isVerboseLog) { lgError($"{exc}"); } } } } public int msQueueLen { set { qMsLen = value; lblQueueMessLen.Text = qMsLen.ToString(); showQueueData(); // se supero max precedente, ed è > 10... loggo! if (qMsLen > maxMsQueue && qMsLen > 10) { maxMsQueue = qMsLen; lgInfo($"[WARN] Coda FLog di {value} record"); } else { maxMsQueue--; maxMsQueue = maxMsQueue < qMsLen ? qMsLen : maxMsQueue; } } get { return qMsLen; } } /// /// Numero max linee da mostrare (da controllo)... /// public int nLine2show { get { int answ = 5; try { Int32.TryParse(nLines.Text, out answ); } catch { } return answ; } set { nLines.Text = value.ToString(); } } /// /// Imposta COLORE SFONDO x Semaforo IN /// public Semaforo sIN { get { return _sIN; } set { _sIN = value; var newColor = decSemaforo(value); if (newColor != bIN.BackColor) { bIN.BackColor = newColor; bIN.Refresh(); } } } /// /// Imposta COLORE SFONDO x Semaforo OUT /// public Semaforo sOUT { get { return _sOUT; } set { _sOUT = value; var newColor = decSemaforo(value); if (newColor != bOUT.BackColor) { bOUT.BackColor = newColor; bOUT.Refresh(); } } } /// /// Task watcher (in modalità "accodamento in testa" ultimi messaggi...) /// public string taskWatcher { get { return lblTaskLog.Text; } set { try { lblTaskLog.Text = limitLine2show($"{value}{Environment.NewLine}{lblTaskLog.Text}"); lblTaskLog.Refresh(); } catch (Exception exc) { lgError($"Errore in esecuzione taskWatcher{Environment.NewLine}--> {value}"); if (isVerboseLog) { lgError($"{exc}"); } } } } #endregion Public Properties #region Private Methods private void BtnOpenLog_Click(object sender, EventArgs e) { try { string logPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}logs\\{CurrIOB}\\{DateTime.Today:yyyy-MM-dd}.log"; Process.Start(logPath); } catch (Exception exc) { lgError($"Eccezione in show log (MAIN):{Environment.NewLine}{exc}"); } } private void BtnSendPLC_Click(object sender, EventArgs e) { // invia a MES il parametro selezionato (es ART / ODL / PRG NAME, come task2exe..) Dictionary forcedTask = new Dictionary(); // guardo i parametri... if (!string.IsNullOrEmpty(txtValue.Text)) { forcedTask.Add(cmbParamValues.SelectedValue.ToString(), txtValue.Text); } // chiedo esecuzione task! iobObj.processTask(forcedTask); chkEdit.Checked = false; toggleEditMes2Plc(); } private void checkEditMes2Plc() { cmbParamValues.Enabled = enableEditMes2Plc; txtValue.Enabled = enableEditMes2Plc; if (enableEditMes2Plc) { // aggiorno (se possibile) i parametri selezionabili... fixComboParameters(); } } private void checkFastTask() { // decremento... fastCount--; // se il counter è a zero eseguo... if (fastCount <= 0) { fastCount = utils.CRI("fastCount"); // avvio fase raccolta dati e invio con adapter iobObj.getAndSend(gatherCycle.HF); } } private void checkNormTask() { // decremento... normCount--; // se il counter è a zero eseguo... if (normCount <= 0) { normCount = utils.CRI("normCount"); // avvio fase raccolta dati e invio con adapter iobObj.getAndSend(gatherCycle.MF); } } private void checkSampleMem() { // decremento contatore... sampleMemCount--; if (sampleMemCount <= 0) { sampleMemCount = utils.CRI("sampleMemCount"); // avvio fase raccolta dati e invio con adapter iobObj.saveMemDump(dumpType.SAMPLE); } } private void checkSendTask() { // avvio fase invio con adapter (code MST) iobObj.getAndSend(gatherCycle.VHF); } private void checkSlowTask() { slowCount--; if (slowCount <= 0) { slowCount = utils.CRI("slowCount"); // avvio fase raccolta dati e invio con adapter iobObj.getAndSend(gatherCycle.LF); } } private void checkVerySlowData() { verySlowCount--; if (verySlowCount <= 0) { verySlowCount = utils.CRI("verySlowCount"); // avvio fase raccolta dati e invio con adapter iobObj.getAndSend(gatherCycle.VLF); } } private void ChkEdit_CheckedChanged(object sender, EventArgs e) { toggleEditMes2Plc(); } /// /// Chiusura adapter /// private void closeAdapter() { fermaTutto(true, false, true, false); } private void displTimer_Tick(object sender, EventArgs e) { } /// /// Ferma tutti i componenti adapter + update buttons /// /// indica se fermare il timer (gather) principale (solo se non si chiude) /// indica se tentare di riconnettersi /// indica se sia richeisto di SVUOTARE le code delel info /// indica se si debba aggiornare la form (no se si sta chiudendo...) private void fermaTutto(bool stopTimer, bool tryRestart, bool forceDequeue, bool updateForm) { iobObj.stopAdapter(tryRestart, forceDequeue); // salvo! savePersistLayer(utils.defPersLayerFile); savePersistLayer(utils.histPersLayerFile); stop.Enabled = false; start.Enabled = true; restart.Enabled = false; if (stopTimer) { gather.Enabled = false; iobObj.tryDisconnect(); } newDisplayData currDispData = new newDisplayData(); currDispData.semIn = Semaforo.SS; currDispData.semOut = Semaforo.SS; if (updateForm) { updateFormDisplay(currDispData); } } private void fixComboParameters() { if (iobObj != null) { if (iobObj.memMap != null) { if (iobObj.memMap.mMapWrite != null) { if (iobObj.memMap.mMapWrite.Count > 0) { var oldParams = cmbParamValues.DataSource; List parametri = new List(); foreach (var item in iobObj.memMap.mMapWrite) { parametri.Add(item.Key); } // salvo selezione int oldIdx = cmbParamValues.SelectedIndex; // riassegno e ri-seleziono cmbParamValues.DataSource = parametri; cmbParamValues.SelectedIndex = oldIdx >= 0 ? oldIdx : 0; ; } } } } } private void gather_Tick(object sender, EventArgs e) { bool doLog = false; if (iobObj != null) { if (iobObj.periodicLog) { doLog = true; } try { refreshFormData(); // check esecuzione SendTask (VHF) COMUNQUE... checkSendTask(); // eseguo cicli attivi SOLO se adapter è in EFFETTIVO running... if (iobObj.adpRunning) { if (iobObj.connectionOk) { // se richiesto faccio memory DUMP INIZIALE! if (iobObj.doStartMemDump) { lgInfo("Inizio dump memoria"); iobObj.saveMemDump(dumpType.STARTUP); // fatto! non ripeto... iobObj.doStartMemDump = false; lgInfo("Finito dump memoria"); } // controllo se sia abilitato sampleDump della meoria (periodico) if (iobObj.doSampleMemory) { checkSampleMem(); } // check esecuzione FastTask checkFastTask(); // check esecuzione NormTask checkNormTask(); // check esecuzione SlowTask checkSlowTask(); // check esecuzione AlarmSync checkVerySlowData(); if (utils.CRI("waitEndCycle") > 0) { Thread.Sleep(utils.CRI("waitEndCycle")); } } else { DateTime dtVeto = lastStartTry.AddMilliseconds(waitRecMSec); if (iobObj.adpTryRestart && (DateTime.Now > dtVeto)) { if (doLog) { lgInfo($"Retry Time Elapsed ({waitRecMSec} ms)--> tryConnect"); } lastStartTry = DateTime.Now; iobObj.tryConnect(); } } } else { if (doLog) { lgInfo("Adapter stopped"); } // verifico SE debba tentare il riavvio, ovvero NON running ma adpTryRestart e non ho riprovato x oltre waitRecMSec DateTime dtVeto = lastStartTry.AddMilliseconds(waitRecMSec); if (iobObj.adpTryRestart && (DateTime.Now > dtVeto)) { lastStartTry = DateTime.Now; avviaAdapter(chkForceDequeue.Checked); } } } catch (Exception exc) { lgError(string.Format("Eccezione in fase di gatherTick: {0}{1}", Environment.NewLine, exc)); } } } /// /// Init oggetti datamonitor /// private void initDatamonitor() { for (int i = 0; i < 4; i++) { dMonDisplVetoVeto.Add(i, DateTime.Now); dMonValues.Add(i, ""); } } /// /// GEstione evento refresh /// /// /// private void IobObj_eh_refreshed(object sender, iobRefreshedEventArgs e) { // aggiorno! updateFormDisplay(e.DisplayDataObject); } /// /// Carica file ini della configurazione richiesta /// /// private void loadIniFile(string iniConfFile) { // out di cosa faccio... displayTaskAndLog($"[STARTUP] Loading iniConfFile: {iniConfFile}"); // leggo file IniFile fIni = new IniFile(iniConfFile); // leggo vendor e modello... curVendor = fIni.ReadString("MACHINE", "VENDOR", "ACME"); curModel = fIni.ReadString("MACHINE", "MODEL", "NONE"); // verifico tipo adapter try { tipoScelto = (tipoAdapter)Enum.Parse(typeof(tipoAdapter), fIni.ReadString("IOB", "CNCTYPE", "DEMO")); } catch (Exception exc) { lgError($"Eccezione in conversione tipo adapter: richiesto un tipo non codificato...{Environment.NewLine}{exc}"); tipoScelto = tipoAdapter.ND; } // carivo vettore parametri opzionai Dictionary optParRead = new Dictionary(); string[] optParRows = fIni.ReadSection("OPTPAR"); if (optParRows.Length > 0) { try { string[] kvp; foreach (var item in optParRows) { kvp = item.Split('='); optParRead.Add(kvp[0], kvp[1]); } lgInfo($"Caricati {optParRead.Count} parametri opzionali da OPTPAR"); } catch (Exception exc) { lgError(string.Format("EXCEPTION in fase di lettura OPTPAR: {0}{1}", Environment.NewLine, exc)); } } // inizializzio conf IOB IOBConf = new IobConfiguration { pingMsTimeout = fIni.ReadInteger("IOB", "PING_MS_TIMEOUT", 500), vendor = curVendor, model = curModel, tipoIob = tipoScelto, optPar = optParRead, versIOB = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), codIOB = CurrIOB, cncIpAddr = fIni.ReadString("CNC", "IP", "::1"), cncPort = fIni.ReadString("CNC", "PORT", "0"), iniFileName = iniConfFile, cpuType = fIni.ReadString("CNC", "CPUTYPE", ""), rack = (short)fIni.ReadInteger("CNC", "RACK", 0), slot = (short)fIni.ReadInteger("CNC", "SLOT", 0), serverData = new serverMapo(fIni.ReadString("SERVER", "MPIP", "::1"), fIni.ReadString("SERVER", "MPURL", "/"), fIni.ReadString("SERVER", "CMDBASE", "/"), fIni.ReadString("SERVER", "CMDFLOG", "/"), fIni.ReadString("SERVER", "CMDALIVE", "/"), fIni.ReadString("SERVER", "CMDENABLED", "/"), fIni.ReadString("SERVER", "CMDREBO", "/"), fIni.ReadString("SERVER", "CMD_ODL_STARTED", "/IOB/getCurrOdlStart/"), fIni.ReadString("SERVER", "CLI_INST", "SW_CLI"), fIni.ReadString("SERVER", "CMD_FORCLE_SPLIT_ODL", "/IOB/forceSplitOdlFull/")), MAX_COUNTER_BLINK = Convert.ToInt32(fIni.ReadString("BLINK", "MAX_COUNTER_BLINK", "1")), BLINK_FILT = Convert.ToInt32(fIni.ReadString("BLINK", "BLINK_FILT", "0")), TCMaxDelayFactor = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_MAX_TC_FACTOR", "1.2").Replace(".", ",")), TCLambda = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_LAMBDA", "0.5").Replace(".", ",")), TCMaxIncrPz = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_MAX_INCR", "5").Replace(".", ",")) }; lgInfo($"Creato IOBConf!"); // salvo serializzando json... nella folder x Cliente oppure Vendor_Model string confJson = JsonConvert.SerializeObject(IOBConf, Formatting.Indented); string path = fileMover.GetExecutingDirectoryName(); // Directory.GetCurrentDirectory(); string fileName = Path.GetFileName(iniConfFile).Replace(".ini", ".iob"); string dirPath = $"{path}\\DATA\\{IOBConf.serverData.ClientInstall}"; string fullPath = $"{dirPath}\\{fileName}"; // verifica directory Directory.CreateDirectory(dirPath); // salvataggio File.WriteAllText(fullPath, confJson); loadIobType(); // avvio macchina con adapter specificato... if (utils.CRB("autoStartOnLoad")) { displayTaskAndLog("Auto Starting..."); // avvio! avviaAdapter(chkForceDequeue.Checked); displayTaskAndLog("Auto Started!"); } try { // segnalo reboot (programma)... metto in coda invio... //iobObj.sendToMoonPro(urlType.FLog, "IOB INI Loaded"); //iobObj.QueueFLog.Enqueue(iobObj.qEncodeFLog("IOB-STATUS", "IOB INI Loaded")); } catch (Exception exc) { lgError(string.Format("EXCEPTION in fase di chiamata URL di segnalazione caricamento INI file:{0}{1}", Environment.NewLine, exc)); } } /// /// carica IOB richiesto /// private void loadIobType() { if (IOBConf != null) { switch (tipoScelto) { case tipoAdapter.OSAI_OPEN: case tipoAdapter.OSAI_CNDEX: case tipoAdapter.OSAI_VB6: // versione EgwProxy.OsaiCncLib iobObj = new IobOSAI(this, IOBConf); start.Enabled = true; break; case tipoAdapter.ND: default: iobObj = new IobSimula(this, IOBConf); start.Enabled = false; break; } lblCNC.Text = $"CNC: {IOBConf.tipoIob} [{IOBConf.cncIpAddr}:{IOBConf.cncPort}]"; lblSrvUrl.Text = $"SRV: {IOBConf.serverData.MPIP} | URL: {IOBConf.serverData.MPURL}{IOBConf.serverData.CMDBASE}"; // aggancio evento refresh iobObj.eh_refreshed += IobObj_eh_refreshed; // carico i default values su interfaccia setDefaults(); displayTaskAndLog(string.Format("Caricata conf per adapter {0}", tipoScelto)); } } /// /// Fase chiusura Form /// /// /// private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { closeAdapter(); } /// /// Completato resize form /// /// /// private void MainForm_Resize(object sender, EventArgs e) { } /// /// Mostrata form /// /// /// private void MainForm_Shown(object sender, EventArgs e) { displayTaskAndLog("Main Form SHOWN (Adapter)"); } private void mLoadConf_Click(object sender, EventArgs e) { // mostro selettore file x leggere adapter.. OpenFileDialog openFileDial = new OpenFileDialog(); // directory iniziale openFileDial.InitialDirectory = utils.confDir; // string.Format(@"{0}\{1}", Application.StartupPath, utils.CRS("dataConfPath")); // Set filter options and filter index. openFileDial.Filter = "INI Files (.ini)|*.ini|All Files (*.*)|*.*"; openFileDial.FilterIndex = 1; // altre opzioni openFileDial.Multiselect = false; // Call the ShowDialog method to show the dialog box. DialogResult userClickedOK = openFileDial.ShowDialog(); // Process input if the user clicked OK. if (userClickedOK == DialogResult.OK) { string iniConfFile = openFileDial.FileName; loadIniFile(iniConfFile); lgInfo("INI LOADED"); } } private void refreshFormData() { // aggiorno visualizzazioni varie in form... evQueueLen = iobObj.QueueIN.Count; flQueueLen = iobObj.QueueFLog.Count; alQueueLen = iobObj.QueueAlarm.Count; msQueueLen = iobObj.QueueMessages.Count; // aggiorno labels counters... counterIob = $"pz IOB {iobObj.contapezziIOB}"; counterMac = $"pz PLC {iobObj.contapezziPLC}"; // verifico IOB status IobWinStatus currIobStatus = new IobWinStatus() { CodIob = iobObj.cIobConf.codIOB, queueEvLen = evQueueLen, queueFlLen = flQueueLen, queueAlLen = alQueueLen, queueMsLen = msQueueLen, counterIOB = iobObj.contapezziIOB, counterMAC = iobObj.contapezziPLC, lastUpdate = lastIobStatus.lastUpdate, online = utils.IOB_Online, lastDataIn = iobObj.lastReadPLC }; // se diverso SALVO! if (lastIobStatus.online != currIobStatus.online || lastIobStatus.lastDataIn != currIobStatus.lastDataIn || lastIobStatus.counterIOB != currIobStatus.counterIOB || lastIobStatus.counterMAC != currIobStatus.counterMAC || lastIobStatus.queueEvLen != currIobStatus.queueEvLen || lastIobStatus.queueFlLen != currIobStatus.queueFlLen || lastIobStatus.queueAlLen != currIobStatus.queueAlLen || lastIobStatus.queueMsLen != currIobStatus.queueMsLen) { // aggiorno data currIobStatus.lastUpdate = DateTime.Now; // salvo su redis e in obj corrente iobObj.redisMan.iobStatus = currIobStatus; lastIobStatus = currIobStatus; } // se diverso SALVO MP IO status if (lastSrvStatus.online != utils.MPIO_Online) { // aggiorno ServerMpStatus currSrvStatus = iobObj.redisMan.servStatus; currSrvStatus.online = utils.MPIO_Online; currSrvStatus.lastUpdate = DateTime.Now; // salvo su redis e in obj corrente iobObj.redisMan.servStatus = currSrvStatus; lastSrvStatus = currSrvStatus; } } /// /// Button restart /// /// /// private void restart_Click(object sender, EventArgs e) { string message = "Attenzione: con l'operazione di reset veranno persi (e non inviati) i dati eventualmente accumulati (indipendentemente dalla selezione del checkbox 'svuota coda')."; string caption = "Conferma Reset Dati IOB"; MessageBoxButtons buttons = MessageBoxButtons.YesNo; DialogResult result; // verifica con messagebox result = MessageBox.Show(message, caption, buttons); // solo se ho conferma da utente if (result == DialogResult.Yes) { // faccio stop... SENZA inviare fermaAdapter(false, false, true); displayTaskAndLog("RESTARTING: Adapter Stopped"); // rileggo INI loadIniFile(defConfFilePath); displayTaskAndLog("RESTARTING: Ini File Reloaded"); // faccio start... CON RESET delel code avviaAdapter(true); displayTaskAndLog("RESTARTING: Adapter Started"); // resetto i data monitor... dataMonitor_0 = ""; dataMonitor_1 = ""; dataMonitor_2 = ""; dataMonitor_3 = ""; } } /// /// impostazione valori defaults /// private void setDefaults() { stop.Enabled = false; evQueueLen = 0; flQueueLen = 0; nLine2show = utils.CRI("numRowConsole"); } private void splitContainer1_Panel1_Paint(object sender, PaintEventArgs e) { } /// /// Avvio dell'adapter /// /// /// private void start_Click(object sender, EventArgs e) { avviaAdapter(chkForceDequeue.Checked); // salvo che ho avviato adapter lgInfo("Completato LOAD Adapter"); } /// /// fermata dell'adapter /// /// /// private void stop_Click(object sender, EventArgs e) { fermaAdapter(false, chkForceDequeue.Checked, true); // salvo che ho fermato adapter lgInfo("UNLOAD Adapter"); } private void TabData_Selected(object sender, TabControlEventArgs e) { } private void toggleEditMes2Plc() { // abilita i campi --> PLC per editing enableEditMes2Plc = !enableEditMes2Plc; checkEditMes2Plc(); } #endregion Private Methods #region Protected Methods protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } /// /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere... /// /// protected void lgError(string txt2log) { if (!string.IsNullOrEmpty(txt2log)) { lg.Factory.Configuration.Variables["codIOB"] = this.CurrIOB; lg.Error(txt2log); // salvo anche in logwatcher... SE non si dimostra ricorsivo... if (!txt2log.Contains("logWatcher")) { newDisplayData currDispData = new newDisplayData(); currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | ERROR | {txt2log}"; updateFormDisplay(currDispData); } } } /// /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere... /// /// protected void lgInfo(string txt2log) { lg.Factory.Configuration.Variables["codIOB"] = this.CurrIOB; lg.Info(txt2log); // salvo anche in logwatcher... newDisplayData currDispData = new newDisplayData(); currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | INFO | {txt2log}"; updateFormDisplay(currDispData); } /// /// Init form (grafica) con helper x testi e varie /// protected void myGraphInitForm() { lblStatus.Text = "Loading"; // aggiunta tooltip x send forzato ToolTip ttForceSend = new ToolTip(); // imposto delay. ttForceSend.AutoPopDelay = 3000; ttForceSend.InitialDelay = 500; ttForceSend.ReshowDelay = 500; // sempre visibile (che sia o meno attiva la form). ttForceSend.ShowAlways = true; // imposto tooltip ttForceSend.SetToolTip(this.chkForceDequeue, "Forza invio eventi allo stop"); } /// /// MOstra info su coda complessiva /// protected void showQueueData() { lblQueueLenTop.Text = totQueue == 0 ? "realtime" : $"ev: {qEvLen} | flog: {qFlLen} | tot: {totQueue}"; } #endregion Protected Methods #region Public Methods /// /// Decodifica colore da valore semaforico /// /// /// public static Color decSemaforo(Semaforo valore) { Color colore = Color.LightGray; switch (valore) { case Semaforo.SV: colore = Color.LightGreen; break; case Semaforo.SG: colore = Color.LightGoldenrodYellow; break; case Semaforo.SR: colore = Color.Red; break; case Semaforo.SS: colore = Color.DarkGray; break; default: colore = Color.LightGray; break; } return colore; } /// /// Avvio l'adapter /// /// indica se sia richeisto di SVUOTARE le code delel info public void avviaAdapter(bool resetQueue) { displayTaskAndLog("Adapter starting"); // se NON sta girando... if (!iobObj.adpRunning) { iobObj.startAdapter(resetQueue); displayTaskAndLog("Adapter started!"); // fix buttons start/stop/dump start.Enabled = false; stop.Enabled = true; restart.Enabled = true; displayTaskAndLog("Start Timers"); // inizializzo contatori fast/mid/slow fastCount = utils.CRI("fastCount"); normCount = utils.CRI("normCount"); slowCount = utils.CRI("slowCount"); verySlowCount = utils.CRI("verySlowCount"); displayTaskAndLog("Adapter Running..."); // init max queue maxEvQueue = 1; maxFlQueue = 1; try { // segnalo reboot (programma)... iobObj.QueueFLog.Enqueue(iobObj.qEncodeFLog("IOB-STATUS", "IOB Started")); } catch (Exception exc) { lgError(string.Format("EXCEPTION in fase di chiamata URL di segnalazione AVVIO IOB:{0}{1}", Environment.NewLine, exc)); } } else { displayTaskAndLog("Adapter STILL Running..."); } } /// /// mostra un testo sulla status bar + LOG /// /// public void displayTaskAndLog(string txt2show) { lblStatus.Text = txt2show; lblStatus.Invalidate(); lgInfo(txt2show); } /// /// Ferma l'adapter /// /// determina se si debba tentare riavvio automatico (per caduta connessione) /// indica se sia richeisto di SVUOTARE le code delel info /// indica se aggiornare la form prima di fermare public void fermaAdapter(bool tryRestart, bool forceDequeue, bool updateForm) { fermaTutto(false, tryRestart, forceDequeue, updateForm); } /// /// Effettua un trim della stringa al numero max di linee da mostrare a video /// /// /// public string limitLine2show(string newString) { if (!string.IsNullOrEmpty(newString)) { // se num righe superiore a limite trimmo... if (newString.Split('\n').Length > nLine2show) { //int idx = newString.LastIndexOf('\r'); int idx = newString.LastIndexOf(Environment.NewLine); newString = newString.Substring(0, idx); } } return newString; } /// /// Salva su file l'oggetto di persistenza dati /// /// public void savePersistLayer(string filePath) { // in primis check semaforo salvataggio... if (!iobObj.adpSaving) { // alzo semaforo salvataggio iobObj.adpSaving = true; // se HO dei dati... if (iobObj.persistenceLayer != null) { try { utils.WritePlain(iobObj.persistenceLayer, filePath); } catch (Exception exc) { lgError(string.Format("Errore salvataggio file{0}{1}", Environment.NewLine, exc)); } } else { lgInfo("persistenceLayer null, non salvato..."); } // abbasso semaforo salvataggio iobObj.adpSaving = false; } } /// /// Mostra update delle statistiche di comunicazione (numero chiamate, tempo medio...) /// /// public void updateComStats(string txt2show) { lblComStats.Text = string.Format("{0} | ", txt2show); } /// /// Effettua update form una volta ricevuto OBJ che contiene le varie innovazioni... /// /// public void updateFormDisplay(newDisplayData currDispData) { // ciclo x ogni oggetto x caricare le innovazioni... if (currDispData != null && currDispData.hasData) { DateTime adesso = DateTime.Now; // RealTime display if (!string.IsNullOrWhiteSpace(currDispData.newInData)) { dataMonitor_0 = limitLine2show($"{currDispData.newInData}{Environment.NewLine}{dataMonitor_0}"); } if (!string.IsNullOrWhiteSpace(currDispData.newSignalData)) { dataMonitor_1 = limitLine2show($"{currDispData.newSignalData}{Environment.NewLine}{dataMonitor_1}"); } if (!string.IsNullOrWhiteSpace(currDispData.newFLogData)) { dataMonitor_3 = limitLine2show($"{currDispData.newFLogData}{Environment.NewLine}{dataMonitor_3}"); } if (!string.IsNullOrWhiteSpace(currDispData.newUrlCallData)) { dataMonitor_2 = limitLine2show($"{currDispData.newUrlCallData}{Environment.NewLine}{dataMonitor_2}"); } // Bitmap lettura attuale if (currDispData.counter >= 0) { if (logCounterVeto < adesso || lblCounter.Text != $"{currDispData.counter}") { lblCounter.Text = $"{currDispData.counter}"; lblCounter.Refresh(); logCounterVeto = adesso.AddMilliseconds(delayShowLogMs); } } // Bitmap lettura attuale if (!string.IsNullOrWhiteSpace(currDispData.currBitmap)) { lblBitmap.Text = currDispData.currBitmap; lblBitmap.Refresh(); } // LiveLog if (!string.IsNullOrWhiteSpace(currDispData.newLiveLogData)) { logWatcher = currDispData.newLiveLogData; } // semafori if (currDispData.semOut != Semaforo.ND) { // aggiorno SE diverso if (sOUT != currDispData.semOut) { sOUT = currDispData.semOut; } } if (currDispData.semIn != Semaforo.ND) { //aggiorno SE diverso if (sIN != currDispData.semIn) { sIN = currDispData.semIn; } } } } public void WriteTextSafe(string text) { if (lblOutMessage3.InvokeRequired) { var d = new SafeCallDelegate(WriteTextSafe); lblOutMessage3.Invoke(d, new object[] { text }); } else { lblOutMessage3.Text = text; } } #endregion Public Methods } }