/* * Copyright Copyright 2017, Steamware s.r.l. & CMS/SCM s.p.a. * * Based on data, code and example by MTC consortium & System Insights, Inc. * * */ using System; using System.Collections.Generic; using System.Drawing; using System.Threading; using System.Windows.Forms; using NLog; using MTC; using NLog.Config; using NLog.Targets; using System.Collections; using System.Configuration; using System.Diagnostics; using System.IO; using MTConnect; namespace MTC_ADB { public partial class MainForm : Form { #region variabili ed oggetti globali /// /// porta servizio MTC ADB /// protected int portMTC = 7879; /// /// Oggetto x gestione dell'adapter GENERICO (x poter usare metodi di ognuno...) /// AdapterGeneric agObj; /// /// timer base in avvio /// protected int startTimerMs = 250; /// /// timer base (base moltiplica) /// protected int timerIntMs = 100; // di norma 100 msec x timer base... /// /// contatore veloce /// protected int fastCount = 1; // 100ms primo refresh... /// /// contatore normale /// protected int normCount = 2; // 200ms primo refresh... /// /// contatore slow /// protected int slowCount = 3; // 300ms primo refresh... /// /// contatore lentissimo /// protected int verySlowCount = 4; // 400ms primo refresh... /// /// ultimo tentativo riavvio... /// protected DateTime lastStartTry; /// /// tipo di adapter prescelto... /// protected tipoAdapter tipoScelto = tipoAdapter.DB; /// /// oggetto logging /// public static Logger lg; #endregion public MainForm() { InitializeComponent(); myInit(); } /// /// inizializzazione specifica /// private void myInit() { #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 // avvio logger... LogManager.ReconfigExistingLoggers(); lg = LogManager.GetCurrentClassLogger(); // inizio setDefaults(); displayTaskAndWait("Starting..."); lastStartTry = DateTime.Now; advProgBar(); // fix icon! Icon = Icon.ExtractAssociatedIcon(defIconFilePath); notifyIcon1.Icon = Icon.ExtractAssociatedIcon(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"); advProgBar(); displayTaskAndWait("Starting MainForm"); // avvio adapter... agObj = new AdapterGeneric(this); loadPersistLayer(defPersLayerFile); lg.Info("PersLayerFile READ"); agObj.loadPersData(); lg.Info("PersLayerFile LOADED"); // Start timer periodico gather.Interval = utils.CRI("timerIntMs"); gather.Enabled = true; displayTaskAndWait("Running"); createTrayMenu(); displayTaskAndWait("Tray Menu OK"); // avvio minimizzato se richiesto if (utils.CRB("startMinimized")) { // imposto minimized se necessario! if (WindowState != FormWindowState.Minimized) { WindowState = FormWindowState.Minimized; } displayTaskAndWait("Minimized"); } displayTaskAndWait("Main Form OK"); // SE abilitato provo ad avviare... if (utils.CRB("autoStartOnLoad")) { avviaAdapter(); } checkStarted(); checkConnected(); } /// /// Lettura conf DB /// private void loadServerConf() { agObj.loadServerConf(); lblServer.Text = string.Format("{0} | {1}", agObj.ServerType, agObj.ServerAddress); displayTaskAndWait("...LOADING DB CONF..."); checkConnected(); } /// /// Tentativo connessione al DB /// private void connectAdapter() { displayTaskAndWait("...CONNECTIONG DB..."); agObj.tryConnect(); checkConnected(); } /// /// Tentativo disconnessione al DB /// private void disconnectAdapter() { displayTaskAndWait("...DISCONNECTIONG DB..."); agObj.tryDisconnect(); checkConnected(); } /// /// Verifica se il server sia connesso... /// private void checkConnected() { lblLastData.Text = DateTime.Now.ToString("yy-MM-dd HH:mm:ss"); if (agObj.connectionOk) { lblStatus.Text = "CONNECTED"; lblStatus.BackColor = Color.ForestGreen; lblStatus.ForeColor = Color.Yellow; btnConnect.Text = "close"; lblServer.ForeColor = Color.Black; lblServer.Text = string.Format("{0} | {1}", agObj.ServerType, agObj.ServerAddress); // recupero conteggio degli eventi... advProgBar(); lblNumData.Text = string.Format("{0} new data", agObj.numRecAvail); displayTaskAndWait("DB Server CONNECTED"); } else { lblStatus.Text = "offline"; lblStatus.BackColor = Color.DimGray; lblStatus.ForeColor = Color.White; btnConnect.Text = "open"; lblServer.ForeColor = Color.DimGray; lblServer.Text = string.Format("???{0}???", agObj.ServerType, agObj.ServerAddress); lblNumData.Text = "#"; displayTaskAndWait("ERROR connecting to DB Server"); } } /// /// Verifica se l'adapter sia partito... /// private void checkStarted() { if (agObj.adpRunning) { btnStart.Text = "ADP STOP"; btnStart.ForeColor = Color.DarkRed; displayTaskAndWait("ADP STARTED"); } else { btnStart.Text = "ADP START"; btnStart.ForeColor = Color.ForestGreen; displayTaskAndWait("ADP STOPPED"); } } /// /// Verifica finale a fine show... /// /// /// private void MainForm_Shown(object sender, EventArgs e) { // avvio minimizzato se richiesto if (utils.CRB("startMinimized")) { // controllo e mando a tray... sendToTray(); } displayTaskAndWait("Main Form SHOWN"); } /// /// mostra un testo sulla status bar ed attende startTimerMs /// /// public void displayTaskAndWait(string txt2show) { toolStripStatusLabel1.Text = txt2show; lg.Info(txt2show); // aggiorno componenti principali... toolStripStatusLabel1.Invalidate(); lblServer.Refresh(); lblStatus.Refresh(); lblNumData.Refresh(); advProgBar(); Thread.Sleep(startTimerMs); } /// /// 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 MTC-ADB"); } // se è permesso tray close... if (utils.CRB("trayClose")) { trayMenu.Items.Add("Close MTC-ADB"); } advProgBar(); } /// /// 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; } } /// /// evento resize /// /// /// private void MainForm_Resize(object sender, EventArgs e) { checkFormVisibility(); } /// /// 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; } } } /// /// File persistenza generale /// protected string defPersLayerFile { get { return string.Format(@"{0}\{1}", utils.dataDatDir, utils.CRS("defaultPersLayerFile")); } } protected string defIconFilePath { get { return string.Format(@"{0}\MTCA.ico", utils.resxDir); } } /// /// impostazione valori defaults /// private void setDefaults() { MainProgrBar.Minimum = 0; MainProgrBar.Maximum = 300; MainProgrBar.Value = 0; MainProgrBar.Step = 1; portMTC = utils.CRI("portMTC"); } /// /// Avvio adapter /// public void avviaAdapter() { // avvio adapter vero e proprio... displayTaskAndWait("Adapter starting"); // inizio con la connessione al DB if (!agObj.connectionOk) { loadServerConf(); connectAdapter(); advProgBar(); } agObj.startAdapter(portMTC); //displayTaskAndWait("Adapter started!"); btnOpenDump.Enabled = true; if (utils.CRB("openDumpOnStart")) { displayTaskAndWait("Dump Window starting"); apriDumpAgent(); displayTaskAndWait("Dump Windows OK"); } displayTaskAndWait("Start Timers"); // inizializzo contatori fast/mid/slow fastCount = utils.CRI("fastCount"); normCount = utils.CRI("normCount"); slowCount = utils.CRI("slowCount"); verySlowCount = utils.CRI("verySlowCount"); displayTaskAndWait("Adapter 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); } private void gather_Tick(object sender, EventArgs e) { // eseguo cicli attivi SOLO se adapter è in EFFETTIVO running... if (agObj.adpRunning) { // inizio a riportare che sto eseguendo.. advProgBar(); if (agObj.connectionOk) { // check esecuzione FastTask checkFastTask(); // check esecuzione NormTask checkNormTask(); // check esecuzione SlowTask checkSlowTask(); // check esecuzione VerySlowTask checkVerySlowTask(); } else { double currWait = DateTime.Now.Subtract(lastStartTry).TotalMilliseconds; if (agObj.adpTryRestart && currWait > utils.CRI("waitRecMSec")) { // provo a connettermi... lblStatus.Text = "...CONNECTING..."; lblStatus.BackColor = Color.Goldenrod; displayTaskAndWait("Server Conf READ"); lastStartTry = DateTime.Now; agObj.tryConnect(); agObj.loadPersData(); checkStarted(); checkConnected(); } } // se è arrivato a MAX resetto... if (MainProgrBar.Value >= MainProgrBar.Maximum) { MainProgrBar.Value = 0; } } else { // 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 (agObj.adpTryRestart && currWait > utils.CRI("waitRecMSec")) { lastStartTry = DateTime.Now; avviaAdapter(); } } advProgBar(); } public void resetProgBar() { MainProgrBar.Value = 0; } private void checkSlowTask() { slowCount--; if (slowCount <= 0) { slowCount = utils.CRI("slowCount"); agObj.gaterAndSend(gatherCycle.LF); // tenta salvataggio valori ATTUALI dei parametri ove applicabile/aggiornati --> sia file corrente che file "history" persistData(); } } private void checkVerySlowTask() { verySlowCount--; if (verySlowCount <= 0) { verySlowCount = utils.CRI("verySlowCount"); agObj.gaterAndSend(gatherCycle.VLF); } } /// /// file persistenza generale /// public string histPersLayerFile { get { return string.Format(@"{0}\{1:yyyy}\{1:yyyy-MM-dd}.mtc", utils.dataDatDir, DateTime.Now); } } /// /// file persistenza generale data attuale ANTICIPATA di xx giorni /// /// num DD di anticipo /// public string prevPersLayerFile(int numDD) { return string.Format(@"{0}\{1:yyyy}\{1:yyyy-MM-dd}.mtc", utils.dataDatDir, DateTime.Now.AddDays(-numDD)); } /// /// salva i valori attuali del file di conf sia in file corrente che in cartella valori storici /// public void persistData() { // salvo ogni "autoSaveSec" secondi dall'ultimo salvataggio... TimeSpan tempoMod = new TimeSpan(0); if (File.Exists(defPersLayerFile)) { DateTime adesso = DateTime.Now; tempoMod = DateTime.Now.Subtract(File.GetLastWriteTime(defPersLayerFile)); } if (tempoMod.TotalSeconds > utils.CRI("autoSaveSec")) { savePersistLayer(defPersLayerFile); savePersistLayer(histPersLayerFile); } } private void checkNormTask() { // decremento... normCount--; // se il counter è a zero eseguo... if (normCount <= 0) { normCount = utils.CRI("normCount"); agObj.gaterAndSend(gatherCycle.MF); lblLastData.Text = DateTime.Now.ToString("yy-MM-dd HH:mm:ss"); } } /// /// Avanza la barra di stato... /// public void advProgBar() { try { MainProgrBar.PerformStep(); if (MainProgrBar.Value >= MainProgrBar.Maximum) resetProgBar(); MainProgrBar.Invalidate(); } catch { } } private void checkFastTask() { // decremento... fastCount--; // se il counter è a zero eseguo... if (fastCount <= 0) { fastCount = utils.CRI("fastCount"); agObj.gaterAndSend(gatherCycle.HF); } } /// /// 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)); } } /// /// Salva su file l'oggetto di persistenza dati /// /// public void savePersistLayer(string filePath) { // in primis check semaforo salvataggio... if (!agObj.adpSaving) { // alzo semaforo salvataggio agObj.adpSaving = true; // se HO dei dati... if (agObj.persistenceLayer != null) { try { utils.WritePlain(agObj.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 agObj.adpSaving = false; } } /// /// Carica da file l'oggetto di persistenza dati /// /// public void loadPersistLayer(string filePath) { // inizializzo prima di leggere... agObj.persistenceLayer = new Dictionary(); agObj.persistenceLayer = utils.ReadPlain(filePath); // 2017.03.23 check problema files corrotti... if (agObj.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(prevPersLayerFile(numDD)); } catch { } numDD++; } // se sono uscito PROVO a passare il file storico letto buono (oppure vuoto...) agObj.persistenceLayer = lastRead; } } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { closeAdapter(); } 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) { agObj.stopAdapter(tryRestart); // salvo! savePersistLayer(defPersLayerFile); savePersistLayer(histPersLayerFile); if (stopTimer) { gather.Enabled = false; agObj.tryDisconnect(); } // verifica e display checkStarted(); displayTaskAndWait("Adapter Stopped"); } /// /// toggle connessione... /// /// /// private void btnConnect_Click(object sender, EventArgs e) { // blocco button btnConnect.Enabled = false; btnConnect.Refresh(); advProgBar(); // processo if (agObj.connectionOk) { lblStatus.Text = "...CLOSING..."; lblStatus.BackColor = Color.Goldenrod; displayTaskAndWait("Closing DB Connection"); // CHIUDO! disconnectAdapter(); } else { lblStatus.Text = "...CONNECTING..."; lblStatus.BackColor = Color.Goldenrod; displayTaskAndWait("Opening DB Connection"); // APRO! loadServerConf(); connectAdapter(); } // sblocco button... btnConnect.Enabled = true; btnConnect.Refresh(); advProgBar(); } private void btnStart_Click(object sender, EventArgs e) { // blocco button btnStart.Enabled = false; btnStart.Refresh(); advProgBar(); // processo if (agObj.adpRunning) { // CHIUDO! fermaTutto(true, false); } else { gather.Enabled = true; avviaAdapter(); } checkStarted(); checkConnected(); // sblocco button... btnStart.Enabled = true; btnStart.Refresh(); advProgBar(); } } }