Files
2019-08-01 05:37:51 +02:00

797 lines
26 KiB
C#

/*
* 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
/// <summary>
/// porta servizio MTC ADB
/// </summary>
protected int portMTC = 7879;
/// <summary>
/// Oggetto x gestione dell'adapter GENERICO (x poter usare metodi di ognuno...)
/// </summary>
AdapterGeneric agObj;
/// <summary>
/// timer base in avvio
/// </summary>
protected int startTimerMs = 250;
/// <summary>
/// timer base (base moltiplica)
/// </summary>
protected int timerIntMs = 100; // di norma 100 msec x timer base...
/// <summary>
/// contatore veloce
/// </summary>
protected int fastCount = 1; // 100ms primo refresh...
/// <summary>
/// contatore normale
/// </summary>
protected int normCount = 2; // 200ms primo refresh...
/// <summary>
/// contatore slow
/// </summary>
protected int slowCount = 3; // 300ms primo refresh...
/// <summary>
/// contatore lentissimo
/// </summary>
protected int verySlowCount = 4; // 400ms primo refresh...
/// <summary>
/// ultimo tentativo riavvio...
/// </summary>
protected DateTime lastStartTry;
/// <summary>
/// tipo di adapter prescelto...
/// </summary>
protected tipoAdapter tipoScelto = tipoAdapter.DB;
/// <summary>
/// oggetto logging
/// </summary>
public static Logger lg;
#endregion
public MainForm()
{
InitializeComponent();
myInit();
}
/// <summary>
/// inizializzazione specifica
/// </summary>
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();
}
/// <summary>
/// Lettura conf DB
/// </summary>
private void loadServerConf()
{
agObj.loadServerConf();
lblServer.Text = string.Format("{0} | {1}", agObj.ServerType, agObj.ServerAddress);
displayTaskAndWait("...LOADING DB CONF...");
checkConnected();
}
/// <summary>
/// Tentativo connessione al DB
/// </summary>
private void connectAdapter()
{
displayTaskAndWait("...CONNECTIONG DB...");
agObj.tryConnect();
checkConnected();
}
/// <summary>
/// Tentativo disconnessione al DB
/// </summary>
private void disconnectAdapter()
{
displayTaskAndWait("...DISCONNECTIONG DB...");
agObj.tryDisconnect();
checkConnected();
}
/// <summary>
/// Verifica se il server sia connesso...
/// </summary>
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");
}
}
/// <summary>
/// Verifica se l'adapter sia partito...
/// </summary>
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");
}
}
/// <summary>
/// Verifica finale a fine show...
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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");
}
/// <summary>
/// mostra un testo sulla status bar ed attende startTimerMs
/// </summary>
/// <param name="txt2show"></param>
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);
}
/// <summary>
/// crea menù tray x applicazione
/// </summary>
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();
}
/// <summary>
/// doppio click su tray icon
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
// SOLO SE PERMESSO mostrare full...
if (utils.CRB("windowCanMax"))
{
Show();
WindowState = FormWindowState.Normal;
}
}
/// <summary>
/// evento resize
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainForm_Resize(object sender, EventArgs e)
{
checkFormVisibility();
}
/// <summary>
/// Verifica stato windows (minimized/normal) e visibilità con tray...
/// </summary>
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;
}
}
/// <summary>
/// Gestisce "andata nel tray" della form
/// </summary>
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();
}
/// <summary>
/// click su menù contestuale in tray
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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;
}
}
}
/// <summary>
/// File persistenza generale
/// </summary>
protected string defPersLayerFile
{
get
{
return string.Format(@"{0}\{1}", utils.dataDatDir, utils.CRS("defaultPersLayerFile"));
}
}
protected string defIconFilePath
{
get
{
return string.Format(@"{0}\Scma.ico", utils.resxDir);
}
}
/// <summary>
/// impostazione valori defaults
/// </summary>
private void setDefaults()
{
MainProgrBar.Minimum = 0;
MainProgrBar.Maximum = 300;
MainProgrBar.Value = 0;
MainProgrBar.Step = 1;
portMTC = utils.CRI("portMTC");
}
/// <summary>
/// Avvio adapter
/// </summary>
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...");
}
/// <summary>
/// fermata dell'adapter
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void stop_Click(object sender, EventArgs e)
{
fermaAdapter(false);
// salvo che ho fermato adapter
lg.Info("UNLOAD Adapter");
}
/// <summary>
/// Ferma l'adapter
/// </summary>
/// <param name="tryRestart">determina se si debba tentare riavvio automatico (per caduta connessione)</param>
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);
}
}
/// <summary>
/// file persistenza generale
/// </summary>
public string histPersLayerFile
{
get
{
return string.Format(@"{0}\{1:yyyy}\{1:yyyy-MM-dd}.mtc", utils.dataDatDir, DateTime.Now);
}
}
/// <summary>
/// file persistenza generale data attuale ANTICIPATA di xx giorni
/// </summary>
/// <param name="numDD">num DD di anticipo</param>
/// <returns></returns>
public string prevPersLayerFile(int numDD)
{
return string.Format(@"{0}\{1:yyyy}\{1:yyyy-MM-dd}.mtc", utils.dataDatDir, DateTime.Now.AddDays(-numDD));
}
/// <summary>
/// salva i valori attuali del file di conf sia in file corrente che in cartella valori storici
/// </summary>
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");
}
}
/// <summary>
/// Avanza la barra di stato...
/// </summary>
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);
}
}
/// <summary>
/// apro eseguibile dump
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dump_Click(object sender, EventArgs e)
{
apriDumpAgent();
}
/// <summary>
/// apre agent di dump in CMD
/// </summary>
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));
}
}
/// <summary>
/// Salva su file l'oggetto di persistenza dati
/// </summary>
/// <param name="filePath"></param>
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;
}
}
/// <summary>
/// Carica da file l'oggetto di persistenza dati
/// </summary>
/// <param name="filePath"></param>
public void loadPersistLayer(string filePath)
{
// inizializzo prima di leggere...
agObj.persistenceLayer = new Dictionary<string, string>();
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<string, string> lastRead = new Dictionary<string, string>();
// 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);
}
/// <summary>
/// Ferma tutti i componenti adapter + update buttons
/// </summary>
/// <param name="stopTimer">determina se fermare il timer (gather) principale (solo se non si chiude)</param>
/// <param name="tryRestart">determina se tentare di riconnettersi</param>
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");
}
/// <summary>
/// toggle connessione...
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}