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
}
}