No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

285 líneas
9.0 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. /// <summary>
  70. /// 读卡方法,返回读卡器数据
  71. /// </summary>
  72. /// <param name="adr">设备读取地址</param>
  73. /// <returns></returns>
  74. public DKoutput? ReadCard(int adr)
  75. {
  76. if (_serialPort == null) return null;
  77. DKoutput dKoutput = new();
  78. var readByte = ReadByte(adr);
  79. _serialPort.Write(readByte, 0, readByte.Length);
  80. var result = SendMessage(readByte, 150, 18);
  81. if (result == null)
  82. {
  83. return null;
  84. }
  85. else
  86. {
  87. //获取校验码
  88. var crc = result.Skip(16).Take(2).ToArray();
  89. //获取卡号
  90. var cardNo = result.Skip(6).Take(10).ToArray();
  91. //获取读卡器数据
  92. var readData = result.Skip(0).Take(16).ToArray();
  93. //获取读卡器地址
  94. var address = result.Skip(1).Take(1).ToArray();
  95. //判断数据是否合法
  96. var temcrc = CRC16.ToCRC16(readData);
  97. if (crc.ByteArrayToHexString() == temcrc.ByteArrayToHexString())
  98. {
  99. dKoutput.Address = address.ByteArrayToHexString();
  100. dKoutput.ResData = cardNo.ByteArrayToHexString();
  101. return dKoutput;
  102. }
  103. else
  104. {
  105. return null;
  106. }
  107. }
  108. }
  109. /// <summary>
  110. /// 生成读取命令
  111. /// </summary>
  112. /// <returns></returns>
  113. private byte[] ReadByte(int adr)
  114. {
  115. //根据读取地址生成读取命令
  116. byte[] data1 = new byte[3] { 04, (byte)adr, 01 };
  117. //生成crc校验码
  118. byte[] data2 = CRC16.ToCRC16(data1);
  119. byte[] data3 = new byte[data1.Length + data2.Length];
  120. data1.CopyTo(data3, 0);
  121. data2.CopyTo(data3, data1.Length);
  122. return data3;
  123. }
  124. /// <summary>
  125. /// 获取本机可用串口
  126. /// </summary>
  127. /// <returns></returns>
  128. public string[] GetLocalSerialPortNames()
  129. {
  130. return SerialPort.GetPortNames();
  131. }
  132. /// <summary>
  133. /// 发送数据
  134. /// </summary>
  135. /// <param name="msg">数据</param>
  136. /// <param name="timeout">超时时间</param>
  137. /// <param name="count">串口回复字节数</param>
  138. /// <returns></returns>
  139. public byte[]? SendMessage(byte[] msg, long timeout, int count)
  140. {
  141. if (_serialPort == null) return null;
  142. var stopwatch = Stopwatch.StartNew();
  143. try
  144. {
  145. _serialPort.DiscardInBuffer();
  146. _serialPort.Write(msg, 0, msg.Length);
  147. var tmpCount = count;
  148. byte[] buffer = new byte[tmpCount];
  149. int offset = 0;
  150. while (tmpCount > 0)
  151. {
  152. if (stopwatch.ElapsedMilliseconds >= timeout)
  153. {
  154. return null;
  155. }
  156. int res = _serialPort.BytesToRead;
  157. if (res > 0)
  158. {
  159. var readCount = _serialPort.Read(buffer, offset, tmpCount);
  160. if (buffer.Skip(0).Take(1).ToArray().ByteArrayToHexString() == "05")
  161. {
  162. return null;
  163. }
  164. offset += readCount;
  165. tmpCount -= readCount;
  166. }
  167. }
  168. return buffer;
  169. }
  170. catch (Exception ex)
  171. {
  172. return null;
  173. }
  174. }
  175. /// <summary>
  176. /// 发送数据
  177. /// </summary>
  178. public void SendMessage(int adr)
  179. {
  180. var readByte = ReadByte(adr);
  181. if (_serialPort == null) return;
  182. _serialPort.Write(readByte, 0, readByte.Length);
  183. }
  184. /// <summary>
  185. /// 读取数据
  186. /// </summary>
  187. /// <returns></returns>
  188. public byte[]? GetMessage(int count, long timeout)
  189. {
  190. if (_serialPort == null) return null;
  191. var stopwatch = Stopwatch.StartNew();
  192. try
  193. {
  194. _serialPort.DiscardInBuffer();
  195. var tmpCount = count;
  196. byte[] buffer = new byte[tmpCount];
  197. int offset = 0;
  198. while (tmpCount > 0)
  199. {
  200. var readCount = _serialPort.Read(buffer, offset, tmpCount);
  201. if (readCount == 6)
  202. {
  203. tmpCount = 0;
  204. continue;
  205. }
  206. offset += readCount;
  207. tmpCount -= readCount;
  208. if (stopwatch.ElapsedMilliseconds >= timeout)
  209. {
  210. return null;
  211. }
  212. }
  213. return buffer;
  214. }
  215. catch (Exception ex)
  216. {
  217. return null;
  218. }
  219. }
  220. private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
  221. {
  222. throw new NotImplementedException();
  223. }
  224. ///// <summary>
  225. ///// 发送数据
  226. ///// </summary>
  227. ///// <param name="msg">数据</param>
  228. ///// <param name="timeout">超时时间</param>
  229. ///// <param name="count">串口回复字节数</param>
  230. ///// <returns></returns>
  231. //public async Task<byte[]?> SendMessageAsync(byte[] msg, TimeSpan timeout, int count)
  232. //{
  233. // var sendTask = Task.Run(() => SendMessage(msg, timeout, count));
  234. // //try
  235. // //{
  236. // // await Task.WhenAny(sendTask, Task.Delay(timeout));
  237. // //}
  238. // //catch (TaskCanceledException)
  239. // //{
  240. // // return null;
  241. // //}
  242. // return await sendTask;
  243. //}
  244. /// <summary>
  245. /// 发出蜂鸣声音3次,代表扣款成功!
  246. /// </summary>
  247. public void OpenBeep(int addr)
  248. {
  249. //byte[] sendData = new byte[] { 0x07, (byte)addr, 0x33, 0x08, 0x02, 0x03, 0x33, 0xB1 };
  250. byte[] data1 = new byte[6] { 0x07, (byte)addr, 0x33, 0x08, 0x02, 0x03 };
  251. //生成crc校验码
  252. byte[] data2 = CRC16.ToCRC16(data1);
  253. byte[] data3 = new byte[data1.Length + data2.Length];
  254. data1.CopyTo(data3, 0);
  255. data2.CopyTo(data3, data1.Length);
  256. if (_serialPort != null)
  257. {
  258. _serialPort.DiscardInBuffer();
  259. _serialPort.Write(data3, 0, data3.Length);
  260. }
  261. }
  262. }
  263. public class SerialParam
  264. {
  265. public string PortName { get; set; } = "COM3";
  266. public int BaudRate { get; set; } = 57600;
  267. public int DataBits { get; set; } = 8;
  268. public Parity PortParity { get; set; } = Parity.None;
  269. public StopBits PortStopBits { get; set; } = StopBits.One;
  270. }
  271. }