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 { /// /// 所有串行通信类的基类,提供了一些基础的服务 /// public class SerialBase { #region Constructor /// /// 实例化一个无参的构造方法 /// public SerialBase( ) { SP_ReadData = new SerialPort( ); hybirdLock = new SimpleHybirdLock( ); } #endregion #region Public Method /// /// 初始化串口信息,9600波特率,8位数据位,1位停止位,无奇偶校验 /// /// 端口号信息,例如"COM3" public void SerialPortInni( string portName ) { SerialPortInni( portName, 9600 ); } /// /// 初始化串口信息,波特率,8位数据位,1位停止位,无奇偶校验 /// /// 端口号信息,例如"COM3" /// 波特率 public void SerialPortInni( string portName, int baudRate ) { SerialPortInni( portName, baudRate, 8, StopBits.One, Parity.None ); } /// /// 初始化串口信息,波特率,数据位,停止位,奇偶校验需要全部自己来指定 /// /// 端口号信息,例如"COM3" /// 波特率 /// 数据位 /// 停止位 /// 奇偶校验 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; // 奇偶校验 } /// /// 根据自定义初始化方法进行初始化串口信息 /// /// 初始化的委托方法 public void SerialPortInni( Action 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 ); } /// /// 打开一个新的串行端口连接 /// public void Open( ) { if (!SP_ReadData.IsOpen) { SP_ReadData.Open( ); InitializationOnOpen( ); } } /// /// 获取一个值,指示串口是否处于打开状态 /// /// 是或否 public bool IsOpen( ) { return SP_ReadData.IsOpen; } /// /// 关闭端口连接 /// public void Close( ) { if(SP_ReadData.IsOpen) { ExtraOnClose( ); SP_ReadData.Close( ); } } /// /// 读取串口的数据 /// /// 发送的原始字节数据 /// 带接收字节的结果对象 public OperateResult ReadBase(byte[] send) { hybirdLock.Enter( ); if (IsClearCacheBeforeRead) ClearSerialCache( ); OperateResult sendResult = SPSend( SP_ReadData, send ); if (!sendResult.IsSuccess) { hybirdLock.Leave( ); return OperateResult.CreateFailedResult( sendResult ); } OperateResult receiveResult = SPReceived( SP_ReadData, true ); hybirdLock.Leave( ); return receiveResult; } /// /// 清除串口缓冲区的数据,并返回该数据,如果缓冲区没有数据,返回的字节数组长度为0 /// /// 是否操作成功的方法 public OperateResult ClearSerialCache( ) { return SPReceived( SP_ReadData, false ); } #endregion #region virtual Method /// /// 检查当前接收的字节数据是否正确的 /// /// 输入字节 /// 检查是否正确 protected virtual bool CheckReceiveBytes(byte[] rBytes ) { return true; } #endregion #region Initialization And Extra /// /// 在打开端口时的初始化方法,按照协议的需求进行必要的重写 /// /// 是否初始化成功 protected virtual OperateResult InitializationOnOpen( ) { return OperateResult.CreateSuccessResult( ); } /// /// 在将要和服务器进行断开的情况下额外的操作,需要根据对应协议进行重写 /// /// 当断开连接时额外的操作结果 protected virtual OperateResult ExtraOnClose( ) { return OperateResult.CreateSuccessResult( ); } #endregion #region Private Method /// /// 发送数据到串口里去 /// /// 串口对象 /// 字节数据 /// 是否发送成功 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( ); } } /// /// 从串口接收一串数据信息,可以指定是否一定要接收到数据 /// /// 串口对象 /// 是否必须要等待数据返回 /// 结果数据对象 protected virtual OperateResult 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( $"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( ex.Message ); } } // resetEvent.Set( ); byte[] result = ms.ToArray( ); ms.Dispose( ); return OperateResult.CreateSuccessResult( result ); } #endregion #region Object Override /// /// 返回表示当前对象的字符串 /// /// 字符串 public override string ToString() { return "SerialBase"; } #endregion #region Public Properties /// /// 接收数据的超时时间,默认5000ms /// public int ReceiveTimeout { get { return receiveTimeout; } set { receiveTimeout = value; } } /// /// 连续串口缓冲数据检测的间隔时间,默认20ms /// public int SleepTime { get { return sleepTime; } set { if (value > 0) sleepTime = value; } } /// /// 是否在发送数据前清空缓冲数据,默认是false /// 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 } }