ThorntonSerialDevice.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. using Aitex.Core.RT.Event;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.SCCore;
  4. using Aitex.Core.Util;
  5. using System;
  6. using System.Collections.Concurrent;
  7. using System.Collections.Generic;
  8. using System.IO.Ports;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. namespace MECF.Framework.Common.Device.ResistivityProbe
  14. {
  15. public class ThorntonSerialDevice
  16. {
  17. #region Delegate
  18. public delegate void ThorntonDataChanged(string name, List<string> lstContent);
  19. #endregion
  20. #region 常量
  21. private const string CONSTANT_COMMAND = "D00Z\r";
  22. private const char SPLIT_CHARACTER = '\t';
  23. #endregion
  24. #region 内部变量
  25. /// <summary>
  26. /// 连接状态
  27. /// </summary>
  28. private bool _connected;
  29. /// <summary>
  30. /// 串口
  31. /// </summary>
  32. private SerialPort _serialPort;
  33. /// <summary>
  34. /// 模块名称
  35. /// </summary>
  36. private string _name;
  37. /// <summary>
  38. /// 定时器
  39. /// </summary>
  40. private PeriodicJob _periodJob;
  41. /// <summary>
  42. /// 接收超时
  43. /// </summary>
  44. private int _receiveTimeout = 2000;
  45. /// <summary>
  46. /// 错误信息
  47. /// </summary>
  48. private string _errmsg = "";
  49. /// <summary>
  50. /// warning信息
  51. /// </summary>
  52. private string _warnMsg = "";
  53. /// <summary>
  54. /// 重连
  55. /// </summary>
  56. private bool _reconnected;
  57. /// <summary>
  58. /// 离线时间
  59. /// </summary>
  60. private DateTime _offlineDateTime;
  61. /// <summary>
  62. /// 首次连接成功
  63. /// </summary>
  64. private bool _isFirstConnected = false;
  65. /// <summary>
  66. /// 锁
  67. /// </summary>
  68. private object _locker = new object();
  69. #endregion
  70. #region 公共变量
  71. public event ThorntonDataChanged OnDataChanged;
  72. #endregion
  73. #region 属性
  74. /// <summary>
  75. /// 连接状态
  76. /// </summary>
  77. public bool Connected
  78. {
  79. get { return _connected; }
  80. set { _connected = value; }
  81. }
  82. #endregion
  83. /// <summary>
  84. /// 构造函数
  85. /// </summary>
  86. /// <param name="name"></param>
  87. /// <param name="portName"></param>
  88. /// <param name="baudRate"></param>
  89. /// <param name="stopBits"></param>
  90. /// <param name="dataBits"></param>
  91. /// <param name="parity"></param>
  92. public ThorntonSerialDevice(string name, string portName, int baudRate = 9600, StopBits stopBits = StopBits.One, int dataBits = 8, Parity parity = Parity.None, bool reconnected = false, int receiveTimeout = 2000)
  93. {
  94. _serialPort = new SerialPort();
  95. _serialPort.BaudRate = baudRate;
  96. _serialPort.StopBits = stopBits;
  97. _serialPort.DataBits = dataBits;
  98. _serialPort.Parity = parity;
  99. _serialPort.PortName = portName;
  100. _serialPort.ErrorReceived += SerialPort_ErrorReceived;
  101. _serialPort.WriteTimeout = receiveTimeout;
  102. _serialPort.ReadTimeout = receiveTimeout;
  103. _receiveTimeout = receiveTimeout;
  104. _name = name;
  105. _reconnected = reconnected;
  106. _periodJob = new PeriodicJob(500, OnTimer, $"{_name}_reader", true, true);
  107. }
  108. /// <summary>
  109. /// 启动
  110. /// </summary>
  111. public void Start()
  112. {
  113. //Open();
  114. }
  115. /// <summary>
  116. /// 打开串口
  117. /// </summary>
  118. private void Open()
  119. {
  120. lock (_locker)
  121. {
  122. if (!_connected)
  123. {
  124. try
  125. {
  126. if (!_serialPort.IsOpen)
  127. {
  128. _serialPort.Open();
  129. LOG.WriteLog(eEvent.INFO_RESISTIVITY, _name, $"connect port[{_serialPort.PortName}] success");
  130. }
  131. _connected = true;
  132. }
  133. catch (Exception ex)
  134. {
  135. WriteErrorMsg(ex.Message);
  136. }
  137. }
  138. }
  139. }
  140. /// <summary>
  141. /// 关闭
  142. /// </summary>
  143. public void Close()
  144. {
  145. try
  146. {
  147. _connected = false;
  148. _serialPort.Close();
  149. _periodJob.Stop();
  150. }
  151. catch (Exception ex)
  152. {
  153. WriteErrorMsg(ex.Message);
  154. }
  155. }
  156. #region 事件
  157. /// <summary>
  158. /// 串口错误
  159. /// </summary>
  160. /// <param name="sender"></param>
  161. /// <param name="e"></param>
  162. private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
  163. {
  164. LOG.WriteLog(eEvent.ERR_RESISTIVITY, _name, e.EventType.ToString());
  165. }
  166. #endregion
  167. /// <summary>
  168. /// 定时器
  169. /// </summary>
  170. /// <returns></returns>
  171. private bool OnTimer()
  172. {
  173. if (!_connected)
  174. {
  175. if (_reconnected)
  176. {
  177. Open();
  178. }
  179. else
  180. {
  181. _periodJob.Stop();
  182. }
  183. }
  184. else
  185. {
  186. ReadData();
  187. }
  188. return true;
  189. }
  190. /// <summary>
  191. /// 读取数据
  192. /// </summary>
  193. public void ReadData()
  194. {
  195. string str = "";
  196. try
  197. {
  198. _serialPort.WriteLine(CONSTANT_COMMAND);
  199. DateTime dt = DateTime.Now;
  200. while (DateTime.Now.Subtract(dt).TotalMilliseconds <= _receiveTimeout)
  201. {
  202. if (_serialPort.BytesToRead > 0)
  203. {
  204. string tmp = _serialPort.ReadLine();
  205. if (!string.IsNullOrEmpty(tmp))
  206. {
  207. WriteInfoMsg(0, tmp);
  208. }
  209. if (tmp != CONSTANT_COMMAND)
  210. {
  211. str = tmp;
  212. break;
  213. }
  214. }
  215. else
  216. {
  217. Thread.Sleep(100);
  218. }
  219. }
  220. if (!string.IsNullOrEmpty(str))
  221. {
  222. string[] strAry = str.Split(SPLIT_CHARACTER);
  223. if (strAry.Length >= 4)
  224. {
  225. List<string> lst = new List<string>();
  226. for (int i = 2; i < strAry.Length; i += 2)
  227. {
  228. lst.Add(strAry[i]);
  229. }
  230. if (OnDataChanged != null)
  231. {
  232. OnDataChanged(_name, lst);
  233. }
  234. }
  235. }
  236. _errmsg = "";
  237. }
  238. catch (Exception ex)
  239. {
  240. WriteWarnMsg($"read exception{ex.Message}--{str}");
  241. }
  242. }
  243. /// <summary>
  244. /// 记录错误信息
  245. /// </summary>
  246. /// <param name="msg"></param>
  247. private void WriteErrorMsg(string msg, bool disConnected = true)
  248. {
  249. if (disConnected)
  250. {
  251. _connected = false;
  252. _offlineDateTime = DateTime.Now;
  253. }
  254. if (_errmsg != msg)
  255. {
  256. _errmsg = msg;
  257. LOG.WriteLog(eEvent.ERR_RESISTIVITY, _name, msg);
  258. }
  259. }
  260. /// <summary>
  261. /// 记录错误信息
  262. /// </summary>
  263. /// <param name="msg"></param>
  264. private void WriteWarnMsg(string msg)
  265. {
  266. if (_warnMsg != msg)
  267. {
  268. _warnMsg = msg;
  269. LOG.WriteLog(eEvent.WARN_RESISTIVITY, _name, msg);
  270. }
  271. }
  272. /// <summary>
  273. /// 写日志
  274. /// </summary>
  275. /// <param name="bytes"></param>
  276. private void WriteInfoMsg(int logType, string str)
  277. {
  278. bool enableLog = false;
  279. if (SC.ContainsItem("Log.EnableResistivityLog"))
  280. {
  281. enableLog = SC.GetValue<bool>("Log.EnableResistivityLog");
  282. }
  283. if (enableLog)
  284. {
  285. string type = logType == 0 ? "receive" : "send";
  286. LOG.WriteBackgroundLog(eEvent.INFO_RESISTIVITY, _name, $"{type} {str}");
  287. }
  288. }
  289. }
  290. }