using System.Diagnostics; using System.IO.Ports; namespace UHFHelper { public class UHF_RS485_Helper { private SerialPort? _serialPort; private SerialParam? _serialParam; /// /// 单例模式 /// private static UHF_RS485_Helper? Instance { get; set; } public static UHF_RS485_Helper GetInstance() { if (Instance == null) { Instance = new UHF_RS485_Helper(); } return Instance; } /// /// 打开串口 /// /// public void Open(SerialParam param) { _serialParam = param; _serialPort = new SerialPort(_serialParam.PortName, _serialParam.BaudRate, _serialParam.PortParity, _serialParam.DataBits); _serialPort.Open(); } /// /// 获取串口状态 /// /// public bool GetSerialPortState() { if (_serialPort!=null) { return _serialPort.IsOpen; } else { return false; } } /// /// 关闭串口 /// public void Close() { if (_serialPort == null) return; _serialPort.Close(); _serialPort.Dispose(); _serialPort = null; } /// /// 读卡方法,返回读卡器数据 /// /// 设备读取地址 /// public async Task ReadCard(int adr) { DKoutput dKoutput = new(); var readByte = ReadByte(adr); var result = await SendMessageAsync(readByte, TimeSpan.FromSeconds(1), 18); if (result == null) { return null; } else { //获取校验码 var crc = result.Skip(16).Take(2).ToArray(); //获取卡号 var cardNo = result.Skip(6).Take(10).ToArray(); //获取读卡器数据 var readData = result.Skip(0).Take(16).ToArray(); //获取读卡器地址 var address = result.Skip(1).Take(1).ToArray(); //判断数据是否合法 var temcrc = CRC16.ToCRC16(readData); if (crc.ByteArrayToHexString() == temcrc.ByteArrayToHexString()) { dKoutput.Address = address.ByteArrayToHexString(); dKoutput.ResData = cardNo.ByteArrayToHexString(); return dKoutput; } else { return null; } } } /// /// 生成读取命令 /// /// private byte[] ReadByte(int adr) { //根据读取地址生成读取命令 byte[] data1 = new byte[3] { 04, (byte)adr, 01 }; //生成crc校验码 byte[] data2 = CRC16.ToCRC16(data1); byte[] data3 = new byte[data1.Length + data2.Length]; data1.CopyTo(data3, 0); data2.CopyTo(data3, data1.Length); return data3; } /// /// 获取本机可用串口 /// /// public string[] GetLocalSerialPortNames() { return SerialPort.GetPortNames(); } /// /// 发送数据 /// /// 数据 /// 超时时间 /// 串口回复字节数 /// public byte[]? SendMessage(byte[] msg, TimeSpan timeout, int count) { if (_serialPort == null) return null; var stopwatch = Stopwatch.StartNew(); var originalWriteTimeout = _serialPort.WriteTimeout; var originalReadTimeout = _serialPort.ReadTimeout; try { _serialPort.WriteTimeout = (int)Math.Max((timeout - stopwatch.Elapsed).TotalMilliseconds, 0); _serialPort.Write(msg, 0, msg.Length); var tmpCount = count; byte[] buffer = new byte[tmpCount]; int offset = 0; while (tmpCount > 0) { _serialPort.ReadTimeout = (int)Math.Max((timeout - stopwatch.Elapsed).TotalMilliseconds, 0); var readCount = _serialPort.Read(buffer, offset, tmpCount); if (readCount==6) { tmpCount = 0; continue; } offset += readCount; tmpCount -= readCount; } _serialPort.DiscardInBuffer(); return buffer; }catch(Exception ex) { return null; } finally { _serialPort.ReadTimeout = originalReadTimeout; _serialPort.WriteTimeout = originalWriteTimeout; } } /// /// 发送数据 /// /// 数据 /// 超时时间 /// 串口回复字节数 /// public async Task SendMessageAsync(byte[] msg, TimeSpan timeout, int count) { var sendTask = Task.Run(() => SendMessage(msg, timeout, count)); try { await Task.WhenAny(sendTask, Task.Delay(timeout)); } catch (TaskCanceledException) { throw new TimeoutException(); } return await sendTask; } /// /// 发出蜂鸣声音3次,代表扣款成功! /// public async void OpenBeep(int addr) { byte[] sendData = new byte[]{ 0x07, (byte)addr, 0x33, 0x08, 0x02, 0x03, 0x33,0xB1 }; await SendMessageAsync(sendData, TimeSpan.FromSeconds(1), 6); } } public class SerialParam { public string PortName { get; set; } = "COM3"; public int BaudRate { get; set; } = 57600; public int DataBits { get; set; } = 8; public Parity PortParity { get; set; } = Parity.None; public StopBits PortStopBits { get; set; } = StopBits.One; } }