AsyncSerialPort.cs 8.6 KB

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