/// <summary> /// 将命令发送到发送缓冲区 /// </summary> /// <param name="Address"> /// 地址: /// 作为下行通信协议,应填写设备的硬件地址 /// 作为上行通信协议,可不填 /// </param> /// <param name="AFN">功能码</param> /// <param name="DataArea"> /// 包括帧头、帧尾(但不包括校验)的完整报文数据 /// important:根据协议的具体实现有所不同 /// </param> /// <param name="NeedReply">该报文是否需要回复</param> /// <param name="IPAddr"> /// 通信数据目标的IP地址:仅供TCP Server通信方式使用 /// </param> /// <param name="sync"> /// 用于同步通信的通信状态控制:比如用于顺序发送文件等。平常的数据通信不使用此重载 /// </param> /// <returns></returns> public virtual bool Main_SendToCache(int Address, int AFN, byte[] DataArea, bool NeedReply, string IPAddr, ref ProtocolSyncStatus sync) { /// 通信未连接则不发送到缓冲区 if (!this.m_Comm.Connected) { return(false); } ProtocolFrameStruct se1 = new ProtocolFrameStruct(Address, AFN); SyncStatus.Success = false; try { se1.DataArea = DataArea; se1.NeedReply = NeedReply; se1.IPAddr = IPAddr; se1.WaitingFlag = false; se1.ResendCount = 0; lock (SendCacheLock) { SendCache.Enqueue(se1); } sync = SyncStatus; return(true); } catch { return(false); } }
/// <summary> /// 完全克隆一个协议帧 /// </summary> /// <returns></returns> public ProtocolFrameStruct Clone() { ProtocolFrameStruct item = (ProtocolFrameStruct)this.MemberwiseClone(); // 因为数组是对象,浅表副本只复制引用,所以要处理一下 byte[] data = (byte[])this.DataArea.Clone(); item.DataArea = data; return(item); }
/// <summary> /// 将一个完整的接收报文发送到接收缓冲区等待处理 /// </summary> /// <param name="Address"> /// 地址: /// 作为下行通信协议,应填写设备的硬件地址 /// 作为上行通信协议,应填写RTU的站地址 /// </param> /// <param name="AFN">功能码</param> /// <param name="DataArea">包括帧头、帧尾(但不包括校验)的完整报文数据</param> /// <param name="IPAddr"> /// 通信数据目标的IP地址:仅供TCP Server通信方式使用 /// </param> /// <returns></returns> public virtual bool Main_RecvToCache(int Address, int AFN, byte[] DataArea, string IPAddr) { ProtocolFrameStruct re1 = new ProtocolFrameStruct(Address, AFN); try { re1.DataArea = DataArea; re1.IPAddr = IPAddr; lock (RecvCacheLock) { RecvCache.Enqueue(re1); } return(true); } catch { return(false); } }
/// <summary> /// 标准的通信协议发送处理驱动 /// </summary> public virtual void Main_CommDriver_Send() { try { // 将发送缓冲区中的第一个命令发送出去 if (SendCache.Count > 0) { se = SendCache.Peek(); if (se.WaitingFlag) { //当前命令已经发送,正在等待 Main_CommDriver_Resend(); } else { //发送一个新的命令 se.SendTick = HyTick.TickTimeGet(); Main_SendCmd(); if (se.NeedReply) { // 需要等待回复的报文:应该置标志并等待接收、重发等处理 se.WaitingFlag = true; } else { // 不需要等待回复的报文:应该直接从发送缓冲区清除 lock (SendCacheLock) { SendCache.Dequeue(); } } } } } catch (Exception ex) { //System.Windows.Forms.MessageBox.Show("方法Main_CommDriver_Send()出现了错误!" + ex.Message); } }
/// <summary> /// 标准的通信协议接收处理驱动 /// </summary> public virtual void Main_CommDriver_Recv() { try { // 把接收缓冲区中所有的报文都处理完 while (RecvCache.Count > 0) { re = RecvCache.Peek(); if (Frame_Analysis()) { ///协议通信正常 if (m_HardAddress != null) { if (m_HardAddress.ContainsKey(re.Address)) { m_HardAddress[re.Address].ErrorCount = 0; m_HardAddress[re.Address].CommStatus = true; } } else { this.m_CommStatus = true; this.m_ErrorCount = 0; } } else { } lock (RecvCacheLock) { RecvCache.Dequeue(); } } } catch (Exception ex) { //System.Windows.Forms.MessageBox.Show("方法Main_CommDriver_Recv()出现了错误!" + ex.Message); } }
/// <summary> /// 标准的通信协议轮询处理驱动 /// </summary> public virtual void Polling_Driver() { try { /// 通信未连接则不进行轮询 if (!this.m_Comm.Connected) { return; } // 定时把轮询的报文发送到发送缓冲区中 if (this.PollingList.Count == 0) { return; } // 若发送缓冲区非空,则意味着前次的轮询未完或者有命令正在处理,目前可以不轮询 if (SendCache.Count > 0) { return; } if (this.m_PollingIndex == 0) { ///表示要开始一次新的轮询周期 if (m_TimeDifferenceCalcFlag_Polling) { m_TimeDifferenceCalcFlag_Polling = false; //记录上次轮询所花费的时间 this.m_LastPollingPeriod = HyTick.TickTimeDifference(this.m_PollingTick, HyTick.TickTimeGet()); if (this.m_MinPollingPeriod > this.m_LastPollingPeriod) { this.m_MinPollingPeriod = this.m_LastPollingPeriod; } } if (!HyTick.TickTimeIsArrived(this.m_PollingTick, this.m_PollingInterval)) { return; } ///记录本次轮询周期开始的时刻 this.m_PollingTick = HyTick.TickTimeGet(); m_TimeDifferenceCalcFlag_Polling = true; } // 现在可以把当前的一个轮询报文发送到缓冲区 ProtocolFrameStruct pl = PollingList[this.m_PollingIndex].Clone(); pl.NeedReply = true; pl.ResendCount = 0; pl.WaitingFlag = false; lock (SendCacheLock) { SendCache.Enqueue(pl); this.m_PollingIndex++; this.m_PollingIndex %= PollingList.Count; } } catch (Exception ex) { //System.Windows.Forms.MessageBox.Show("方法Polling_Driver()出现了错误!" + ex.Message); } }