using NLog;
using System;
using System.Collections.Generic;
using System.Linq;

namespace MTC_Adapter
{
    using MTC;
    using MTConnect;
    using System.Globalization;
    using System.IO;
    using System.Text;


    #region macro oggetti da istanziare a blocchi da configurazione XML

    /// <summary>
    /// Singola pompa da vuoto, 0..n
    /// </summary>
    public class VacuumPump : element
    {
        /// <summary>
        /// valore indca stato aperto/chiuso
        /// </summary>
        public Event mVacPumpStatus;
        /// <summary>
        /// valore work time della pompa vuoto
        /// </summary>
        public Event mVacPumpWrkTime;
        /// <summary>
        /// Classe Vacuum Pump (pompa)
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public VacuumPump(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mVacPumpStatus = new Event(string.Format("{0}_Status", ident));
            mVacPumpWrkTime = new Event(string.Format("{0}_WrkTime", ident));
        }
    }
    /// <summary>
    /// Singolo attuatore vuoto, 0..n
    /// </summary>
    public class VacuumAct : element
    {
        /// <summary>
        /// valore numero attivazioni/disattivazioni valvola
        /// </summary>
        public Event mVacActCount;
        /// <summary>
        /// Classe Vacuum Actuator (valvola)
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public VacuumAct(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mVacActCount = new Event(string.Format("{0}_Count", ident));
        }
    }
    /// <summary>
    /// Singolo attuatore per lubrificazione, 0..n
    /// </summary>
    public class Lubro : element
    {
        /// <summary>
        /// numero pompate necessarie per far scattare sensore
        /// </summary>
        public Event mLubroNum;
        /// <summary>
        /// Status
        /// </summary>
        public Event mLubroStatus;
        /// <summary>
        /// Classe Lubrorefrigerante
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public Lubro(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mLubroNum = new Event(string.Format("{0}_Num", ident));
            mLubroStatus = new Event(string.Format("{0}_Status", ident));
        }
    }
    /// <summary>
    /// Singola Slitta Mag, 0..n
    /// </summary>
    public class SlittaMag : element
    {
        /// <summary>
        /// valore numero attivazioni/disattivazioni slitta magazzino
        /// </summary>
        public Event mSlittaMagCount;
        /// <summary>
        /// Classe Slitta Magazzino
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public SlittaMag(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mSlittaMagCount = new Event(string.Format("{0}_Count", ident));
        }
    }
    /// <summary>
    /// Singolo attuatore Protezione Magazzino, 0..n
    /// </summary>
    public class ProtMag : element
    {
        /// <summary>
        /// valore numero attivazioni/disattivazioni valvola
        /// </summary>
        public Event mProtMagCount;
        /// <summary>
        /// Classe Protezione Magazzino
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public ProtMag(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mProtMagCount = new Event(string.Format("{0}_Count", ident));
        }
    }
    /// <summary>
    /// Singolo refrigeratore, 0..n
    /// </summary>
    public class Cooler : element
    {
        /// <summary>
        /// Stato istantaneo (evento aperto/chiuso)
        /// </summary>
        public Event mCoolStatus;
        /// <summary>
        /// Classe refrigeratore
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public Cooler(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mCoolStatus = new Event(string.Format("{0}_Status", ident));
        }
    }
    /// <summary>
    /// Singola Pressione rilevata, 0..n
    /// </summary>
    public class Press : element
    {
        /// <summary>
        /// valore pressione istantaneo
        /// </summary>
        public Sample mPressValIst;
        /// <summary>
        /// Classe pressione con Idx e descrizione
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public Press(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mPressValIst = new Sample(string.Format("{0}_Value", ident));
        }
    }
    /// <summary>
    /// Singola temperatura rilevata, 0..n
    /// </summary>
    public class Tempe : element
    {
        /// <summary>
        /// valore temperatura istantaneo
        /// </summary>
        public Sample mTempValIst;
        /// <summary>
        /// Classe temperatura con Idx e descrizione
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public Tempe(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mTempValIst = new Sample(string.Format("{0}_Value", ident));
        }
    }
    /// <summary>
    /// Singola Area Memoria (Kvara 1..4)
    /// </summary>
    public class MemArea : element
    {
        /// <summary>
        /// Programma caricato
        /// </summary>
        public MTConnect.Message mMemAreaProgName;
        /// <summary>
        /// Programma Running (in esecuzione) - ON/OFF
        /// </summary>
        public MTConnect.Message mMemAreaRunning;
        /// <summary>
        /// Num esecuzioni programma
        /// </summary>
        public Event mMemAreaProgNumExe;
        /// <summary>
        /// Num esecuzioni programma
        /// </summary>
        public Event mMemAreaProgNumRep;
        /// <summary>
        /// INIT Classe Memory Area
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public MemArea(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mMemAreaProgName = new MTConnect.Message(string.Format("{0}_PROG_NAME", ident));
            mMemAreaRunning = new MTConnect.Message(string.Format("{0}_RUNNING", ident));
            mMemAreaProgNumExe = new Event(string.Format("{0}_NUM_EXE", ident));
            mMemAreaProgNumRep = new Event(string.Format("{0}_NUM_REP", ident));
        }
    }
    /// <summary>
    /// Singolo path, da 1..20
    /// </summary>
    public class Path : element
    {
        /// <summary>
        /// Tipo Path (LAVOR/ASSERV)
        /// </summary>
        public MTConnect.Message mPathType;
        /// <summary>
        /// Cod Particolare su Path
        /// </summary>
        public Event mPathPartId;
        /// <summary>
        /// Contapezzi x PATH
        /// </summary>
        public Event mPathPartCount;
        /// <summary>
        /// Codici M sul PATH
        /// </summary>
        public MTConnect.Message mPathCodM;
        /// <summary>
        /// Codici S sul PATH
        /// </summary>
        public MTConnect.Message mPathCodS;
        /// <summary>
        /// Codici T sul PATH
        /// </summary>
        public MTConnect.Message mPathCodT;
        /// <summary>
        /// Modalità RUN del PATH: AUTO/EDIT/MDI/JOG/JOGINC/REF/HANDLE
        /// </summary>
        public Event mPathRunMode;
        /// <summary>
        /// Modalità execution del path: RUN/HOLD/FEED_HOLD/...
        /// </summary>
        public Event mPathExeMode;
        /// <summary>
        /// Programma corrente
        /// </summary>
        public Event mPathCurrProg;
        /// <summary>
        /// Area Programma corrente/selezionata
        /// </summary>
        public Event mPathCurrArea;
        /// <summary>
        /// num riga corrente
        /// </summary>
        public Event mPathCurrProgRowNum;
        /// <summary>
        /// Assi attivi per path
        /// </summary>
        public Event mPathActiveAxes;
        /// <summary>
        /// Feedrate
        /// </summary>
        public Sample mPathFeed;
        /// <summary>
        /// Override feed
        /// </summary>
        public Sample mPathFeedOver;
        /// <summary>
        /// Override speed
        /// </summary>
        public Sample mPathRapidOver;
        /// <summary>
        /// Override Jog
        /// </summary>
        public Sample mPathJogOver;
        /// <summary>
        /// Override Spindle_01
        /// </summary>
        public Sample mPathSpindleOver_01;
        /// <summary>
        /// Override Spindle_02
        /// </summary>
        public Sample mPathSpindleOver_02;
        /// <summary>
        /// Override Spindle_03
        /// </summary>
        public Sample mPathSpindleOver_03;
        /// <summary>
        /// Override Spindle_04
        /// </summary>
        public Sample mPathSpindleOver_04;
        /// <summary>
        /// Posizione X
        /// </summary>
        public Sample mPathPosActX;
        /// <summary>
        /// Posizione Y
        /// </summary>
        public Sample mPathPosActY;
        /// <summary>
        /// Posizione Z
        /// </summary>
        public Sample mPathPosActZ;
        /// <summary>
        /// Angolo I
        /// </summary>
        public Sample mPathPosActI;
        /// <summary>
        /// Angolo J
        /// </summary>
        public Sample mPathPosActJ;
        /// <summary>
        /// Angolo K
        /// </summary>
        public Sample mPathPosActK;
        /// <summary>
        /// Stato dei codici G attivi
        /// </summary>
        public MTConnect.Message mPathCodG_Act;
        /// <summary>
        /// Stato dei SubMode attivi
        /// </summary>
        public MTConnect.Message mPathSubMode;
        /// <summary>
        /// Allarmi CNC del PATH
        /// </summary>
        public Condition mPathAlarmCNC;
        /// <summary>
        /// Allarmi PCL del PATH
        /// </summary>
        public Condition mPathAlarmPLC;
        /// <summary>
        /// Classe Path con Idx e descrizione
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public Path(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mPathFeed = new Sample(string.Format("{0}_FeedRate", ident));
            mPathFeedOver = new Sample(string.Format("{0}_FeedOverr", ident));
            mPathRapidOver = new Sample(string.Format("{0}_RapidOverr", ident));
            mPathJogOver = new Sample(string.Format("{0}_JogOverr", ident));
            mPathSpindleOver_01 = new Sample(string.Format("{0}_SpindleOver_01", ident));
            mPathSpindleOver_02 = new Sample(string.Format("{0}_SpindleOver_02", ident));
            mPathSpindleOver_03 = new Sample(string.Format("{0}_SpindleOver_03", ident));
            mPathSpindleOver_04 = new Sample(string.Format("{0}_SpindleOver_04", ident));
            mPathPosActX = new Sample(string.Format("{0}_PosActX", ident));
            mPathPosActY = new Sample(string.Format("{0}_PosActY", ident));
            mPathPosActZ = new Sample(string.Format("{0}_PosActZ", ident));
            mPathPosActI = new Sample(string.Format("{0}_PosActI", ident));
            mPathPosActJ = new Sample(string.Format("{0}_PosActJ", ident));
            mPathPosActK = new Sample(string.Format("{0}_PosActK", ident));
            // aggiunta x revisione 2016.05.05
            mPathType = new MTConnect.Message(string.Format("{0}_Type", ident));
            mPathPartId = new Event(string.Format("{0}_PartId", ident));
            mPathPartCount = new Event(string.Format("{0}_PZ_TOT", ident));
            mPathCodM = new MTConnect.Message(string.Format("{0}_Cod_M", ident));
            mPathCodS = new MTConnect.Message(string.Format("{0}_Cod_S", ident));
            mPathCodT = new MTConnect.Message(string.Format("{0}_Cod_T", ident));
            mPathRunMode = new Event(string.Format("{0}_RUN_MODE", ident));
            mPathExeMode = new Event(string.Format("{0}_EXE_MODE", ident));
            mPathCurrProg = new Event(string.Format("{0}_CurrProg", ident));
            mPathCurrArea = new Event(string.Format("{0}_CurrArea", ident));
            mPathCurrProgRowNum = new Event(string.Format("{0}_CurrProg_RowNum", ident));
            mPathActiveAxes = new Event(string.Format("{0}_ActiveAxes", ident));
            mPathCodG_Act = new MTConnect.Message(string.Format("{0}_CodG_Act", ident));
            mPathSubMode = new MTConnect.Message(string.Format("{0}_SubMode", ident));
            mPathAlarmCNC = new Condition(string.Format("{0}_AlarmCNC", ident));
            mPathAlarmPLC = new Condition(string.Format("{0}_AlarmPLC", ident));
        }
    }
    /// <summary>
    /// Singolo mandrino, 1..n
    /// </summary>
    public class UnOp : element
    {
        /// <summary>
        /// ToolID
        /// </summary>
        public Event mUnOpToolId;
        /// <summary>
        /// valore numero Cambi Utensili effettuato
        /// </summary>
        public Event mUnOpNumCU;
        /// <summary>
        /// status utensil
        /// </summary>
        public Event mUnOpStatus;
        /// <summary>
        /// valore vita residua utensile
        /// </summary>
        public Event mUnOpVitaRes;
        /// <summary>
        /// tipologia di vita residua utensile:
        /// 0 : "ND" (famiglia senza gestione vitautensili)
        /// 1 : "Time [s]"
        /// 2 : "Stroke [n]"
        /// 3 : "Distance [m]" ([ft] se la macchina è impostata in pollici)
        /// </summary>
        public MTConnect.Message mUnOpVitaResType;
        /// <summary>
        /// valore speed
        /// </summary>
        public Sample mUnOpSpeed;
        /// <summary>
        /// valore speed override
        /// </summary>
        public Sample mUnOpSpeedOverr;
        /// <summary>
        /// valore load
        /// </summary>
        public Sample mUnOpLoad;
        /// <summary>
        /// valore tempo cumulato di impiego
        /// </summary>
        public Sample mUnOpAccTime;
        /// <summary>
        /// contatore cumulato di giri mandrino (migliaia)
        /// </summary>
        public Sample mUnOpKRev;
        /// <summary>
        /// Classe Unita Operatrice (Mandrino) con Idx e descrizione
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public UnOp(element baseElem)
        {
            ident = baseElem.ident;
            dataRefList = baseElem.dataRefList;

            mUnOpToolId = new Event(string.Format("{0}_ToolId", ident));
            mUnOpNumCU = new Event(string.Format("{0}_NumCU", ident));
            mUnOpStatus = new Event(string.Format("{0}_Status", ident));
            mUnOpVitaRes = new Event(string.Format("{0}_VitaRes", ident));
            mUnOpSpeed = new Sample(string.Format("{0}_Speed", ident));
            mUnOpSpeedOverr = new Sample(string.Format("{0}_SpeedOverr", ident));
            mUnOpLoad = new Sample(string.Format("{0}_Load", ident));
            mUnOpAccTime = new Sample(string.Format("{0}_AccTime", ident));
            mUnOpVitaResType = new MTConnect.Message(string.Format("{0}_VitaResType", ident));
            mUnOpKRev = new Sample(string.Format("{0}_KRev", ident));
        }
    }
    /// <summary>
    /// Asse singolo, 1..n
    /// </summary>
    public class Axis : element
    {
        /// <summary>
        /// Processo di appartenenza
        /// </summary>
        public MTConnect.Message mAxMainProc;
        /// <summary>
        /// Bit se sia master (=1) o slave (=0)
        /// </summary>
        public MTConnect.Message mAxIsMaster;
        /// <summary>
        /// ID del master
        /// </summary>
        public Event mAxMastId;
        /// <summary>
        /// Gruppo di appartenenza dell'asse
        /// </summary>
        public Event mAxGrp;
        /// <summary>
        /// Event tipo asse: lineare, rotazionale...
        /// </summary>
        public Event mAxType;
        /// <summary>
        /// Bit direzione: 1 = avanti/clockwise, 0 indietro/counterclockwise
        /// </summary>
        public Event mAxDir;
        /// <summary>
        /// Load
        /// </summary>
        public Sample mAxLoad;
        /// <summary>
        /// Posizione Attuale
        /// </summary>
        public Sample mAxPosAct;
        /// <summary>
        /// Posizione Target
        /// </summary>
        public Sample mAxPosTgt;
        /// <summary>
        /// Feed Attuale
        /// </summary>
        public Sample mAxFeedAct;
        /// <summary>
        /// Feed Override
        /// </summary>
        public Sample mAxFeedOver;
        /// <summary>
        /// Accelerazione Attuale
        /// </summary>
        public Sample mAxAccelAct;
        /// <summary>
        /// Tempo Lavoro cumulato
        /// </summary>
        public Sample mAxAccTime;
        /// <summary>
        /// Carica batteria
        /// </summary>
        public Sample mAxBattery;
        /// <summary>
        /// Distanza compiuta nell'intervallo di tempo
        /// </summary>
        public Sample mAxDistDone;
        /// <summary>
        /// numero di inversioni di direzione fatte nell'intervallo di tempo
        /// </summary>
        public Sample mAxInvDDone;
        /// <summary>
        /// Allarmi CNC del PATH
        /// </summary>
        public Condition mAxAlarmCNC;
        /// <summary>
        /// Allarmi PCL del PATH
        /// </summary>
        public Condition mAxAlarmPLC;
        /// <summary>
        /// Classe Asse con relativo ID UNIVOCO
        /// </summary>
        /// <param name="baseElem">element base contenente parametri (da XML)</param>
        public Axis(element baseElem)
        {
            ident = baseElem.ident;
            // valori da conf esplicita
            dataRefList = baseElem.dataRefList;
            try
            {
                mAxType = new Event(dataRefList[0].Key);
                mAxType.Value = dataRefList[0].Value;
            }
            catch
            {
                mAxType = new Event(string.Format("{0}_Type", ident));
                mAxType.Value = "LINEAR";

            }
            try
            {
                mAxGrp = new Event(dataRefList[1].Key);
                mAxGrp.Value = dataRefList[1].Value;
            }
            catch
            {
                mAxGrp = new Event(string.Format("{0}_Grp", ident));
                mAxGrp.Value = "00";

            }
            // valori standard
            mAxMainProc = new MTConnect.Message(string.Format("{0}_MainProc", ident));
            mAxIsMaster = new MTConnect.Message(string.Format("{0}_IsMast", ident));
            mAxMastId = new Event(string.Format("{0}_MastId", ident));
            mAxDir = new Event(string.Format("{0}_Dir", ident));
            mAxLoad = new Sample(string.Format("{0}_Load", ident));
            mAxPosAct = new Sample(string.Format("{0}_PosAct", ident));
            mAxPosTgt = new Sample(string.Format("{0}_PosTgt", ident));
            mAxFeedAct = new Sample(string.Format("{0}_FeedAct", ident));
            mAxFeedOver = new Sample(string.Format("{0}_FeedOver", ident));
            mAxAccelAct = new Sample(string.Format("{0}_AccelAct", ident));
            mAxAccTime = new Sample(string.Format("{0}_AccTime", ident));
            mAxBattery = new Sample(string.Format("{0}_Battery", ident));
            mAxDistDone = new Sample(string.Format("{0}_DistDone", ident));
            mAxInvDDone = new Sample(string.Format("{0}_InvDDone", ident));

            mAxAlarmCNC = new Condition(string.Format("{0}_AlarmCNC", ident));
            mAxAlarmPLC = new Condition(string.Format("{0}_AlarmPLC", ident));
        }

    }

