Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/MECF/Framework/Common/Communications/AsyncSerialPort.cs

280 lines
6.3 KiB
C#
Raw Normal View History

2023-04-13 11:51:03 +08:00
using System;
using System.IO.Ports;
using System.Text;
using Aitex.Core.RT.Log;
namespace MECF.Framework.Common.Communications
{
public class AsyncSerialPort : IDisposable
{
private static object _locker = new object();
protected SerialPort _port;
private string _buff = "";
private bool _isAsciiMode;
private bool _isLineBased;
public string PortName
{
get
{
return _port.PortName;
}
set
{
_port.PortName = value;
}
}
public bool EnableLog { get; set; }
public bool IsAsciiMode
{
get
{
return _isAsciiMode;
}
set
{
_isAsciiMode = value;
}
}
public event Action<string> OnErrorHappened;
public event Action<string> OnDataChanged;
public event Action<byte[]> OnBinaryDataChanged;
public AsyncSerialPort(string name, int baudRate, int dataBits, Parity parity = Parity.None, StopBits stopBits = StopBits.One, string newline = "\r", bool isAsciiMode = true)
{
_isAsciiMode = isAsciiMode;
_isLineBased = !string.IsNullOrEmpty(newline);
_port = new SerialPort();
_port.PortName = name;
_port.BaudRate = baudRate;
_port.DataBits = dataBits;
_port.Parity = parity;
_port.StopBits = stopBits;
_port.RtsEnable = false;
_port.DtrEnable = false;
_port.ReadTimeout = 1000;
_port.WriteTimeout = 1000;
if (!string.IsNullOrEmpty(newline))
{
_port.NewLine = newline;
}
_port.Handshake = Handshake.None;
_port.DataReceived += DataReceived;
_port.ErrorReceived += ErrorReceived;
}
public void Dispose()
{
Close();
}
public bool Open()
{
if (_port.IsOpen)
{
Close();
}
try
{
_port.Open();
_port.DiscardInBuffer();
_port.DiscardOutBuffer();
_buff = "";
}
catch (Exception ex)
{
string message = _port.PortName + " port open failedplease check configuration." + ex.Message;
LOG.Write(message);
return false;
}
return true;
}
public bool IsOpen()
{
return _port.IsOpen;
}
public bool Close()
{
if (_port.IsOpen)
{
try
{
_port.Close();
}
catch (Exception ex)
{
string reason = _port.PortName + " port close failed." + ex.Message;
ProcessError(reason);
return false;
}
}
return true;
}
public bool Write(string msg)
{
try
{
lock (_locker)
{
if (_port.IsOpen)
{
_port.Write(msg);
if (EnableLog)
{
LOG.Info($"Communication {_port.PortName} Send {msg} succeeded.", isTraceOn: false);
LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, string.Join(" ", Array.ConvertAll(Encoding.ASCII.GetBytes(msg), (byte x) => x.ToString("X2")))), isTraceOn: false);
}
}
}
return true;
}
catch (Exception ex)
{
string text = $"Communication {_port.PortName} Send {msg} failed. {ex.Message}.";
LOG.Info(text, isTraceOn: false);
ProcessError(text);
return false;
}
}
public bool Write(byte[] msg)
{
try
{
lock (_locker)
{
if (_port.IsOpen)
{
_port.Write(msg, 0, msg.Length);
if (EnableLog)
{
LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, string.Join(" ", Array.ConvertAll(msg, (byte x) => x.ToString("X2")))), isTraceOn: false);
LOG.Info($"Communication {_port.PortName} Send {Encoding.ASCII.GetString(msg)} succeeded.", isTraceOn: false);
}
}
}
return true;
}
catch (Exception ex)
{
string text = string.Format("Communication {0} Send {1} failed. {2}.", _port.PortName, string.Join(" ", Array.ConvertAll(msg, (byte x) => x.ToString("X2"))), ex.Message);
LOG.Info(text, isTraceOn: false);
ProcessError(text);
return false;
}
}
public void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (!_port.IsOpen)
{
LOG.Write("discard " + _port.PortName + " received data, but port not open");
}
else if (_isAsciiMode)
{
AsciiDataReceived();
}
else
{
BinaryDataReceived();
}
}
private void AsciiDataReceived()
{
string text = _port.ReadExisting();
if (_isLineBased)
{
_buff += text;
int num = _buff.LastIndexOf(_port.NewLine, StringComparison.Ordinal);
if (num <= 0)
{
return;
}
num += _port.NewLine.Length;
string text2 = _buff.Substring(0, num);
_buff = _buff.Substring(num);
if (EnableLog)
{
LOG.Info($"Communication {_port.PortName} Receive {text2}.", isTraceOn: false);
LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, string.Join(" ", Array.ConvertAll(Encoding.ASCII.GetBytes(text2), (byte x) => x.ToString("X2")))), isTraceOn: false);
}
if (this.OnDataChanged != null)
{
this.OnDataChanged(text2);
}
return;
}
string text3 = text;
if (EnableLog)
{
LOG.Info($"Communication {_port.PortName} Receive {text3}.", isTraceOn: false);
LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, string.Join(" ", Array.ConvertAll(Encoding.ASCII.GetBytes(text3), (byte x) => x.ToString("X2")))), isTraceOn: false);
}
if (this.OnDataChanged != null)
{
this.OnDataChanged(text3);
}
}
public void BinaryDataReceived()
{
byte[] array = new byte[_port.BytesToRead];
int num = _port.Read(array, 0, array.Length);
if (num == 0)
{
return;
}
byte[] array2 = new byte[num];
Buffer.BlockCopy(array, 0, array2, 0, num);
if (EnableLog)
{
StringBuilder str = new StringBuilder(512);
Array.ForEach(array2, delegate(byte x)
{
str.Append(x.ToString("X2") + " ");
});
LOG.Info($"Communication {_port.PortName} Receive {str}.", isTraceOn: false);
LOG.Info($"Communication {_port.PortName} Receive {Encoding.ASCII.GetString(array2)}.", isTraceOn: false);
}
if (this.OnBinaryDataChanged != null)
{
this.OnBinaryDataChanged(array2);
}
}
private void ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{
string text = $"Communication {_port.PortName} {e.EventType.ToString()}.";
LOG.Error(text);
ProcessError(text);
}
public void ClearPortBuffer()
{
_port.DiscardInBuffer();
_port.DiscardOutBuffer();
}
private void ProcessError(string reason)
{
if (this.OnErrorHappened != null)
{
this.OnErrorHappened(reason);
}
}
}
}