You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

305 lines
9.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Collections;
using HuizhongLibrary.Network;
using HuizhongLibrary.Log;
namespace HuizhongLibrary
{
public class SerialPortService
{
private Byte[] m_Data;
public Byte[] Data
{
get { return m_Data; }
set { m_Data = value; }
}
private List<byte> m_SocketBuffer = new List<byte>();
/// <summary>
/// 网络数据缓存
/// </summary>
public List<byte> SocketBuffer
{
get { return m_SocketBuffer; }
set { m_SocketBuffer = value; }
}
private int m_RefshSecond = 30;
public int RefshSecond
{
get { return m_RefshSecond; }
set { m_RefshSecond = value; }
}
private int m_MaxWaitMsgNumber = 1;
/// <summary>
/// 最大消息等待回包数量(滑动窗口)
/// </summary>
public int MaxWaitMsgNumber
{
get { return m_MaxWaitMsgNumber; }
set { m_MaxWaitMsgNumber = value; }
}
private int m_ReadBufferSize = 4096;
public int ReadBufferSize
{
get { return m_ReadBufferSize; }
set { m_ReadBufferSize = value; }
}
private int m_WriteBufferSize = 4096;
public int WriteBufferSize
{
get { return m_WriteBufferSize; }
set { m_WriteBufferSize = value; }
}
private string m_StringNewLine = "0";
/// <summary>
/// 读取数据的方式(0 byte方式读取1按回车读取
/// </summary>
public string StringNewLine
{
get { return m_StringNewLine; }
set { m_StringNewLine = value; }
}
public int ReadSleep = 0;
public bool IsRunSendThread = true;
public int MaxSendNumber = 0;
public event Action<SerialPort> ReceiveData;
public event Action<SerialPort> SendData;
public event Action<string> ReceiveString;
/// <summary>
/// 超出最大发送次数
/// </summary>
public event Action<SocketMessage> OverMaxSend;
public SocketMessages ListMessage = new SocketMessages();
public int WaitMsgNumber = 0;
private AutoResetEvent AutoReset = new AutoResetEvent(false);
private bool IsRun = false;
private DateTime CacheDataTime = DateTime.Now;
public SerialPortService()
{
}
SerialPort comm = null;
#region 使用串口通讯
public void Start(string PortName, int BaudRate, int DataBits, Parity par, StopBits sBits)
{
comm = new SerialPort();
comm.ReadBufferSize = ReadBufferSize;
comm.WriteBufferSize = WriteBufferSize;
comm.PortName = PortName;
comm.BaudRate = BaudRate;
comm.DataBits = DataBits;
comm.Parity = par;
comm.StopBits = sBits;
//comm.ReadTimeout = 500;
//comm.WriteTimeout = 500;
comm.NewLine = StringNewLine;
comm.Encoding = Encoding.Default;
comm.DataReceived += new SerialDataReceivedEventHandler(comm_DataReceived);
comm.Open();
if (IsRunSendThread == true)
{
IsRun = true;
Thread t1 = new Thread(new ThreadStart(this.WhileListUserSocket));
t1.Start();
}
}
#endregion
#region 停止通讯
public void Stop()
{
this.IsRun = false;
if (comm!=null)comm.Close();
}
#endregion
#region 读取到数据发生
void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (ReadSleep > 0) Thread.Sleep(ReadSleep);
if (this.StringNewLine == "0")
{
int ReceiveLen = comm.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
byte[] Bytes = new byte[ReceiveLen];//声明一个临时数组存储当前来的串口数据
comm.Read(Bytes, 0, ReceiveLen);
AddData(Bytes, ReceiveLen);
if (this.ReceiveData != null) this.ReceiveData(comm);
}
else
{
try
{
while (true)
{
if (comm.BytesToRead == 0) return;
string RevData = comm.ReadLine();
if (string.IsNullOrEmpty(RevData) == true) return;
if (this.ReceiveString != null) this.ReceiveString(RevData);
}
}
catch (Exception ex)
{
ErrorFollow.TraceWrite("comm_DataReceived", ex.StackTrace, ex.Message);
}
}
}
#endregion
#region 返回要发送的消息
public SocketMessage GetNextSocketMessage(int RefshSecond)
{
try
{
var item = ListMessage.GetNextSocketMessage(RefshSecond);
if (item == null) return null;
if (item.SendNumber > 0) DecrementWaitMsgNumber();
return item;
}
catch (Exception ex)
{
ErrorFollow.TraceWrite("SerialPortService.GetNextSocketMessage", ex.StackTrace, ex.Message);
}
return null;
}
#endregion
#region 移除已发送消息
public void RemoveSocketMessage()
{
ListMessage.RemoveEmploy();
}
#endregion
#region 增加等待回复的消息数
public void IncrementWaitMsgNumber()
{
Interlocked.Increment(ref WaitMsgNumber);
}
#endregion
#region 减少等待回复的消息数
public void DecrementWaitMsgNumber()
{
Interlocked.Decrement(ref WaitMsgNumber);
}
#endregion、
#region 消除已回复消息
public SocketMessage EndWaitMsg(string SequenceID)
{
try
{
SocketMessage msg = ListMessage.CheckOut(SequenceID);
DecrementWaitMsgNumber();
return msg;
}
catch (Exception ex)
{
ErrorFollow.TraceWrite("SerialPortService.IncrementWaitMsgNumber", ex.StackTrace, ex.Message);
}
return null;
}
#endregion
#region 消除已回复首行消息
public SocketMessage EndFirstMsg()
{
try
{
SocketMessage msg = ListMessage.CheckOut();
DecrementWaitMsgNumber();
return msg;
}
catch (Exception ex)
{
ErrorFollow.TraceWrite("SerialPortService.EndFirstMsg", ex.StackTrace, ex.Message);
}
return null;
}
#endregion
#region 移除消息
public void RemoveMsg(string FunNo)
{
try
{
ListMessage.Remove(FunNo);
}
catch (Exception ex)
{
ErrorFollow.TraceWrite("SerialPortService.RemoveMsg", ex.StackTrace, ex.Message);
}
}
#endregion
#region 合并缓存数据
public void AddData(byte[] RevData, int Len)
{
if (CacheDataTime.AddSeconds(10) < DateTime.Now)
{
SocketBuffer.Clear();
}
Data = new byte[Len + SocketBuffer.Count];
for (int i = 0; i < SocketBuffer.Count; i++)
{
Data[i] = SocketBuffer[i];
}
Buffer.BlockCopy(RevData, 0, Data, SocketBuffer.Count, Len);
SocketBuffer.Clear();
}
#endregion
#region 直接发送数据
public void Send(byte[] Bytes)
{
comm.Write(Bytes, 0, Bytes.Length);
}
#endregion
#region 直接发送数据(String)
public void Send(string Data)
{
comm.Write(Data);
}
#endregion
#region 轮循消息列表
void WhileListUserSocket()
{
while (IsRun)
{
SocketMessage Msg = GetNextSocketMessage(this.RefshSecond);
try
{
if (Msg != null)
{
Msg.SendTime = DateTime.Now;
Msg.SendNumber++;
IncrementWaitMsgNumber();
if (this.MaxSendNumber > 0 && Msg.SendNumber > this.MaxSendNumber)
{
EndWaitMsg(Msg.SequenceID);
if (this.OverMaxSend != null) this.OverMaxSend(Msg);
continue;
}
comm.Write(Msg.Bytes, 0, Msg.Bytes.Length);
if (this.SendData != null) this.SendData(comm);
}
}
catch { }
AutoReset.WaitOne(500, false);
}
}
#endregion
#region 新增缓存
public void AddBuff(byte[] SrcArray, int offset)
{
for (int i = offset; i < SrcArray.Length; i++)
{
SocketBuffer.Add(SrcArray[i]);
}
CacheDataTime = DateTime.Now;
}
#endregion
}
}