using IOB_UT_NEXT;
using IOB_UT_NEXT.Config;
using System;
using System.Collections.Generic;
using System.Linq;

namespace IOB_WIN_SIEMENS.IobSiemens
{
    public class SiemensFapeV2 : Siemens
    {
        /* --------------------------------------------------------------------------------
         * Controlli SIEMENS FAPE (es punzonatrice Tecnomeccanica di LVF)
         * - basasto su SIEMENS
         * - S7 vers 1200
         * - x poter funzionare --> protezione: meccanismi di collegamento / consenti put/get
         *
         * V1.0 (2018):
         *  - abilitata 1 area in lettura DB15
         *      DB15 | Read seguenti byte:
         *      - B0, WORD, Stato Macchina Generale
         *      - B2, WORD, Posizione sequenza contatore
         *      - B4, WORD, contatore cicli eseguiti per lubrifica
         *      - B40, DWORD, contapezzi azzerabile da operatore
         *      - B44, DWORD, contapezzi ASSOLUTO
         *  - abilitata 1 area in scrittura DB16 (NON la usano)
         *
         * V2.0 (2024):
         *  - abilitata 1 area in lettura DB17
         *      DB17 v.2 | Read seguenti byte:
         *      - B0, WORD, Stato Macchina Generale
         *      - B2, WORD, Posizione sequenza contatore
         *      - B4, WORD, contatore cicli eseguiti per lubrifica
         *      - B6, DWORD, contapezzi azzerabile da operatore
         *      - B10, DWORD, contapezzi ASSOLUTO
         *
         *      DB17 v.3 | Read seguenti byte:
         *      - B0, WORD, Semaforo Macchina
         *      - B2, WORD, Stato Macchina Generale
         *      - B4, WORD, Posizione sequenza contatore
         *      - B6, WORD, contatore cicli eseguiti per lubrifica
         *      - B8, DWORD, contapezzi azzerabile da operatore
         *      - B12, DWORD, contapezzi ASSOLUTO
         *
         *  - abilitata 1 area in scrittura DB16
         *      DB16 | Write seguenti byte:
         *      - B0, STRING(30), Commessa
         *      - B32, STRING(30), Articolo
         *      - B64, DWORD, NumPezzi
         *      - B68, BOOL, Reset Contapezzi Parziale(autoresetta)
         *
         * -------------------------------------------------------------------------------- */

        #region Public Constructors

        /// <summary>
        /// Classe base con i metodi x Siemens
        /// </summary>
        /// <param name="caller">Form chiamante</param>
        /// <param name="IOBConf">Configurazione (legacy)</param>
        /// <param name="IobConfFull">Configurazione (v 4.x)</param>
        public SiemensFapeV2(AdapterFormNext caller, IobConfTree IobConfFull) : base(caller, IobConfFull)
        {
            string sFapeVers = getOptPar("FAPE_VERS");
            if (!string.IsNullOrEmpty(sFapeVers))
            {
                int.TryParse(sFapeVers, out FapeVers);
            }
            int yRef = FapeVers == 1 ? 2018 : 2024;
            // inizializzo dizionari decodifica da conf json...
            // cerco nella conf specifica...
            if (memMap.DataDecodMap != null && memMap.DataDecodMap.Count > 0)
            {
                if (memMap.DataDecodMap.ContainsKey("StatoMacchina"))
                {
                    DictState = memMap.DataDecodMap["StatoMacchina"];
                }
                else
                {
                    lgError("Errore: missing DataDecodMap.StatoMacchina dict");
                }
                if (memMap.DataDecodMap.ContainsKey("StepCiclo"))
                {
                    DictStCic = memMap.DataDecodMap["StepCiclo"];
                }
                else
                {
                    lgError("Errore: missing DataDecodMap.StepCiclo dict");
                }
            }
            else
            {
                lgInfo("Attenzione. non ho trovcato dizionari di decodifica (DataDecodMap) nel file json!");
            }
            lgInfo($"NEW IOB SIEMENS versione FAPE v.{FapeVers} - {yRef}");
        }