    #endregion


    public class AdapterGeneric
    {
        /// <summary>
        /// alias booleano false = R
        /// </summary>
        public bool R = false;
        /// <summary>
        /// alias booleano true = W
        /// </summary>
        public bool W = true;
        /// <summary>
        /// wrapper di log
        /// </summary>
        public static Logger lg;
        /// <summary>
        /// valore booleano di check se sia in fase di COMUNICAZIONE ATTIVA con il PLC/NC
        /// </summary>
        protected bool adpCommAct;
        /// <summary>
        /// valore booleano di check se sia stato AVVIATO l'adapter (Running)
        /// </summary>
        public bool adpRunning = false;
        /// <summary>
        /// valore booleano di check se l'adapter STIA SALVANDO
        /// </summary>
        public bool adpSaving = false;
        /// <summary>
        /// valore booleano (richiesta di riavvio automatico)
        /// </summary>
        public bool adpTryRestart;
        /// <summary>
        /// Ultimo valore watchdog rilevato
        /// </summary>
        public bool lastWatchDog = false;
        /// <summary>
        /// Determina se utilizzare blocchi di memoria IOT contigui (e quindi processing "monoblocco" semplificato"=
        /// </summary>
        public bool procIotMem = false;
        /// <summary>
        /// porta x adapter (x restart)
        /// </summary>
        protected int adpPortNum;
        /// <summary>
        /// DataOra ultimo avvio adapter x watchdog
        /// </summary>
        protected DateTime adpStartRun;
        /// <summary>
        /// Data/ora ultimo avvio adapter
        /// </summary>
        public DateTime dtAvvioAdp = DateTime.Now;
        /// <summary>
        /// Data/ora ultimo spegnimento adapter
        /// </summary>
        public DateTime dtStopAdp = DateTime.Now;
        /// <summary>
        /// vettore gestione cronometraggi
        /// </summary>
        public DateTime inizio;
        /// <summary>
        /// Conteggio ATTUALE ore macchina ON
        /// </summary>
        public double contOreMaccOn;
        /// <summary>
        /// Conteggio ATTUALE ore macchina IN LAVORO
        /// </summary>
        public double contOreMaccLav;
        /// <summary>
        /// Conteggio ATTUALE numero movimenti Slitta Tastatore
        /// </summary>
        public double contSlittaTast;
        /// <summary>
        /// Vettore ATTUALE dei contatori giri cumulati elettromandrino (migliaia)
        /// </summary>
        public uint[] contGiriElettrom;
        /// <summary>
        /// Vettore ATTUALE dei contatori del movimento degli assi
        /// </summary>
        public double[] contDistMovAssi;
        /// <summary>
        /// Vettore ATTUALE dei contatori del tempo cumulato degli assi
        /// </summary>
        public double[] contAccTimeAssi;
        /// <summary>
        /// Vettore ATTUALE dei contatori del num inv degli assi
        /// </summary>
        public uint[] contNumInvAssi;
        /// <summary>
        /// vettore dei ProgramName dei path ATTIVI
        /// </summary>
        public string[] currPathProgrName;
        /// <summary>
        /// vettore dei PartId dei path ATTIVI
        /// </summary>
        public string[] currPathPartId;
        /// <summary>
        /// Vettore ATTUALE dei contatori del num pezzi fatti x PartId
        /// </summary>
        public uint[] currPathPartCount;
        /// <summary>
        /// Vettore ATTUALE dei contatori del work time x VacPump
        /// </summary>
        public uint[] currVacPumpWrkTime;
        /// <summary>
        /// Vettore ATTUALE dei contatori del numero impieghi VacAct
        /// </summary>
        public uint[] currVacActCount;
        /// <summary>
        /// Vettore ATTUALE dei contatori del Lubro
        /// </summary>
        public uint[] currLubroCount;
        /// <summary>
        /// Vettore ATTUALE dei contatori del numero cambi utensili x UnOp
        /// </summary>
        public uint[] currNumCambiUt;
        /// <summary>
        /// Vettore ATTUALE dei contatori del numero movimenti Slitta Magazzino
        /// </summary>
        public uint[] currSlittaMag;
        /// <summary>
        /// Vettore ATTUALE dei contatori del numero movimenti Protezione Magazzino
        /// </summary>
        public uint[] currProtMag;

        /// <summary>
        /// Conteggio ISTANTANEO ore macchina ON
        /// </summary>
        public double istOreMaccOn;
        /// <summary>
        /// isteggio ISTANTANEO ore macchina IN LAVORO
        /// </summary>
        public double istOreMaccLav;
        /// <summary>
        /// Conteggio ISTANTANEO contatore del numero movimenti Slitta Tastatore
        /// </summary>
        public double istSlittaTast;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori giri cumulati elettromandrino (migliaia)
        /// </summary>
        public uint[] istGiriElettrom;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori del movimento degli assi
        /// </summary>
        public double[] istDistMovAssi;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori del tempo cumulato degli assi
        /// </summary>
        public double[] istAccTimeAssi;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori del num inv degli assi
        /// </summary>
        public uint[] istNumInvAssi;
        /// <summary>
        /// vettore dei Program Name dei path ISTANTANEI (nuovi/letti)
        /// </summary>
        public string[] istPathProgrName;
        /// <summary>
        /// vettore dei PartId dei path ISTANTANEI (nuovi/letti)
        /// </summary>
        public string[] istPathPartId;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori del num pezzi fatti x PartId
        /// </summary>
        public uint[] istPathPartCount;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori del work time x VacPump
        /// </summary>
        public uint[] istVacPumpWrkTime;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori del numero impieghi VacAct
        /// </summary>
        public uint[] istVacActCount;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori del Lubro
        /// </summary>
        public uint[] istLubroCount;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori del numero cambi utensili x UnOp
        /// </summary>
        public uint[] istNumCambiUt;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori del numero movimenti Slitta Magazzino
        /// </summary>
        public uint[] istSlittaMag;
        /// <summary>
        /// Vettore ISTANTANEO dei contatori del numero movimenti Protezione Magazzino
        /// </summary>
        public uint[] istProtMag;

        /// <summary>
        /// data-ora ultimo controllo movimento assi
        /// </summary>
        public DateTime lastChekAccumTimeAxis;

        /// <summary>
        /// posizione precedente assi per calcolo distanze...
        /// </summary>
        public double[] prevPosAxis;
        /// <summary>
        /// direzione precedente assi per calcolo inversioni...
        /// </summary>
        public int[] prevDirAxis;


        /// <summary>
        /// adapter globale
        /// </summary>
        public Adapter mAdapter = new Adapter();
        /// <summary>
        /// Form chiamante
        /// </summary>
        protected MainForm parentForm;
        /// <summary>
        /// Conf adapter corrente
        /// </summary>
        public AdapterConf currAdpConf;

        #region altri oggetti

        // 16 byte di strobe (4 word da 32 bit di flags...)
        public byte[] Strobes = new byte[16];
        // 16 byte di strobe in risposta (4 word da 32 bit di flags...)
        public byte[] Acknowl = new byte[16];

        // 1024 bit di strobe degli allarmi attivi (32 word da 4byte/32 bit di flags...)
        public byte[] AlarmFlags;

        /// <summary>
        /// Oggetto elenco allarmi
        /// </summary>
        public allarme[] elencoAllarmi;

        public Dictionary<string, string> elencoSubMode;

        /// <summary>
        /// Prima word di strobe da array flag completo
        /// </summary>
        public StFlag32 STRB_DW0
        {
            get
            {
                return (StFlag32)BitConverter.ToUInt32(Strobes, 0);
            }
        }
        /// <summary>
        /// Seconda word di strobe da array flag completo
        /// </summary>
        public StFlag32 STRB_DW1
        {
            get
            {
                return (StFlag32)BitConverter.ToUInt32(Strobes, 4);
            }
        }
        /// <summary>
        /// Terza word di strobe da array flag completo
        /// </summary>
        public StFlag32 STRB_DW2
        {
            get
            {
                return (StFlag32)BitConverter.ToUInt32(Strobes, 8);
            }
        }
        /// <summary>
        /// Quarta word di strobe da array flag completo
        /// </summary>
        public StFlag32 STRB_DW3
        {
            get
            {
                return (StFlag32)BitConverter.ToUInt32(Strobes, 12);
            }
        }
        /// <summary>
        /// Quarta word di strobe da array flag completo
        /// </summary>
        public StFlag32 STRB_DW4
        {
            get
            {
                return (StFlag32)BitConverter.ToUInt32(Strobes, 16);
            }
        }
        /// <summary>
        /// Prima word di ACKnowledgment da array flag completo
        /// </summary>
        public StFlag32 ACK_DW0
        {
            get
            {
                return (StFlag32)BitConverter.ToUInt32(Acknowl, 0);
            }
        }
        /// <summary>
        /// Seconda word di ACKnowledgment da array flag completo
        /// </summary>
        public StFlag32 ACK_DW1
        {
            get
            {
                return (StFlag32)BitConverter.ToUInt32(Acknowl, 4);
            }
        }
        /// <summary>
        /// Terza word di ACKnowledgment da array flag completo
        /// </summary>
        public StFlag32 ACK_DW2
        {
            get
            {
                return (StFlag32)BitConverter.ToUInt32(Acknowl, 8);
            }
        }
        /// <summary>
        /// Quarta word di ACKnowledgment da array flag completo
        /// </summary>
        public StFlag32 ACK_DW3
        {
            get
            {
                return (StFlag32)BitConverter.ToUInt32(Acknowl, 12);
            }
        }

        /// <summary>
        /// Strobe mask PLC
        /// </summary>
        public Strobe STROBE_PLC = 0;
        /// <summary>
        /// Strobe mask adapter
        /// </summary>
        public Strobe STROBE_ADP = 0;
        /// <summary>
        /// Status flag
        /// </summary>
        public StatusBitMap STATUS_FLAG = 0;
        /// <summary>
        /// Variabili stato macchina principali
        /// </summary>
        public StFlag8 ST_MACCH = 0;

        public List<string> codaM = new List<string>();
        public List<string> codaS = new List<string>();
        public List<string> codaT = new List<string>();

        #endregion

        #region Events & samples

