| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 | using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.IO.Ports;using System.Threading;using MECF.Framework.RT.Core.ThreadLock;using log4net.Core;namespace MECF.Framework.RT.Core.IoProviders.Siemens.Serial{    /// <summary>    /// 所有串行通信类的基类,提供了一些基础的服务    /// </summary>    public class SerialBase    {        #region Constructor        /// <summary>        /// 实例化一个无参的构造方法        /// </summary>        public SerialBase( )        {            SP_ReadData = new SerialPort( );            hybirdLock = new SimpleHybirdLock( );        }        #endregion        #region Public Method        /// <summary>        /// 初始化串口信息,9600波特率,8位数据位,1位停止位,无奇偶校验        /// </summary>        /// <param name="portName">端口号信息,例如"COM3"</param>        public void SerialPortInni( string portName )        {            SerialPortInni( portName, 9600 );        }        /// <summary>        /// 初始化串口信息,波特率,8位数据位,1位停止位,无奇偶校验        /// </summary>        /// <param name="portName">端口号信息,例如"COM3"</param>        /// <param name="baudRate">波特率</param>        public void SerialPortInni( string portName, int baudRate )        {            SerialPortInni( portName, baudRate, 8, StopBits.One, Parity.None );        }        /// <summary>        /// 初始化串口信息,波特率,数据位,停止位,奇偶校验需要全部自己来指定        /// </summary>        /// <param name="portName">端口号信息,例如"COM3"</param>        /// <param name="baudRate">波特率</param>        /// <param name="dataBits">数据位</param>        /// <param name="stopBits">停止位</param>        /// <param name="parity">奇偶校验</param>        public void SerialPortInni( string portName, int baudRate, int dataBits, StopBits stopBits, Parity parity )        {            if (SP_ReadData.IsOpen)            {                return;            }            SP_ReadData.PortName     = portName;    // 串口            SP_ReadData.BaudRate     = baudRate;    // 波特率            SP_ReadData.DataBits     = dataBits;    // 数据位            SP_ReadData.StopBits     = stopBits;    // 停止位            SP_ReadData.Parity       = parity;      // 奇偶校验        }        /// <summary>        /// 根据自定义初始化方法进行初始化串口信息        /// </summary>        /// <param name="initi">初始化的委托方法</param>        public void SerialPortInni( Action<SerialPort> initi )        {            if (SP_ReadData.IsOpen)            {                return;            }            SP_ReadData.PortName = "COM5";            SP_ReadData.BaudRate = 9600;            SP_ReadData.DataBits = 8;            SP_ReadData.StopBits = StopBits.One;            SP_ReadData.Parity = Parity.None;            initi.Invoke( SP_ReadData );        }        /// <summary>        /// 打开一个新的串行端口连接        /// </summary>        public void Open( )        {            if (!SP_ReadData.IsOpen)            {                SP_ReadData.Open( );                InitializationOnOpen( );            }        }        /// <summary>        /// 获取一个值,指示串口是否处于打开状态        /// </summary>        /// <returns>是或否</returns>        public bool IsOpen( )        {            return SP_ReadData.IsOpen;        }        /// <summary>        /// 关闭端口连接        /// </summary>        public void Close( )        {            if(SP_ReadData.IsOpen)            {                ExtraOnClose( );                SP_ReadData.Close( );            }        }        /// <summary>        /// 读取串口的数据        /// </summary>        /// <param name="send">发送的原始字节数据</param>        /// <returns>带接收字节的结果对象</returns>        public OperateResult<byte[]> ReadBase(byte[] send)        {            hybirdLock.Enter( );            if (IsClearCacheBeforeRead) ClearSerialCache( );            OperateResult sendResult = SPSend( SP_ReadData, send );            if (!sendResult.IsSuccess)            {                hybirdLock.Leave( );                return OperateResult.CreateFailedResult<byte[]>( sendResult );            }            OperateResult<byte[]> receiveResult = SPReceived( SP_ReadData, true );            hybirdLock.Leave( );            return receiveResult;        }        /// <summary>        /// 清除串口缓冲区的数据,并返回该数据,如果缓冲区没有数据,返回的字节数组长度为0        /// </summary>        /// <returns>是否操作成功的方法</returns>        public OperateResult<byte[]> ClearSerialCache( )        {            return SPReceived( SP_ReadData, false );        }        #endregion        #region virtual Method        /// <summary>        /// 检查当前接收的字节数据是否正确的        /// </summary>        /// <param name="rBytes">输入字节</param>        /// <returns>检查是否正确</returns>        protected virtual bool CheckReceiveBytes(byte[] rBytes )        {            return true;        }        #endregion        #region Initialization And Extra        /// <summary>        /// 在打开端口时的初始化方法,按照协议的需求进行必要的重写        /// </summary>        /// <returns>是否初始化成功</returns>        protected virtual OperateResult InitializationOnOpen( )        {            return OperateResult.CreateSuccessResult( );        }        /// <summary>        /// 在将要和服务器进行断开的情况下额外的操作,需要根据对应协议进行重写        /// </summary>        /// <returns>当断开连接时额外的操作结果</returns>        protected virtual OperateResult ExtraOnClose( )        {            return OperateResult.CreateSuccessResult( );        }        #endregion        #region Private Method                /// <summary>        /// 发送数据到串口里去        /// </summary>        /// <param name="serialPort">串口对象</param>        /// <param name="data">字节数据</param>        /// <returns>是否发送成功</returns>        protected virtual OperateResult SPSend( SerialPort serialPort, byte[] data )        {            if (data != null && data.Length > 0)            {                try                {                    serialPort.Write( data, 0, data.Length );                    return OperateResult.CreateSuccessResult( );                }                catch(Exception ex)                {                    return new OperateResult( ex.Message );                }            }            else            {                return OperateResult.CreateSuccessResult( );            }        }        /// <summary>        /// 从串口接收一串数据信息,可以指定是否一定要接收到数据        /// </summary>        /// <param name="serialPort">串口对象</param>        /// <param name="awaitData">是否必须要等待数据返回</param>        /// <returns>结果数据对象</returns>        protected virtual OperateResult<byte[]> SPReceived( SerialPort serialPort, bool awaitData )        {            byte[] buffer = new byte[1024];            System.IO.MemoryStream ms = new System.IO.MemoryStream( );            DateTime start = DateTime.Now;                                  // 开始时间,用于确认是否超时的信息            while (true)            {                System.Threading.Thread.Sleep( sleepTime );                try                {                    if (serialPort.BytesToRead < 1)                    {                        if ((DateTime.Now - start).TotalMilliseconds > ReceiveTimeout)                        {                            ms.Dispose( );                            return new OperateResult<byte[]>( $"Time out: {ReceiveTimeout}" );                        }                        else if (ms.Length > 0)                        {                            break;                        }                        else if (awaitData)                        {                            continue;                        }                        else                        {                            break;                        }                    }                    // 继续接收数据                    int sp_receive = serialPort.Read( buffer, 0, buffer.Length );                    ms.Write( buffer, 0, sp_receive );                }                catch (Exception ex)                {                    ms.Dispose( );                    return new OperateResult<byte[]>( ex.Message );                }            }            // resetEvent.Set( );            byte[] result = ms.ToArray( );            ms.Dispose( );            return OperateResult.CreateSuccessResult( result );        }                #endregion        #region Object Override        /// <summary>        /// 返回表示当前对象的字符串        /// </summary>        /// <returns>字符串</returns>        public override string ToString()        {            return "SerialBase";        }        #endregion        #region Public Properties        /// <summary>        /// 接收数据的超时时间,默认5000ms        /// </summary>        public int ReceiveTimeout        {            get { return receiveTimeout; }            set { receiveTimeout = value; }        }        /// <summary>        /// 连续串口缓冲数据检测的间隔时间,默认20ms        /// </summary>        public int SleepTime        {            get { return sleepTime; }            set { if (value > 0) sleepTime = value; }        }        /// <summary>        /// 是否在发送数据前清空缓冲数据,默认是false        /// </summary>        public bool IsClearCacheBeforeRead        {            get { return isClearCacheBeforeRead; }            set { isClearCacheBeforeRead = value; }        }        #endregion        #region Private Member                private SerialPort SP_ReadData = null;                    // 串口交互的核心        private SimpleHybirdLock hybirdLock;                      // 数据交互的锁        private int receiveTimeout = 5000;                        // 接收数据的超时时间        private int sleepTime = 20;                               // 睡眠的时间        private bool isClearCacheBeforeRead = false;              // 是否在发送前清除缓冲        #endregion    }}
 |