AsyncSerialPort.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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 bool IsAsciiMode
  24. {
  25. get => _isAsciiMode;
  26. set { _isAsciiMode = value; }
  27. }
  28. private bool _isLineBased;
  29. public AsyncSerialPort(string name, int baudRate, int dataBits, Parity parity = Parity.None, StopBits stopBits = StopBits.One, string newline = "\r", bool isAsciiMode=true)
  30. {
  31. _isAsciiMode = isAsciiMode;
  32. _isLineBased = !string.IsNullOrEmpty(newline);
  33. _port = new SerialPort();
  34. _port.PortName = name;
  35. _port.BaudRate = baudRate;
  36. _port.DataBits = dataBits;
  37. _port.Parity = parity;
  38. _port.StopBits = stopBits;
  39. _port.RtsEnable = false;
  40. _port.DtrEnable = false;
  41. _port.ReadTimeout = 1000;
  42. _port.WriteTimeout = 1000;
  43. if (!string.IsNullOrEmpty(newline))
  44. {
  45. _port.NewLine = newline;
  46. }
  47. _port.Handshake = Handshake.None;
  48. _port.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
  49. _port.ErrorReceived += new SerialErrorReceivedEventHandler(ErrorReceived);
  50. }
  51. public void Dispose()
  52. {
  53. Close();
  54. }
  55. public bool Open()
  56. {
  57. if (_port.IsOpen) Close();
  58. //Close();
  59. try
  60. {
  61. _port.Open();
  62. _port.DiscardInBuffer();
  63. _port.DiscardOutBuffer();
  64. _buff = "";
  65. }
  66. catch (Exception e)
  67. {
  68. string reason = _port.PortName + " port open failed,please check configuration." + e.Message;
  69. //ProcessError( reason );
  70. LOG.Write(reason);
  71. return false;
  72. }
  73. return true;
  74. }
  75. public bool IsOpen()
  76. {
  77. return _port.IsOpen;
  78. }
  79. public bool Close()
  80. {
  81. if (_port.IsOpen)
  82. {
  83. try
  84. {
  85. _port.Close();
  86. }
  87. catch (Exception e)
  88. {
  89. string reason = _port.PortName + " port close failed." + e.Message;
  90. ProcessError( reason );
  91. return false;
  92. }
  93. }
  94. return true;
  95. }
  96. //结束符号, 由调用者 负责加上
  97. public bool Write(string msg)
  98. {
  99. try
  100. {
  101. lock (_locker)
  102. {
  103. if (_port.IsOpen)
  104. {
  105. _port.Write(msg);
  106. if (EnableLog)
  107. {
  108. LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, msg));
  109. LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, string.Join(" ", Array.ConvertAll(Encoding.ASCII.GetBytes(msg), x => x.ToString("X2")))));
  110. }
  111. }
  112. }
  113. return true;
  114. }
  115. catch (Exception e)
  116. {
  117. string reason = string.Format("Communication {0} Send {1} failed. {2}.", _port.PortName, msg, e.Message);
  118. LOG.Info(reason);
  119. ProcessError( reason );
  120. return false;
  121. }
  122. }
  123. public bool Write(byte[] msg)
  124. {
  125. try
  126. {
  127. lock (_locker)
  128. {
  129. if (_port.IsOpen)
  130. {
  131. _port.Write(msg, 0, msg.Length);
  132. if (EnableLog)
  133. {
  134. LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, string.Join(" ", Array.ConvertAll(msg, x => x.ToString("X2")))));
  135. LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, Encoding.ASCII.GetString(msg)));
  136. }
  137. }
  138. }
  139. return true;
  140. }
  141. catch (Exception e)
  142. {
  143. string reason = string.Format("Communication {0} Send {1} failed. {2}.", _port.PortName, string.Join(" ", Array.ConvertAll(msg, x => x.ToString("X2"))), e.Message);
  144. LOG.Info(reason);
  145. ProcessError(reason);
  146. return false;
  147. }
  148. }
  149. public void DataReceived(object sender, SerialDataReceivedEventArgs e)
  150. {
  151. if (!_port.IsOpen)
  152. {
  153. LOG.Write($"discard {_port.PortName} received data, but port not open");
  154. return;
  155. }
  156. if (_isAsciiMode)
  157. {
  158. AsciiDataReceived();
  159. }
  160. else
  161. {
  162. BinaryDataReceived();
  163. }
  164. }
  165. private void AsciiDataReceived()
  166. {
  167. string str = _port.ReadExisting(); //字符串方式读
  168. if (_isLineBased)
  169. {
  170. _buff += str;
  171. int index = _buff.LastIndexOf(_port.NewLine, StringComparison.Ordinal);
  172. if (index >= 0)
  173. {
  174. index += _port.NewLine.Length;
  175. string msg = _buff.Substring(0, index);
  176. _buff = _buff.Substring(index);
  177. if (EnableLog)
  178. {
  179. LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, msg));
  180. LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, string.Join(" ", Array.ConvertAll(Encoding.ASCII.GetBytes(msg), x => x.ToString("X2")))));
  181. }
  182. if (OnDataChanged != null)
  183. OnDataChanged(msg);
  184. }
  185. }
  186. else
  187. {
  188. string msg = str;
  189. if (EnableLog)
  190. {
  191. LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, msg));
  192. LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, string.Join(" ", Array.ConvertAll(Encoding.ASCII.GetBytes(msg), x => x.ToString("X2")))));
  193. }
  194. if (OnDataChanged != null)
  195. OnDataChanged(msg);
  196. }
  197. }
  198. public void BinaryDataReceived( )
  199. {
  200. byte[] readBuffer = new byte[_port.BytesToRead];
  201. int readCount = _port.Read(readBuffer, 0, readBuffer.Length);
  202. if (readCount == 0)
  203. {
  204. //LOG.Write($"read zero length data, {_port.PortName}");
  205. return;
  206. }
  207. byte[] buffer = new byte[readCount];
  208. Buffer.BlockCopy(readBuffer, 0, buffer, 0, readCount);
  209. if (EnableLog)
  210. {
  211. StringBuilder str = new StringBuilder(512);
  212. Array.ForEach(buffer, x => str.Append(x.ToString("X2") + " "));
  213. LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, str));
  214. LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, Encoding.ASCII.GetString(buffer)));
  215. }
  216. if (OnBinaryDataChanged != null)
  217. OnBinaryDataChanged(buffer);
  218. }
  219. void ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
  220. {
  221. string reason = string.Format("Communication {0} {1}.", _port.PortName, e.EventType.ToString());
  222. LOG.Error(reason);
  223. ProcessError( reason );
  224. }
  225. public void ClearPortBuffer()
  226. {
  227. _port.DiscardInBuffer();
  228. _port.DiscardOutBuffer();
  229. }
  230. void ProcessError(string reason)
  231. {
  232. if (OnErrorHappened != null)
  233. OnErrorHappened(reason);
  234. }
  235. }
  236. }