AsyncSerialPort.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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.Log;
  7. using Aitex.Core.RT.SCCore;
  8. using System.Linq;
  9. using MECF.Framework.Common.Equipment;
  10. using DocumentFormat.OpenXml.Wordprocessing;
  11. namespace MECF.Framework.Common.Communications
  12. {
  13. public class AsyncSerialPort : IDisposable
  14. {
  15. public string PortName
  16. {
  17. get { return _port.PortName; }
  18. set
  19. {
  20. {
  21. _port.PortName = value;
  22. }
  23. }
  24. }
  25. public event Action<string> OnErrorHappened;
  26. public event Action<string> OnDataChanged;
  27. public event Action<byte[]> OnBinaryDataChanged;
  28. private static Object _locker = new Object();
  29. protected SerialPort _port;
  30. private string _buff = "";
  31. public bool EnableLog { get; set; }
  32. public StringBuilder str { get; set; }
  33. public byte[] GetData { get; set; }
  34. public bool bValidate { get; set; }
  35. private bool _isAsciiMode;
  36. private static BitArray _EnableLog;
  37. private Stopwatch timeoutStopWatch = new Stopwatch();
  38. public bool IsConnected => timeoutStopWatch.ElapsedMilliseconds < 2 * 1000;
  39. public AsyncSerialPort(string name, int baudRate, int dataBits, Parity parity = Parity.None, StopBits stopBits = StopBits.One, string newline = "\r", bool isAsciiMode = true)
  40. {
  41. _isAsciiMode = isAsciiMode;
  42. _port = new SerialPort();
  43. _port.PortName = name;
  44. _port.BaudRate = baudRate;
  45. _port.DataBits = dataBits;
  46. _port.Parity = parity;
  47. _port.StopBits = stopBits;
  48. _port.RtsEnable = false;
  49. _port.DtrEnable = false;
  50. _port.ReadTimeout = 1000;
  51. _port.WriteTimeout = 1000;
  52. _port.NewLine = newline;
  53. _port.Handshake = Handshake.None;
  54. _port.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
  55. _port.ErrorReceived += new SerialErrorReceivedEventHandler(ErrorReceived);
  56. EnableLog = GetEnableFlag(name);
  57. str = new StringBuilder();
  58. bValidate = false;
  59. GetData = new byte[] { };
  60. }
  61. public void Dispose()
  62. {
  63. Close();
  64. }
  65. public bool Open()
  66. {
  67. if (_port.IsOpen) Close();
  68. try
  69. {
  70. _port.Open();
  71. _port.DiscardInBuffer();
  72. _port.DiscardOutBuffer();
  73. _buff = "";
  74. }
  75. catch (Exception e)
  76. {
  77. string reason = _port.PortName + " port open failed,please check configuration。" + e.Message;
  78. //ProcessError( reason );
  79. //LOG.Write(reason);
  80. return false;
  81. }
  82. return true;
  83. }
  84. public bool IsOpen()
  85. {
  86. return _port.IsOpen;
  87. }
  88. public bool Close()
  89. {
  90. if (_port.IsOpen)
  91. {
  92. try
  93. {
  94. LOG.Write(eEvent.EV_DEVICE_INFO, ModuleName.System, $"{_port.PortName}关闭");
  95. _port.Close();
  96. }
  97. catch (Exception e)
  98. {
  99. string reason = _port.PortName + " port close failed。" + e.Message;
  100. ProcessError(reason);
  101. return false;
  102. }
  103. }
  104. return true;
  105. }
  106. //结束符号, 由调用者 负责加上
  107. public bool Write(string msg)
  108. {
  109. try
  110. {
  111. //if (SC.GetValue<bool>("System.EnableDeviceLog"))
  112. //{
  113. // LOG.Write(eEvent.EV_DEVICE_INFO, ModuleName.System, $"{_port.PortName} start sendxx {msg}");
  114. //}
  115. if (_port.IsOpen)
  116. {
  117. //if (SC.GetValue<bool>("System.EnableDeviceLog"))
  118. //{
  119. // LOG.Write(eEvent.EV_DEVICE_INFO, ModuleName.System, $"{_port.PortName} sendxx {msg}");
  120. //}
  121. _port.Write(msg);
  122. //if (EnableLog)
  123. //{
  124. // //LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, msg));
  125. //}
  126. }
  127. //lock (_locker)
  128. //{
  129. //}
  130. return true;
  131. }
  132. catch (Exception e)
  133. {
  134. string reason = string.Format("Communication {0} Send {1} failed. {2}.", _port.PortName, msg, e.Message);
  135. //LOG.Info(reason);
  136. ProcessError(reason);
  137. return false;
  138. }
  139. }
  140. public bool Write(byte[] msg)
  141. {
  142. try
  143. {
  144. if (_port.IsOpen)
  145. {
  146. if (SC.GetValue<bool>("System.EnableDeviceLog"))
  147. {
  148. LOG.Write(eEvent.EV_DEVICE_INFO, ModuleName.System, $"{_port.PortName} sendxxx {msg}");
  149. }
  150. _port.Write(msg, 0, msg.Length);
  151. //if (EnableLog)
  152. //{
  153. // //LOG.Info(string.Format("Communication {0} Send {1} succeeded.", _port.PortName, string.Join(" ", Array.ConvertAll(msg, x => x.ToString("X2")))));
  154. //}
  155. }
  156. //lock (_locker)
  157. //{
  158. //}
  159. return true;
  160. }
  161. catch (Exception e)
  162. {
  163. string reason = string.Format("Communication {0} Send {1} failed. {2}.", _port.PortName, string.Join(" ", Array.ConvertAll(msg, x => x.ToString("X2"))), e.Message);
  164. //LOG.Info(reason);
  165. ProcessError(reason);
  166. return false;
  167. }
  168. }
  169. public void HandlePorts(byte[] obj, int _length, byte start, string Module, eEvent errdevice, int nOffset)
  170. {
  171. lock (_locker)
  172. {
  173. GetData = (byte[])GetData.Concat(obj).ToArray();
  174. //str.Append(System.Text.Encoding.Default.GetString(obj));
  175. var strData1 = System.Text.Encoding.Default.GetString(GetData);
  176. for (int i = 0; i < GetData.Length; i++)
  177. {
  178. if (GetData[i] == start)
  179. {
  180. if ((GetData.Length - i) >= _length)
  181. {
  182. bValidate = true;
  183. byte[] array = new byte[GetData.Length - i - nOffset];
  184. Array.Copy(GetData, i + nOffset, array, 0, _length - nOffset);
  185. str.Append(System.Text.Encoding.Default.GetString(array));
  186. //str.Remove(0, i);
  187. //str.Remove(i + _length - 1, str.Length - i - _length);
  188. break;
  189. }
  190. }
  191. }
  192. if (GetData.Length > _length * 3 && !bValidate)
  193. {
  194. LOG.Write(errdevice, Module, $"Receive invalidate data:{str} ");
  195. }
  196. }
  197. }
  198. public void DataReceived(object sender, SerialDataReceivedEventArgs e)
  199. {
  200. if (!_port.IsOpen)
  201. {
  202. LOG.Write(eEvent.EV_DEVICE_INFO, ModuleName.System, $"discard {_port.PortName} received data, but port not open");
  203. return;
  204. }
  205. timeoutStopWatch.Restart();
  206. if (_isAsciiMode)
  207. {
  208. AsciiDataReceived();
  209. }
  210. else
  211. {
  212. BinaryDataReceived();
  213. }
  214. }
  215. private void AsciiDataReceived()
  216. {
  217. string str = _port.ReadExisting(); //字符串方式读
  218. _buff += str;
  219. int index = _buff.LastIndexOf(_port.NewLine, StringComparison.Ordinal);
  220. if (index > 0)
  221. {
  222. index += _port.NewLine.Length;
  223. string msg = _buff.Substring(0, index);
  224. _buff = _buff.Substring(index);
  225. if (OnDataChanged != null)
  226. OnDataChanged(msg);
  227. }
  228. }
  229. public void BinaryDataReceived()
  230. {
  231. byte[] readBuffer = new byte[_port.BytesToRead];
  232. int readCount = _port.Read(readBuffer, 0, readBuffer.Length);
  233. if (readCount == 0)
  234. {
  235. //LOG.Write($"read zero length data, {_port.PortName}");
  236. return;
  237. }
  238. byte[] buffer = new byte[readCount];
  239. Buffer.BlockCopy(readBuffer, 0, buffer, 0, readCount);
  240. if (EnableLog)
  241. {
  242. StringBuilder str = new StringBuilder(512);
  243. Array.ForEach(buffer, x => str.Append(x.ToString("X2") + " "));
  244. //LOG.Info(string.Format("Communication {0} Receive {1}.", _port.PortName, str));
  245. }
  246. if (OnBinaryDataChanged != null)
  247. OnBinaryDataChanged(buffer);
  248. }
  249. void ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
  250. {
  251. string reason = string.Format("Communication {0} {1}.", _port.PortName, e.EventType.ToString());
  252. //LOG.Error(reason);
  253. ProcessError(reason);
  254. }
  255. public void ClearPortBuffer()
  256. {
  257. _port.DiscardInBuffer();
  258. _port.DiscardOutBuffer();
  259. }
  260. void ProcessError(string reason)
  261. {
  262. if (OnErrorHappened != null)
  263. OnErrorHappened(reason);
  264. }
  265. bool GetEnableFlag(string portName)
  266. {
  267. if (_EnableLog == null)
  268. {
  269. Process cur = Process.GetCurrentProcess();
  270. if (cur.ProcessName != "Venus_RT")
  271. return false;
  272. string[] strArray = SC.GetStringValue("System.COMLogFlag").Split(',');
  273. int[] bitData = new int[8];
  274. for (int i = 0; i < strArray.Length; i++)
  275. {
  276. if (int.TryParse(strArray[i], System.Globalization.NumberStyles.HexNumber, null, out int Flag))
  277. {
  278. bitData[i] = Flag;
  279. }
  280. else
  281. {
  282. bitData[i] = 0;
  283. LOG.Write(eEvent.WARN_DEVICE_INFO, "System", $"Parse System.COMLogFlag failed: {strArray[i]}.");
  284. }
  285. }
  286. _EnableLog = new BitArray(bitData);
  287. }
  288. if (int.TryParse(portName.Substring(3), out int nCom))
  289. {
  290. if (_EnableLog.Length > nCom)
  291. {
  292. return _EnableLog[nCom];
  293. }
  294. }
  295. return false;
  296. }
  297. public bool ReConnect(string com = null)
  298. {
  299. if (IsConnected == true)
  300. {
  301. return true;
  302. }
  303. Close();
  304. string[] coms = SerialPort.GetPortNames();
  305. string newPortName = com == null ? PortName : com;
  306. for (int i = 0; i < coms.Length; i++)
  307. {
  308. if (coms[i].ToUpper() == newPortName)
  309. {
  310. if (_port.IsOpen)
  311. {
  312. return true;
  313. }
  314. else
  315. {
  316. _port.PortName = newPortName;
  317. Open();
  318. return _port.IsOpen;
  319. }
  320. }
  321. }
  322. return false;
  323. }
  324. }
  325. }