/// <summary>
 /// 进行会话初始化工作,即发送Hello报文
 /// </summary>
 /// <returns>错误码</returns>
 public enErrCode InitiateConnect()
 {
     byte[] payload = new byte[3];
     // 重置client sequence number
     m_u8TxPacketId = 0;
     // prepare hello packet
     payload[0] = API_VERSION;            // version
     payload[1] = m_u8TxPacketId;         // cliSeqNo
     payload[2] = 0;                      // mode
     // send hello packet
     sendRequestNoCheck(enCmd.CMID_HELLO, // cmdId
                        false,            // isAck
                        false,            // shouldBeAcked
                        payload,          // payload
                        3,                // length
                        null);            // replyCb
     // remember state
     m_SerStatus = enSerStatus.SER_ST_HELLO_SENT;
     return(enErrCode.ERR_NONE);
 }
Exemple #2
0
        /// <summary>
        /// 会话状态变更回调函数,Serial层通过此函数通知Session层,当前会话状态变更
        /// </summary>
        /// <param name="newStatus">新的会话状态</param>
        private void SessionStatusChanged(enSerStatus newStatus)
        {
            switch (newStatus)
            {
            case enSerStatus.SER_ST_DISCONNECTED:
            {
                Status = newStatus;
                CommStackLog.RecordInf(enLogLayer.eSession, "Disconnected!");
                m_sigDisconnected.Set();
                m_sigConnected.Reset();
                m_sigSessionOK.Reset();
                // 然后通知上层新的会话需求
                if (SessionLost != null)
                {
                    SessionLost();
                }

                break;
            }

            case enSerStatus.SER_ST_CONNECTED:
            {
                Status = newStatus;
                CommStackLog.RecordInf(enLogLayer.eSession, "Connected!");
                m_sigDisconnected.Reset();
                // 新的会话构建完成,设置通知信号量
                m_sigConnected.Set();
                m_sigSessionOK.Set();

                if (SessionBuilt != null)
                {
                    SessionBuilt();
                }

                break;
            }

            default:
                break;
            }
        }
        /// <summary>
        /// 接受新的数据帧解析函数
        /// </summary>
        /// <param name="rxFrame">帧数据及</param>
        /// <param name="rxFrameLen">帧长度</param>
        private void rxHdlcFrame(byte[] rxFrame, byte rxFrameLen)
        {
            if (rxFrame == null)
            {
                return;
            }
            if (isInvalidCmd(rxFrame[1]))
            {
                CommStackLog.RecordErr(enLogLayer.eSerial, "Err cmd(0x" + rxFrame[1].ToString("X2") + ")");
                return;
            }

            bool isAck       = false;
            bool shouldAck   = false;
            bool isRepeatId  = false;
            bool isNotifData = false;

            //接收报文的个数
            m_i32RxFrameCnt++;
            // parse header
            m_u8RxControl = rxFrame[0];
            m_RxCmdId     = (enCmd)rxFrame[1];
            m_u8RxSeqNum  = rxFrame[2];
            m_u8RxPyldLen = rxFrame[3];
            enNotifyType notType = (enNotifyType)rxFrame[4];

            if (m_RxCmdId == enCmd.CMDID_NOTIFICATION &&
                (notType == enNotifyType.NOTIFID_NOTIFDATA || notType == enNotifyType.NOTIFID_NOTIFEVENT))
            {
                isNotifData = true;
            }

            // 提取出HDLC帧中负载数据
            Array.Copy(rxFrame, 4, m_u8aRxPayload, 0, m_u8RxPyldLen);
            // 解析接受到的HDLC帧是响应帧还是数据帧(请求帧)
            isAck = ((m_u8RxControl & FLAG_ACK) != 0);
            // 如果HDLC帧是数据帧解析接受到的HDLC帧是否需要应答
            shouldAck = ((m_u8RxControl & FLAG_ACKNOWLEDGED) != 0);
            // 应答报文
            if (isAck)
            {
                // 通知上层响应帧到达
                if (m_u8RxPyldLen > 0)
                {
                    // Kous: 是上层应用请求的响应报文,回调上层应用定义的响应通知函数
                    dispatchResponse(m_RxCmdId, m_u8aRxPayload, m_u8RxPyldLen);
                }
            }
            // 请求报文
            else
            {
                // 非数据通知时才检测更新m_u8RxPacketId
                if (!isNotifData)
                {
                    // 是否为重复请求报文
                    if (m_bRxPacketIdInit && m_u8RxSeqNum == m_u8RxPacketId)
                    {
                        CommStackLog.RecordInf(enLogLayer.eSerial, "SO(" + m_u8RxSeqNum.ToString() + ") repeats");
                        isRepeatId = true;
                    }
                    else
                    {
                        isRepeatId        = false;
                        m_bRxPacketIdInit = true;
                        m_u8RxPacketId    = m_u8RxSeqNum; // 记录接收到的报文序列号
                    }
                }
                // 如果报文是需要响应的报文,则在Ser层直接回应
                if (shouldAck)
                {
                    byte   len     = 1;
                    byte[] payload = new byte[len];
                    payload[0] = (byte)eRC.RC_OK;
                    //Thread.Sleep(20);
                    output1Frame(FLAG_ACK | FLAG_ACKNOWLEDGED, (byte)m_RxCmdId, m_u8RxPacketId, len, payload, true);
                }

                switch (m_RxCmdId)
                {
                case enCmd.CMID_HELLO_RESPONSE:
                {
                    if (m_u8RxPyldLen >= 5 &&
                        m_u8aRxPayload[HELLO_RESP_OFFS_RC] == 0 &&
                        m_u8aRxPayload[HELLO_RESP_OFFS_VERSION] == API_VERSION)
                    {
                        // change state
                        m_SerStatus = enSerStatus.SER_ST_CONNECTED;
                        // record manager sequence number
                        m_bRxPacketIdInit = true;
                        m_u8RxPacketId    = m_u8aRxPayload[HELLO_RESP_OFFS_MGRSEQNO];
                        // 通知会话层新的会话已经建立
                        if (m_evStatusChanged != null)
                        {
                            m_evStatusChanged(m_SerStatus);
                        }

                        // 新的会话建立完成,则下发CLI命令
                        m_hdlcore.MoniterCli();
                    }
                    ;
                    break;
                }

                case enCmd.CMID_MGR_HELLO:
                {
                    // 以下8行用于过滤短时间内收到的重复MgrHello报文
                    TimeSpan tsMgrHello = DateTime.Now - m_dtLastMgrHello;
                    m_dtLastMgrHello = DateTime.Now;
                    // 4秒内收到的MgrHello认为为重复
                    if (tsMgrHello.TotalMilliseconds < 2000)
                    {
                        CommStackLog.RecordInf(enLogLayer.eSerial, "Redundant MgrHello");
                        break;
                    }
                    // 以上8行用于过滤短时间内收到的重复MgrHello报文

                    if (m_u8RxPyldLen >= 2)
                    {
                        // change state
                        m_SerStatus = enSerStatus.SER_ST_DISCONNECTED;
                        // 通知会话层新的当前会话已经失效
                        if (m_evStatusChanged != null)
                        {
                            m_evStatusChanged(m_SerStatus);
                        }
                    }
                    break;
                }

                default:
                {
                    // dispatch
                    //if (m_u8RxPyldLen > 0 && m_evRequestArrived != null && isRepeatId == false)
                    //    m_evRequestArrived(m_RxCmdId, m_u8RxControl, m_u8aRxPayload, m_u8RxPyldLen);
                    if (m_u8RxPyldLen > 0 && m_evRequestArrived != null)
                    {
                        if (isNotifData)
                        {
                            m_evRequestArrived(m_RxCmdId, m_u8RxControl, m_u8aRxPayload, m_u8RxPyldLen);
                        }
                        else if (isRepeatId == false)
                        {
                            m_evRequestArrived(m_RxCmdId, m_u8RxControl, m_u8aRxPayload, m_u8RxPyldLen);
                        }
                    }

                    break;
                }
                }

                // Kous: 清空接收负载缓存
                Array.Clear(m_u8aRxPayload, 0, m_u8RxPyldLen);
                m_u8RxPyldLen = 0;
            }
        }