示例#1
0
        /// <summary>
        /// 分发响应
        /// </summary>
        /// <param name="cmdId">响应报文命令ID</param>
        /// <param name="payload">响应负载</param>
        /// <param name="length">响应负载长度</param>
        private void dispatchResponse(enCmd cmdId, byte[] payload, byte length)
        {
            eRC rc = (eRC)payload[0];

            m_u8RxDataLen = (byte)(length - 1);
            Array.Copy(payload, 1, m_u8aRxData, 0, m_u8RxDataLen);
            // 检查接收到的命令id是否与请求的id相同
            if (cmdId == m_ReqCmdId)
            {
                if (m_evReplyArrived != null)
                {
                    // call the callback
                    m_evReplyArrived(cmdId, rc, m_u8aRxData, m_u8RxDataLen);
                    // reset
                    m_ReqCmdId = enCmd.CMDID_END;
                    // Kous: 注销事件处理函数的方式可能存在问题
                    m_evReplyArrived = null;
                    // Kous: 清空接收数据缓存
                    Array.Clear(m_u8aRxData, 0, m_u8RxDataLen);
                    m_u8RxDataLen = 0;
                }
                else
                {
                    CommStackLog.RecordErr(enLogLayer.eSerial, "m_evReplyArrived=null");
                }
            }
            else
            {
                CommStackLog.RecordErr(enLogLayer.eSerial, "cmdId=" + cmdId.ToString() + " m_ReqCmdId=" + m_ReqCmdId.ToString());
            }
        }
示例#2
0
        /// <summary>
        /// 发送请求去报文
        /// </summary>
        /// <param name="cmdId">输出报文的命令ID</param>
        /// <param name="isAck">输出报文是否为响应报文</param>
        /// <param name="shouldBeAcked">输出报文是否需要响应</param>
        /// <param name="payload">输出报文的负载</param>
        /// <param name="length">输出报文的负载长度</param>
        /// <param name="replyCb">响应回调函数</param>
        /// <param name="bRetry">是否为重发报文</param>
        /// <returns>错误码</returns>
        private enErrCode sendRequestNoCheck(enCmd cmdId,
                                             bool isAck,
                                             bool shouldBeAcked,
                                             byte[]    payload,
                                             byte length,
                                             DlgtReply replyCb,
                                             bool bRetry = false)
        {
            byte control = 0;

            // register reply callback
            m_ReqCmdId       = cmdId;
            m_evReplyArrived = replyCb;

            // create the control byte
            if (isAck)
            {
                control |= FLAG_ACK;
            }
            else
            {
                control |= FLAG_DATA;
            }

            if (shouldBeAcked)
            {
                control |= FLAG_ACKNOWLEDGED;
            }
            else
            {
                control |= FLAG_UNACKNOWLEDGED;
            }

            lock (m_hdlcore)
            {
                // send the frame over serial
                if (bRetry)
                {
                    m_u8TxPacketId--;
                }

                if (!output1Frame(control, (byte)cmdId, m_u8TxPacketId, length, payload))
                {
                    return(enErrCode.ERR_INVALID_PARAM);
                }
                // increment the txPacketId
                m_u8TxPacketId++;
            }

            return(enErrCode.ERR_NONE);
        }
示例#3
0
 /// <summary>
 /// 发送请求去报文
 /// </summary>
 /// <param name="cmdId">输出报文的命令ID</param>
 /// <param name="isAck">输出报文是否为响应报文</param>
 /// <param name="payload">输出报文的负载</param>
 /// <param name="length">输出报文的负载长度</param>
 /// <param name="replyCb">响应回调函数</param>
 /// <param name="bRetry">是否为重发报文</param>
 /// <returns>错误码</returns>
 public enErrCode SendRequest(enCmd cmdId,
                              bool isAck,
                              byte[]    payload,
                              byte length,
                              DlgtReply replyCb,
                              bool bRetry = false)
 {
     // abort if not connected
     if (m_SerStatus != enSerStatus.SER_ST_CONNECTED)
     {
         return(enErrCode.ERR_NOT_CONNECTED);
     }
     // send the request
     return(sendRequestNoCheck(cmdId, isAck, !isAck, payload, length, replyCb, bRetry));
 }
示例#4
0
        public void Reset()
        {
            // 重置底层
            if (m_Ser != null)
            {
                m_Ser.Reset();
            }

            m_bBusyTx          = false;
            m_u8CmdId          = enCmd.CMDID_END;
            m_u8OutputBufLen   = 0;
            Adapter2MeshBridge = null;
            lock (m_dicAsyncCmdRespRecords)
            {
                m_dicAsyncCmdRespRecords.Clear();
            }

            m_asigMgrResponsed.Reset();
        }
示例#5
0
        /// <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;
            }
        }