        /// <summary>
        /// Asset Changed - cambio asset
        /// </summary>
        public Event mAssetChg = new Event("MTC_asset_chg");
        /// <summary>
        /// Asset Removed - cambio asset
        /// </summary>
        public Event mAssetRem = new Event("MTC_asset_rem");

        /// <summary>
        /// D.D1.AVAIL - disponibilità
        /// </summary>
        public Event mAvail = new Event("AVAIL");
        /// <summary>
        /// XX.XX.STOP - stop per pressione emergenze
        /// </summary>
        public Event mEStop = new Event("E_STOP");
        /// <summary>
        /// STATUS "logico" adapter macchina (ON/OFF) 
        /// </summary>
        public Event mStatus = new Event("STATUS");
        /// <summary>
        /// Minuti accensione globale macchina
        /// </summary>
        public Sample mAccTime = new Sample("ACC_TIME");
        /// <summary>
        /// Minuti funzionamento globale macchina (IN LAVORO)
        /// </summary>
        public Sample mAccTimeWork = new Sample("ACC_TIME_WORK");
        /// <summary>
        /// Conteggio Impieghi Slitta Tastatore
        /// </summary>
        public Sample mSlittaTast = new Sample("SlittaTastatore_Count");
        /// <summary>
        /// Orologio
        /// </summary>
        public Sample mClock = new Sample("CLOCK");
        /// <summary>
        /// Status macchina accesa/spenta 
        /// </summary>
        public Event mPower = new Event("POWER");
        /// <summary>
        /// processo selezionato
        /// </summary>
        public Event mProcSel = new Event("PROC_SEL");
        /// <summary>
        /// ID operatore?!?
        /// </summary>
        public Event mOperator = new Event("OperatorId");
        /// <summary>
        /// Stato protezioni (0/1, off/on)
        /// </summary>
        public Event mProtectionStatus = new Event("PROTECTION_STATUS");

        #endregion

        #region Conditions

        // vettori vari: allarmi sistema, PLC, CNC
        public Condition mAlarmCNC = new Condition("CNC");
        public Condition mAlarmPLC = new Condition("PLC");

        #endregion

        #region Messages

        /// <summary>
        /// modalità funzionale
        /// </summary>
        public MTConnect.Message mFunctionalMode = new MTConnect.Message("FUNCT_MODE");
        /// <summary>
        /// Azioni operatore (Start/Stop/reset)
        /// </summary>
        public MTConnect.Message mUserAction = new MTConnect.Message("USER_ACTION");
        /// <summary>
        /// Testing macchina
        /// </summary>
        public MTConnect.Message mTestingData = new MTConnect.Message("TESTING_DATA");
        /// <summary>
        /// Strobe rilevati ma non qualificati
        /// </summary>
        public MTConnect.Message mUnkStrobe = new MTConnect.Message("UNK_STROBE");
        /// <summary>
        /// Status rilevati ma non qualificati
        /// </summary>
        public MTConnect.Message mUnkStatus = new MTConnect.Message("UNK_STATUS");
        /// <summary>
        /// Messaggi generali
        /// </summary>
        public MTConnect.Message mMessage = new MTConnect.Message("MESSAGE");

        #endregion

        #region oggetti complessi/completi


        public VacuumPump[] vettVacPump;
        public VacuumAct[] vettVacAct;
        public Lubro[] vettLubro;
        public SlittaMag[] vettSlittaMag;
        public ProtMag[] vettProtMag;
        public Cooler[] vettCooler;
        public Press[] vettPress;
        public Tempe[] vettTempe;
        public Path[] vettPath;
        public UnOp[] vettUnOp;
        public Axis[] vettAxis;
        public MemArea[] vettMemArea;

        #endregion

        public event EventHandler eh_refreshed;

        /// <summary>
        /// inizializzo l'oggetto sulla form SULLA BASE DEL FILE DI CONFIGURAZIONE letto
        /// </summary>
        /// <param name="caller"></param>
        /// <param name="adpConf"></param>
        public AdapterGeneric(MainForm caller, AdapterConf adpConf)
        {
            lg = LogManager.GetCurrentClassLogger();
            lg.Info("Avvio AdapterGeneric");

            procIotMem = utils.CRB("procIotMem");

            currAdpConf = adpConf;

            // inizializzo vettore gruppi assi, MAX 20!!!
            FeedRateGrp = new int[20];

            // salvo il form chiamante
            parentForm = caller;

            // item disponibilità
            mAdapter.AddDataItem(mAvail);
            mAvail.Value = "AVAILABLE";
            mMessage.Value = "";

            // assets
            mAdapter.AddDataItem(mAssetChg);
            mAdapter.AddDataItem(mAssetRem);
            mAssetChg.Value = "";
            mAssetRem.Value = "";

            // status, clock, emergency stop
            mAdapter.AddDataItem(mStatus);
            mAdapter.AddDataItem(mAccTime);
            mAdapter.AddDataItem(mAccTimeWork);
            mAdapter.AddDataItem(mSlittaTast);
            mAdapter.AddDataItem(mClock);
            mAdapter.AddDataItem(mPower);
            mAdapter.AddDataItem(mProcSel);
            mAdapter.AddDataItem(mEStop);

            // programma e produzione
            mAdapter.AddDataItem(mOperator);

            // modalità esecutiva e funzionale
            mFunctionalMode.Value = "";
            mAdapter.AddDataItem(mFunctionalMode);


            // testing e autodiagnostica
            mAdapter.AddDataItem(mTestingData);

            // stato protezioni
            mAdapter.AddDataItem(mProtectionStatus);

            // strobe/status non riconosciuti
            mAdapter.AddDataItem(mUnkStatus);
            mAdapter.AddDataItem(mUnkStrobe);

            // Aree memoria
            vettMemArea = new MemArea[adpConf.nMemArea];
            for (int i = 0; i < adpConf.nMemArea; i++)
            {
                vettMemArea[i] = new MemArea(adpConf.MemArea[i]);
                mAdapter.AddDataItem(vettMemArea[i].mMemAreaProgName);
                mAdapter.AddDataItem(vettMemArea[i].mMemAreaRunning);
                mAdapter.AddDataItem(vettMemArea[i].mMemAreaProgNumExe);
                mAdapter.AddDataItem(vettMemArea[i].mMemAreaProgNumRep);
            }
            // Pompe vuoto
            vettVacPump = new VacuumPump[adpConf.nVacuumPump];
            for (int i = 0; i < adpConf.nVacuumPump; i++)
            {
                vettVacPump[i] = new VacuumPump(adpConf.VacuumPump[i]);
                mAdapter.AddDataItem(vettVacPump[i].mVacPumpStatus);
                mAdapter.AddDataItem(vettVacPump[i].mVacPumpWrkTime);
            }
            // Attuatori vuoto
            vettVacAct = new VacuumAct[adpConf.nVacuumAct];
            for (int i = 0; i < adpConf.nVacuumAct; i++)
            {
                vettVacAct[i] = new VacuumAct(adpConf.VacuumAct[i]);
                mAdapter.AddDataItem(vettVacAct[i].mVacActCount);
            }
            // Lubrorefrigeranti
            vettLubro = new Lubro[adpConf.nLubro];
            for (int i = 0; i < adpConf.nLubro; i++)
            {
                vettLubro[i] = new Lubro(adpConf.Lubro[i]);
                mAdapter.AddDataItem(vettLubro[i].mLubroNum);
                mAdapter.AddDataItem(vettLubro[i].mLubroStatus);
            }
            // Slitta Mag
            vettSlittaMag = new SlittaMag[adpConf.nSlittaMag];
            for (int i = 0; i < adpConf.nSlittaMag; i++)
            {
                vettSlittaMag[i] = new SlittaMag(adpConf.SlittaMag[i]);
                mAdapter.AddDataItem(vettSlittaMag[i].mSlittaMagCount);
            }
            // Protezione Mag
            vettProtMag = new ProtMag[adpConf.nProtMag];
            for (int i = 0; i < adpConf.nProtMag; i++)
            {
                vettProtMag[i] = new ProtMag(adpConf.ProtMag[i]);
                mAdapter.AddDataItem(vettProtMag[i].mProtMagCount);
            }
            // Cooler
            vettCooler = new Cooler[adpConf.nCooler];
            for (int i = 0; i < adpConf.nCooler; i++)
            {
                vettCooler[i] = new Cooler(adpConf.Cooler[i]);
                mAdapter.AddDataItem(vettCooler[i].mCoolStatus);
            }
            // Press
            vettPress = new Press[adpConf.nPress];
            for (int i = 0; i < adpConf.nPress; i++)
            {
                vettPress[i] = new Press(adpConf.Press[i]);
                mAdapter.AddDataItem(vettPress[i].mPressValIst);
            }
            // Temp
            vettTempe = new Tempe[adpConf.nTemp];
            for (int i = 0; i < adpConf.nTemp; i++)
            {
                vettTempe[i] = new Tempe(adpConf.Temp[i]);
                mAdapter.AddDataItem(vettTempe[i].mTempValIst);
            }
            // Path
            vettPath = new Path[adpConf.nPath];
            for (int i = 0; i < adpConf.nPath; i++)
            {
                vettPath[i] = new Path(adpConf.Path[i]);
                mAdapter.AddDataItem(vettPath[i].mPathFeed);
                mAdapter.AddDataItem(vettPath[i].mPathFeedOver);
                mAdapter.AddDataItem(vettPath[i].mPathRapidOver);
                mAdapter.AddDataItem(vettPath[i].mPathJogOver);
                mAdapter.AddDataItem(vettPath[i].mPathSpindleOver_01);
                mAdapter.AddDataItem(vettPath[i].mPathSpindleOver_02);
                mAdapter.AddDataItem(vettPath[i].mPathSpindleOver_03);
                mAdapter.AddDataItem(vettPath[i].mPathSpindleOver_04);
                mAdapter.AddDataItem(vettPath[i].mPathPosActX);
                mAdapter.AddDataItem(vettPath[i].mPathPosActY);
                mAdapter.AddDataItem(vettPath[i].mPathPosActZ);
                mAdapter.AddDataItem(vettPath[i].mPathPosActI);
                mAdapter.AddDataItem(vettPath[i].mPathPosActJ);
                mAdapter.AddDataItem(vettPath[i].mPathPosActK);
                // aggiunta x revisione 2016.05.05
                mAdapter.AddDataItem(vettPath[i].mPathType);
                mAdapter.AddDataItem(vettPath[i].mPathPartId);
                mAdapter.AddDataItem(vettPath[i].mPathPartCount);
                mAdapter.AddDataItem(vettPath[i].mPathCodM);
                mAdapter.AddDataItem(vettPath[i].mPathCodS);
                mAdapter.AddDataItem(vettPath[i].mPathCodT);
                mAdapter.AddDataItem(vettPath[i].mPathRunMode);
                mAdapter.AddDataItem(vettPath[i].mPathExeMode);
                mAdapter.AddDataItem(vettPath[i].mPathCurrProg);
                mAdapter.AddDataItem(vettPath[i].mPathCurrArea);
                mAdapter.AddDataItem(vettPath[i].mPathCurrProgRowNum);
                mAdapter.AddDataItem(vettPath[i].mPathActiveAxes);
                mAdapter.AddDataItem(vettPath[i].mPathCodG_Act);
                mAdapter.AddDataItem(vettPath[i].mPathSubMode);
                // aggiungo condizioni allarme...
                mAdapter.AddDataItem(vettPath[i].mPathAlarmCNC);
                mAdapter.AddDataItem(vettPath[i].mPathAlarmPLC);
            }
            // UnOp
            vettUnOp = new UnOp[adpConf.nUnOp];
            for (int i = 0; i < adpConf.nUnOp; i++)
            {
                vettUnOp[i] = new UnOp(adpConf.UnOp[i]);
                mAdapter.AddDataItem(vettUnOp[i].mUnOpToolId);
                mAdapter.AddDataItem(vettUnOp[i].mUnOpNumCU);
                mAdapter.AddDataItem(vettUnOp[i].mUnOpStatus);
                mAdapter.AddDataItem(vettUnOp[i].mUnOpVitaRes);
                mAdapter.AddDataItem(vettUnOp[i].mUnOpVitaResType);
                mAdapter.AddDataItem(vettUnOp[i].mUnOpSpeed);
                mAdapter.AddDataItem(vettUnOp[i].mUnOpSpeedOverr);
                mAdapter.AddDataItem(vettUnOp[i].mUnOpLoad);
                mAdapter.AddDataItem(vettUnOp[i].mUnOpAccTime);
                mAdapter.AddDataItem(vettUnOp[i].mUnOpKRev);
            }
            // Assi
            vettAxis = new Axis[adpConf.nAxis];
            for (int i = 0; i < adpConf.nAxis; i++)
            {
                vettAxis[i] = new Axis(adpConf.Axis[i]);
                mAdapter.AddDataItem(vettAxis[i].mAxMainProc);
                mAdapter.AddDataItem(vettAxis[i].mAxIsMaster);
                mAdapter.AddDataItem(vettAxis[i].mAxMastId);
                mAdapter.AddDataItem(vettAxis[i].mAxType);
                mAdapter.AddDataItem(vettAxis[i].mAxDir);
                mAdapter.AddDataItem(vettAxis[i].mAxLoad);
                mAdapter.AddDataItem(vettAxis[i].mAxPosAct);
                mAdapter.AddDataItem(vettAxis[i].mAxPosTgt);
                mAdapter.AddDataItem(vettAxis[i].mAxFeedAct);
                mAdapter.AddDataItem(vettAxis[i].mAxFeedOver);
                mAdapter.AddDataItem(vettAxis[i].mAxAccelAct);
                mAdapter.AddDataItem(vettAxis[i].mAxAccTime);
                mAdapter.AddDataItem(vettAxis[i].mAxBattery);
                mAdapter.AddDataItem(vettAxis[i].mAxDistDone);
                mAdapter.AddDataItem(vettAxis[i].mAxInvDDone);
                mAdapter.AddDataItem(vettAxis[i].mAxAlarmCNC);
                mAdapter.AddDataItem(vettAxis[i].mAxAlarmPLC);
            }



            // messaggi ulteriori
            mAdapter.AddDataItem(mMessage);

            // allarmi "base"
            mAdapter.AddDataItem(mAlarmCNC);
            mAdapter.AddDataItem(mAlarmPLC);

            // azioni utente
            mAdapter.AddDataItem(mUserAction);

            // concluso!
            lg.Info("Istanziata classe AdapterGeneric");
        }
        /// <summary>
        /// caricamento allarmi da file
        /// </summary>
        protected void loadAllarmi()
        {
            if (utils.CRB("verbose")) lg.Info("Inizio caricamento vettore allarmi");
            int totRighe = 0;
            string fileName = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("AlarmList"));
            string linea;
            totRighe = File.ReadLines(fileName).Count();
            // creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco...
            elencoAllarmi = new allarme[File.ReadLines(fileName).Count()];
            // carica da file...
            System.IO.StreamReader file = new System.IO.StreamReader(fileName);
            // leggo 1 linea alla volta...
            int rumRiga = 0;
            while ((linea = file.ReadLine()) != null)
            {
                // SE non è un commento...
                if (linea.Substring(0, 1) != "#")
                {
                    //elencoAllarmi[rumRiga] = decodeAlarmLine(linea, ':');
                    elencoAllarmi[rumRiga] = decodeAlarmLine(linea, utils.CRC("testCharSep"));
                    rumRiga++;
                }
            }
            // chiudo file
            file.Close();
            // ora trimmo vettore al solo numero VERO degli allarmi caricati...
            Array.Resize<allarme>(ref elencoAllarmi, rumRiga);

