Ejemplo n.º 1
0
 /// <summary>
 ///     入队一条指令
 /// </summary>
 /// <param name="allowDiscard">是否允许丢弃该指令</param>
 /// <param name="cmdEventHandler">串口指令事件处理器</param>
 /// <param name="sendCMDTimeout">发送指令超时时长(毫秒)</param>
 /// <param name="reciveDataTimeout">接收数据超时时长(毫秒)</param>
 /// <param name="cmd">指令</param>
 public void EnqueueBytes(Boolean allowDiscard, SerialPortCMDEventHandler cmdEventHandler, int sendCMDTimeout, int reciveDataTimeout, byte[] cmd)
 {
     if (!useCMDQueue)
     {
         System.Console.WriteLine("不使用队列的串口设备不能调用此方法");
         return;
     }
     CMDQueue.Enqueue(allowDiscard, cmdEventHandler, sendCMDTimeout, reciveDataTimeout, cmd);
 }
Ejemplo n.º 2
0
        /// <summary>
        ///     关闭串口
        /// </summary>
        internal void Close()
        {
            IsClosed = true;
            if (OpenStatusListenerTimer != null)
            {
                try
                {
                    OpenStatusListenerTimer.Dispose();
                }
                catch (Exception ex)
                {
                    System.Console.Write(ex);
                    OpenStatusListenerTimer = null;
                }
            }

            if (AfterOpenEventHandlerListenerTimer != null)
            {
                try
                {
                    AfterOpenEventHandlerListenerTimer.Dispose();
                }
                catch (Exception ex)
                {
                    System.Console.Write(ex);
                    AfterOpenEventHandlerListenerTimer = null;
                }
            }

            if (CMDQueue != null)
            {
                try
                {
                    CMDQueue.Dispose();
                }
                catch (Exception ex)
                {
                    System.Console.Write(ex);
                    CMDQueue = null;
                }
            }

            if (serialPort == null)
            {
                return;
            }

            try
            {
                serialPort.Close();// 尝试关闭
            }
            catch (Exception ex)
            {
                System.Console.Write(ex);
                serialPort = null;
            }
        }
        private int byteLength   = 0;  // 部分响应信息字节长度

        /// <summary>
        ///     开始打开串口
        /// </summary>
        /// <param name="SerialDataReceivedEventHandlerX">串口数据接收事件处理器扩展</param>
        /// <param name="BeforeOpen">尝试打开串口前操作</param>
        /// <param name="OpenSuccess">尝试打开串口成功操作</param>
        /// <param name="OpenError">尝试打开串口失败操作</param>
        /// <param name="StillOpen">仍处于打开状态操作</param>
        /// <param name="Disconnect">已经断开操作</param>
        /// <param name="BeforeReOpen">尝试重新打开串口前操作</param>
        /// <param name="ReOpenSuccess">尝试重新打开串口成功操作</param>
        /// <param name="ReOpenError">尝试重新打开串口失败操作</param>
        /// <param name="AfterOpen">串口打开后操作</param>
        internal void Start(
            SerialDataReceivedEventHandlerX SerialDataReceivedEventHandlerX,
            BeforeOpen BeforeOpen,
            OpenSuccess OpenSuccess,
            OpenError OpenError,
            StillOpen StillOpen,
            Disconnect Disconnect,
            BeforeReOpen BeforeReOpen,
            ReOpenSuccess ReOpenSuccess,
            ReOpenError ReOpenError,
            AfterOpen AfterOpen
            )
        {
            // 设置串口数据接收事件处理器
            serialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler((sender, e) =>
            {
                if (IsClosed)
                {
                    return;
                }
                byte[] readedBytes = new byte[serialPort.BytesToRead];
                int byteLength     = readedBytes.Length;
                if (byteLength == 0)
                {
                    CMDQueue.CancelCurrentCMD();
                    return;
                }
                serialPort.Read(readedBytes, 0, byteLength);
                String hexString = HexUtils.BytesToHexString(readedBytes, true).Trim();
                if ("".Equals(hexString))
                {
                    CMDQueue.CancelCurrentCMD();
                    return;
                }
                if (ModbusUtils.IsFullCmd(hexString))
                {
                    if (useCMDQueue)
                    {
                        CMDQueue.FinishCurrentCMD(hexString);
                    }
                    SerialDataReceivedEventHandlerX?.Invoke(this.sid, this.portName, hexString);
                    this.hexString  = "";
                    this.byteLength = 0;
                }
                else
                {
                    this.hexString  += " " + hexString;
                    this.hexString   = this.hexString.Trim();
                    this.byteLength += byteLength;
                    if (ModbusUtils.IsFullCmd(this.hexString))
                    {
                        if (useCMDQueue)
                        {
                            CMDQueue.FinishCurrentCMD(hexString);
                        }
                        SerialDataReceivedEventHandlerX?.Invoke(this.sid, this.portName, this.hexString);
                        this.hexString  = "";
                        this.byteLength = 0;
                    }
                }
            });

            // 每100毫秒执行一次指令队列
            if (useCMDQueue)
            {
                CMDQueue = new SerialPortCMDQueue(this.sid, this.portName, serialPort);
                CMDQueue.Start();
            }

            BeforeOpen?.Invoke(this.sid, this.portName);      // 尝试打开串口前操作
            if (this.Open())                                  // 尝试打开串口
            {
                OpenSuccess?.Invoke(this.sid, this.portName); // 尝试打开串口成功操作
                OpenStatus = true;
                if (AfterOpen != null)
                {
                    AfterOpenEventHandlerListenerTimer = new Timer((obj) =>
                    {
                        AfterOpen(this.sid, this.portName);// 串口打开后操作
                    }, null, 0, this.afterOpenEventHandlerPeriod);
                }
            }
            else
            {
                OpenError?.Invoke(this.sid, this.portName);// 尝试打开串口失败操作
                OpenStatus = null;
                if (AfterOpen != null)
                {
                    AfterOpenEventHandlerListenerTimer = new Timer((obj) =>
                    {
                        if (IsClosed)
                        {
                            return;
                        }
                        AfterOpen(this.sid, this.portName);// 串口打开后操作
                    }, null, Timeout.Infinite, Timeout.Infinite);
                }
            }
            // 无论打开成功与否,后续都需要监听该串口是否处于打开状态。
            OpenStatusListenerTimer = new Timer((o) =>
            {
                if (IsClosed)
                {
                    return;
                }
                switch (OpenStatus)                                         // 上一次的串口打开状态
                {
                case null:                                                  // 首次打开串口失败
                case false:                                                 // 后续打开串口失败
                    {
                        BeforeReOpen?.Invoke(this.sid, this.portName);      // 尝试重新打开串口前操作
                        if (this.Open())                                    // 尝试重新打开串口
                        {
                            ReOpenSuccess?.Invoke(this.sid, this.portName); // 尝试重新打开串口成功操作
                            OpenStatus = true;
                            if (AfterOpen != null)
                            {
                                AfterOpenEventHandlerListenerTimer.Change(0, this.afterOpenEventHandlerPeriod);    // 重新开启计时器
                            }
                        }
                        else
                        {
                            ReOpenError?.Invoke(this.sid, this.portName);    // 尝试重新打开串口失败
                            OpenStatus = false;
                        }
                    }
                    break;

                case true:                                              // 首次或后续打开串口成功
                    {
                        if (serialPort.IsOpen)                          // 仍处于打开状态
                        {
                            StillOpen?.Invoke(this.sid, this.portName); // 仍处于打开状态操作
                            OpenStatus = true;
                        }
                        else                                             // 已经断开
                        {
                            Disconnect?.Invoke(this.sid, this.portName); // 已经断开操作
                            OpenStatus = false;
                            if (AfterOpen != null)
                            {
                                AfterOpenEventHandlerListenerTimer.Change(Timeout.Infinite, Timeout.Infinite);    // 暂停计时器
                            }
                        }
                    }
                    break;
                }
            }, null, this.checkOpenStatusPeriod, this.checkOpenStatusPeriod);
        }