//数据包处理函数 private void PacketHandler(SerialRecvMsg recvMsg) { if (recvMsg.PacketData.PacketIsAck()) //判断是否是响应数据包, 若是响应, 则将其从重发字典中移除 { recvMsg.PacketData.generateSendUType(); string key = recvMsg.PacketData.SendUType; if (key != null) { lock (resendDic) { if (resendDic.ContainsKey(key)) { resendDic.Remove(key); } } } } #if DEBUG //将发送消息投入调试接收队列中 if (SerialComDebug.isPauseDebug == false) //若当前不是暂停状态 { recvMsg.RecvTime = DateTime.Now; //记录时间 this.DebugQueue_Enqueue(recvMsg); } #endif recvMsg.IsFromExtern = true; //外部消息 this.RecvQueue_Enqueue(recvMsg); //投入接收消息队列中 }
//串口数据接收状态机 private void RecvPacketStateMachine(byte RecvByte) { switch (CurrentRecvState) { case RECVPACKSTATE.IdleState: //空闲态 if (RecvByte == (byte)0x5A) { CurrentRecvState = RECVPACKSTATE.StartFieldState; } else { CurrentRecvState = RECVPACKSTATE.IdleState; } break; case RECVPACKSTATE.StartFieldState: //接收起始符 if (RecvByte == (byte)0xA5) { CurrentRecvState = RECVPACKSTATE.DataPacketState; DataCnt = 0; } else { CurrentRecvState = RECVPACKSTATE.IdleState; } break; case RECVPACKSTATE.DataPacketState: //接收数据 if (DataCnt < 19) { RecvDataField[DataCnt] = RecvByte; DataCnt++; CurrentRecvState = RECVPACKSTATE.DataPacketState; } else { RecvDataField[DataCnt] = RecvByte; //若校验通过, 则解析数据 if (AppUtil.GetChecksum(RecvDataField, 0, 19) == RecvDataField[19]) { byte DIRECT = (byte)(RecvDataField[0] >> 4); //指令方向, 先过滤一些数据 if (DIRECT == 0x02 || DIRECT == 0x04 || DIRECT == 0x08) //2:(终端-主机), 4:(中继-主机), 8:(非本组设备之间的通信) { SerialRecvMsg recvMsg = new SerialRecvMsg(); Array.Copy(RecvDataField, 0, recvMsg.PacketData.DataBytes, 2, RecvDataField.Length); recvMsg.PacketData.updateDataBytesToField(); //将接收到的字节更新到数据包的各个字段(如dir, path, cmd等) PacketHandler(recvMsg); } } CurrentRecvState = RECVPACKSTATE.IdleState; } break; default: CurrentRecvState = RECVPACKSTATE.IdleState; break; } }
//从接收队列中取走消息, 返回null代表无消息 public SerialRecvMsg RecvQueue_Dequeue() { SerialRecvMsg recvMsg = null; if (serialRecvQueue.Count > 0) { lock (this.serialRecvQueue) { recvMsg = serialRecvQueue.Dequeue(); } } return(recvMsg); }
//向接收队列中投递消息 public bool RecvQueue_Enqueue(SerialRecvMsg recvMsg) { lock (this.serialRecvQueue) { serialRecvQueue.Enqueue(recvMsg); } RecvQueueWaitHandle.Set(); return(true); }
//从重发字典中取出消息, 判断是否超时, 然后投入"底层发送队列" private void SerialResend() { DateTime dtNow; List <string> list = new List <string>(); while (true) { if (serialPortIsOpen && (resendDic.Count > 0)) { lock (resendDic) { dtNow = DateTime.Now; list.Clear(); //遍历重发字典, 查找超时的消息, 并进行响应操作 foreach (var sendMsg in resendDic) { if ((int)((dtNow - sendMsg.Value.SendTime).TotalMilliseconds) > sendMsg.Value.SendWaitTime) //若超时 { list.Add(sendMsg.Key); //将超时消息的键存入list中, 为后面的移除工作做准备 if (sendMsg.Value.SendNumMax > 0) //若重发次数大于0, 则继续投入发送队列中 { this.SendQueue_Enqueue(sendMsg.Value); } else //若不能再重发了, 则投入接收处理的队列中 { SerialRecvMsg recvMsg = new SerialRecvMsg(); recvMsg.PacketData = sendMsg.Value.PacketData; //将发送命令变为响应 if (recvMsg.PacketData.Cmd != 0x09) { recvMsg.PacketData.Cmd += 1; } else { recvMsg.PacketData.Cmd = 0x10; } recvMsg.IsFromExtern = false; //内部消息(由于多次重发还是未收到响应导致) this.RecvQueue_Enqueue(recvMsg); //投入接收消息队列中 #if DEBUG //将发送消息投入调试队列中 if (SerialComDebug.isPauseDebug == false) //若当前不是暂停状态 { recvMsg.RecvTime = DateTime.Now; //记录时间 this.DebugQueue_Enqueue(recvMsg); } #endif } } } //将超时消息从重发字典中移除 if (list.Count > 0) { foreach (string key in list) { resendDic.Remove(key); } } } } Thread.Sleep(5); } }