        private Dictionary<string, string> DictState = new Dictionary<string, string>();
        private Dictionary<string, string> DictStCic = new Dictionary<string, string>();

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Recupero dati override in formato dictionary
        /// </summary>
        /// <returns></returns>
        public override Dictionary<string, string> getDynData()
        {
            Dictionary<string, string> outVal = new Dictionary<string, string>();
            ExtractFapeData();
            string curState = "";
            string curPosiz = "";
            // rivedere da conf estesa decodifica?!?
            if (FapeVers == 3)
            {
                // stato
                curState = $"{valState}";
                // cerco nella conf specifica...
                if (DictState.Count > 0 && DictState.ContainsKey($"{valState}"))
                {
                    curState = DictState[$"{valState}"];
                }

                // posizione
                curPosiz = $"{valStepCic}";
                // cerco nella conf specifica...
                if (DictStCic.Count > 0 && DictStCic.ContainsKey($"{valStepCic}"))
                {
                    curPosiz = DictStCic[$"{valStepCic}"];
                }
            }
            // se non trovato ancora..
            if (string.IsNullOrEmpty(curState) || string.IsNullOrEmpty(curPosiz))
            {
                if (FapeVers == 1)
                {
                    curState = ((stMacc2018)valState).ToString();
                    curPosiz = ((posSeq2018)valStepCic).ToString();
                    //outVal.Add("CURR_STATO", ((stMacc2018)valState).ToString());
                    //outVal.Add("CURR_POSIT", ((posSeq2018)valStepCic).ToString());
                }
                else
                {
                    curState = ((stMacc2024)valState).ToString();
                    curPosiz = ((posSeq2024)valStepCic).ToString();
                    //outVal.Add("CURR_STATO", ((stMacc2024)valState).ToString());
                    //outVal.Add("CURR_POSIT", ((posSeq2024)valStepCic).ToString());
                }
            }
            // salvo valori!
            outVal.Add("CURR_STATO", curState);
            outVal.Add("CURR_POSIT", curPosiz);

            // aggiungo main state se disponibile...
            if (FapeVers > 2)
            {
                outVal.Add("CURR_LAMP", ((mainState)valMain).ToString());
            }
            return outVal;
        }

        /// <summary>
        /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid)
        /// </summary>
        public override void processOverride()
        {
        }

        #endregion Public Methods

        #region Protected Fields

        /// <summary>
        /// Stato impianto codificato come valore mainState
        /// </summary>
        protected ushort valMain = 0;

        /// <summary>
        /// Posizione corrente ciclo
        /// </summary>
        protected ushort valStepCic = 0;

        /// <summary>
        /// Stato Dettagliato macchina
        /// </summary>
        protected ushort valState = 0;

        #endregion Protected Fields

        #region Protected Methods

