public void AddStack(byte stackAddress)
        {
            m_mutexStackAddressMessages.WaitOne();

            //Si no existe la cola la creamos
            if (!StackAddressMessageContains(stackAddress))
            {
                CStackMessages stack = new CStackMessages(stackAddress, m_frameWindow);
                StackAddressMessageAdd(stackAddress, stack);

                stack.SendMessage           += SendMessage;
                stack.ConnectionMaintenance += ConnectMaintenance;
                stack.ConnectionTimeOut     += ConnectTimeOut;
            }

            m_mutexStackAddressMessages.Release();
        }
        public uint Send(byte[] Datos, byte command, byte address, bool delayedResponse = false)
        {
            //Incrementamos el Number Message
            m_NumberMessage = System.Convert.ToUInt32(m_NumberMessage + 1);
            uint NumMessage = m_NumberMessage;

            //Incrementamos el FID
            if (m_FID >= MAX_FID)
            {
                m_FID = (byte)0;
            }
            m_FID += 1;

            //Creamos el mensaje
            CMessageCom message = new CMessageCom(m_NumberMessage, m_FID, command, Datos, address);

            message.DelayedResponse = delayedResponse;

            CStackMessages stackAddressMessages = null;

            m_mutexStackAddressMessages.WaitOne();

            //Los broadcast los enviamos directamente
            if ((address & (byte)EnumAddress.MASK_BROADCAST_ADDRESS) != (byte)EnumAddress.MASK_BROADCAST_ADDRESS)
            {
                //Si existe la cola lo ponemos en cola, sino, lo enviamos directamente
                if (StackAddressMessageContains(address & (byte)EnumAddress.MASK_STATION_ADDRESS))
                {
                    stackAddressMessages = StackAddressMessageGet(address & (byte)EnumAddress.MASK_STATION_ADDRESS);
                }
            }

            m_mutexStackAddressMessages.Release();

            if (stackAddressMessages != null)
            {
                stackAddressMessages.Add(message);
            }
            else
            {
                SendMessage(message);
            }

            return(NumMessage);
        }
        private void ConnectTimeOut(byte address, byte command)
        {
            CStackMessages stackAddressMessages = null;

            m_mutexStackAddressMessages.WaitOne();

            if (StackAddressMessageContains(address & (byte)EnumAddress.MASK_STATION_ADDRESS))
            {
                stackAddressMessages = StackAddressMessageGet(address & (byte)EnumAddress.MASK_STATION_ADDRESS);
                StackAddressMessageRemove(address & (byte)EnumAddress.MASK_STATION_ADDRESS);
            }

            m_mutexStackAddressMessages.Release();

            if (stackAddressMessages != null)
            {
                stackAddressMessages.Dispose();
            }

            if (ConnectionErrorEvent != null)
            {
                ConnectionErrorEvent(EnumConnectError.TIME_OUT, address, command);
            }
        }
        private void DataReceived(byte Origen, byte Command, byte[] Data, byte FID, bool Response)
        {
            uint           NumMessage           = (uint)0;
            CStackMessages stackAddressMessages = null;

            //Si es un HandShake respondemos directamente
            if (Command == (byte)EnumCommandFrame.M_NULL)
            {
                if (Response)
                {
                    return;
                }

                byte[] Datos = new byte[1];
                Datos[0] = (byte)EnumCommandFrame.M_ACK;

                CMessageCom message = new CMessageCom((uint)0, (byte)(0xFD), Command, Datos, Origen, true);
                SendMessage(message);
            }
            else if (Command == (byte)EnumCommandFrame.M_NACK)
            {
                m_mutexStackAddressMessages.WaitOne();
                if (m_htStackAddressMessages != null)
                {
                    //Respuesta de una dirección a la que hemos enviado un mensaje
                    if (StackAddressMessageContains(Origen & (byte)EnumAddress.MASK_STATION_ADDRESS))
                    {
                        stackAddressMessages = StackAddressMessageGet(Origen & (byte)EnumAddress.MASK_STATION_ADDRESS);
                    }
                }
                m_mutexStackAddressMessages.Release();

                //Recuperar número de mensaje y eliminarlo de la lista
                if (stackAddressMessages != null)
                {
                    NumMessage = stackAddressMessages.Response(FID, Data[(byte)EnumErrorFrame.Opcode]);
                }
            }
            else
            {
                //FIXME . Modo BURST solo se utiliza para la DME.
                //Para la DME todas las comunicaciones van contra la dirección 00 pero cuando se envía un ACK se tiene que hacer contra la 10, sino, responde NACK
                if (m_flowControlMethod == EnumFrameFlowControl.BURST & Command == (byte)EnumCommandFrame.M_ACK)
                {
                    Origen = (byte)0;
                }

                m_mutexStackAddressMessages.WaitOne();
                if (m_htStackAddressMessages != null)
                {
                    //Respuesta de una dirección a la que hemos enviado un mensaje
                    if (StackAddressMessageContains(Origen & (byte)EnumAddress.MASK_STATION_ADDRESS))
                    {
                        stackAddressMessages = StackAddressMessageGet(Origen & (byte)EnumAddress.MASK_STATION_ADDRESS);
                    }
                }
                m_mutexStackAddressMessages.Release();

                //Recuperar número de mensaje y eliminarlo de la lista
                if (stackAddressMessages != null)
                {
                    NumMessage = stackAddressMessages.Response(FID, Command);
                }
            }

            if (MessageResponseEvent != null)
            {
                MessageResponseEvent(NumMessage, Data, Command, Origen);
            }
        }