using AutoUpdaterDotNET; using IOB_UT; using NLog; using NLog.Targets; using System; using System.Collections.Generic; using System.Configuration; using System.Diagnostics; using System.Drawing; using System.Threading; using System.Windows.Forms; using NLog.Config; namespace IOB_WIN { public partial class MainForm : Form { #region inizializzazione contatori /// /// contatore veloce /// protected int fastCount; /// /// contatore normale /// protected int normCount; /// /// contatore lento /// protected int slowCount; /// /// contatore sync allarmi /// protected int verySlowCount; /// /// timer base in avvio /// protected int startTimerMs = 250; /// /// ultimo tentativo riavvio... /// protected DateTime lastStartTry; /// /// Data-Ora prima apertura FORM... /// protected DateTime firstStart; #endregion #region inizializzazione oggetti base /// /// oggetto logging /// public static Logger lg; /// /// Oggetto x gestione dell'adapter GENERICO (x poter usare metodi di ognuno...) /// IobGeneric iobObj; /// /// configurazione caricata /// IobConfiguration IOBConf; /// /// tipo di adapter prescelto... /// public tipoAdapter tipoScelto = tipoAdapter.DEMO; /// /// URLK stringa di UPDATE... /// protected string updateUrl { get { return string.Format("http://seriate.steamware.net:8083/SWS/MAPO-IOB-WIN/{0}/manifest.xml", utils.CRS("appVers")); } } #endregion #region utils ed helpers private class Item { public string Name; public int Value; public Item(string name, int value) { Name = name; Value = value; } } /// /// mostra un testo sulla status bar + LOG /// /// public void displayTaskAndLog(string txt2show) { lblStatus.Text = txt2show; lblStatus.Invalidate(); lg.Info(txt2show); } /// /// Mostra update delle statistiche di comunicazione (numero chiamate, tempo medio...) /// /// public void updateComStats(string txt2show) { lblComStats.Text = string.Format("{0} | ", txt2show); } #endregion #region gestione form e visibilità // apro eseguibile dump private void dump_Click(object sender, EventArgs e) { apriDumpAgent(); } /// /// apre agent di dump in CMD /// private static void apriDumpAgent() { string path = Application.StartupPath; try { Process.Start(string.Format(@"{0}\..\..\dump\dump.exe", path)); } catch { Process.Start(string.Format(@"{0}\dump\dump.exe", path)); } } /// /// Avvio MainForm /// public MainForm() { // se NON sono in DEBUG faccio check update... #if !(DEBUG) // avvio autoupdater... AutoUpdater.Start(updateUrl); #endif // continuo avvio... InitializeComponent(); lblStatus.Text = "Loading"; // inizializzo orologi firstStart = DateTime.Now; lastStartTry = DateTime.Now; // fix icon! notifyIcon1.Text = string.Format("IOB-WIN | {0}", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version); Icon = Icon.ExtractAssociatedIcon(utils.defIconFilePath); notifyIcon1.Icon = Icon.ExtractAssociatedIcon(utils.defIconFilePath); // fix versione! lblApp.Text = string.Format("{0}", ConfigurationManager.AppSettings.Get("appName")); lblVers.Text = string.Format(" v.{0}", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version); startTimerMs = utils.CRI("startTimerMs"); #if DEBUG // Setup the logging view for Sentinel - http://sentinel.codeplex.com var sentinalTarget = new NLogViewerTarget() { Name = "sentinal", Address = "udp://127.0.0.1:9999", IncludeNLogData = false }; var sentinalRule = new LoggingRule("*", LogLevel.Trace, sentinalTarget); LogManager.Configuration.AddTarget("sentinal", sentinalTarget); LogManager.Configuration.LoggingRules.Add(sentinalRule); #endif LogManager.ReconfigExistingLoggers(); lg = LogManager.GetCurrentClassLogger(); displayTaskAndLog("MainForm Starting"); // se abilitato autoload conf leggo file corretto... if (utils.CRB("autoLoadConf")) { loadIniFile(utils.defConfFilePath); lg.Info("INI LOADED"); loadPersistLayer(utils.defPersLayerFile); lg.Info("PersLayerFile READ"); iobObj.loadPersData(); lg.Info("PersLayerFile LOADED"); } else { // definisco e avvio tipo adapter generico tipoScelto = tipoAdapter.ND; IOBConf = new IobConfiguration(); loadIobType(); displayTaskAndLog("Waiting for config file selection"); } // Start timer periodico comunicazione gather.Interval = utils.CRI("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"); createTrayMenu(); displayTaskAndLog("Tray Menu OK"); // avvio minimizzato se richiesto if (utils.CRB("startMinimized")) { // imposto minimized se necessario! if (WindowState != FormWindowState.Minimized) { WindowState = FormWindowState.Minimized; } displayTaskAndLog("Minimized"); } displayTaskAndLog("Main Form OK"); } /// /// Fase chiusura Form /// /// /// private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { closeAdapter(); } /// /// Mostrata form /// /// /// private void MainForm_Shown(object sender, EventArgs e) { // avvio minimizzato se richiesto if (utils.CRB("startMinimized")) { // controllo e mando a tray... sendToTray(); } displayTaskAndLog("Main Form SHOWN"); } /// /// Completato resize form /// /// /// private void MainForm_Resize(object sender, EventArgs e) { checkFormVisibility(); } #endregion #region gestione tray /// /// crea menù tray x applicazione /// private void createTrayMenu() { // Fix testi menù tray... trayMenu.Items.Clear(); // SE permessa massimizzazione... if (utils.CRB("windowCanMax")) { trayMenu.Items.Add("Show IOB-WIN"); } // se è permesso tray close... if (utils.CRB("trayClose")) { trayMenu.Items.Add("Close IOB-WIN"); } } /// /// doppio click su tray icon /// /// /// private void notifyIcon1_DoubleClick(object sender, EventArgs e) { // SOLO SE PERMESSO mostrare full... if (utils.CRB("windowCanMax")) { Show(); WindowState = FormWindowState.Normal; } } /// /// Verifica stato windows (minimized/normal) e visibilità con tray... /// private void checkFormVisibility() { // se non può massimizzare imposto COMUNQUE a minimized... if (!utils.CRB("windowCanMax")) { WindowState = FormWindowState.Minimized; } // controllo cosa devo mostrare... if (WindowState == FormWindowState.Minimized) { notifyIcon1.Visible = false; sendToTray(); } else { notifyIcon1.Visible = false; } } /// /// Gestisce "andata nel tray" della form /// private void sendToTray() { if (!notifyIcon1.Visible) { notifyIcon1.BalloonTipTitle = utils.CRS("appName"); notifyIcon1.BalloonTipText = string.Format("{0} running on tray", utils.CRS("appName")); notifyIcon1.Visible = true; notifyIcon1.ShowBalloonTip(100); } Hide(); } /// /// click su menù contestuale in tray /// /// /// private void trayMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e) { if (e.ClickedItem.Text.StartsWith("Close")) { // stop adapter... closeAdapter(); // chiudo! Close(); } else if (e.ClickedItem.Text.StartsWith("Show")) { if (utils.CRB("windowCanMax")) { Show(); WindowState = FormWindowState.Normal; } } } #endregion #region gestione metodi specifici FORM /// /// Avanza la barra di stato... /// public void advProgBar() { try { MainProgrBar.PerformStep(); MainProgrBar.Invalidate(); // aggiorno runtime... TimeSpan uptime = DateTime.Now.Subtract(iobObj.dtAvvioAdp); tslRunTime.Text = string.Format("Running: {0}gg {1:00}:{2:00}:{3:00}", uptime.Days, uptime.Hours, uptime.Minutes, uptime.Seconds); } catch { } } private void checkSendTask() { // avvio fase invio con adapter (code MST) iobObj.getAndSend(gatherCycle.VHF); } 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 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 refreshFormData() { // aggiorno visualizzazioni varie in form... lQueueLen.Text = iobObj.QueueIN.Count.ToString(); } private void gather_Tick(object sender, EventArgs e) { // eseguo cicli attivi SOLO se adapter è in EFFETTIVO running... if (iobObj.adpRunning) { // inizio a riportare che sto eseguendo.. advProgBar(); if (iobObj.connectionOk) { // check esecuzione FastTask checkFastTask(); // check esecuzione NormTask checkNormTask(); // check esecuzione SlowTask checkSlowTask(); // check esecuzione AlarmSync checkVerySlowData(); // check esecuzione SendTask (VHF) checkSendTask(); if (utils.CRI("waitEndCycle") > 0) { Thread.Sleep(utils.CRI("waitEndCycle")); } } else { double currWait = DateTime.Now.Subtract(lastStartTry).TotalMilliseconds; if (iobObj.adpTryRestart && currWait > utils.CRI("waitRecMSec")) { lastStartTry = DateTime.Now; iobObj.tryConnect(); iobObj.loadPersData(); } } // se è arrivato a MAX resetto... if (MainProgrBar.Value >= MainProgrBar.Maximum) { MainProgrBar.Value = 0; } } else { if (iobObj.verboseLog) lg.Info("PLC <--> IOB Not connected"); // verifico SE debba tentare il riavvio, ovvero NON running ma tryReconn e non ho riprovato x oltre waitRecMSec double currWait = DateTime.Now.Subtract(lastStartTry).TotalMilliseconds; if (iobObj.adpTryRestart && currWait > utils.CRI("waitRecMSec")) { lastStartTry = DateTime.Now; avviaAdapter(); iobObj.loadPersData(); } } } /// /// Chiusura adapter /// private void closeAdapter() { fermaTutto(true, false); } /// /// Ferma tutti i componenti adapter + update buttons /// /// determina se fermare il timer (gather) principale (solo se non si chiude) /// determina se tentare di riconnettersi private void fermaTutto(bool stopTimer, bool tryRestart) { iobObj.stopAdapter(tryRestart); // salvo! savePersistLayer(utils.defPersLayerFile); savePersistLayer(utils.histPersLayerFile); stop.Enabled = false; dump.Enabled = false; start.Enabled = true; if (stopTimer) { gather.Enabled = false; iobObj.tryDisconnect(); } sIN = Semaforo.SS; sOUT = Semaforo.SS; } /// /// Carica file ini della configurazione richiesta /// /// private void loadIniFile(string iniConfFile) { displayTaskAndLog(string.Format("Loading iniConfFile: {0}", iniConfFile)); IniFile fIni = new IniFile(iniConfFile); tipoScelto = (tipoAdapter)Enum.Parse(typeof(tipoAdapter), fIni.ReadString("IOB", "CNCTYPE", "DEMO")); IOBConf = new IobConfiguration { tipoIob = tipoScelto, versIOB = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), codIOB = fIni.ReadString("IOB", "IDXMACC", "0"), cncIpAddr = fIni.ReadString("CNC", "IP", "::1"), cncPort = fIni.ReadString("CNC", "PORT", "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", "/")), MAX_COUNTER_BLINK = Convert.ToInt32(fIni.ReadString("BLINK", "MAX_COUNTER_BLINK", "1")), BLINK_FILT = Convert.ToInt32(fIni.ReadString("BLINK", "BLINK_FILT", "0")) }; loadIobType(); // avvio macchina con adapter specificato... if (utils.CRB("autoStartOnLoad")) { displayTaskAndLog("Auto Starting..."); // avvio! avviaAdapter(); displayTaskAndLog("Auto Started!"); } } /// /// 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) { lg.Error(string.Format("Errore salvataggio file{0}{1}", Environment.NewLine, exc)); } } else { lg.Info("persistenceLayer null, non salvato..."); } // abbasso semaforo salvataggio iobObj.adpSaving = false; } } /// /// Carica da file l'oggetto di persistenza dati /// /// public void loadPersistLayer(string filePath) { // inizializzo prima di leggere... iobObj.persistenceLayer = new Dictionary(); iobObj.persistenceLayer = utils.ReadPlain(filePath); // 2017.03.23 check problema files corrotti... if (iobObj.persistenceLayer.Count == 0) { // se avesse letto un valore NON coerente (senza righe) PROVA a leggere a ritroso vecchi files... da histPersLayerFile e precedenti... int numDD = 0; int maxNumDD = utils.CRI("maxNumDD"); Dictionary lastRead = new Dictionary(); // continuo fino a che non leggo almeno 1 riga valida e non ho raggiunto maxDD while (numDD < maxNumDD && lastRead.Count == 0) { // leggo il file storico alla data anticipata... (ci provo...) try { lastRead = utils.ReadPlain(utils.prevPersLayerFile(numDD)); } catch { } numDD++; } // se sono uscito PROVO a passare il file storico letto buono (oppure vuoto...) iobObj.persistenceLayer = lastRead; } } #endregion 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); lg.Info("INI LOADED"); loadPersistLayer(utils.defPersLayerFile); lg.Info("PersLayerFile READ"); iobObj.loadPersData(); lg.Info("PersLayerFile LOADED"); } } /// /// carica IOB richiesto /// private void loadIobType() { switch (tipoScelto) { case tipoAdapter.DEMO: iobObj = new IobDemo(this, IOBConf); start.Enabled = true; break; case tipoAdapter.FANUC: iobObj = new IobFanuc(this, IOBConf); start.Enabled = true; break; case tipoAdapter.SIEMENS: iobObj = new IobSiemens(this, IOBConf); start.Enabled = true; break; case tipoAdapter.ND: default: iobObj = new IobDemo(this, IOBConf); start.Enabled = false; break; } lblTopSx.Text = string.Format("CNC: {0}{1}IP: {2}:{3}", IOBConf.tipoIob, Environment.NewLine, IOBConf.cncIpAddr, IOBConf.cncPort); lblTopCent.Text = string.Format("IOB {0}", IOBConf.codIOB); lblTopDx.Text = string.Format("SRV: {0}{1}URL: {2}{3}", IOBConf.serverData.MPIP, Environment.NewLine, IOBConf.serverData.MPURL, IOBConf.serverData.CMDBASE); // carico i default values su interfaccia setDefaults(); displayTaskAndLog(string.Format("Caricata conf per adapter {0}", tipoScelto)); } /// /// impostazione valori defaults /// private void setDefaults() { stop.Enabled = false; dump.Enabled = false; lQueueLen.Text = "ND"; nLine2show = utils.CRI("numRowConsole"); MainProgrBar.Minimum = 0; MainProgrBar.Maximum = 1000; MainProgrBar.Value = 0; MainProgrBar.Step = 1; } public void resetProgBar() { MainProgrBar.Value = 0; } /// /// Visualizzazione stato di comunicazione attiva con PLC /// public bool commPlcActive { set { // se true --> comunica/verde, altrimenti grigio lblApp.ForeColor = value ? Color.SeaGreen : Color.Black; lblVers.ForeColor = value ? Color.SeaGreen : Color.DarkSlateGray; statusStrip1.Refresh(); } } /// /// Avvio dell'adapter /// /// /// private void start_Click(object sender, EventArgs e) { avviaAdapter(); iobObj.loadPersData(); // salvo che ho avviato adapter lg.Info("Completato LOAD Adapter"); } public void avviaAdapter() { displayTaskAndLog("Adapter starting"); // se NON sta girando... if (!iobObj.adpRunning) { int porta = Convert.ToInt32(port.Text); iobObj.startAdapter(porta); displayTaskAndLog("Adapter started!"); // fix buttons start/stop/dump start.Enabled = false; stop.Enabled = true; dump.Enabled = true; if (utils.CRB("openDumpOnStart")) { displayTaskAndLog("Dump Window starting"); apriDumpAgent(); displayTaskAndLog("Dump Windows OK"); } 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..."); // forzo check allarmi.. iobObj.forceAlarmCheck(); } else { displayTaskAndLog("Adapter STILL Running..."); } } /// /// fermata dell'adapter /// /// /// private void stop_Click(object sender, EventArgs e) { fermaAdapter(false); // salvo che ho fermato adapter lg.Info("UNLOAD Adapter"); } /// /// Ferma l'adapter /// /// determina se si debba tentare riavvio automatico (per caduta connessione) public void fermaAdapter(bool tryRestart) { fermaTutto(false, tryRestart); } /// /// Stringa dati monitoraggio mostrata (1 SX)... /// public string dataMonitor_0 { get { return lblRawData.Text; } set { lblRawData.Text = value; } } /// /// Stringa dati monitoraggio mostrata (1 SX)... /// public string dataMonitor_1 { get { return lblOutMessage.Text; } set { lblOutMessage.Text = value; } } /// /// Stringa dati monitoraggio mostrata (2 centro)... /// public string dataMonitor_2 { get { return lblOutMessage2.Text; } set { lblOutMessage2.Text = value; } } /// /// Stringa dati monitoraggio mostrata (3 dx)... /// public string dataMonitor_3 { get { return lblOutMessage3.Text; } set { lblOutMessage3.Text = value; lg.Info("---------------- START CHECK OTHER ------------------"); lg.Info(value); lg.Info("---------------- END CHECK OTHER ------------------"); } } /// /// label del numero di record processati (libera) /// public string dataProcLabel { get { return tslDataProc.Text; } set { tslDataProc.Text = value; } } /// /// 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 { set { bIN.BackColor = decSemaforo(value); bIN.Refresh(); } } /// /// Imposta COLORE SFONDO x Semaforo OUT /// public Semaforo sOUT { set { bOUT.BackColor = decSemaforo(value); bOUT.Refresh(); } } /// /// Decodifica colore da valore semaforico /// /// /// public 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; } private void displTimer_Tick(object sender, EventArgs e) { // aggiorno solo componenti visuali... // aggiorno uptime... TimeSpan uptime = DateTime.Now.Subtract(firstStart); tslUptime.Text = string.Format("Uptime: {0}gg {1:00}:{2:00}:{3:00}", uptime.Days, uptime.Hours, uptime.Minutes, uptime.Seconds); } private void mCheckUpdates_Click(object sender, EventArgs e) { AutoUpdater.Start(updateUrl); } } }