Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

295 рядки
9.5 KiB

  1. using System.Diagnostics;
  2. using System.IO.Ports;
  3. namespace UHFHelper
  4. {
  5. public class UHF_RS485_Helper
  6. {
  7. private SerialPort? _serialPort;
  8. private SerialParam? _serialParam;
  9. public Action OpenOk { get; set; }
  10. public Action DisConnect { get; set; }
  11. /// <summary>
  12. /// 单例模式
  13. /// </summary>
  14. private static UHF_RS485_Helper? Instance { get; set; }
  15. public static UHF_RS485_Helper GetInstance()
  16. {
  17. if (Instance == null)
  18. {
  19. Instance = new UHF_RS485_Helper();
  20. }
  21. return Instance;
  22. }
  23. /// <summary>
  24. /// 打开串口
  25. /// </summary>
  26. /// <param name="param"></param>
  27. public void Open(SerialParam param)
  28. {
  29. if (SerialPort.GetPortNames().Contains(param.PortName))
  30. {
  31. _serialParam = param;
  32. _serialPort = new SerialPort(_serialParam.PortName, _serialParam.BaudRate, _serialParam.PortParity, _serialParam.DataBits);
  33. try
  34. {
  35. _serialPort.Open();
  36. if (_serialPort.IsOpen) OpenOk?.Invoke();
  37. }
  38. catch (Exception)
  39. {
  40. }
  41. }
  42. }
  43. /// <summary>
  44. /// 获取串口状态
  45. /// </summary>
  46. /// <returns></returns>
  47. public bool GetSerialPortState()
  48. {
  49. if (_serialPort != null)
  50. {
  51. return _serialPort.IsOpen;
  52. }
  53. else
  54. {
  55. DisConnect?.Invoke();
  56. return false;
  57. }
  58. }
  59. /// <summary>
  60. /// 关闭串口
  61. /// </summary>
  62. public void Close()
  63. {
  64. if (_serialPort == null) return;
  65. _serialPort.Close();
  66. _serialPort.Dispose();
  67. _serialPort = null;
  68. }
  69. private object async = new object();
  70. /// <summary>
  71. /// 读卡方法,返回读卡器数据
  72. /// </summary>
  73. /// <param name="adr">设备读取地址</param>
  74. /// <returns></returns>
  75. public DKoutput? ReadCard(int adr)
  76. {
  77. lock (async)
  78. {
  79. try
  80. {
  81. if (_serialPort == null) return null;
  82. DKoutput dKoutput = new();
  83. var readByte = ReadByte(adr);
  84. _serialPort.Write(readByte, 0, readByte.Length);
  85. var result = SendMessage(readByte, 150, 18);
  86. if (result == null)
  87. {
  88. return null;
  89. }
  90. else
  91. {
  92. //获取校验码
  93. var crc = result.Skip(16).Take(2).ToArray();
  94. //获取卡号
  95. var cardNo = result.Skip(6).Take(10).ToArray();
  96. //获取读卡器数据
  97. var readData = result.Skip(0).Take(16).ToArray();
  98. //获取读卡器地址
  99. var address = result.Skip(1).Take(1).ToArray();
  100. //判断数据是否合法
  101. var temcrc = CRC16.ToCRC16(readData);
  102. if (crc.ByteArrayToHexString() == temcrc.ByteArrayToHexString())
  103. {
  104. dKoutput.Address = address.ByteArrayToHexString();
  105. dKoutput.ResData = cardNo.ByteArrayToHexString();
  106. return dKoutput;
  107. }
  108. else
  109. {
  110. return null;
  111. }
  112. }
  113. }
  114. catch (Exception ex) {
  115. return null;
  116. }
  117. }
  118. }
  119. /// <summary>
  120. /// 生成读取命令
  121. /// </summary>
  122. /// <returns></returns>
  123. private byte[] ReadByte(int adr)
  124. {
  125. //根据读取地址生成读取命令
  126. byte[] data1 = new byte[3] { 04, (byte)adr, 01 };
  127. //生成crc校验码
  128. byte[] data2 = CRC16.ToCRC16(data1);
  129. byte[] data3 = new byte[data1.Length + data2.Length];
  130. data1.CopyTo(data3, 0);
  131. data2.CopyTo(data3, data1.Length);
  132. return data3;
  133. }
  134. /// <summary>
  135. /// 获取本机可用串口
  136. /// </summary>
  137. /// <returns></returns>
  138. public string[] GetLocalSerialPortNames()
  139. {
  140. return SerialPort.GetPortNames();
  141. }
  142. /// <summary>
  143. /// 发送数据
  144. /// </summary>
  145. /// <param name="msg">数据</param>
  146. /// <param name="timeout">超时时间</param>
  147. /// <param name="count">串口回复字节数</param>
  148. /// <returns></returns>
  149. public byte[]? SendMessage(byte[] msg, long timeout, int count)
  150. {
  151. if (_serialPort == null) return null;
  152. var stopwatch = Stopwatch.StartNew();
  153. try
  154. {
  155. _serialPort.DiscardInBuffer();
  156. _serialPort.Write(msg, 0, msg.Length);
  157. var tmpCount = count;
  158. byte[] buffer = new byte[tmpCount];
  159. int offset = 0;
  160. while (tmpCount > 0)
  161. {
  162. if (stopwatch.ElapsedMilliseconds >= timeout)
  163. {
  164. return null;
  165. }
  166. int res = _serialPort.BytesToRead;
  167. if (res > 0)
  168. {
  169. var readCount = _serialPort.Read(buffer, offset, tmpCount);
  170. if (buffer.Skip(0).Take(1).ToArray().ByteArrayToHexString() == "05")
  171. {
  172. return null;
  173. }
  174. offset += readCount;
  175. tmpCount -= readCount;
  176. }
  177. }
  178. return buffer;
  179. }
  180. catch (Exception ex)
  181. {
  182. return null;
  183. }
  184. }
  185. /// <summary>
  186. /// 发送数据
  187. /// </summary>
  188. public void SendMessage(int adr)
  189. {
  190. var readByte = ReadByte(adr);
  191. if (_serialPort == null) return;
  192. _serialPort.Write(readByte, 0, readByte.Length);
  193. }
  194. /// <summary>
  195. /// 读取数据
  196. /// </summary>
  197. /// <returns></returns>
  198. public byte[]? GetMessage(int count, long timeout)
  199. {
  200. if (_serialPort == null) return null;
  201. var stopwatch = Stopwatch.StartNew();
  202. try
  203. {
  204. _serialPort.DiscardInBuffer();
  205. var tmpCount = count;
  206. byte[] buffer = new byte[tmpCount];
  207. int offset = 0;
  208. while (tmpCount > 0)
  209. {
  210. var readCount = _serialPort.Read(buffer, offset, tmpCount);
  211. if (readCount == 6)
  212. {
  213. tmpCount = 0;
  214. continue;
  215. }
  216. offset += readCount;
  217. tmpCount -= readCount;
  218. if (stopwatch.ElapsedMilliseconds >= timeout)
  219. {
  220. return null;
  221. }
  222. }
  223. return buffer;
  224. }
  225. catch (Exception ex)
  226. {
  227. return null;
  228. }
  229. }
  230. private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
  231. {
  232. throw new NotImplementedException();
  233. }
  234. ///// <summary>
  235. ///// 发送数据
  236. ///// </summary>
  237. ///// <param name="msg">数据</param>
  238. ///// <param name="timeout">超时时间</param>
  239. ///// <param name="count">串口回复字节数</param>
  240. ///// <returns></returns>
  241. //public async Task<byte[]?> SendMessageAsync(byte[] msg, TimeSpan timeout, int count)
  242. //{
  243. // var sendTask = Task.Run(() => SendMessage(msg, timeout, count));
  244. // //try
  245. // //{
  246. // // await Task.WhenAny(sendTask, Task.Delay(timeout));
  247. // //}
  248. // //catch (TaskCanceledException)
  249. // //{
  250. // // return null;
  251. // //}
  252. // return await sendTask;
  253. //}
  254. /// <summary>
  255. /// 发出蜂鸣声音3次,代表扣款成功!
  256. /// </summary>
  257. public void OpenBeep(int addr)
  258. {
  259. //byte[] sendData = new byte[] { 0x07, (byte)addr, 0x33, 0x08, 0x02, 0x03, 0x33, 0xB1 };
  260. byte[] data1 = new byte[6] { 0x07, (byte)addr, 0x33, 0x08, 0x02, 0x03 };
  261. //生成crc校验码
  262. byte[] data2 = CRC16.ToCRC16(data1);
  263. byte[] data3 = new byte[data1.Length + data2.Length];
  264. data1.CopyTo(data3, 0);
  265. data2.CopyTo(data3, data1.Length);
  266. if (_serialPort != null)
  267. {
  268. _serialPort.DiscardInBuffer();
  269. _serialPort.Write(data3, 0, data3.Length);
  270. }
  271. }
  272. }
  273. public class SerialParam
  274. {
  275. public string PortName { get; set; } = "COM3";
  276. public int BaudRate { get; set; } = 57600;
  277. public int DataBits { get; set; } = 8;
  278. public Parity PortParity { get; set; } = Parity.None;
  279. public StopBits PortStopBits { get; set; } = StopBits.One;
  280. }
  281. }