diff --git a/UHFHelper/UHFCommon.cs b/UHFHelper/UHFCommon.cs index 0d7227b..eb11577 100644 --- a/UHFHelper/UHFCommon.cs +++ b/UHFHelper/UHFCommon.cs @@ -1,11 +1,46 @@ -namespace UHFHelper +using System.Runtime.InteropServices; +using System.Text; + +namespace UHFHelper { + + public static class UHFHelper + { + /// + /// 解析数据 + /// + /// + /// + public static string ByteArrayToHexString(this byte[] data) + { + StringBuilder sb = new(data.Length * 3); + foreach (byte b in data) + sb.Append(Convert.ToString(b, 16).PadLeft(2, '0')); + return sb.ToString().ToUpper(); + + } + } + public class Resultoutput { public bool Res { get; set; } public string? ResMes { get; set; } } + + + public class DKoutput + { + /// + /// 刷卡机地址 + /// + public string? Address { get; set; } + /// + /// 刷卡器数据 + /// + public string? ResData { get; set; } + } + /// /// 蜂鸣开关 /// @@ -15,4 +50,38 @@ open=0, close=1, } + /// + /// CRC算法 + /// + public class CRC16 + { + /// + /// CRC算法 + /// + /// + /// + public static byte[] ToCRC16(byte[] pucY) + { + ushort uiCrcValue = 0xFFFF; + for ( int ucI = 0; ucI < pucY.Length; ucI++) + { + uiCrcValue = Convert.ToUInt16(uiCrcValue ^ pucY[ucI]); + for ( int ucJ = 0; ucJ < 8; ucJ++) + { + if ((uiCrcValue & 0x0001)==1) + { + uiCrcValue =Convert.ToUInt16((uiCrcValue >> 1) ^ 0x8408); + } + else + { + uiCrcValue = Convert.ToUInt16((uiCrcValue >> 1)); + } + } + } + byte[] tem = new byte[2]; + tem[0] = (byte)uiCrcValue; + tem[1] = (byte)(uiCrcValue >> 8); + return tem; + } + } } diff --git a/UHFHelper/UHFHelper.csproj b/UHFHelper/UHFHelper.csproj index 14ee644..1b84fdc 100644 --- a/UHFHelper/UHFHelper.csproj +++ b/UHFHelper/UHFHelper.csproj @@ -7,6 +7,10 @@ AnyCPU;x86 + + + + ..\lib\UHFReader18CSharp.dll diff --git a/UHFHelper/UHF_RS485_Helper.cs b/UHFHelper/UHF_RS485_Helper.cs new file mode 100644 index 0000000..2d2bec3 --- /dev/null +++ b/UHFHelper/UHF_RS485_Helper.cs @@ -0,0 +1,197 @@ +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(16).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; + } + } + + 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; + } +} diff --git a/test/Form1.Designer.cs b/test/Form1.Designer.cs index aa02f2f..c69e3fd 100644 --- a/test/Form1.Designer.cs +++ b/test/Form1.Designer.cs @@ -34,6 +34,11 @@ this.button3 = new System.Windows.Forms.Button(); this.button4 = new System.Windows.Forms.Button(); this.textBox1 = new System.Windows.Forms.TextBox(); + this.button5 = new System.Windows.Forms.Button(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.button6 = new System.Windows.Forms.Button(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox4 = new System.Windows.Forms.TextBox(); this.SuspendLayout(); // // button1 @@ -92,11 +97,60 @@ this.textBox1.Size = new System.Drawing.Size(100, 23); this.textBox1.TabIndex = 4; // + // button5 + // + this.button5.Location = new System.Drawing.Point(55, 323); + this.button5.Name = "button5"; + this.button5.Size = new System.Drawing.Size(108, 23); + this.button5.TabIndex = 5; + this.button5.Text = "rs485打开串口"; + this.button5.UseVisualStyleBackColor = true; + this.button5.Click += new System.EventHandler(this.button5_Click); + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Location = new System.Drawing.Point(178, 323); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(121, 25); + this.comboBox1.TabIndex = 6; + // + // button6 + // + this.button6.Location = new System.Drawing.Point(322, 323); + this.button6.Name = "button6"; + this.button6.Size = new System.Drawing.Size(75, 23); + this.button6.TabIndex = 7; + this.button6.Text = "读取"; + this.button6.UseVisualStyleBackColor = true; + this.button6.Click += new System.EventHandler(this.button6_Click); + // + // label2 + // + this.label2.Location = new System.Drawing.Point(451, 324); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(266, 23); + this.label2.TabIndex = 8; + this.label2.Text = "label2"; + // + // textBox4 + // + this.textBox4.Location = new System.Drawing.Point(451, 369); + this.textBox4.Name = "textBox4"; + this.textBox4.Size = new System.Drawing.Size(100, 23); + this.textBox4.TabIndex = 9; + // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.textBox4); + this.Controls.Add(this.label2); + this.Controls.Add(this.button6); + this.Controls.Add(this.comboBox1); + this.Controls.Add(this.button5); this.Controls.Add(this.textBox1); this.Controls.Add(this.button4); this.Controls.Add(this.label1); @@ -105,6 +159,7 @@ this.Controls.Add(this.button1); this.Name = "Form1"; this.Text = "Form1"; + this.Load += new System.EventHandler(this.Form1_Load); this.ResumeLayout(false); this.PerformLayout(); @@ -118,5 +173,10 @@ private Button button3; private Button button4; private TextBox textBox1; + private Button button5; + private ComboBox comboBox1; + private Button button6; + private Label label2; + private TextBox textBox4; } } \ No newline at end of file diff --git a/test/Form1.cs b/test/Form1.cs index 7d8fae8..d95eff4 100644 --- a/test/Form1.cs +++ b/test/Form1.cs @@ -1,3 +1,4 @@ +using System.Text; using UHFHelper; namespace test @@ -44,8 +45,44 @@ namespace test private void button4_Click(object sender, EventArgs e) { - var res = UHFCardHelper.GetInstance().WriteCard(textBox1.Text); + var res = UHFCardHelper.GetInstance().WriteCard(textBox1.Text); MessageBox.Show(res.ResMes); } + + private void Form1_Load(object sender, EventArgs e) + { + + //// 鿴ô + //foreach (var val in UHF_RS485_Helper.GetLocalSerialPortNames()) + //{ + // this.comboBox1.Items.Add(val); + //} + } + UHF_RS485_Helper uHF_RS485_Helper; + private void button5_Click(object sender, EventArgs e) + { + // ʼ + UHF_RS485_Helper.GetInstance().Open(new SerialParam + { + PortName = "COM5", + BaudRate = 57600, + DataBits = 8 + }); + if (!UHF_RS485_Helper.GetInstance().GetSerialPortState()) + { + MessageBox.Show("ʧ"); + } + } + + private async void button6_Click(object sender, EventArgs e) + { + if (UHF_RS485_Helper.GetInstance().GetSerialPortState()) + { + var oldss = await UHF_RS485_Helper.GetInstance().ReadCard(01); + var sss = oldss?.ResData; + textBox4.Text = sss; + label2.Text = sss; + } + } } } \ No newline at end of file