예제 #1
0
        /// <summary>
        /// Get the Number Message of a specific sent message
        /// </summary>
        /// <param name="FID">Message's FID</param>
        /// <param name="Command">Message's command</param>
        /// <returns>Number Message</returns>
        /// <remarks>This function use the FID if the frame window is greater than 1, otherwise use the command</remarks>
        public uint Response(byte FID, byte Command)
        {
            uint        numMessage = (uint)0;
            CMessageCom message    = null;

            if (m_frameWindow > 1)
            {
                for (var i = 0; i <= m_Messages.Count - 1; i++)
                {
                    if (m_Messages[i].FID() == FID)
                    {
                        message = m_Messages[i];
                        m_Messages.RemoveAt(System.Convert.ToInt32(i));
                        break;
                    }
                }
            }
            else
            {
                if (m_Messages.Count > 0)
                {
                    if (m_Messages[0].Command() == Command)
                    {
                        message = m_Messages[0];
                        m_Messages.RemoveAt(0);
                    }
                }
            }

            if (message != null)
            {
                //Desactivamos el timer de timeout ya que no esperamos respuesta
                m_TimerConnectTimeOut.Change(Timeout.Infinite, Timeout.Infinite); //Stop the Timer

                m_ToSendFrameWindow++;
                numMessage = message.NumberMessage();

                //Si no hay mas mensajes para enviar empezamos el mantenimiento de la conexión
                if (m_Messages.Count == 0)
                {
                    m_TimerConnectMaintenance.Change(TIMER_CONNECT_MAINTENANCE, TIMER_CONNECT_MAINTENANCE); //Start the Timer
                }
            }

            TryToSend();

            return(numMessage);
        }
        private void ConnectMaintenance(byte address)
        {
            //Incrementamos el Number Message
            m_NumberMessage = System.Convert.ToUInt32(m_NumberMessage + 1);

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

            // 11/05/2016 Se cambia a SYN (como originalmente)
            CMessageCom message = new CMessageCom((uint)0, m_FID, (byte)EnumCommandFrame.M_SYN, new byte[] { }, address);

            SendMessage(message);
        }
예제 #3
0
        /// <summary>
        /// Send messages until the pending messages to response is equal to the frame window
        /// </summary>
        private void TryToSend()
        {
            while (m_ToSendFrameWindow > 0)
            {
                CMessageCom message = ReadMessage();

                if (ReferenceEquals(message, null))
                {
                    break;
                }
                else
                {
                    //Decrementamos la ventana de mensajes
                    m_ToSendFrameWindow--;

                    //Activamos el timer de timeout
                    m_TimerConnectTimeOut.Change(Timeout.Infinite, Timeout.Infinite); //Stop the Timer
                    if (message.DelayedResponse)
                    {
                        //No desactivamos el mantenimiento de la conexión ya que el tiempo de respuesta es demasiado elevado
                        m_TimerConnectMaintenance.Change(TIMER_CONNECT_MAINTENANCE, TIMER_CONNECT_MAINTENANCE);                     //Start the Timer

                        m_TimerConnectTimeOut.Change(TIME_TIMEOUT_MESSAGE_DELAYED_RESPONSE, TIME_TIMEOUT_MESSAGE_DELAYED_RESPONSE); //Start the Timer
                    }
                    else
                    {
                        //Desactivamos el mantenimiento de la conexión
                        m_TimerConnectMaintenance.Change(Timeout.Infinite, Timeout.Infinite);     //Stop the Timer

                        m_TimerConnectTimeOut.Change(TIME_TIMEOUT_MESSAGE, TIME_TIMEOUT_MESSAGE); //Start the Timer
                    }

                    //FIXME . Modo BURST solo se utiliza para la DME.
                    //Para la DME todas las comunicaciones van contra la dirección 0x00 pero cuando se envía un ACK se tiene que hacer contra la 0x10, sino, responde NACK
                    if (m_frameWindow > 1 & message.Command() == (byte)EnumCommandFrame.M_ACK)
                    {
                        message.Address = (byte)(0x10);
                    }

                    if (SendMessageEvent != null)
                    {
                        SendMessageEvent(message);
                    }
                }
            }
        }
        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 SendMessage(CMessageCom message)
        {
            m_mutexStackDll.WaitOne();
            if (m_StackDll != null)
            {
                m_StackDll.SendData(message.Data(), message.Address, message.Command(), message.FID(), message.Response());
            }
            m_mutexStackDll.Release();

            //Se notifica de los Reset para poder continuar con el updater en las estaciones de protocolo 1
            if (message.Command() == (byte)EnumCommandFrame.M_RESET)
            {
                if (ResetSendedEvent != null)
                {
                    ResetSendedEvent(message.Address);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Manage a timeout communication. Tries to resend the message. If attempts have been exhausted, raise an event
        /// </summary>
        /// <param name="state">Timer state</param>
        private void Elapsed_ConnectTimeOut(object state)
        {
            m_TimerConnectTimeOut.Change(Timeout.Infinite, Timeout.Infinite); //Stop the Timer

            if (m_Messages.Count > 0)
            {
                CMessageCom message = m_Messages[0];

                if (message.TriesRemaining() > 0)
                {
                    message.DecrementTriesRemaining();
                    m_Messages[0] = message;
                    if (message.DelayedResponse)
                    {
                        m_TimerConnectTimeOut.Change(TIME_TIMEOUT_MESSAGE_DELAYED_RESPONSE, TIME_TIMEOUT_MESSAGE_DELAYED_RESPONSE); //Start the Timer
                    }
                    else
                    {
                        m_TimerConnectTimeOut.Change(TIME_TIMEOUT_MESSAGE, TIME_TIMEOUT_MESSAGE); //Start the Timer
                    }


                    if (SendMessageEvent != null)
                    {
                        SendMessageEvent(message);
                    }
                }
                else
                {
                    m_Messages.RemoveAt(0);

                    if (ConnectionTimeOutEvent != null)
                    {
                        ConnectionTimeOutEvent(m_address, message.Command());
                    }
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Get the next message to send in the FIFO list
        /// </summary>
        /// <returns>Message to send</returns>
        private CMessageCom ReadMessage()
        {
            CMessageCom message = null;

            //Si está en modo BURST envía el siguiente que todavía no haya enviado
            if (m_frameWindow > 1)
            {
                for (var i = 0; i <= m_Messages.Count - 1; i++)
                {
                    if (m_Messages[i].TriesRemaining() == CMessageCom.MAX_MESSAGE_TRIES)
                    {
                        message = m_Messages[i];
                        message.DecrementTriesRemaining();
                        m_Messages[i] = message;

                        break;
                    }
                }

                //Si está en modo SINGLE envía el primero
            }
            else
            {
                if (m_Messages.Count > 0)
                {
                    if (m_Messages[0].TriesRemaining() == CMessageCom.MAX_MESSAGE_TRIES)
                    {
                        message = m_Messages[0];
                        message.DecrementTriesRemaining();
                        m_Messages[0] = message;
                    }
                }
            }

            return(message);
        }
        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);
            }
        }
예제 #9
0
 /// <summary>
 /// Add a new message to the FIFO list
 /// </summary>
 /// <param name="message">New message to send</param>
 public void Add(CMessageCom message)
 {
     m_Messages.Add(message);
     TryToSend();
 }