280 lines
6.3 KiB
C#
280 lines
6.3 KiB
C#
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 failed,please 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);
|
||
}
|
||
}
|
||
}
|
||
}
|