using MTC;
using MTConnect;
using SCMCncLib;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace MTC_Adapter
{
    public class AdapterESA : AdapterGeneric
    {
        /// <summary>
        /// Configurazione valori da leggere IOT_Byte
        /// </summary>
        public otherData[] mapIOT_Byte;
        /// <summary>
        /// Configurazione valori da leggere IOT_Word
        /// </summary>
        public otherData[] mapIOT_Word;
        /// <summary>
        /// Configurazione valori da leggere IOT_DWord
        /// </summary>
        public otherData[] mapIOT_DWord;
        /// <summary>
        /// Configurazione valori da leggere IOT_String
        /// </summary>
        public otherData[] mapIOT_String;

        /// <summary>
        /// Oggetto elenco allarmi SOLO CNC (OCCHIO codice numerico = INDICE!!!)
        /// </summary>
        public allarme[] elencoAllarmiCNC;

        /// <summary>
        /// dimensione buffer BYTE (da file map)
        /// </summary>
        public int numByte = 0;
        /// <summary>
        /// dimensione buffer WORD (da file map)
        /// </summary>
        public int numWord = 0;
        /// <summary>
        /// dimensione buffer DWORD (da file map)
        /// </summary>
        public int numDWord = 0;
        /// <summary>
        /// Dimensione buffer string (FISSO!!!)
        /// </summary>
        public int numString = 255;

        /// <summary>
        /// Carico file conf dati IOT
        /// </summary>
        protected override void loadOtherFile()
        {
            base.loadOtherFile();
            loadByteListMap();
            loadWordListMap();
            loadDWordListMap();
            loadStringListMap();
            loadAllarmiCNC();
        }
        /// <summary>
        /// Carico conf vettore dati STRING
        /// </summary>
        private void loadStringListMap()
        {
            loadConfFile(ref mapIOT_String, filePath("IOTStringFilePath"), 1, ref numString);
            // riporto numString a 255!
            numString = 255;
        }
        /// <summary>
        /// Carico conf vettore dati DWORD
        /// </summary>
        private void loadDWordListMap()
        {
            loadConfFile(ref mapIOT_DWord, filePath("IOTDWordFilePath"), 1, ref numDWord);
        }
        /// <summary>
        /// Carico conf vettore dati WORD
        /// </summary>
        private void loadWordListMap()
        {
            loadConfFile(ref mapIOT_Word, filePath("IOTWordFilePath"), 1, ref numWord);
        }
        /// <summary>
        /// Carico conf vettore dati BYTE
        /// </summary>
        private void loadByteListMap()
        {
            loadConfFile(ref mapIOT_Byte, filePath("IOTByteFilePath"), 1, ref numByte);
        }
        /// <summary>
        /// caricamento allarmi da file (CON RIEMPIMENTO MANCANTI!!!!)
        /// </summary>
        protected void loadAllarmiCNC()
        {
            if (utils.CRB("verbose")) lg.Info("Inizio caricamento vettore allarmi");
            int totRighe = 0;
            string fileName = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("AlarmListCNC"));
            string linea;
            try
            {
                string lastLine = File.ReadLines(fileName).Last();
                totRighe = startNumb(lastLine, utils.CRC("testCharSep"));
            }
            catch
            {
                totRighe = File.ReadLines(fileName).Count();
            }
            // creo un vettore della dimensione corretta... PRENDO IL MASSIMO dei valori...
            elencoAllarmiCNC = new allarme[totRighe];
            // ora creo un vettore di allarmi VUOTI...
            for (int i = 1; i <= totRighe; i++)
            {
                elencoAllarmiCNC[i - 1] = new allarme(i.ToString(), "CNC", "WARNING", string.Format("[{0}] MISSING", i));
            }
            // carica da file...
            System.IO.StreamReader file = new System.IO.StreamReader(fileName);
            // leggo 1 linea alla volta...
            int numRiga = 0;
            while ((linea = file.ReadLine()) != null)
            {
                // SE non è un commento...
                if (linea.Substring(0, 1) != "#")
                {
                    // recupero numRiga da prima parte linea...
                    numRiga = startNumb(linea, utils.CRC("testCharSep"));
                    elencoAllarmiCNC[numRiga - 1] = decodeAlarmLine(linea, utils.CRC("testCharSep"));
                }
            }
            // chiudo file
            file.Close();
            if (utils.CRB("verbose")) lg.Info(string.Format("Fine caricamento vettore allarmi CNC: {0} allarmi caricati!", numRiga));
        }
        /// <summary>
        /// Restituisce path completo file da chaive configurazione
        /// </summary>
        /// <param name="keyFile">chaive conf x file richiesto</param>
        /// <returns></returns>
        protected string filePath(string keyFile)
        {
            return string.Format(@"{0}\{1}", utils.confDir, utils.CRS(keyFile));
        }
        /// <summary>
        /// Legge il file di conf di una MAP di informazioni da gestire con lettura set memoria
        /// </summary>
        /// <param name="vettoreConf">nome vettore memoria</param>
        /// <param name="nomeFile">file origine</param>
        /// <param name="memSize">dimensione (in byte) della memoria</param>
        /// <param name="numVett">dimensione (in byte) della memoria</param>
        protected void loadConfFile(ref otherData[] vettoreConf, string nomeFile, int memSize, ref int numVett)
        {
            otherData lastData = new otherData();
            int totRighe = 0;
            string linea;
            totRighe = File.ReadLines(nomeFile).Count();
            // creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco...
            vettoreConf = new otherData[File.ReadLines(nomeFile).Count()];
            // carica da file...
            StreamReader file = new StreamReader(nomeFile);
            // leggo 1 linea alla volta...
            int numRiga = 0;
            int bitNum = 0;
            int byteNum = 0;
            while ((linea = file.ReadLine()) != null)
            {
                // SE non è un commento...
                if (linea.Substring(0, 1) != "#")
                {
                    // se finisce per BIT allora processo bit-a-bit...
                    if (linea.EndsWith("BOOL"))
                    {
                        try
                        {
                            string[] memIdx = linea.Split(utils.CRC("testCharSep"))[0].Split('.');
                            // calcolo bit e byte number...
                            int.TryParse(memIdx[0], out byteNum);
                            if (memIdx.Length > 1)
                            {
                                int.TryParse(memIdx[1], out bitNum);
                            }
                            else
                            {
                                bitNum = 0;
                            }
                        }
                        catch
                        {
                            byteNum = 0;
                            bitNum = 0;
                        }
                        lastData = decodeBitData(linea, utils.CRC("testCharSep"), byteNum, 1, bitNum);
                        vettoreConf[numRiga] = lastData;
                    }
                    else
                    {
                        lastData = decodeOtherData(linea, utils.CRC("testCharSep"), "", 1, memSize);
                        vettoreConf[numRiga] = lastData;
                    }
                    numRiga++;
                }
            }
            // salvo lunghezza file...
            try
            {
                numVett = Convert.ToInt32(lastData.memAddr) + 1;
            }
            catch
            {
                numVett = numRiga + 1;
            }
            // chiudo file
            file.Close();
            // ora trimmo vettore al solo numero VERO dei valori caricati...
            Array.Resize<otherData>(ref vettoreConf, numRiga);

            if (utils.CRB("verbose")) lg.Info(string.Format("Fine caricamento vettore di {0} variabili per file {1}", numRiga, nomeFile));
        }

        /// <summary>
        /// oggetto onnessione ESA
        /// </summary>
        protected thdNcEsaGvKvara ncDevice;
        /// <summary>
        /// thread del processo comunicazione esa
        /// </summary>
        protected Thread thdDevice;

        /// <summary>
        /// estende l'init della classe base...
        /// </summary>
        /// <param name="caller"></param>
        /// <param name="adpConf"></param>
        public AdapterESA(MainForm caller, AdapterConf adpConf) : base(caller, adpConf)
        {
            string iniPath = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("defaultEsaFile"));

            lg.Info("Start init Adapter ESA dal file {0}", iniPath);

            IniFiles.IniFile EsaIni = new IniFiles.IniFile(iniPath);

            if (utils.CRB("verbose")) lg.Info("step 01: impostato INI File {0}", iniPath);

            loadOtherFile();

            //ncDevice = new thdNcEsaGvKvara(EsaIni, mapIOT_Byte.Length, mapIOT_Word.Length, mapIOT_DWord.Length, 255); // impostato a 255 byte (char) FISSO x la parte stringa... mapIOT_String.Length);
            ncDevice = new thdNcEsaGvKvara(EsaIni, numByte, numWord, numDWord, numString); // impostato a 255 byte (char) FISSO x la parte stringa... mapIOT_String.Length);

            if (utils.CRB("verbose")) lg.Info("step 02: avviato thdNcEsaGvKvara da INI File {0}", iniPath);

            // inizializzo posizioni assi...
            prevPosAxis = new double[adpConf.nAxis];
            prevDirAxis = new int[adpConf.nAxis];

            // verifica avvio...
            lg.Info("ESA: tryConnect");
            tryConnect();
            lg.Info("End init Adapter ESA");
        }

        public override void tryDisconnect()
        {
            base.tryDisconnect();
            // disconnetto
            ncDevice.Disconnect();
            connectionOk = false;
        }

        public override void tryConnect()
        {
            base.tryConnect();

            // se non già connesso provo a connettermi...
            if (!ncDevice.Connected)
            {
                // provo a collegarmi
                if (!ncDevice.Connect())
                {
                    //altrimenti disconnette...
                    ncDevice.Disconnect();
                    connectionOk = false;
                }
                else
                {
                    connectionOk = true;
                }
            }
        }

        /// <summary>
        /// Verifico connessione ESA...
        /// </summary>
        /// <returns></returns>
        public override bool connectionOk
        {
            get
            {
                return ncDevice.Connected;
            }
        }

        /// <summary>
        /// Carica ed acquisisce dati del buffer Byte (8 bit) di memoria
        /// </summary>
        protected void getIotMem_Byte()
        {
            // HARD CODE: forzo path 1 (indice 0...)
            int idxPath = 0;
            // accodo dati path in DataMonitor......
            StringBuilder sb = new StringBuilder();

            if (connectionOk)
            {
                // leggo TUTTO il blocco di memoria
                inizio = DateTime.Now;
                ncDevice.ReadBufferByte();
                if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-PLC_IOT-Byte", ncDevice.PLC_MemoryAreaIOT_Byte.Length), DateTime.Now.Subtract(inizio).Ticks);
            }
            else
            {
                lg.Error("Errore connessione mancante in getIotMem_Byte");
            }
            // Processing area BYTE
            int numero = 0;
            string status = "";
            string pathExeMode = "";
            string pathRunMode = "";
            string ProgAreaRun = "";
            int ProgAreaRunCode = 0;
            bool isFeedHold = false;
            bool isActive = false;
            bool isReady = false;
            int bitNum = 0;
            int byteNum = 0;
            byte currByte;
            for (int i = 0; i < mapIOT_Byte.Length; i++)
            {
                // vado a gestire le variabili BYTE
                if (mapIOT_Byte[i].dataType == "BYTE")
                {
                    int.TryParse(mapIOT_Byte[i].memAddr, out byteNum);
                    if (mapIOT_Byte[i].varName == "IOT_OVRF")
                    {
                        FeedRateOver = ncDevice.PLC_MemoryAreaIOT_Byte[byteNum];
                    }
                    else if (mapIOT_Byte[i].varName == "IOT_OVRS")
                    {
                        SpeedRateOver = ncDevice.PLC_MemoryAreaIOT_Byte[byteNum];
                    }
                    else if (mapIOT_Byte[i].varName == "IOT_MODECN")
                    {
                        // Modo CN:0=Nessuno,1=Manuale,2=Automatico, 3=Pom,4=Mdi,5=SemiAutomatico,6=Rap,7=Test
                        int modoCn = ncDevice.PLC_MemoryAreaIOT_Byte[byteNum];
                        switch (modoCn)
                        {
                            case 1:
                                pathRunMode = "MANUAL";
                                break;
                            case 2:
                                pathRunMode = "AUTOMATIC";
                                break;
                            case 3:
                                pathRunMode = "POM";
                                break;
                            case 4:
                                pathRunMode = "MANUAL_DATA_INPUT";
                                break;
                            case 5:
                                pathRunMode = "SEMI_AUTOMATIC"; //"SEMIAUTO";
                                break;
                            case 6:
                                pathRunMode = "RAP"; //"MANUAL";
                                break;
                            case 7:
                                pathRunMode = "TES"; //"MANUAL";
                                break;
                            case 0:
                            default:
                                pathRunMode = "NA";
                                break;
                        }
                        // salvo run mode
                        vettPath[idxPath].mPathRunMode.Value = pathRunMode;
                    }
                    else if (mapIOT_Byte[i].varName.StartsWith("IOT_LUB_"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(mapIOT_Byte[i].varName.Replace("IOT_LUB_", "").Replace("_STA", "").Replace("_CNT", ""));
                            // salvo in vettore SE possibile...
                            if (numero <= vettLubro.Length)
                            {
                                if (mapIOT_Byte[i].varName.EndsWith("_STA"))
                                {
                                    if (ncDevice.PLC_MemoryAreaIOT_Byte[byteNum] != 0)
                                    {
                                        status = "EMPTY";
                                    }
                                    else
                                    {
                                        status = "OK";
                                    }
                                    vettLubro[numero - 1].mLubroStatus.Value = status;
                                }
                                else if (mapIOT_Byte[i].varName.EndsWith("_CNT"))
                                {
                                    vettLubro[numero - 1].mLubroNum.Value = ncDevice.PLC_MemoryAreaIOT_Byte[byteNum];
                                }
                            }
                            else
                            {
                                lg.Error("Errore in inserimento vettore " + mapIOT_Byte[i].varName);
                            }
                        }
                        catch (Exception exc)
                        {
                            lg.Error(exc, "Errore in decodifica " + mapIOT_Byte[i].varName);
                        }
                    }
                    else if (mapIOT_Byte[i].varName.StartsWith("IOT_I_MD_"))
                    {
                        try
                        {
                            numero = Convert.ToInt32(mapIOT_Byte[i].varName.Replace("IOT_I_MD_", ""));
                            // salvo in vettore SE possibile...
                            if (numero <= vettUnOp.Length)
                            {
                                vettUnOp[numero - 1].mUnOpLoad.Value = ncDevice.PLC_MemoryAreaIOT_Byte[byteNum];
                            }
                            else
                            {
                                lg.Error("Errore in inserimento vettore " + mapIOT_Byte[i].varName);
                            }
                        }
                        catch (Exception exc)
                        {
                            lg.Error(exc, "Errore in decodifica " + mapIOT_Byte[i].varName);
                        }
                    }
                }
                // gestisco le variabili BIT/BOOL
                else if (mapIOT_Byte[i].dataType == "BOOL")
                {
                    string[] memIdx = mapIOT_Byte[i].memAddr.Split('.');
                    // calcolo bit e byte number...
                    int.TryParse(memIdx[0], out byteNum);
                    if (memIdx.Length > 1)
                    {
                        int.TryParse(memIdx[1], out bitNum);
                    }
                    // leggo byte...
                    currByte = ncDevice.PLC_MemoryAreaIOT_Byte[byteNum];
                    if (mapIOT_Byte[i].varName == "IOT_MACHON")
                    {
                        if (((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum)))
                        {
                            mPower.Value = "ON";
                        }
                        else
                        {
                            mPower.Value = "OFF";
                        }
                    }
                    else if (mapIOT_Byte[i].varName == "IOT_READY")
                    {
                        isReady = ((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum));
                    }
                    else if (mapIOT_Byte[i].varName == "IOT_EXEC")
                    {
                        isActive = ((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum));
                    }
                    else if (mapIOT_Byte[i].varName == "IOT_HOLD")
                    {
                        isFeedHold = ((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum));
                    }
                    else if (mapIOT_Byte[i].varName == "IOT_EMG")
                    {
                        if (((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum)))
                        {
                            mEStop.Value = "TRIGGERED";
                        }
                        else
                        {
                            mEStop.Value = "ARMED";
                        }
                    }
                    else if (mapIOT_Byte[i].varName == "IOT_ALRM")
                    {
                        if (((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum)))
                        {
                            // inutile, leggo sempre TUTTI gli allarmi...
                        }
                    }
                    else if (mapIOT_Byte[i].varName.StartsWith("IOT_EXEC_A_"))
                    {
                        ProgAreaRun = "OFF";
                        ProgAreaRunCode = 0;
                        // recupero NUMERO
                        try
                        {
                            numero = Convert.ToInt32(mapIOT_Byte[i].varName.Replace("IOT_EXEC_A_", ""));
                            // salvo SOLO SE ha bit = 1..
                            if (((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum)))
                            {
                                ProgAreaRun = "ON";
                                ProgAreaRunCode = 1;
                            }
                            vettMemArea[numero - 1].mMemAreaRunning.Code = ProgAreaRunCode.ToString();
                            vettMemArea[numero - 1].mMemAreaRunning.Value = ProgAreaRun;
                        }
                        catch (Exception exc)
                        {
                            lg.Error(exc, "Errore in decodifica " + mapIOT_Byte[i].varName);
                        }
                    }
                    else if (mapIOT_Byte[i].varName.StartsWith("IOT_VAC_"))
                    {
                        // recupero NUMERO
                        try
                        {
                            numero = Convert.ToInt32(mapIOT_Byte[i].varName.Replace("IOT_VAC_", ""));
                            // controllo SE ha bit = 1 è ON..
                            string VacStat = "";
                            if (((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum)))
                            {
                                VacStat = "ON";
                            }
                            else
                            {
                                VacStat = "OFF";
                            }
                            // salvo in vettore SE possibile...
                            if (numero <= vettVacPump.Length)
                            {
                                vettVacPump[numero - 1].mVacPumpStatus.Value = VacStat;
                            }
                            else
                            {
                                lg.Error("Errore in inserimento vettore " + mapIOT_Byte[i].varName);
                            }
                        }
                        catch (Exception exc)
                        {
                            lg.Error(exc, "Errore in decodifica " + mapIOT_Byte[i].varName);
                        }
                    }
                }
            }

            // imposto exe mode alla fine secondo gerarchia stati...
            if (isFeedHold)
            {
                pathExeMode = "FEED_HOLD"; //"FEEDHOLD";
            }
            else if (isActive)
            {
                pathExeMode = "ACTIVE";
            }
            else if (isReady)
            {
                pathExeMode = "READY";
            }
            vettPath[idxPath].mPathExeMode.Value = pathExeMode;

            // sistemo le stringhe x display
            sb.AppendLine(string.Format("RunMode: {0}", pathRunMode));
            sb.AppendLine(string.Format("ExeMode: {0}", pathExeMode));
            sb.AppendLine(string.Format("FeedRateOver: {0} %", FeedRateOver));
            sb.AppendLine(string.Format("SpeedRateOver: {0} %", SpeedRateOver));

            // update form!
            parentForm.dataMonitor_1 += sb.ToString();
        }
        /// <summary>
        /// Carica ed acquisisce dati del buffer WORD (16 bit) di memoria
        /// </summary>
        protected void getIotMem_Word()
        {
            if (connectionOk)
            {
                // leggo TUTTO il blocco di memoria
                inizio = DateTime.Now;
                ncDevice.ReadBufferWord();
                if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-PLC_IOT-Word", ncDevice.PLC_MemoryAreaIOT_Word.Length), DateTime.Now.Subtract(inizio).Ticks);
            }
            else
            {
                lg.Error("Errore connessione mancante in getIotMem_Word");
            }

            int numAlarmCNC = 0;
            int numero = 0;
            int byteNum = 0;
            // Processing area WORD
            for (int i = 0; i < mapIOT_Word.Length; i++)
            {
                int.TryParse(mapIOT_Word[i].memAddr, out byteNum);

                if (mapIOT_Word[i].varName == "IOT_CN_MSG")
                {
                    // leggo codice allarme...
                    numAlarmCNC = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
                    // controllo, SE è 0 --> normal/niente, altrimenti è l'allarme indicato!!!
                    if (numAlarmCNC == 0)
                    {
                        mAlarmCNC.Normal();
                    }
                    else
                    {
                        allarme currAllarm = elencoAllarmiCNC[numAlarmCNC - 1];
                        Condition.Level livello = Condition.Level.NORMAL;
                        switch (currAllarm.livello)
                        {
                            case "WARNING":
                                livello = Condition.Level.WARNING;
                                break;
                            case "FAULT":
                            default:
                                livello = Condition.Level.FAULT;
                                break;
                        }
                        mAlarmCNC.Add(livello, currAllarm.descrizione, currAllarm.codNum, "", "");
                    }
                }
                else if (mapIOT_Word[i].varName.StartsWith("IOT_S_MD_"))
                {
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_S_MD_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= vettUnOp.Length)
                        {
                            vettUnOp[numero - 1].mUnOpSpeed.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_Word[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_Word[i].varName);
                    }
                }
                else if (mapIOT_Word[i].varName.StartsWith("IOT_T_MD_"))
                {
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_T_MD_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= vettUnOp.Length)
                        {
                            vettUnOp[numero - 1].mUnOpToolId.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_Word[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_Word[i].varName);
                    }
                }
                else if (mapIOT_Word[i].varName.StartsWith("IOT_C_TC_"))
                {
                    // recupero NUMERO
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_C_TC_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= vettUnOp.Length)
                        {
                            vettUnOp[numero - 1].mUnOpNumCU.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_Word[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_Word[i].varName);
                    }
                }
                else if (mapIOT_Word[i].varName.StartsWith("IOT_C_H_MD_"))
                {
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_C_H_MD_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= vettUnOp.Length)
                        {
                            vettUnOp[numero - 1].mUnOpAccTime.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_Word[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_Word[i].varName);
                    }
                }
                else if (mapIOT_Word[i].varName.StartsWith("IOT_C_H_VAC_"))
                {
                    // recupero NUMERO
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_C_H_VAC_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= vettVacPump.Length)
                        {
                            vettVacPump[numero - 1].mVacPumpWrkTime.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_Word[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_Word[i].varName);
                    }
                }
                else if (mapIOT_Word[i].varName.StartsWith("IOT_PGMR_A_"))
                {
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_PGMR_A_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= vettMemArea.Length)
                        {
                            vettMemArea[numero - 1].mMemAreaProgNumRep.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_Word[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_Word[i].varName);
                    }
                }
                else if (mapIOT_Word[i].varName.StartsWith("IOT_C_EXEC_A_"))
                {
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_C_EXEC_A_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= vettMemArea.Length)
                        {
                            vettMemArea[numero - 1].mMemAreaProgNumExe.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_Word[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_Word[i].varName);
                    }
                }
            }
        }
        /// <summary>
        /// Carica ed acquisisce dati del buffer DWORD (32 bit) di memoria
        /// </summary>
        protected void getIotMem_DWord()
        {
            // accodo dati path in DataMonitor......
            StringBuilder sb = new StringBuilder();
            if (connectionOk)
            {
                // leggo TUTTO il blocco di memoria
                inizio = DateTime.Now;
                ncDevice.ReadBufferDWord();
                if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-PLC_IOT-DWord", ncDevice.PLC_MemoryAreaIOT_DWord.Length), DateTime.Now.Subtract(inizio).Ticks);
            }
            else
            {
                lg.Error("Errore connessione mancante in getIotMem_DWord");
            }

            int numero = 0;
            int byteNum = 0;
            double valDouble = 0;
            // Processing area WORD
            for (int i = 0; i < mapIOT_DWord.Length; i++)
            {
                int.TryParse(mapIOT_DWord[i].memAddr, out byteNum);
                if (mapIOT_DWord[i].varName == "IOT_FEED")
                {
                    FeedRate = BitConverter.ToInt32(BitConverter.GetBytes(ncDevice.PLC_MemoryAreaIOT_DWord[byteNum]), 0);
                }
                else if (mapIOT_DWord[i].varName.StartsWith("IOT_FEED_"))
                {
                    // recupero NUMERO
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_FEED_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= FeedRateGrp.Length)
                        {
                            FeedRateGrp[numero - 1] = BitConverter.ToInt32(BitConverter.GetBytes(ncDevice.PLC_MemoryAreaIOT_DWord[byteNum]), 0);
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_DWord[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_DWord[i].varName);
                    }
                }
                else if (mapIOT_DWord[i].varName.StartsWith("IOT_C_KU_AX_"))
                {
                    // recupero NUMERO
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_C_KU_AX_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= vettAxis.Length)
                        {
                            vettAxis[numero - 1].mAxDistDone.Value = ncDevice.PLC_MemoryAreaIOT_DWord[byteNum];
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_DWord[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_DWord[i].varName);
                    }
                }
                else if (mapIOT_DWord[i].varName.StartsWith("IOT_C_KINV_AX_"))
                {
                    // recupero NUMERO
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_C_KINV_AX_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= vettAxis.Length)
                        {
                            vettAxis[numero - 1].mAxInvDDone.Value = ncDevice.PLC_MemoryAreaIOT_DWord[byteNum];
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_DWord[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_DWord[i].varName);
                    }
                }
                else if (mapIOT_DWord[i].varName.StartsWith("IOT_POS_AX_"))
                {
                    // recupero NUMERO
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_POS_AX_", ""));
                        // recupero valore pos assi (in micron)
                        valDouble = (double)BitConverter.ToInt32(BitConverter.GetBytes(ncDevice.PLC_MemoryAreaIOT_DWord[byteNum]), 0);
                        // salvo in vettore SE possibile...
                        if (numero <= vettAxis.Length)
                        {
                            // riporto il dato in mm (divido x 1000)
                            vettAxis[numero - 1].mAxPosAct.Value = valDouble / utils.CRI("fattdecimale");
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_DWord[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_DWord[i].varName);
                    }
                }
                else if (mapIOT_DWord[i].varName.StartsWith("IOT_C_KREV_MD_"))
                {
                    // recupero NUMERO
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_C_KREV_MD_", ""));
                        // salvo in vettore SE possibile...
                        if (numero <= vettUnOp.Length)
                        {
                            vettUnOp[numero - 1].mUnOpKRev.Value = ncDevice.PLC_MemoryAreaIOT_DWord[byteNum];
                        }
                        else
                        {
                            lg.Error("Errore in inserimento vettore " + mapIOT_DWord[i].varName);
                        }
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_DWord[i].varName);
                    }
                }
                else if (mapIOT_DWord[i].varName.StartsWith("IOT_PLC_MSG_"))
                {
                    // recupero NUMERO
                    try
                    {
                        numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_PLC_MSG_", ""));
                        // copio allarmi in vettore generale AlarmFlags (dove lo gestisce) 4 byte alla volta
                        Buffer.BlockCopy(BitConverter.GetBytes(ncDevice.PLC_MemoryAreaIOT_DWord[byteNum]), 0, AlarmFlags, numero * 4, 4);
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_DWord[i].varName);
                    }
                }
            }
            // aggiungo feedrate
            sb.AppendLine(string.Format("FeedRate: {0} mm/min", FeedRate));
            // verifico se nei gruppi di feed ho qualcosa di diverso da zero...
            for (int i = 0; i < 20; i++)
            {
                if (FeedRateGrp[i] != 0) sb.AppendLine(string.Format("FeedRate_{1}: {0:00} mm/min", FeedRateGrp[i], i));
            }
            // update form!
            parentForm.dataMonitor_1 += sb.ToString();
        }
        /// <summary>
        /// Carica ed acquisisce dati del buffer STRING di memoria
        /// </summary>
        protected void getIotMem_String()
        {
            // accodo dati path in DataMonitor......
            StringBuilder sb = new StringBuilder();
            if (connectionOk)
            {
                // leggo TUTTO il blocco di memoria
                inizio = DateTime.Now;
                ncDevice.ReadBufferString();
                if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-PLC_IOT-DWord", ncDevice.PLC_MemoryAreaIOT_DWord.Length), DateTime.Now.Subtract(inizio).Ticks);
            }
            else
            {
                lg.Error("Errore connessione mancante in getIotMem_DWord");
            }

            // Processing area STRING: OGNI area di memoria...
            for (int j = 0; j < mapIOT_String.Length; j++)
            {
                string valString = "";

                for (int i = 0; i < numString; i++)
                {
                    try
                    {
                        valString += Convert.ToChar(ncDevice.PLC_MemoryAreaIOT_String[j, i]).ToString().Replace("\0", " ");
                    }
                    catch (Exception exc)
                    {
                        lg.Error(exc, "Errore in decodifica " + mapIOT_String[i].varName);
                    }
                }
                // trimmo!
                valString = valString.Trim();
                // salvo
                vettMemArea[j].mMemAreaProgName.Code = j.ToString();
                vettMemArea[j].mMemAreaProgName.Value = valString;
                // aggiungo nomi programmi...
                sb.AppendLine(string.Format("{0}: {1}", mapIOT_String[j].varName, valString));
            }
            // update form!
            parentForm.dataMonitor_1 += sb.ToString();
        }
        public override void getGlobalData()
        {
            base.getGlobalData();
        }

        /// <summary>
        /// Processing di TUTTA l'area di memoria configurata e delle variabili derivate...
        /// </summary>
        public override void processAllMemory()
        {
            // inizializzo data monitor su FORM
            parentForm.dataMonitor_1 = "";

            // recupero le varie memorie (prima string che mi serve x area selezionata --> programma selezionato)
            getIotMem_String();
            getIotMem_Byte();
            getIotMem_Word();
            getIotMem_DWord();

            // processo componenti specifici x info...
            getUnOp();
            getPath();
            getAxis();
        }

        /// <summary>
        /// Recupera la speed override x i mandrini (UnOp)
        /// </summary>
        public override void getUnOp()
        {
            // cicl su UnOp
            for (int i = 0; i < currAdpConf.nUnOp; i++)
            {
                vettUnOp[i].mUnOpSpeedOverr.Value = SpeedRateOver;
            }
        }

        /// <summary>
        /// Carica info accessorie assi (direzione, feed, ...)
        /// </summary>
        public override void getAxis()
        {
            // mostro assi in DataMonitor......
            StringBuilder sb = new StringBuilder();

            // nuova posizione (per calcoli)
            double newPos = 0;
            double distPerc = 0;
            int newDir = 0;
            string tipoAsse = "";
            string direzione = "";

            // leggo in modo "cablato" i dati dei vari assi...
            for (int i = 0; i < currAdpConf.nAxis; i++)
            {
                // verifico: se l'asse appartiene ad un gruppo uso la sua feedrate...
                int axGroup = 0;
                try
                {
                    axGroup = Convert.ToInt32(vettAxis[i].mAxGrp.Value);
                }
                catch
                { }
                if (axGroup > 0)
                {
                    vettAxis[i].mAxFeedAct.Value = FeedRateGrp[axGroup - 1];
                }
                else
                {
                    vettAxis[i].mAxFeedAct.Value = FeedRate;
                }
                vettAxis[i].mAxFeedOver.Value = FeedRateOver;

                // calcolo distanza e salvo valore...
                newPos = Convert.ToDouble(vettAxis[i].mAxPosAct.Value);
                distPerc = newPos - prevPosAxis[i];

                // sistemo direzione +/- (POS/NEG se lineari, CCW/CW se rotativi)
                if (distPerc != 0)
                {
                    newDir = Convert.ToInt32(distPerc / Math.Abs(distPerc));
                }
                else
                {
                    newDir = prevDirAxis[i];
                }


                // verifico tipo direzione da tipo asse...
                tipoAsse = vettAxis[i].mAxType.Value.ToString();
                if (tipoAsse == "LINEAR")
                {
                    // ?: conditional operator.  
                    direzione = (newDir > 0) ? "POSITIVE" : "NEGATIVE";
                }
                else if (tipoAsse == "ROTARY")
                {
                    direzione = (newDir > 0) ? "CLOCKWISE" : "COUNTER_CLOCKWISE";
                }

                vettAxis[i].mAxDir.Value = direzione;

                // se la direzione è variata salvo il cambio direzione...
                if (newDir != prevDirAxis[i])
                {
                    // salvo "+1" come cambi direzione
                    istNumInvAssi[i]++;
                }

                if (utils.CRB("verbose"))
                {
                    sb.AppendLine(string.Format("Asse {0}: PosAct:{1:N3} | {2}", i, (double)(newPos), direzione));
                }

                // salvo valori vettore prec...
                prevPosAxis[i] = newPos;
                prevDirAxis[i] = newDir;
            }

            parentForm.dataMonitor_1 += sb.ToString();
        }
    }
}
