Sic.Framework/MECF.Framework.Common/MECF/Framework/Common/Communications/AsyncSerialPort.cs

280 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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