AsyncSerialPort.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. using System;
  2. using System.IO.Ports;
  3. using System.Text;
  4. using Aitex.Core.RT.Event;
  5. using Aitex.Core.RT.Log;
  6. using MECF.Framework.Common.Utilities;
  7. namespace MECF.Framework.Common.Communications
  8. {
  9. public class AsyncSerialPort : IDisposable
  10. {
  11. public string PortName { get { return _port.PortName; } set {
  12. {
  13. _port.PortName = value;
  14. } } }
  15. public event Action<string> OnErrorHappened;
  16. public event Action<string> OnDataChanged;
  17. public event Action<byte[]> OnBinaryDataChanged;
  18. private static Object _locker = new Object();
  19. protected SerialPort _port;
  20. private string _buff = "";
  21. public bool EnableLog { get; set; }
  22. private bool _isAsciiMode;
  23. public AsyncSerialPort(string name, int baudRate, int dataBits, Parity parity = Parity.None, StopBits stopBits = StopBits.One, string newline = "\r", bool isAsciiMode=true)
  24. {
  25. _isAsciiMode = isAsciiMode;
  26. _port = new SerialPort();
  27. _port.PortName = name;
  28. _port.BaudRate = baudRate;
  29. _port.DataBits = dataBits;
  30. _port.Parity = parity;
  31. _port.StopBits = stopBits;
  32. _port.RtsEnable = false;
  33. _port.DtrEnable = false;
  34. _port.ReadTimeout = 1000;
  35. _port.WriteTimeout = 1000;
  36. _port.NewLine = newline;
  37. _port.Handshake = Handshake.None;
  38. _port.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
  39. _port.ErrorReceived += new SerialErrorReceivedEventHandler(ErrorReceived);
  40. }
  41. public void Dispose()
  42. {
  43. Close();
  44. }
  45. public bool Open()
  46. {
  47. if (_port.IsOpen) Close();
  48. try
  49. {
  50. _port.Open();
  51. _port.DiscardInBuffer();
  52. _port.DiscardOutBuffer();
  53. _buff = "";
  54. }
  55. catch (Exception e)
  56. {
  57. string reason = _port.PortName + " port open failed,please check configuration。" + e.Message;
  58. //ProcessError( reason );
  59. LOG.Write(reason);
  60. return false;
  61. }
  62. return true;
  63. }
  64. public bool IsOpen()
  65. {
  66. return _port.IsOpen;
  67. }
  68. public bool Close()
  69. {
  70. if (_port.IsOpen)
  71. {
  72. try
  73. {
  74. _port.Close();
  75. }
  76. catch (Exception e)
  77. {
  78. string reason = _port.PortName + " port close failed。" + e.Message;
  79. ProcessError( reason );
  80. return false;
  81. }
  82. }
  83. return true;
  84. }
  85. //结束符号, 由调用者 负责加上
  86. public bool Write(string msg)
  87. {
  88. try
  89. {
  90. lock (_locker)
  91. {
  92. if (_port.IsOpen)
  93. {
  94. _port.Write(msg);
  95. if (EnableLog)
  96. {
  97. LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, msg));
  98. }
  99. }
  100. }
  101. return true;
  102. }
  103. catch (Exception e)
  104. {
  105. string reason = string.Format("Communication {0} Send {1} failed. {2}.", _port.PortName, msg, e.Message);
  106. LOG.Info(reason);
  107. ProcessError( reason );
  108. return false;
  109. }
  110. }
  111. public bool Write(byte[] msg)
  112. {
  113. try
  114. {
  115. lock (_locker)
  116. {
  117. if (_port.IsOpen)
  118. {
  119. _port.Write(msg, 0, msg.Length);
  120. if (EnableLog)
  121. {
  122. LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, string.Join(" ", Array.ConvertAll(msg, x => x.ToString("X2")))));
  123. }
  124. }
  125. }
  126. return true;
  127. }
  128. catch (Exception e)
  129. {
  130. string reason = string.Format("Communication {0} Send {1} failed. {2}.", _port.PortName, string.Join(" ", Array.ConvertAll(msg, x => x.ToString("X2"))), e.Message);
  131. LOG.Info(reason);
  132. ProcessError(reason);
  133. return false;
  134. }
  135. }
  136. public void DataReceived(object sender, SerialDataReceivedEventArgs e)
  137. {
  138. if (!_port.IsOpen)
  139. {
  140. LOG.Write($"discard {_port.PortName} received data, but port not open");
  141. return;
  142. }
  143. if (_isAsciiMode)
  144. {
  145. AsciiDataReceived();
  146. }
  147. else
  148. {
  149. BinaryDataReceived();
  150. }
  151. }
  152. private void AsciiDataReceived()
  153. {
  154. string str = _port.ReadExisting(); //字符串方式读
  155. _buff += str;
  156. int index = _buff.LastIndexOf(_port.NewLine, StringComparison.Ordinal);
  157. if (index > 0)
  158. {
  159. index += _port.NewLine.Length;
  160. string msg = _buff.Substring(0, index);
  161. _buff = _buff.Substring(index);
  162. if (EnableLog)
  163. {
  164. LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, msg));
  165. }
  166. if (OnDataChanged != null)
  167. OnDataChanged(msg);
  168. }
  169. }
  170. public void BinaryDataReceived( )
  171. {
  172. byte[] readBuffer = new byte[_port.BytesToRead];
  173. int readCount = _port.Read(readBuffer, 0, readBuffer.Length);
  174. if (readCount == 0)
  175. {
  176. //LOG.Write($"read zero length data, {_port.PortName}");
  177. return;
  178. }
  179. byte[] buffer = new byte[readCount];
  180. Buffer.BlockCopy(readBuffer, 0, buffer, 0, readCount);
  181. if (EnableLog)
  182. {
  183. StringBuilder str = new StringBuilder(512);
  184. Array.ForEach(buffer, x => str.Append(x.ToString("X2") + " "));
  185. LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, str));
  186. }
  187. if (OnBinaryDataChanged != null)
  188. OnBinaryDataChanged(buffer);
  189. }
  190. void ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
  191. {
  192. string reason = string.Format("Communication {0} {1}.", _port.PortName, e.EventType.ToString());
  193. LOG.Error(reason);
  194. ProcessError( reason );
  195. }
  196. public void ClearPortBuffer()
  197. {
  198. _port.DiscardInBuffer();
  199. _port.DiscardOutBuffer();
  200. }
  201. void ProcessError(string reason)
  202. {
  203. if (OnErrorHappened != null)
  204. OnErrorHappened(reason);
  205. }
  206. }
  207. }