You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

UHF_RS485_Helper.cs 8.1 KiB

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