        /// <summary>
        /// Effettua decodifica aree memoria alla bitmap usata x MAPO
        /// </summary>
        protected override void decodeToBaseBitmap()
        {
            // init a zero...
            B_input = 0;
            // FAPE: leggo i primi 2 WORD x decodifica stato e posizione...
            ExtractFapeData();
#if false
            mainState _stMain = ((mainState)valMain);
            stMacc2024 _stMacch = ((stMacc2024)valStatus);
            posSeq2024 _posSeq = ((posSeq2024)valPosit); 
#endif

            /* -----------------------------------------------------
             * bitmap MAPO - 47
             * B0: POWER_ON
             * B1: RUN
             * B2: pzCount
             * B3: allarme
             * B4: manuale
             * B5: emergenza
            ----------------------------------------------------- */

            // bit 0 (poweron) imposto a 1 SE connected...
            B_input = currPLC.IsConnected ? 1 : 0;

            // verifico versione decodifica da + recente a + vecchia...
            if (FapeVers == 3)
            {
                DecodeV3(ref B_input);
            }
            else if (FapeVers == 2)
            {
                DecodeV2(ref B_input);
            }
            else
            {
                DecodeV1(ref B_input);
            }

            // FIXME ToDo !!! verificare da qui...

            // procedo SOLO SE è enabled IOB
            if (IobOnline)
            {
                // 2026.04.24 controllo ODL solo se son passati ALMENO 10 sec
                int newIdx = CurrOdl();
                currODL = $"{currIdxODL}";
#if DEBUG
                lgInfo($"SiemensTorri | Verifica ODL | IdxODL {currIdxODL}");
#else
                lgDebug($"SiemensTorri | Verifica ODL | IdxODL {currIdxODL}");
#endif
            }
            else
            {
                // imposto currODL a vuoto!
                currODL = "";
                if (periodicLog)
                {
                    lgInfo($"Fanuc | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto");
                }
            }
            // verifico NON sia vietato gestione contapezzi
            if (!plcPzCountValid || !rawInputRead)
            {
                lgInfo($"Veto check contapezzi e ODL fino alle {dtVetoReadPzCount}");
            }
            else
            {
                if (!string.IsNullOrEmpty(currODL) && currIdxODL > 0)
                {
                    // ora processo il contapezzi... controllo se è passato intervallo minimo tra 2
                    // controlli/elaborazioni x distanziare invio e ridurre letture
                    if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay))
                    {
                        // se sono differenti MOSTRO...
                        if (contapezziPLC != contapezziIOB)
                        {
                            // registro contapezzi
                            lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}");
                        }
                        // verifico se variato contapezzi... e se passato ritardo minimo...
                        if (contapezziPLC > contapezziIOB)
                        {
                            // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio
                            contapezziIOB++;
                            needRefreshPzCount = true;
                            // salvo in semaforo!
                            B_input += (1 << 2);
                            // registro contapezzi
                            lgInfo($"contapezziPLC SIEMENS: {contapezziPLC} | contapezziIOB {contapezziIOB}");
                        }

                        if (needRefreshPzCount)
                        {
                            // invio a server contapezzi (aggiornato)
                            string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString());
                            // verifica se tutto OK
                            if (retVal != contapezziIOB.ToString())
                            {
                                // errore salvataggio contapezzi
                                lgInfo($"Errore salvataggio Contapezzi SIEMENS: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}");
                                // rileggo il counter pezzi da server
                                pzCntReload(true);
                            }
                            // resetto timer...
                            lastPzCountSend = DateTime.Now;
                        }
                    }
                }
                else
                {
                    if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay))
                    {
                        lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC SIEMENS {contapezziPLC} | contapezziIOB {contapezziIOB}");
                        // resetto timer...
                        lastPzCountSend = DateTime.Now;
                    }
                }
            }
            // log opzionale!
            if (verboseLog)
            {
                lgInfo(string.Format("Trasformazione B_input: {0}", B_input));
            }
        }

        /// <summary>
        /// Esegue decodificada stati in modalità "classica" (2018)
        /// </summary>
        /// <returns></returns>
        protected void DecodeV1(ref int B_input)
        {
            // Guardo SOLO stato macchina V1 (2018)
            stMacc2018 _stMacch = ((stMacc2018)valState);
            // controllo stato macchina x impostare altri bit...
            switch (_stMacch)
            {
                case stMacc2018.EMERGENZA_INSERITA:
                    B_input += (1 << 5);
                    break;

                case stMacc2018.AVARIA_ARIA:
                case stMacc2018.AVARIA_PRESSIONE_OLIO:
                case stMacc2018.AVARIA_LIVELLO_OLIO:
                case stMacc2018.AVARIA_TEMPERATURA_OLIO:
                    B_input += (1 << 3);
                    B_input += (1 << 6);
                    break;

                case stMacc2018.AVARIA_MOTORE_POMPA_IDRAULICA:
                case stMacc2018.AVARIA_MOTORE_RAFFREDDO_IDRAULICA:
                case stMacc2018.COMUNICAZIONE_ASSENTE:
                case stMacc2018.AVARIA_SINCRONISMO_PORTE:
                case stMacc2018.AVARIA_LIBERA:
                case stMacc2018.ATTIVAZIONE_IN_CORSO:
                    B_input += (1 << 3);
                    break;

                case stMacc2018.MODO_MANUALE_ATTREZZAGGIO:
                    B_input += (1 << 4);
                    break;

                case stMacc2018.CICLO_IN_CORSO:
                    B_input += (1 << 1);
                    break;

                case stMacc2018.MODO_AUTOMATICO_LOCALE:
                case stMacc2018.MODO_AUTOMATICO_ROBOT:
                    B_input += (1 << 7);
                    break;

                case stMacc2018.LIBERO:
                default:
                    break;
            }
        }

        /// <summary>
        /// Esegue decodificada stati in modalità "v2" (2024) con 2 valori senza macro stato
        /// </summary>
        /// <returns></returns>
        protected void DecodeV2(ref int B_input)
        {
            // Guardo SOLO stato macchina V2 (2024)
            stMacc2024 _stMacch = ((stMacc2024)valState);

            // controllo stato macchina x impostare altri bit... semplificato sui VALORI interi val status...

            // da 00..50 -> pronta NON faccio nulla
            if (valState < 51)
            {
                //B_input = 1;
            }
            // lavora
            else if (valState >= 51 && valState < 100)
            {
                B_input += (1 << 1);
            }
            // manuale/warning
            else if (valState >= 100 && valState < 199)
            {
                B_input += (1 << 3);
            }
            // allarme
            else if (valState >= 200)
            {
                B_input += (1 << 4);
            }

            // controllo COMUNQUE emergenza premuta...
            if (_stMacch == stMacc2024.MACCHINA_NON_ATTIVA)
            {
                B_input += (1 << 5);
            }
        }

        /// <summary>
        /// Esegue decodificada stati in modalità "v3" (2024) con 3 valori guardando SOLO macro stato
        /// </summary>
        /// <returns></returns>
        protected void DecodeV3(ref int B_input)
        {
            // Guardo SOLO stato MAIN V3 (2024)
            mainState _stMain = ((mainState)valMain);
            stMacc2024 _stMacch = ((stMacc2024)valState);

            // controllo stato macchina x impostare altri bit...
            switch (_stMain)
            {
                case mainState.Pronta:
                    break;

                case mainState.Lavora:
                    B_input += (1 << 1);
                    break;

                case mainState.Warning:
                    B_input += (1 << 4);
                    break;

                case mainState.Allarme:
                    B_input += (1 << 3);
                    break;

                case mainState.ND:
                default:
                    break;
            }

            // controllo COMUNQUE emergenza premuta...
            if (_stMacch == stMacc2024.MACCHINA_NON_ATTIVA)
            {
                B_input += (1 << 5);
            }
        }

        #endregion Protected Methods

        #region Private Fields

        private int FapeVers = 1;

        #endregion Private Fields

        #region Private Enums

        /// <summary>
        /// Enum degli stati macchina (B0)
        /// </summary>
        private enum mainState
        {
            ND = 0,
            Pronta = 1,
            Lavora = 2,
            Warning = 3,
            Allarme = 4
        }

        /// <summary>
        /// Posizione sequenza ciclo standard punzonatrice
        /// </summary>
        private enum posSeq2018
        {
            CICLO_AUTOMATICO_FERMO = 0,
            CONTROLLO_MODO_OPERATIVO = 5,
            MODO_ATTIVO_CON_ROBOT = 8,
            SBLOCCAGGIO_PEZZO = 10,
            APERTURA_PORTELLO_ROBOT = 11,
            CONSENSO_ACCESSO_AL_ROBOT = 12,
            CARICO_ROBOT_IN_CORSO = 14,
            CARICO_ROBOT_CONCLUSO = 16,
            CHIUSURA_PORTELLO_ROBOT = 18,
            VERIFICA_POSIZIONE_CARRI = 20,
            BLOCCAGGIO_PEZZO = 22,
            ATTESA_CARRO_A_DESTRA = 24,
            DISCESA_RAPIDO_BROCCIATURA = 25,
            CICLO_DI_BROCCIATURA = 26,
            RITORNO_BROCCIATRICE = 28,
            COMANDO_CARRO_A_SINISTRA = 30,
            CICLO_DI_ALESATURA = 32,
            RITORNO_CARRO_ALESATURA = 34,
            COMANDO_CARRO_A_DESTRA = 36,
            INCREMENTO_CONTAPEZZI = 38,
            CONTROLLO_TIME_OUT_CICLO = 40,
            RILANCIO_CICLO_F42 = 42,
            ATTESA_FINE_CICLO = 45
        }

        /// <summary>
        /// Posizione sequenza ciclo standard punzonatrice
        /// </summary>
        private enum posSeq2024
        {
            CICLO_NON_ATTIVO_0 = 0,
            CONTROLLO_TIPO_CARICO_5 = 5,
            APERTURA_PORTELLO_ACCESSO_AREA_ROBOT_10 = 10,
            ATTESA_SCARICO_CARICO_PEZZO_DA_ROBOT_15 = 15,
            ATTESA_ROBOT_FUORI_AREA_20 = 20,
            ATTESA_CADUTA_SEGNALE_ROBOT_FUORI_AREA_25 = 25,
            CHIUSURA_PORTELLO_ACCESSO_AREA_ROBOT_30 = 30,
            FASE_1_STAFFAGGIO_PEZZO_50 = 50,
            FASE_2_POSIZIONAMENTO_CONTRASTO_PEZZO_60 = 60,
            FASE_3_PUNZONATURA_1_LUBRIFICAZIONE_PUNZONE_69 = 69,
            FASE_3_PUNZONATURA_1_DISCESA_RAPIDA_70 = 70,
            FASE_3_PUNZONATURA_1_DISCESA_LENTA_74 = 74,
            FASE_3_PUNZONATURA_1_DISCESA_LENTISSIMA_75 = 75,
            FASE_3_PUNZONATURA_1_ARRESTO_AZIONAMENTO_79 = 79,
            FASE_3_PUNZONATURA_1_RITARDO_PER_RISALITA_80 = 80,
            FASE_3_PUNZONATURA_1_SALITA_LENTA_85 = 85,
            FASE_3_PUNZONATURA_1_SALITA_RAPIDA_90 = 90,
            FASE_3_PUNZONATURA_1_SALITA_FINALE_95 = 95,
            FASE_3_PUNZONATURA_1_ARRESTO_AZIONAMENTO_96 = 96,
            FASE_4_TRASLAZIONE_1_RITARDO_AVVIO_105 = 105,
            FASE_4_TRASLAZIONE_1_MOVIMENTO_SU_PUNZONATURA_2_110 = 110,
            FASE_4_TRASLAZIONE_1_ARRESTO_AZIONAMENTO_114 = 114,
            FASE_5_PUNZONATURA_2_RITARDO_AVVIO_115 = 115,
            FASE_5_PUNZONATURA_2_LUBRIFICAZIONE_PUNZONE_119 = 119,
            FASE_5_PUNZONATURA_2_DISCESA_RAPIDA_120 = 120,
            FASE_5_PUNZONATURA_2_DISCESA_LENTA_124 = 124,
            FASE_5_PUNZONATURA_2_DISCESA_LENTISSIMA_125 = 125,
            FASE_5_PUNZONATURA_2_ARRESTO_AZIONAMENTO_126 = 126,
            FASE_5_PUNZONATURA_2_RITARDO_PER_RISALITA_130 = 130,
            FASE_5_PUNZONATURA_2_SALITA_LENTA_135 = 135,
            FASE_5_PUNZONATURA_2_SALITA_RAPIDA_140 = 140,
            FASE_5_PUNZONATURA_2_SALITA_FINALE_145 = 145,
            FASE_5_PUNZONATURA_2_ARRESTO_AZIONAMENTO_146 = 146,
            INCREMENTO_CONTATORI_PEZZI_ESEGUITI_155 = 155,
            FASE_6_TRASLAZIONE_2_RITARDO_AVVIO_156 = 156,
            FASE_6_TRASLAZIONE_2_MOVIMENTO_SU_PUNZONATURA_1_160 = 160,
            FASE_6_TRASLAZIONE_2_ARRESTO_AZIONAMENTO_161 = 161,
            FASE_7_DISINSERIMENTO_CONTRASTO_165 = 165,
            FASE_8_DESTAFFAGGIO_PEZZO_170 = 170,
            DISATTIVAZIONE_AZIONAMENTO_180 = 180,
            VERIFICA_RIAVVIO_CICLO_CON_CARICO_DA_ROBOT_190 = 190,
            CICLO_TERMINATO_300 = 300
        }

        /// <summary>
        /// Enum degli stati macchina (B0)
        /// </summary>
        private enum stMacc2018
        {
            COMUNICAZIONE_ASSENTE = 0,
            EMERGENZA_INSERITA = 1,
            AVARIA_ARIA = 2,
            AVARIA_PRESSIONE_OLIO = 3,
            AVARIA_LIVELLO_OLIO = 4,
            AVARIA_TEMPERATURA_OLIO = 5,
            AVARIA_MOTORE_POMPA_IDRAULICA = 6,
            AVARIA_MOTORE_RAFFREDDO_IDRAULICA = 7,
            AVARIA_SINCRONISMO_PORTE = 8,
            AVARIA_LIBERA = 9,
            ATTIVAZIONE_IN_CORSO = 10,
            MODO_MANUALE_ATTREZZAGGIO = 11,
            MODO_AUTOMATICO_LOCALE = 12,
            MODO_AUTOMATICO_ROBOT = 13,
            CICLO_IN_CORSO = 14,
            LIBERO = 15
        }

        /// <summary>
        /// Enum degli stati macchina (B0)
        /// </summary>
        private enum stMacc2024
        {
            COMUNICAZIONE_ASSENTE = 0,
            EMERGENZA_RIPRISTINATA = 5,
            MACCHINA_IN_POTENZA = 10,
            MACCHINA_PRONTA_PER_CICLO_LOCALE = 15,
            MACCHINA_PRONTA_PER_CICLO_CON_ROBOT = 20,
            MACCHINA_IN_MANUALE = 25,
            CICLO_RESET_ATTIVO = 50,
            CICLO_AUTOMATICO_LOCALE_ATTIVO = 55,
            CICLO_AUTOMATICO_CON_ROBOT_ATTIVO = 60,
            MANCANZA_OLIO_LUBRIFICAZIONE_PEZZO = 100,
            MANCANZA_OLIO_LUBRIFICAZIONE_CILINDRO = 105,
            ATTESA_BARRIERE_LIBERE = 110,
            ATTESA_BLOCCAGGIO_PORTELLO_ANTERIORE = 111,
            ATTESA_RILASCIO_PULSANTE_RESET = 115,
            ATTESA_ASSE_PUNZONATURA_ALTO = 120,
            ATTESA_BLOCCAGGIO_PEZZO_ALTO = 125,
            ATTESA_BLOCCAGGIO_PEZZO = 126,
            ATTESA_CONTRASTO_PEZZO_DISINSERITO = 130,
            ATTESA_CARRO_IN_POSIZIONE_1 = 135,
            ATTESA_CHIUSURA_PORTELLO_ROBOT = 140,
            ATTESA_ROBOT_FUORI_INGOMBRO = 145,
            ATTESA_TERMINE_CICLO_RESET = 150,
            TIMEOUT_LUBRIFICAZIONE_CILINDRO = 155,
            LIVELLO_OLIO_BASSO_LUBRIFICA_PEZZO = 160,
            LIVELLO_OLIO_BASSO_LUBRIFICA_CILINDRO = 165,
            ATTESA_AREA_TRASLAZIONE_LIBERA = 170,
            ANOMALIA_POSIZIONE_PER_CARICO_ROBOT = 205,
            SOVRAPRESSIONE_PUNZONATURA_1 = 210,
            OLTRE_QUOTA_MASSIMA_PUNZONATURA_1 = 215,
            SOVRAPRESSIONE_PUNZONATURA_2 = 220,
            OLTRE_QUOTA_MASSIMA_PUNZONATURA_2 = 225,
            SOVRAPRESSIONE_TRASLAZIONE_CARRO = 230,
            TIMEOUT_AVVIO_DRIVE_POMPA_IDRAULICA = 235,
            SOVRAPRESSIONE_MOVIMENTO_PUNZONE = 240,
            ALLARME_DRIVE_POMPA_IDRAULICA = 245,
            ANOMALIA_ALIMENTAZIONE_PNEUMATICA = 250,
            APERTURA_ANOMALA_PORTELLO_ROBOT = 255,
            APERTURA_ANOMALA_PORTELLO_ANTERIORE = 260,
            INTRUSIONE_ANOMALA_BARRIERE = 265,
            MACCHINA_NON_ATTIVA = 270,
            ALLARME_AREA_TRASLAZIONE_NON_LIBERA = 275,
            ANOMALIA_SALITA_PUNZONATORE = 301,
            ANOMALIA_TRASLAZIONE_CARRO = 303,
            ANOMALIA_ARRETRAMENTO_CONTRASTO_305 = 305,
            ANOMALIA_APERTURA_STAFFAGGIO = 307,
            ANOMALIA_STAFFAGGIO_PEZZO = 403,
            ANOMALIA_POSIZIONE_CONTRASTO = 405,
            ANOMALIA_PUNZONATURA_1 = 407,
            ANOMALI_TRASLAZIONE_IN_POSIZIONE_2 = 409,
            ANOMALIA_PUNZONATURA_2 = 411,
            ANOMALIA_ARRETRAMENTO_CONTRASTO_413 = 413,
            ANOMALIA_SALITA_STAFFAGGIO = 415,
            ANOMALI_TRASLAZIONE_IN_POSIZIONE_1 = 417,
            ANOMALIA_DISATTIVAZIONE_DRIVE_POMPA = 419,
        }

        #endregion Private Enums

        #region Private Methods

        /// <summary>
        /// recupero dati specifici FAPE da struttura array memoria e versione adapter
        /// </summary>
        private void ExtractFapeData()
        {
            /* ----------------------------------------------
             * NOTA:
             * - v1 (2018): 2 blocchi memoria, area DB15
             * - v2 (2024): 2 blocchi area DB17
             * - v3 (2024): 3 blocchi area DB17 (MacroStato, stato, ciclo)
             *
             * decodifico secondo conf
             * ----------------------------------------------*/
            // leggo secondo versione adapter 1/2/3...
            if (FapeVers <= 2)
            {
                valState = S7.Net.Types.Word.FromByteArray(RawInput.Skip(0).Take(2).ToArray());
                valStepCic = S7.Net.Types.Word.FromByteArray(RawInput.Skip(2).Take(2).ToArray());
            }
            else
            {
                valMain = S7.Net.Types.Word.FromByteArray(RawInput.Skip(0).Take(2).ToArray());
                valState = S7.Net.Types.Word.FromByteArray(RawInput.Skip(2).Take(2).ToArray());
                valStepCic = S7.Net.Types.Word.FromByteArray(RawInput.Skip(4).Take(2).ToArray());
            }
        }

        #endregion Private Methods
    }
}