            // inizializzo a zero il vettore allarmi...
            int numByte = (int)Math.Ceiling(Convert.ToDecimal(rumRiga) / 8);
            // 2016.07.20: dimensione AlarmFlags è la MAX tra quella del numero allarmi ed il numero allarmi standard dalla memoria...
            if (numByte < 32) numByte = 32;
            AlarmFlags = new byte[numByte];
            if (utils.CRB("verbose")) lg.Info(string.Format("Fine caricamento vettore allarmi: {0} allarmi caricati!", rumRiga));
        }
        /// <summary>
        /// Caricamento altri file necessari epr adapter all'avvio
        /// </summary>
        protected virtual void loadOtherFile()
        {

        }
        /// <summary>
        /// caricamento allarmi da file
        /// </summary>
        protected void loadSubMode()
        {
            if (utils.CRB("verbose")) lg.Info("Inizio caricamento vettore SubMode");
            int totRighe = 0;
            string fileName = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("SubModeListFilePath"));
            string linea;
            totRighe = File.ReadLines(fileName).Count();
            // inizializzo
            elencoSubMode = new Dictionary<string, string>();
            // carica da file...
            StreamReader file = new StreamReader(fileName);
            // leggo 1 linea alla volta...
            string[] valori;
            while ((linea = file.ReadLine()) != null)
            {
                // SE non è un commento...
                if (linea.Substring(0, 1) != "#")
                {
                    valori = linea.Split(':');
                    elencoSubMode.Add(valori[0], valori[1]);
                }
            }
            // chiudo file
            file.Close();
            if (utils.CRB("verbose")) lg.Info("Fine caricamento vettore SubMode");
        }
        /// <summary>
        /// Decodifica file allarme 
        /// </summary>
        /// <param name="linea"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        protected allarme decodeAlarmLine(string linea, char separator)
        {
            string[] valori = linea.Split(separator);
            return new allarme(valori[0], valori[1], valori[2], valori[3]);
        }
        /// <summary>
        /// Recupera il numero (iniziale) da una stringa prendendo la aprte sino al separatore...
        /// </summary>
        /// <param name="linea"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        protected int startNumb(string linea, char separator)
        {
            int answ = 0;
            try
            {
                answ = Convert.ToInt32(linea.Substring(0, linea.IndexOf(separator)));
            }
            catch
            { }
            return answ;
        }
        /// <summary>
        /// Decodifica file datiProdSCM 
        /// </summary>
        /// <param name="linea"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        protected datiProdSCM decodeScmProdLine(string linea, char separator)
        {
            string[] valori = linea.Split(separator);
            datiProdSCM answ = null;
            if (valori.Length == 23)
            {
                answ = new datiProdSCM(valori);
            }
            return answ;
        }
        /// <summary>
        /// Decodifica file allarme 
        /// </summary>
        /// <param name="linea"></param>
        /// <param name="separator"></param>
        /// <param name="memPre">tipo memoria (R/D/...)</param>
        /// <param name="baseAddr">indirizzo di partenza memoria</param>
        /// <param name="memSize">dimensione singolo slot in byte</param>
        /// <returns></returns>
        protected otherData decodeOtherData(string linea, char separator, string memPre, int baseAddr, int memSize)
        {
            string[] valori = linea.Split(separator);
            int shift = 0;
            try
            {
                shift = Convert.ToInt32(valori[0]) - 1;
            }
            catch
            { }
            string memAddr = string.Format("{0}{1}", memPre, baseAddr + shift * memSize);
            return new otherData(valori[0], memAddr, valori[1].Trim(), valori[2].Trim());
        }
        /// <summary>
        /// Decodifica file MAP (caso ESA/IOT)
        /// </summary>
        /// <param name="linea"></param>
        /// <param name="separator"></param>
        /// <param name="ByteNum">indirizzo Byte: indirizzo di partenza memoria</param>
        /// <param name="memSize">dimensione singolo slot in byte</param>
        /// <param name="BitNum">indirizzo bit: numero riga x calcolo indice bit</param>
        /// <returns></returns>
        protected otherData decodeBitData(string linea, char separator, int ByteNum, int memSize, int BitNum)
        {
            string[] valori = linea.Split(separator);
            int shift = 0;
            try
            {
                shift = Convert.ToInt32(valori[0]) - 1;
            }
            catch
            { }
            int resto = 0;
            Math.DivRem(BitNum, 8, out resto);
            string memAddr = string.Format("{0}.{1}", ByteNum + shift * memSize, resto);
            return new otherData(valori[0], memAddr, valori[1].Trim(), valori[2].Trim());
        }
        /// <summary>
        /// Decodifica file MAP (caso FANUC/OSAI/...)
        /// </summary>
        /// <param name="linea"></param>
        /// <param name="separator"></param>
        /// <param name="memPre">tipo memoria (R/D/...)</param>
        /// <param name="baseAddr">indirizzo Byte: indirizzo di partenza memoria</param>
        /// <param name="memSize">dimensione singolo slot in byte</param>
        /// <param name="numRiga">indirizzo bit: numero riga x calcolo indice bit</param>
        /// <returns></returns>
        protected otherData decodeBitData(string linea, char separator, string memPre, int baseAddr, int memSize, int numRiga)
        {
            string[] valori = linea.Split(separator);
            int shift = 0;
            try
            {
                shift = (Convert.ToInt32(valori[0]) - 1) / (8 * memSize);
            }
            catch
            { }
            int resto = 0;
            Math.DivRem(numRiga, 8 * memSize, out resto);
            string memAddr = string.Format("{0}{1}.{2}", memPre, baseAddr + shift, resto);
            return new otherData(valori[0], memAddr, valori[1].Trim(), valori[2].Trim());
        }

        #region metodi adapter

        public void loadPersData()
        {
            // nuova lettura valori da file persistenza...
            contOreMaccOn = getStoredValDouble("ACC_TIME");
            contOreMaccLav = getStoredValDouble("ACC_TIME_WORK");
            contSlittaTast = getStoredValDouble("SlittaTastatore_Count");

            for (int i = 0; i < currAdpConf.nUnOp; i++)
            {
                contGiriElettrom[i] = getStoredValUInt(string.Format("UnOp_{0:00}_AccTime", i + 1));
                currNumCambiUt[i] = getStoredValUInt(string.Format("UnOp_{0:00}_NumCU", i + 1));
            }

            for (int i = 0; i < currAdpConf.nAxis; i++)
            {
                contDistMovAssi[i] = getStoredValUInt(string.Format("Axis_{0:00}_DistDone", i + 1));
                contNumInvAssi[i] = getStoredValUInt(string.Format("Axis_{0:00}_InvDDone", i + 1));
                contAccTimeAssi[i] = getStoredValDouble(string.Format("Axis_{0:00}_AccTime", i + 1));
            }

            for (int i = 0; i < currAdpConf.nVacuumPump; i++)
            {
                currVacPumpWrkTime[i] = getStoredValUInt(string.Format("VacPump_{0:00}_WrkTime", i + 1));
            }

            for (int i = 0; i < currAdpConf.nVacuumAct; i++)
            {
                currVacActCount[i] = getStoredValUInt(string.Format("VacAct_{0:00}_Count", i + 1));
            }

            for (int i = 0; i < currAdpConf.nLubro; i++)
            {
                currLubroCount[i] = getStoredValUInt(string.Format("Lubro_{0:00}_Count", i + 1));
            }

            for (int i = 0; i < currAdpConf.nSlittaMag; i++)
            {
                currSlittaMag[i] = getStoredValUInt(string.Format("SlittaMagazzino_{0:00}_Count", i + 1));
            }

            for (int i = 0; i < currAdpConf.nProtMag; i++)
            {
                currProtMag[i] = getStoredValUInt(string.Format("ProtMagazzino_{0:00}_Count", i + 1));
            }
        }

        /// <summary>
        /// Avvia l'adapter sulla porta richiesta
        /// </summary>
        /// <param name="port"></param>
        public virtual void startAdapter(int port)
        {
            lg.Info("Starting adapter...");
            adpRunning = true;
            dtAvvioAdp = DateTime.Now;
            TimingData.resetData();
            // inizializzo vettori di utility..
            loadAllarmi();
            loadSubMode();
            loadOtherFile();

            // salvo porta!
            mAdapter.Port = port;
            adpPortNum = port;
            // avvio!
            mAdapter.Start();

            // setto status a ON
            mStatus.Value = "ON";

            // resetto running flag...
            adpCommAct = false;

            // carico valori da adapter x i conteggi
            contOreMaccOn = currAdpConf.ContOreMaccOn;
            contOreMaccLav = currAdpConf.ContOreMaccLav;
            contSlittaTast = currAdpConf.ContSlittaTast;
            contGiriElettrom = new uint[currAdpConf.nUnOp];
            istGiriElettrom = new uint[currAdpConf.nUnOp];
            currNumCambiUt = new uint[currAdpConf.nUnOp];
            istNumCambiUt = new uint[currAdpConf.nUnOp];
            for (int i = 0; i < currAdpConf.nUnOp; i++)
            {
                // leggo tutti i dati...
                List<DataRefItem<string, string>> listaDR = currAdpConf.UnOp[i].dataRefList;
                // punto all'item
                DataRefItem<string, string> riContRpm = listaDR.Find(x => x.Key == string.Format("UnOp_{0:00}_AccTime", i + 1));
                DataRefItem<string, string> riContNumCU = listaDR.Find(x => x.Key == string.Format("UnOp_{0:00}_NumCU", i + 1));
                // recupero valore giri...
                UInt32 contTotGiri = Convert.ToUInt32(riContRpm.Value);
                // recupero valore num cambi ut...
                UInt32 contNumCU = Convert.ToUInt32(riContNumCU.Value);
                // salvo valore letto
                contGiriElettrom[i] = contTotGiri;
                currNumCambiUt[i] = contNumCU;
            }
            // imposto num assi e leggo valori salvati...
            contDistMovAssi = new double[currAdpConf.nAxis];
            istDistMovAssi = new double[currAdpConf.nAxis];
            contNumInvAssi = new uint[currAdpConf.nAxis];
            istAccTimeAssi = new double[currAdpConf.nAxis];
            contAccTimeAssi = new double[currAdpConf.nAxis];
            istNumInvAssi = new uint[currAdpConf.nAxis];
            lastChekAccumTimeAxis = DateTime.Now;
            for (int i = 0; i < currAdpConf.nAxis; i++)
            {
                // leggo tutti i dati...
                List<DataRefItem<string, string>> listaDR = currAdpConf.Axis[i].dataRefList;
                // punto all'item
                DataRefItem<string, string> riContDist = listaDR.Find(x => x.Key == string.Format("Axis_{0:00}_DistDone", i + 1));
                DataRefItem<string, string> riNumInv = listaDR.Find(x => x.Key == string.Format("Axis_{0:00}_Invers", i + 1));
                DataRefItem<string, string> riAccTime = listaDR.Find(x => x.Key == string.Format("Axis_{0:00}_AccTime", i + 1));
                // recupero valori...
                contDistMovAssi[i] = Convert.ToUInt32(riContDist.Value);
                contNumInvAssi[i] = Convert.ToUInt32(riNumInv.Value);
                contAccTimeAssi[i] = Convert.ToDouble(riAccTime.Value);
                vettAxis[i].mAxAlarmCNC.Normal();
                vettAxis[i].mAxAlarmPLC.Normal();

            }
            currPathPartId = new string[currAdpConf.nPath];
            istPathPartId = new string[currAdpConf.nPath];
            currPathProgrName = new string[currAdpConf.nPath];
            istPathProgrName = new string[currAdpConf.nPath];
            currPathPartCount = new uint[currAdpConf.nPath];
            istPathPartCount = new uint[currAdpConf.nPath];
            for (int i = 0; i < currAdpConf.nPath; i++)
            {
                // leggo tutti i dati...
                List<DataRefItem<string, string>> listaDR = currAdpConf.Path[i].dataRefList;
                // punto all'item
                DataRefItem<string, string> riPathProgr = listaDR.Find(x => x.Key == string.Format("Path_{0:00}_PartId", i + 1));
                DataRefItem<string, string> riPathPzTot = listaDR.Find(x => x.Key == string.Format("Path_{0:00}_PZ_TOT", i + 1));
                // recupero valori...
                currPathPartId[i] = riPathProgr.Value;
                currPathPartCount[i] = Convert.ToUInt32(riPathPzTot.Value);
                currPathProgrName[i] = "";
                vettPath[i].mPathAlarmCNC.Normal();
                vettPath[i].mPathAlarmPLC.Normal();
            }
            currVacPumpWrkTime = new uint[currAdpConf.nVacuumPump];
            istVacPumpWrkTime = new uint[currAdpConf.nVacuumPump];
            for (int i = 0; i < currAdpConf.nVacuumPump; i++)
            {
                // leggo tutti i dati...
                List<DataRefItem<string, string>> listaDR = currAdpConf.VacuumPump[i].dataRefList;
                // punto all'item
                DataRefItem<string, string> riVacPumpWrk = listaDR.Find(x => x.Key == string.Format("VacPump_{0:00}_WrkTime", i + 1));
                // recupero valori...
                currVacPumpWrkTime[i] = Convert.ToUInt32(riVacPumpWrk.Value);
            }
            currVacActCount = new uint[currAdpConf.nVacuumAct];
            istVacActCount = new uint[currAdpConf.nVacuumAct];
            for (int i = 0; i < currAdpConf.nVacuumAct; i++)
            {
                // leggo tutti i dati...
                List<DataRefItem<string, string>> listaDR = currAdpConf.VacuumAct[i].dataRefList;
                // punto all'item
                DataRefItem<string, string> riVacActCount = listaDR.Find(x => x.Key == string.Format("VacAct_{0:00}_Count", i + 1));
                // recupero valori...
                currVacActCount[i] = Convert.ToUInt32(riVacActCount.Value);
            }
            currLubroCount = new uint[currAdpConf.nLubro];
            istLubroCount = new uint[currAdpConf.nLubro];
            for (int i = 0; i < currAdpConf.nLubro; i++)
            {
                // leggo tutti i dati...
                List<DataRefItem<string, string>> listaDR = currAdpConf.Lubro[i].dataRefList;
                // punto all'item
                DataRefItem<string, string> riLubro = listaDR.Find(x => x.Key == string.Format("Lubro_{0:00}_Count", i + 1));
                // recupero valori...
                currLubroCount[i] = Convert.ToUInt32(riLubro.Value);
            }
            currSlittaMag = new uint[currAdpConf.nSlittaMag];
            istSlittaMag = new uint[currAdpConf.nSlittaMag];
            for (int i = 0; i < currAdpConf.nSlittaMag; i++)
            {
                // leggo tutti i dati...
                List<DataRefItem<string, string>> listaDR = currAdpConf.SlittaMag[i].dataRefList;
                // punto all'item
                DataRefItem<string, string> riSlittaMag = listaDR.Find(x => x.Key == string.Format("SlittaMagazzino_{0:00}_Count", i + 1));
                // recupero valori...
                currSlittaMag[i] = Convert.ToUInt32(riSlittaMag.Value);
            }
            currProtMag = new uint[currAdpConf.nProtMag];
            istProtMag = new uint[currAdpConf.nProtMag];
            for (int i = 0; i < currAdpConf.nProtMag; i++)
            {
                // leggo tutti i dati...
                List<DataRefItem<string, string>> listaDR = currAdpConf.ProtMag[i].dataRefList;
                // punto all'item
                DataRefItem<string, string> riProtMag = listaDR.Find(x => x.Key == string.Format("ProtMagazzino_{0:00}_Count", i + 1));
                // recupero valori...
                currProtMag[i] = Convert.ToUInt32(riProtMag.Value);
            }

            //mAlarmSystem.Normal();
            mAlarmCNC.Normal();
            mAlarmPLC.Normal();
            //mAlarmGeneral.Normal();
            adpTryRestart = true;
            parentForm.displayTaskAndWait("Adapter Started!");
        }
        /// <summary>
        /// Effettua refresh del vettore privato degli allarmi attivi
        /// </summary>
        /// <param name="Alarm2Refresh">flag mask degli allarmi da aggiornare</param>
        /// <param name="giveAck">boolean: se si debba tornare ACK</param>
        public virtual void refreshAlarmState(StFlag32 Alarm2Refresh, bool giveAck)
        {
            // carico lo stato di tutti gli allarmi... forzo a 1 il flag degli allarmi
        }

        /// <summary>
        /// ferma l'adapter...
        /// </summary>
        /// <param name="tryRestart">indica se si debba tentare di riavviare l'adapter (con caduta connessione viene fermato in automatico)</param>
        public void stopAdapter(bool tryRestart)
        {
            parentForm.displayTaskAndWait("Stopping adapter...");
            adpTryRestart = false;
            mStatus.Value = "INACTIVE";
            // faccio una chiamata extra ad ogni metodo di check...
            gaterAndSend(gatherCycle.HF);
            gaterAndSend(gatherCycle.MF);
            gaterAndSend(gatherCycle.LF);
            gaterAndSend(gatherCycle.VLF);
            parentForm.displayTaskAndWait("Stopping adapter - last periodic data read...");

            // chiudo la connessione all'adapter...
            tryDisconnect();
            // Stop everything...
            try
            {
                mAdapter.Stop();
            }
            catch (Exception exc)
            {
                lg.Error(exc, "Eccezione in chiusura Adapter");
            }
            dtStopAdp = DateTime.Now;
            adpPortNum = mAdapter.Port;
            adpTryRestart = tryRestart;
            adpRunning = false;
            // chiudo!
            parentForm.resetProgBar();
            parentForm.dataMonitor_1 = "... not connected, waiting for data ...";
            parentForm.dataMonitor_2 = "";
            parentForm.dataMonitor_3 = "";
            parentForm.displayTaskAndWait("Adapter Stopped.");
        }

        /// <summary>
        ///  effettua recupero dati ed invio valori modificati...
        /// </summary>
        /// <param name="ciclo"></param>
        public void gaterAndSend(gatherCycle ciclo)
        {
            // controllo connessione/connettività
            if (connectionOk)
            {
                // controllo non sia già in esecuzione...
                if (!adpCommAct)
                {
                    // provo ad avviare
                    try
                    {
                        // avvio fase raccolta dati
                        mAdapter.Begin();
                        // imposto flag adapter running..
                        adpCommAct = true;
                        adpStartRun = DateTime.Now;
                    }
                    catch (Exception exc)
                    {
                        parentForm.displayTaskAndWait(string.Format("Adapter NOT STARTED!!!{0}{1}", Environment.NewLine, exc));
                        adpCommAct = false;
                        adpStartRun = DateTime.Now;
                    }
                    if (adpCommAct)
                    {
                        // try / catch generale altrimenti segno che è disconnesso...
                        try
                        {
                            // processing degli strobes di allarme (da ULTIMA rappresentazione vettore dell'ADP)
                            processAlarm();

                            // verifico se processare tutto "in un colpo solo"
                            if (procIotMem)
                            {
                                processAllMemory();
                                // ciclo lento x log...
                                if (ciclo == gatherCycle.LF)
                                {
                                    // eventuale log!
                                    if (utils.CRB("recTime")) logTimeResults();
                                }
                            }
                            // oppure in "modalità classica" con multistep...
                            else
                            {
                                // ciclo HF: recupero update status & strobes vari
                                if (ciclo == gatherCycle.HF)
                                {
                                    // parte che eseguo SEMPRE: RECUPERO stato di tutti gli strobe/status e degli ack attualmente noti
                                    getStrobeAndAckStatus();

                                    // faccio refresh degli allarmi segnalati (da strobe su vettore locale)
                                    refreshAlarmState(STRB_DW0, true);
                                    // acquisizione degli status
                                    processStatus();
                                    // processing degli strobes 
                                    processStrobe();
                                }
                                else if (ciclo == gatherCycle.MF)
                                {
                                    // leggo parametri a media freq (dati globali, path, assi, Unità Operatrice)
                                    getGlobalData();
                                    getUnOp();
                                    getPath();
                                    getAxis();

                                    // se NON in modalità PROD eseguo chiamate "extra" x allarmi
                                    if (utils.CRS("mode") == "debug")
                                    {
                                        // SOLO in modalità testing forzo il controllo continuo allarmi...
                                        forceAlarmCheck();
                                    }
                                }
                                // ciclo lento
                                else if (ciclo == gatherCycle.LF)
                                {
                                    // leggo EVENTUALI parametri da config file
                                    getConfigParam();
                                    ///acquisisco dati su programma in esecuzione e dati generali (stato, orologio, power...)
                                    getSlowChangingData();

                                    // eventuale log!
                                    if (utils.CRB("recTime")) logTimeResults();
                                }
                                // ciclo lentissimo
                                else if (ciclo == gatherCycle.VLF)
                                {
                                    lg.Info("Richiesta lettura completa allarmi attivi");
                                    // faccio comunque rilettura completa allarmi...
                                    forceAlarmCheck();
                                }
                                // processo e svuoto eventuali code di invio per Codici M/S/T
                                trySendCodMST();
                            }

                            // INVIO dati variati!
                            mAdapter.SendChanged();
                        }
                        catch (Exception exc)
                        {
                            // segnalo eccezione e indico disconnesso...
                            lg.Error(exc, string.Format("Errore in gestione ciclo principale ADP, fermo adapter{0}{1}", Environment.NewLine, exc));
                            parentForm.fermaAdapter(true);
                        }
                        // tolgo flag running
                        adpCommAct = false;
                    }
                    else
                    {
                        lg.Info("ADP not running...");
                    }
                }
                else
                {
                    // log ADP running
                    lg.Error("Non eseguo chiamata: ADP ancora in running");
                    // se è bloccato da oltre maxSec lo sblocco...
                    if (DateTime.Now.Subtract(adpStartRun).TotalSeconds > utils.CRI("maxAdapterLockSec"))
                    {
                        // tolgo flag running
                        adpCommAct = false;
                        adpStartRun = DateTime.Now;
                    }
                }
            }
            else
            {
                // log connessione KO
                lg.Error("CicloMF - Connessione non disponibile, provo a riconnettere");
                // provo a riconnettere SE abilitato tryRestart...
                if (adpTryRestart && !connectionOk)
                {
                    lg.Info("ConnKO - tryConnect");
                    tryConnect();
                }
            }
            if (eh_refreshed != null)
            {
                eh_refreshed(this, new EventArgs());
            }
        }
        /// <summary>
        /// recupero dati globali (e comuni)
        /// </summary>
        public virtual void getGlobalData()
        {
        }

        /// <summary>
        /// riporta il log di tutti i dati di results temporali registrati
        /// </summary>
        public void logTimeResults()
        {
            if (TimingData.results.Count > 0)
            {
                lg.Info("{0}--------------- START TIMING DATA ---------------", Environment.NewLine);
                int globNumCall = 0;
                TimeSpan globAvgMsec = new TimeSpan(0);
                foreach (TimeRec item in TimingData.results)
                {
                    lg.Info("Chiamate {0}: effettuate {1}, tempo medio {2:N2} msec | impegno canale {3:P3}", item.codCall, item.numCall, item.avgMsec, item.totMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds);
                    globNumCall += item.numCall;
                    globAvgMsec += item.totMsec;
                }
                // riporto conteggio medio al secondo...
                lg.Info("Chiamate GLOBALI: {0}, periodo: {1:N2} minuti.cent, tempo medio {2:N2} msec | impegno canale {3:P3}", globNumCall, DateTime.Now.Subtract(dtAvvioAdp).TotalMinutes, globAvgMsec.TotalMilliseconds / globNumCall, globAvgMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds);
                lg.Info("{0}--------------- STOP TIMING DATA ---------------{0}", Environment.NewLine);
            }
        }

        /// <summary>
        /// verifico se ho dati M/S/T e li invio nel caso
        /// </summary>
        public virtual void trySendCodMST()
        {
            // !!!FARE!!! ciclo su + path
            int idxPath = 1;
            for (int i = 0; i < idxPath; i++)
            {
                // verifico SE ho codici M/S/T da inviare...
                string codiceM = getNextMCode;
                string codiceS = getNextSCode;
                string codiceT = getNextTCode;
                if (codiceM != "")
                {
                    vettPath[i].mPathCodM.Value = string.Format("[M{0}]", codiceM);
                }
                if (codiceS != "")
                {
                    vettPath[i].mPathCodS.Value = string.Format("[S{0}]", codiceS);
                }
                if (codiceT != "")
                {
                    vettPath[i].mPathCodT.Value = string.Format("[T{0}]", codiceT);
                }
            }
        }
        /// <summary>
        /// Metodo base connessione...
        /// </summary>
        public virtual void tryConnect()
        {

        }
        /// <summary>
        /// Metodo base disconnessione...
        /// </summary>
        public virtual void tryDisconnect()
        {

        }
        protected bool _connOk = false;
        /// <summary>
        /// Salva verifica stato connessione OK
        /// </summary>
        /// <returns></returns>
        public virtual bool connectionOk
        {
            get
            {
                return _connOk;
            }
            set
            {
                _connOk = value;
            }
        }

        /// <summary>
        /// effettua ogni log period una rilettura di TUTTI gli allarmi...
        /// </summary>
        public virtual void forceAlarmCheck()
        {
            // carico status allarmi (completo)
            StFlag32 forceAlarm = (StFlag32)unchecked((int)UInt32.MaxValue);
            try
            {
                refreshAlarmState(forceAlarm, false);
            }
            catch
            {
                lg.Error("Errore in fase di esecuzione di forceAlarmCheck");
            }
            if (utils.CRB("recTime")) logTimeResults();
        }
        /// <summary>
        /// recupero dati PATH
        /// </summary>
        public virtual void getPath()
        {
            // SE presente recupero dati path
            checkPath();

            // dati BASE, ciclando su path
            for (int i = 0; i < currAdpConf.nPath; i++)
            {
                vettPath[i].mPathFeed.Value = FeedRate;
                vettPath[i].mPathFeedOver.Value = FeedRateOver;
                vettPath[i].mPathRapidOver.Value = RapidOver;
            }
        }
        /// <summary>
        /// Recupero dati Unità Operatrici / Mandrini
        /// </summary>
        public virtual void getUnOp()
        {
            // cicl su UnOp
            for (int i = 0; i < currAdpConf.nUnOp; i++)
            {
                vettUnOp[i].mUnOpSpeed.Value = SpeedRate;
                vettUnOp[i].mUnOpSpeedOverr.Value = SpeedRateOver;
                vettUnOp[i].mUnOpLoad.Value = UnOpLoad;
            }
        }
        /// <summary>
        /// recupero dati ASSI
        /// </summary>
        public virtual void getAxis()
        {

        }


        /// <summary>
        /// verifica gli status attivi
        /// </summary>
        public virtual void processStatus()
        {
            // da gestire su ogni adapter...
        }
        /// <summary>
        /// processo tutti gli strobe attivi
        /// </summary>
        public virtual void processStrobe()
        {
            // da gestire su ogni adapter...
        }
        /// <summary>
        /// processo il vettore LOCALE degli allarmi
        /// </summary>
        public virtual void processAlarm()
        {
            if (AlarmFlags != null)
            {
                // variabili helper
                StFlag32 AlarmBlock = 0;
                allarme currAllarm;
                // controllo TUTTI i bit della variabile COMPLETA degli status allarmi: se ce ne sono di alzati DEVO processare...
                for (int i = 0; i < AlarmFlags.Length / 4; i++)
                {
                    // leggo 32bit alla volta...
                    AlarmBlock = (StFlag32)BitConverter.ToUInt32(AlarmFlags, i * 4);

                    for (int j = 0; j < 32; j++)
                    {
                        // converto! e aggiungo allarmi sollevati al corretto controller allarmi...
                        if (AlarmBlock.HasFlag((StFlag32)Math.Pow(2, j)))
                        {
                            // recupero allarme da oggetto in memoria...
                            currAllarm = elencoAllarmi[i * 32 + j];
                            // in base al tipo di allarme decodifico condizione...
                            Condition.Level livello = Condition.Level.NORMAL;
                            switch (currAllarm.livello)
                            {
                                case "WARNING":
                                    livello = Condition.Level.WARNING;
                                    break;
                                case "FAULT":
                                default:
                                    livello = Condition.Level.FAULT;
                                    break;
                            }
                            // in base al gruppo decido dove assegnare come CONDITION...
                            switch (currAllarm.gruppo)
                            {
                                case "PLC":
                                    mAlarmPLC.Add(livello, currAllarm.descrizione, currAllarm.codNum, "", "");
                                    break;
                                case "CNC":
                                default:
                                    mAlarmCNC.Add(livello, currAllarm.descrizione, currAllarm.codNum, "", "");
                                    break;
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Classe fittizia in caso di processing GLOBALE di tutto in 1 solo colpo...
        /// </summary>
        public virtual void processAllMemory()
        { }
        /// <summary>
        /// metodo di recupero dei dati di identificativo macchina - DA CONF!!!
        /// </summary>
        public virtual void getConfigParam()
        {

        }
        /// <summary>
        /// dati "lenti" relativi al device
        /// </summary>
        public virtual void getSlowChangingData()
        {
            // dati da PC
            mClock.Value = string.Format("{0:yyyy-MM-dd} {0:HH:mm:ss}", DateTime.Now);
            // da gestire su ogni adapter...
        }
        /// <summary>
        /// recupero di TUTTI gli strobes/status attivi
        /// </summary>
        public virtual void getStrobeAndAckStatus()
        {
            // da gestire su ogni adapter... legge tutto array STROBE!!!
        }
        /// <summary>
        /// Processa la tabella di memoria dei dati di manutenzione
        /// </summary>
        /// <param name="tabDatiMtz"></param>
        /// <param name="maintData"></param>
        public void processMaintData(uint[] tabDatiMtz, otherData[] maintData)
        {
            // uno ad uno vado a inserirli nella mappa dei dati dell'adapter...
            int numero = 0;
            uint valRead = 0;
            for (int i = 0; i < maintData.Length; i++)
            {
                numero = 0;
                valRead = 0;
                // decodifico...
                if (maintData[i].varName == "ACC_TIME")
                {
                    istOreMaccOn = tabDatiMtz[i];
                }
                else if (maintData[i].varName == "ACC_TIME_WORK")
                {
                    istOreMaccLav = tabDatiMtz[i];
                }
                else if (maintData[i].varName == "SlittaTastatore_Count")
                {
                    istSlittaTast = tabDatiMtz[i];
                }
                else if (maintData[i].varName.StartsWith("Path_"))
                {
                    if (maintData[i].varName.EndsWith("_PZ_TOT"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("Path_", "").Replace("_PZ_TOT", ""));
                        }
                        catch
                        {
                        }
                        if (numero > 0)
                        {
                            vettPath[numero - 1].mPathPartCount.Value = tabDatiMtz[i];
                        }
                    }
                }
                else if (maintData[i].varName.StartsWith("Axis_"))
                {
                    if (maintData[i].varName.EndsWith("_DistDone"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("Axis_", "").Replace("_DistDone", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            istDistMovAssi[numero - 1] = tabDatiMtz[i];
                        }
                    }
                    else if (maintData[i].varName.EndsWith("_Invers"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("Axis_", "").Replace("_Invers", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            // 2016.07.06 debug di valori che potrebbero essere nulli...
                            try
                            {
                                valRead = tabDatiMtz[i];
                            }
                            catch (Exception exc)
                            {
                                valRead = 0;
                                lg.Error(string.Format("Errore in recupero num inversioni:{0}parametro: {1}{0}i: {2}{0}Exc: {3}", Environment.NewLine, maintData[i].varName, i, exc));
                            }
                            istNumInvAssi[numero - 1] = valRead;
                        }
                    }
                    else if (maintData[i].varName.EndsWith("_AccTime"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("Axis_", "").Replace("_AccTime", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            // 2016.07.06 debug di valori che potrebbero essere nulli...
                            try
                            {
                                valRead = tabDatiMtz[i];
                            }
                            catch (Exception exc)
                            {
                                valRead = 0;
                                lg.Error(string.Format("Errore in recupero num inversioni:{0}parametro: {1}{0}i: {2}{0}Exc: {3}", Environment.NewLine, maintData[i].varName, i, exc));
                            }
                            istAccTimeAssi[numero - 1] = valRead;
                        }
                    }
                }
                else if (maintData[i].varName.StartsWith("UnOp_"))
                {
                    if (maintData[i].varName.EndsWith("_AccTime"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("UnOp_", "").Replace("_AccTime", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            istGiriElettrom[numero - 1] = tabDatiMtz[i];
                        }
                    }
                    else if (maintData[i].varName.EndsWith("_NumCambiUT"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("UnOp_", "").Replace("_NumCambiUT", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            istNumCambiUt[numero - 1] = tabDatiMtz[i];
                        }
                    }
                }
                else if (maintData[i].varName.StartsWith("VacPump_"))
                {
                    if (maintData[i].varName.EndsWith("_WrkTime"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("VacPump_", "").Replace("_WrkTime", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            istVacPumpWrkTime[numero - 1] = tabDatiMtz[i];
                        }
                    }
                }
                else if (maintData[i].varName.StartsWith("VacAct_"))
                {
                    if (maintData[i].varName.EndsWith("_Count"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("VacAct_", "").Replace("_Count", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            istVacActCount[numero - 1] = tabDatiMtz[i];
                        }
                    }
                }
                else if (maintData[i].varName.StartsWith("Lubro_"))
                {
                    if (maintData[i].varName.EndsWith("_Num"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("Lubro_", "").Replace("_Num", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            istLubroCount[numero - 1] = tabDatiMtz[i];
                        }
                    }
                }
                else if (maintData[i].varName.StartsWith("SlittaMagazzino_"))
                {
                    if (maintData[i].varName.EndsWith("_Count"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("SlittaMagazzino_", "").Replace("_Count", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            istSlittaMag[numero - 1] = tabDatiMtz[i];
                        }
                    }
                }
                else if (maintData[i].varName.StartsWith("ProtMagazzino_"))
                {
                    if (maintData[i].varName.EndsWith("_Count"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(maintData[i].varName.Replace("ProtMagazzino_", "").Replace("_Count", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            istProtMag[numero - 1] = tabDatiMtz[i];
                        }
                    }
                }
            }
        }
        /// <summary>
        /// processa dataLayer e se necessario salva/mostra
        /// </summary>
        public void checkSavePersDataLayer()
        {
            if (persistenceLayer != null)
            {
                bool needSave = false;
                // verifica se si debba aggiornare XML (e salva in adapter dati vari)
                needSave = procOreMaccOn(needSave);
                needSave = procOreMaccLav(needSave);
                needSave = procProgrName(needSave);
                needSave = procPartId(needSave);
                needSave = procPzProd(needSave);
                needSave = procGiriTotUnOp(needSave);
                needSave = procNumCU(needSave);
                needSave = procMovTotAssi(needSave);
                needSave = procAccTimeAssi(needSave);
                needSave = procNumInvAssi(needSave);
                needSave = procVacPump(needSave);
                needSave = procVacAct(needSave);
                needSave = procLubro(needSave);
                needSave = procSlittaMag(needSave);
                needSave = procProtMag(needSave);

                // salvo se necessario!
                if (needSave) parentForm.persistData();
                // ------------------------------------------- 
            }
        }
        /// <summary>
        /// Processa la tabella di memoria degli status di manutenzione
        /// </summary>
        /// <param name="tabDatiStatus"></param>
        /// <param name="statusData"></param>
        public void processStatusData(byte[] tabDatiStatus, otherData[] statusData)
        {
            int bitNum = 0;
            int byteNum = 0;
            byte byteVal;
            // uno ad uno vado a inserirli nella mappa dei dati dell'adapter...
            int numero = 0;
            string status = "";
            for (int i = 0; i < statusData.Length; i++)
            {
                numero = 0;
                status = "";

                // calcolo quale byte e quale bit devo leggere..
                byteNum = i / 8;
                bitNum = i - (8 * byteNum); // indice zero dei bit nel byte ( da cui -1 )
                // faccio vera lettura        
                byteVal = tabDatiStatus[byteNum];
                // leggo bit come ACTIVE/INACTIVE
                if (((StFlag8)byteVal).HasFlag((StFlag8)Math.Pow(2, bitNum)))
                {
                    status = "ACTIVE";
                }
                else
                {
                    status = "INACTIVE";
                }

                if (statusData[i].varName == "PROTECTION_STATUS")
                {
                    mProtectionStatus.Value = status;
                }
                else if (statusData[i].varName.StartsWith("VacPump_"))
                {
                    if (statusData[i].varName.EndsWith("_Status"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(statusData[i].varName.Replace("VacPump_", "").Replace("_Status", ""));
                        }
                        catch
                        {
                        }
                        if (numero > 0)
                        {
                            vettVacPump[numero - 1].mVacPumpStatus.Value = status;
                        }
                    }
                }
                else if (statusData[i].varName.StartsWith("Cooler_"))
                {
                    if (statusData[i].varName.EndsWith("_Status"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(statusData[i].varName.Replace("Cooler_", "").Replace("_Status", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            vettCooler[numero - 1].mCoolStatus.Value = status;
                        }
                    }
                }
                else if (statusData[i].varName.StartsWith("UnOp_"))
                {
                    if (statusData[i].varName.EndsWith("_Status"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(statusData[i].varName.Replace("UnOp_", "").Replace("_Status", ""));
                        }
                        catch
                        { }
                        if (numero > 0)
                        {
                            vettUnOp[numero - 1].mUnOpStatus.Value = status;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// procedura di lettura (multistep) dati da memoria x caricare dati utensile
        /// </summary>
        /// <param name="maxNumOp">num max di teste da recuperare</param>
        public virtual void getDatiUt(int maxNumOp)
        {
            // variabili "Indice" utensile e famiglia da decodificare + utils
            int maxMemAddr = 200;
            byte[] elencoUtMem = new byte[2 * maxNumOp];
            byte[] tabUt_UT = new byte[2 * maxMemAddr];
            byte[] tabFam_FamUt = new byte[2 * maxMemAddr];

            // altre variabili
            int[] idUtMontato = new int[maxNumOp];
            int[] idFamUt = new int[maxNumOp];
            int[] idTipoVitaUt = new int[maxNumOp];
            int[] valVitaUtRes = new int[maxNumOp];
            int[] tabUt = new int[maxMemAddr];
            int[] tabFamUt = new int[maxMemAddr];
            int memIndex = 0;
            byte[] int32Mem = new byte[4];
            byte[] int16Mem = new byte[2];
            byte int8Mem = new byte();

            // step 1: lettura ID dell'utensile x ogni testa... leggo area memoria degli UT montati
            memIndex = getDatiUt_step1(ref elencoUtMem);
            // decodifica da byte a int16 dell'ID Utensile
            for (int i = 0; i < maxNumOp; i++)
            {
                idUtMontato[i] = BitConverter.ToUInt16(elencoUtMem, 2 * i);
            }

            // step 2a: leggo vettore memoria dei maxMemAddr(200) UT in Tabella Utensili
            memIndex = getDatiUt_step2a(ref tabUt_UT);
            // decodifico TUTTI i maxMemAddr utensili
            for (int i = 0; i < maxMemAddr; i++)
            {
                tabUt[i] = BitConverter.ToUInt16(tabUt_UT, 2 * i);
            }
            // step 2b: devo cercare l'UT di ogni UnOp nella Tabella Utensili
            for (int i = 0; i < maxNumOp; i++)
            {
                // spazzo la tab Utensili x cercare quelli delle UnOp...
                for (int j = 0; j < maxMemAddr; j++)
                {
                    // controllo, se l'id utensile è quello dell'attuale UnOp...
                    if (tabUt[j] == idUtMontato[i])
                    {
                        // leggo FamUt puntuale..
                        memIndex = getDatiUt_step2b(ref int16Mem, j);
                        // step 2b: leggo puntualmente la FamUt dal suo indice...
                        idFamUt[i] = BitConverter.ToUInt16(int16Mem, 0);
                    }
                }
            }


            // step 3a: leggo vettore memoria dei maxMemAddr(200) FamUT in Tabella Famiglie Utensili (x ricavare unità misura vita)
            memIndex = getDatiUt_step3a(ref tabFam_FamUt);
            // decodifico TUTTI i maxMemAddr utensili
            for (int i = 0; i < maxMemAddr; i++)
            {
                tabFamUt[i] = BitConverter.ToUInt16(tabFam_FamUt, 2 * i);
            }
            // step 3b: devo cercare la famiglia dell'UT di ogni UnOp nella Tabella Famiglie
            for (int i = 0; i < maxNumOp; i++)
            {
                // poiché potrei trovarlo replicato dopo la prima volta che lo trovo evito di ricontrollare...
                bool found = false;
                // spazzo la tab Utensili x cercare quelli delle UnOp...
                for (int j = 0; j < maxMemAddr; j++)
                {
                    // controllo, se l'id utensile è quello dell'attuale UnOp...
                    if (tabFamUt[j] == idFamUt[i] && !found)
                    {
                        // leggo FamUt puntuale..
                        memIndex = getDatiUt_step3b(ref int8Mem, j);
                        // step 3b: leggo puntualmente il TIPO DI vita UT dal suo indice...
                        idTipoVitaUt[i] = int8Mem;
                        found = true;
                    }
                }
            }

            // step 4: recupero la vita residua dell'utente
            for (int i = 0; i < maxNumOp; i++)
            {
                // spazzo la tab Utensili x cercare quelli delle UnOp...
                for (int j = 0; j < maxMemAddr; j++)
                {
                    // controllo, se l'id utensile è quello dell'attuale UnOp...
                    if (tabUt[j] == idUtMontato[i])
                    {
                        // leggo FamUt puntuale..
                        memIndex = getDatiUt_step4(ref int32Mem, j);
                        // leggo puntualmente valore della vita ut residua da indice utensile...
                        valVitaUtRes[i] = BitConverter.ToInt32(int32Mem, 0);
                    }
                }
            }

            // salvo in adapter vita UT residua...
            for (int i = 0; i < maxNumOp; i++)
            {
                vettUnOp[i].mUnOpToolId.Value = idUtMontato[i];
                vettUnOp[i].mUnOpVitaRes.Value = valVitaUtRes[i];
                // decodifico valore tipo VitaRes...
                string tipoVitaRes = "ND";
                switch (idTipoVitaUt[i])
                {
                    case 1:
                        tipoVitaRes = "Time";
                        break;
                    case 2:
                        tipoVitaRes = "Stroke";
                        break;
                    case 3:
                        tipoVitaRes = "Distance";
                        break;
                    default: break;
                }
                vettUnOp[i].mUnOpVitaResType.Value = tipoVitaRes;
            }
        }
        /// <summary>
        /// Procedura di processing lettura memoria x DatiUt - Step 4
        /// </summary>
        /// <param name="int32Mem"></param>
        /// <param name="j"></param>
        /// <returns></returns>
        public virtual int getDatiUt_step4(ref byte[] int32Mem, int j)
        {
            int memIndex = 13100 + 4 * j;
            //inizio = DateTime.Now;
            //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref int32Mem);
            //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-VitaRes", int32Mem.Length), DateTime.Now.Subtract(inizio).Ticks);
            return memIndex;
        }
        /// <summary>
        /// Procedura di processing lettura memoria x DatiUt - Step 3b
        /// </summary>
        /// <param name="int8Mem"></param>
        /// <param name="j"></param>
        /// <returns></returns>
        public virtual int getDatiUt_step3b(ref byte int8Mem, int j)
        {
            int memIndex = 10700 + 1 * j;
            //inizio = DateTime.Now;
            //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref int8Mem);
            //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-FamUT", 8), DateTime.Now.Subtract(inizio).Ticks);
            return memIndex;
        }
        /// <summary>
        /// Procedura di processing lettura memoria x DatiUt - Step 3a
        /// </summary>
        /// <param name="tabFam_FamUt"></param>
        /// <returns></returns>
        public virtual int getDatiUt_step3a(ref byte[] tabFam_FamUt)
        {
            int memIndex = 8900;
            //inizio = DateTime.Now;
            //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref tabFam_FamUt);
            //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabFamUT-FamUT", tabFam_FamUt.Length), DateTime.Now.Subtract(inizio).Ticks);
            return memIndex;
        }
        /// <summary>
        /// Procedura di processing lettura memoria x DatiUt - Step 2b
        /// </summary>
        /// <param name="int16Mem"></param>
        /// <param name="j"></param>
        /// <returns></returns>
        public virtual int getDatiUt_step2b(ref byte[] int16Mem, int j)
        {
            int memIndex = 11700 + 2 * j;
            //inizio = DateTime.Now;
            //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref int16Mem);
            //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-FamUT", int16Mem.Length), DateTime.Now.Subtract(inizio).Ticks);
            return memIndex;
        }
        /// <summary>
        /// Procedura di processing lettura memoria x DatiUt - Step 2a
        /// </summary>
        /// <param name="tabUt_UT"></param>
        /// <returns></returns>
        public virtual int getDatiUt_step2a(ref byte[] tabUt_UT)
        {
            int memIndex = 11300;
            //inizio = DateTime.Now;
            //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref tabUt_UT);
            //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-UT", tabUt_UT.Length), DateTime.Now.Subtract(inizio).Ticks);
            return memIndex;
        }
        /// <summary>
        /// Procedura di processing lettura memoria x DatiUt - Step 1
        /// </summary>
        /// <param name="elencoUtMem"></param>
        /// <returns></returns>
        public virtual int getDatiUt_step1(ref byte[] elencoUtMem)
        {
            int memIndex = 2960;
            //inizio = DateTime.Now;
            //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref elencoUtMem);
            //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-NUMUT", elencoUtMem.Length), DateTime.Now.Subtract(inizio).Ticks);
            return memIndex;
        }

        #endregion

        #region area metodi comunicazione con PLC/CNC

        public void checkPath()
        {
        }

        /// <summary>
        /// FeedRate globale
        /// </summary>
        public int FeedRate { get; set; }
        /// <summary>
        /// FeedRate di gruppo MAX 20!!!
        /// </summary>
        public int[] FeedRateGrp { get; set; }
        /// <summary>
        /// SpeedRate mandrino globale
        /// </summary>
        public int SpeedRate { get; set; }

        /// <summary>
        /// OVERRIDE FeedRate globale
        /// </summary>
        public int FeedRateOver { get; set; }
        /// <summary>
        /// OVERRIDE dei rapidi
        /// </summary>
        public int RapidOver { get; set; }
        /// <summary>
        /// OVERRIDE SpeedRate mandrino globale
        /// </summary>
        public int SpeedRateOver { get; set; }
        /// <summary>
        /// LOAD mandrino globale
        /// </summary>
        public int UnOpLoad { get; set; }


        /// <summary>
        /// recupera Vettore completo PosAct (fare override!)
        /// </summary>
        public virtual position PosAct
        {
            get
            {
                position answ = new position();
                return answ;
            }
        }

        /// <summary>
        ///  recupera pezzi OK (fare override!)
        /// </summary>
        public virtual int getNumPzOk
        {
            get
            {
                int answ = 0;
                return answ;
            }
        }
        /// <summary>
        /// recupera pezzi KO (fare override!)
        /// </summary>
        public virtual int getNumPzKo
        {
            get
            {
                int answ = 0;
                return answ;
            }
        }

        /// <summary>
        /// Aggiunge nel vettore coda codici M
        /// </summary>
        /// <param name="Coda"></param>
        /// <param name="Codice da accodare"></param>
        public void appendCodeMST(string Coda, string Codice)
        {
            switch (Coda)
            {
                case "S":
                    codaS.Add(Codice);
                    break;
                case "T":
                    codaT.Add(Codice);
                    break;
                case "M":
                default:
                    codaM.Add(Codice);
                    break;
            }
        }

        /// <summary>
        /// recupera primo elemento codaM
        /// </summary>
        protected string getNextMCode
        {
            get
            {
                string answ = "";
                if (codaM.Count > 0)
                {
                    // recupero codice M...
                    answ = codaM.First();
                    // tolgo elemento
                    codaM.RemoveAt(0);
                }
                return answ;
            }
        }
        /// <summary>
        /// recupera primo elemento codaS
        /// </summary>
        protected string getNextSCode
        {
            get
            {
                string answ = "";
                if (codaS.Count > 0)
                {
                    // recupero codice S...
                    answ = codaS.First();
                    // tolgo elemento
                    codaS.RemoveAt(0);
                }
                return answ;
            }
        }
        /// <summary>
        /// recupera primo elemento codaT
        /// </summary>
        protected string getNextTCode
        {
            get
            {
                string answ = "";
                if (codaT.Count > 0)
                {
                    // recupero codice T...
                    answ = codaT.First();
                    // tolgo elemento
                    codaT.RemoveAt(0);
                }
                return answ;
            }
        }

        #endregion

        #region metodi che prevedono salvataggio valori su file XML/BIN

        /// <summary>
        /// Processing delle ore macchina ACCESA
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procOreMaccOn(bool needSave)
        {
            double delta = istOreMaccOn - contOreMaccOn;
            // processo comunque sempre...
            double contatore = updateValDoubleByIncr(0, delta, "ACC_TIME");
            currAdpConf.ContOreMaccOn += delta;
            // salvo valore su persistent layer
            mAccTime.Value = contatore.ToString("0.000", CultureInfo.InvariantCulture);
            // controllo incremento...
            if (delta > 0)
            {
                // segnalo necessità salvataggio!
                needSave = true;
            }
            // salvo su maschera...
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(string.Format("ACC_TIME: {0}", mAccTime.Value));
            parentForm.dataMonitor_1 += sb.ToString();

            // ...aggiorno valore riferimento...
            contOreMaccOn = istOreMaccOn;
            return needSave;
        }
        /// <summary>
        /// Processing delle ore macchina IN LAVORO
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procOreMaccLav(bool needSave)
        {
            double delta = istOreMaccLav - contOreMaccLav;
            double contatore = updateValDoubleByIncr(0, delta, "ACC_TIME_WORK");
            currAdpConf.ContOreMaccLav += delta;
            // salvo valore su persistent layer
            mAccTimeWork.Value = contatore.ToString("0.000", CultureInfo.InvariantCulture);
            // controllo valore riferimento...
            if (delta > 0)
            {
                // segnalo necessità salvataggio!
                needSave = true;
            }
            // salvo su maschera...
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(string.Format("ACC_TIME_WORK: {0}", mAccTimeWork.Value));
            parentForm.dataMonitor_1 += sb.ToString();

            // ...aggiorno valore riferimento...
            contOreMaccLav = istOreMaccLav;
            return needSave;
        }
        /// <summary>
        /// Processing contatore Slitta Tastatore
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procSlittaTast(bool needSave)
        {
            double delta = istSlittaTast - contSlittaTast;
            double contatore = updateValDoubleByIncr(0, delta, "SlittaTastatore_Count");
            currAdpConf.ContSlittaTast += delta;
            // salvo valore su persistent layer
            mSlittaTast.Value = contatore.ToString("0", CultureInfo.InvariantCulture);
            // controllo valore riferimento...
            if (delta > 0)
            {
                // segnalo necessità salvataggio!
                needSave = true;
            }
            // salvo su maschera...
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(string.Format("SlittaTastatore_Count: {0}", mSlittaTast.Value));
            parentForm.dataMonitor_1 += sb.ToString();

            // ...aggiorno valore riferimento...
            contSlittaTast = istSlittaTast;
            return needSave;
        }
        /// <summary>
        /// Processing del program name
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procProgrName(bool needSave)
        {
            // controllo valore riferimento x tutti i path se sia cambiato programma... 
            for (int i = 0; i < currAdpConf.nPath; i++)
            {
                if (istPathProgrName[i] != null)
                {
                    if (istPathProgrName[i] != currPathProgrName[i])
                    {
                        // prendo nuovo valore programma x path!
                        vettPath[i].mPathCurrProg.Value = istPathProgrName[i];
                        // segnalo necessità salvataggio!
                        needSave = true;
                        // ...aggiorno valore riferimento...
                        currPathProgrName[i] = istPathProgrName[i];
                    }
                }
            }
            return needSave;
        }
        /// <summary>
        /// Processing del particolare
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procPartId(bool needSave)
        {
            // controllo valore riferimento x tutti i path se sia cambiato num pz... 
            for (int i = 0; i < currAdpConf.nPath; i++)
            {
                if (istPathPartId[i] != null)
                {
                    if (istPathPartId[i] != currPathPartId[i])
                    {
                        // aggiorno valore in Path RefList
                        updateValString(i, istPathPartId[i], "Path_{0:00}_PartId");

                        // prendo nuovo valore programma x path!
                        vettPath[i].mPathPartId.Value = istPathPartId[i];
                        // imposto a ZERO i pezzi del nuovo articolo
                        vettPath[i].mPathPartCount.Value = 0;
                        // segnalo necessità salvataggio!
                        needSave = true;
                        // ...aggiorno valore riferimento...
                        currPathPartId[i] = istPathPartId[i];
                    }
                }
            }
            return needSave;
        }
        /// <summary>
        /// Processing del num pz prodotti
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procPzProd(bool needSave)
        {
            string outString = string.Format("Path_[1-{0}]_PZ_TOT: ", currAdpConf.nPath);
            // controllo valore riferimento x tutti i path se sia cambiato qta pezzi...
            for (int i = 0; i < currAdpConf.nPath; i++)
            {
                // controllo valore riferimento variato...
                if (istPathPartCount[i] != currPathPartCount[i])
                {
                    if (istPathPartCount[i] > currPathPartCount[i])
                    {
                        uint delta = istPathPartCount[i] - currPathPartCount[i];
                        //uint contatore = updatePathRefListByIncr(i, delta, "Path_{0:00}_PZ_TOT");
                        uint contatore = updateValUIntByIncr(i, delta, "Path_{0:00}_PZ_TOT");
                        // passo valore num pz all'adapter
                        vettPath[i].mPathPartCount.Value = contatore;
                    }
                    else // variato x difetto... azzero!!!
                    {
                        uint newVal = istPathPartCount[i];
                        updateValUInt(i, newVal, "Path_{0:00}_PZ_TOT");
                        // passo valore num pz all'adapter
                        vettPath[i].mPathPartCount.Value = newVal;
                    }

                    // segnalo necessità salvataggio!
                    needSave = true;
                    // ...aggiorno valore riferimento...
                    currPathPartCount[i] = istPathPartCount[i];
                }
                outString += string.Format("{0} | ", vettPath[i].mPathPartCount.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }
        /// <summary>
        /// Processing delle variabili sul numero giri mandrino (totali)
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procGiriTotUnOp(bool needSave)
        {
            uint delta = 0;
            string outString = string.Format("UnOp_[1-{0}]_KRev: ", currAdpConf.nUnOp);
            for (int i = 0; i < currAdpConf.nUnOp; i++)
            {
                delta = istGiriElettrom[i] - contGiriElettrom[i];
                // processo comunque sempre...
                uint contatore = updateValUIntByIncr(i, delta, "UnOp_{0:00}_AccTime");
                // passo valore num giri (migliaia) all'adapter
                vettUnOp[i].mUnOpAccTime.Value = contatore;
                // controllo valore riferimento...
                if (delta > 0)
                {
                    // segnalo necessità salvataggio!
                    needSave = true;
                }
                // ...aggiorno valore riferimento...
                contGiriElettrom[i] = istGiriElettrom[i];
                outString += string.Format("{0} | ", vettUnOp[i].mUnOpAccTime.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }
        /// <summary>
        /// Processing delle variabili sul numero cambi utensile (totali)
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procNumCU(bool needSave)
        {
            uint delta = 0;
            string outString = string.Format("UnOp_[1-{0}]_NumCU: ", currAdpConf.nUnOp);
            for (int i = 0; i < currAdpConf.nUnOp; i++)
            {
                delta = istNumCambiUt[i] - currNumCambiUt[i];
                // processo comunque sempre...
                uint contatore = updateValUIntByIncr(i, delta, "UnOp_{0:00}_NumCU");
                // passo valore num CU all'adapter
                vettUnOp[i].mUnOpNumCU.Value = contatore;
                // controllo valore riferimento...
                if (delta > 0)
                {
                    // segnalo necessità salvataggio!
                    needSave = true;
                }
                // ...aggiorno valore riferimento...
                currNumCambiUt[i] = istNumCambiUt[i];
                outString += string.Format("{0} | ", vettUnOp[i].mUnOpNumCU.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }
        /// <summary>
        /// Processing delle variabili sul totale m percorsi dagli assi
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procMovTotAssi(bool needSave)
        {
            double delta = 0;
            string outString = string.Format("Axis_[1-{0}]_DistDone: ", currAdpConf.nAxis);
            for (int i = 0; i < currAdpConf.nAxis; i++)
            {
                delta = istDistMovAssi[i] - contDistMovAssi[i];
                // processo comunque sempre...
                double contTot = updateValDoubleByIncr(i, delta, "Axis_{0:00}_DistDone");
                // passo valore totale all'adapter
                vettAxis[i].mAxDistDone.Value = contTot.ToString("0.000", CultureInfo.InvariantCulture);
                // controllo valore riferimento...
                if (delta > 0)
                {
                    // segnalo necessità salvataggio!
                    needSave = true;
                }
                // ...aggiorno valore riferimento...
                contDistMovAssi[i] = istDistMovAssi[i];
                outString += string.Format("{0} | ", vettAxis[i].mAxDistDone.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_3 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }
        /// <summary>
        /// Processing delle variabili sul totale tempo lavoro degli assi
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procAccTimeAssi(bool needSave)
        {
            double delta = 0;
            string outString = string.Format("Axis_[1-{0}]_AccTime: ", currAdpConf.nAxis);
            for (int i = 0; i < currAdpConf.nAxis; i++)
            {
                delta = istAccTimeAssi[i] - contAccTimeAssi[i];
                // salvo valore aggiuntivo x ore lavoro assi...
                double oreTot = updateValDoubleByIncr(i, delta, "Axis_{0:00}_AccTime");
                vettAxis[i].mAxAccTime.Value = oreTot.ToString("0.000", CultureInfo.InvariantCulture);
                // controllo valore riferimento...
                if (delta > 0)
                {
                    // segnalo necessità salvataggio!
                    needSave = true;
                }
                // ...aggiorno valore riferimento...
                contAccTimeAssi[i] = istAccTimeAssi[i];
                outString += string.Format("{0} | ", vettAxis[i].mAxAccTime.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_3 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }
        /// <summary>
        /// Processing delle variabili sul totale num inversioni degli assi
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procNumInvAssi(bool needSave)
        {
            long delta = 0;
            string outString = string.Format("Axis_[1-{0}]_InvDDone: ", currAdpConf.nAxis);
            for (int i = 0; i < currAdpConf.nAxis; i++)
            {
                delta = istNumInvAssi[i] - contNumInvAssi[i];
                // processo comunque sempre...
                long contTot = updateValLongByIncr(i, delta, "Axis_{0:00}_InvDDone");
                // passo valore totale all'adapter
                vettAxis[i].mAxInvDDone.Value = contTot;
                // controllo valore riferimento...
                if (delta > 0)
                {
                    // segnalo necessità salvataggio!
                    needSave = true;
                }
                // ...aggiorno valore riferimento...
                contNumInvAssi[i] = istNumInvAssi[i];
                outString += string.Format("{0} | ", vettAxis[i].mAxInvDDone.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_3 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }
        /// <summary>
        /// Processing delle variabili sulle VacPump
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procVacPump(bool needSave)
        {
            uint delta = 0;
            string outString = string.Format("VacPump_[1-{0}]_WrkTime: ", currAdpConf.nVacuumPump);
            for (int i = 0; i < currAdpConf.nVacuumPump; i++)
            {
                delta = istVacPumpWrkTime[i] - currVacPumpWrkTime[i];
                // processo comunque sempre...
                uint contTot = updateValUIntByIncr(i, delta, "VacPump_{0:00}_WrkTime");
                // passo valore totale all'adapter
                vettVacPump[i].mVacPumpWrkTime.Value = contTot;
                // controllo valore riferimento...
                if (delta > 0)
                {
                    // segnalo necessità salvataggio!
                    needSave = true;
                }
                // ...aggiorno valore riferimento...
                currVacPumpWrkTime[i] = istVacPumpWrkTime[i];
                outString += string.Format("{0} | ", vettVacPump[i].mVacPumpWrkTime.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }
        /// <summary>
        /// Processing delle variabili sulle VacAct
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procVacAct(bool needSave)
        {
            uint delta = 0;
            string outString = string.Format("VacPump_[1-{0}]_Count: ", currAdpConf.nVacuumPump);
            for (int i = 0; i < currAdpConf.nVacuumAct; i++)
            {
                delta = istVacActCount[i] - currVacActCount[i];
                // processo comunque sempre...
                uint contTot = updateValUIntByIncr(i, delta, "VacAct_{0:00}_Count");
                // passo valore totale all'adapter
                vettVacAct[i].mVacActCount.Value = contTot;
                // controllo valore riferimento...
                if (delta > 0)
                {
                    // segnalo necessità salvataggio!
                    needSave = true;
                }
                // ...aggiorno valore riferimento...
                currVacActCount[i] = istVacActCount[i];
                outString += string.Format("{0} | ", vettVacAct[i].mVacActCount.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }
        /// <summary>
        /// Processing delle variabili sui componenti Lubro
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procLubro(bool needSave)
        {
            uint delta = 0;
            string outString = string.Format("Lubro_[1-{0}]_Count: ", currAdpConf.nLubro);
            for (int i = 0; i < currAdpConf.nLubro; i++)
            {
                delta = istLubroCount[i] - currLubroCount[i];
                //processo comunque sempre... 
                uint contTot = updateValUIntByIncr(i, delta, "Lubro_{0:00}_Count");
                // passo valore totale all'adapter
                vettLubro[i].mLubroNum.Value = contTot;
                // controllo valore riferimento...
                if (delta > 0)
                {
                    // segnalo necessità salvataggio!
                    needSave = true;
                }
                // ...aggiorno valore riferimento...
                currLubroCount[i] = istLubroCount[i];
                outString += string.Format("{0} | ", vettLubro[i].mLubroNum.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }
        /// <summary>
        /// Processing delle variabili sui componenti SlittaMag
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procSlittaMag(bool needSave)
        {
            uint delta = 0;
            string outString = string.Format("SlittaMagazzino_[1-{0}]_Count: ", currAdpConf.nSlittaMag);
            for (int i = 0; i < currAdpConf.nSlittaMag; i++)
            {
                delta = istSlittaMag[i] - currSlittaMag[i];
                //processo comunque sempre... 
                uint contTot = updateValUIntByIncr(i, delta, "SlittaMagazzino_{0:00}_Count");
                // passo valore totale all'adapter
                vettSlittaMag[i].mSlittaMagCount.Value = contTot;
                // controllo valore riferimento...
                if (delta > 0)
                {
                    // segnalo necessità salvataggio!
                    needSave = true;
                }
                // ...aggiorno valore riferimento...
                currSlittaMag[i] = istSlittaMag[i];
                outString += string.Format("{0} | ", vettSlittaMag[i].mSlittaMagCount.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }
        /// <summary>
        /// Processing delle variabili sui componenti ProtMag
        /// </summary>
        /// <param name="needSave"></param>
        /// <returns></returns>
        public bool procProtMag(bool needSave)
        {
            uint delta = 0;
            string outString = string.Format("ProtMagazzino_[1-{0}]_Count: ", currAdpConf.nProtMag);
            for (int i = 0; i < currAdpConf.nProtMag; i++)
            {
                delta = istProtMag[i] - currProtMag[i];
                //processo comunque sempre... 
                uint contTot = updateValUIntByIncr(i, delta, "ProtMagazzino_{0:00}_Count");
                // passo valore totale all'adapter
                vettProtMag[i].mProtMagCount.Value = contTot;
                // controllo valore riferimento...
                if (delta > 0)
                {
                    // segnalo necessità salvataggio!
                    needSave = true;
                }
                // ...aggiorno valore riferimento...
                currProtMag[i] = istProtMag[i];
                outString += string.Format("{0} | ", vettProtMag[i].mProtMagCount.Value);
            }
            // salvo su maschera...
            parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine);
            return needSave;
        }

        #endregion

        #region layer persistenza dati

        /// <summary>
        /// Dizionario di persistenza per i valori da salvare da/su file
        /// </summary>
        public Dictionary<string, string> persistenceLayer;

        /// <summary>
        /// recupera valore salvato in persistence layer (se non c'è crea...)
        /// </summary>
        /// <param name="keyVal"></param>
        /// <returns></returns>
        private string getStoredVal(string keyVal)
        {
            string value = "";
            try
            {
                if (persistenceLayer != null)
                {
                    if (!persistenceLayer.TryGetValue(keyVal, out value))
                    {
                        persistenceLayer.Add(keyVal, "0");
                    }
                }
            }
            catch
            { }
            return value;
        }
        /// <summary>
        /// recupera valore salvato in persistence layer (se non c'è crea...) come UINT
        /// </summary>
        /// <param name="keyVal"></param>
        /// <returns></returns>
        private uint getStoredValUInt(string keyVal)
        {
            uint answ = 0;
            try
            {
                answ = Convert.ToUInt32(getStoredVal(keyVal));
            }
            catch
            { }
            return answ;
        }
        /// <summary>
        /// recupera valore salvato in persistence layer (se non c'è crea...) come INT
        /// </summary>
        /// <param name="keyVal"></param>
        /// <returns></returns>
        private long getStoredValLong(string keyVal)
        {
            long answ = 0;
            try
            {
                answ = Convert.ToInt64(getStoredVal(keyVal));
            }
            catch
            { }
            return answ;
        }
        /// <summary>
        /// recupera valore salvato in persistence layer (se non c'è crea...) come double
        /// </summary>
        /// <param name="keyVal"></param>
        /// <returns></returns>
        private double getStoredValDouble(string keyVal)
        {
            double answ = 0;
            try
            {
                answ = Convert.ToDouble(getStoredVal(keyVal));
            }
            catch
            { }
            return answ;
        }

        /// <summary>
        /// Aggiorna un valore del dizionario in SOSTITUZIONE
        /// </summary>
        /// <param name="i"></param>
        /// <param name="newVal"></param>
        /// <param name="searchString"></param>
        /// <returns>Nuovo valore incrementato</returns>
        private void updateValString(int i, string newVal, string searchString)
        {
            // stringa da cercare..
            string keyVal = string.Format(searchString, i + 1);
            // salvo in ram!
            persistenceLayer[keyVal] = newVal;
        }
        /// <summary>
        /// Aggiorna un valore del dizionario in SOSTITUZIONE e lo restituisce
        /// </summary>
        /// <param name="i"></param>
        /// <param name="newVal"></param>
        /// <param name="searchString"></param>
        /// <returns>Nuovo valore incrementato</returns>
        private void updateValUInt(int i, uint newVal, string searchString)
        {
            // stringa da cercare..
            string keyVal = string.Format(searchString, i + 1);
            // salvo in ram!
            persistenceLayer[keyVal] = newVal.ToString();
        }
        /// <summary>
        /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce
        /// </summary>
        /// <param name="i"></param>
        /// <param name="delta"></param>
        /// <param name="searchString"></param>
        /// <returns>Nuovo valore incrementato</returns>
        private uint updateValUIntByIncr(int i, uint delta, string searchString)
        {
            // stringa da cercare..
            string keyVal = string.Format(searchString, i + 1);
            // recupero valore precedente...
            uint contAct = getStoredValUInt(keyVal);
            // nuovo valore...
            contAct += delta;
            // salvo in ram!
            persistenceLayer[keyVal] = contAct.ToString();
            // rendo il valore!
            return contAct;
        }
        /// <summary>
        /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce
        /// </summary>
        /// <param name="i"></param>
        /// <param name="delta"></param>
        /// <param name="searchString"></param>
        /// <returns>Nuovo valore incrementato</returns>
        private long updateValLongByIncr(int i, long delta, string searchString)
        {
            // stringa da cercare..
            string keyVal = string.Format(searchString, i + 1);
            // recupero valore precedente...
            long contAct = getStoredValLong(keyVal);
            // nuovo valore...
            contAct += delta;
            // salvo in ram!
            persistenceLayer[keyVal] = contAct.ToString();
            // rendo il valore!
            return contAct;
        }
        /// <summary>
        /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce
        /// </summary>
        /// <param name="i"></param>
        /// <param name="delta"></param>
        /// <param name="searchString"></param>
        /// <returns>Nuovo valore incrementato</returns>
        private double updateValDoubleByIncr(int i, double delta, string searchString)
        {
            // stringa da cercare..
            string keyVal = string.Format(searchString, i + 1);
            // recupero valore precedente...
            double contAct = getStoredValDouble(keyVal);
            // nuovo valore...
            contAct += delta;
            // salvo in ram!
            persistenceLayer[keyVal] = contAct.ToString();
            // rendo il valore!
            return contAct;
        }

        #endregion
    }
}
