话说RFID以前很火所以整理一下一年前自己处理的RFID程序,放源码.
一开始觉得他是个很神奇的东西。 包含串口通讯和网络通讯。 由于网络通讯设备太贵,所以国内的设备基本上都是在外置一个比较便宜的模块在里面。
本案例应该适用于大多数的RFID模块。
首先我们先放上RFID API:如下
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace Rfid { public class EPCSDKHelper { [DllImport("EPCSDK.dll")] public static extern IntPtr OpenComm(int portNo); [DllImport("EPCSDK.dll")] public static extern void CloseComm(IntPtr hCom); [DllImport("EPCSDK.dll")] public static extern bool ReadFirmwareVersion(IntPtr hCom, out int main, out int sub, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool GetReaderParameters(IntPtr hCom, int addr, int paramNum, byte[] parms, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool SetReaderParameters(IntPtr hCom, int addr, int paramNum, byte[] parms, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool StopReading(IntPtr hCom, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool ResumeReading(IntPtr hCom, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool IdentifySingleTag(IntPtr hCom, byte[] tagId, byte[] antennaNo, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool IdentifyUploadedSingleTag(IntPtr hCom, byte[] tagId, byte[] devNos, byte[] antennaNo); [DllImport("EPCSDK.dll")] public static extern bool IdentifyUploadedMultiTags(IntPtr hCom, out byte tagNum, byte[] tagIds, byte[] devNos, byte[] antennaNos); [DllImport("EPCSDK.dll")] public static extern bool ReadTag(IntPtr hCom, byte memBank, byte address, byte length, byte[] data, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool WriteTagSingleWord(IntPtr hCom, byte memBank, byte address, byte data1, byte data2, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool FastWriteTagID(IntPtr hCom, int bytesNum, byte[] bytes, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool FastWriteTagID_Lock(IntPtr hCom, int bytesNum, byte[] bytes, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool InitializeTag(IntPtr hCom, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool LockPassWordTag(IntPtr hCom, byte passwd1, byte passwd2, byte passwd3, byte passwd4, byte lockType, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool UnlockPassWordTag(IntPtr hCom, byte passwd1, byte passwd2, byte passwd3, byte passwd4, byte lockType, byte ReaderAddr); [DllImport("EPCSDK.dll")] public static extern bool KillTag(IntPtr hCom, byte passwd1, byte passwd2, byte passwd3, byte passwd4, byte ReaderAddr); } }
我们看到OpenComm他还是一串口方式打开的。
我们要记录每个设备的信息所以我们需要一个设备类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using RfidService.Common; namespace Rfid { public class RfidDevice { /// <summary> /// 开启监听现成 /// </summary> private Thread _mThread = null; /// <summary> /// 暂停事件 /// </summary> private readonly ManualResetEvent _mManualReset = null; /// <summary> /// 串口号 /// </summary> private readonly int _comNo = 0; /// <summary> /// 时间间隔 /// </summary> private readonly int _timeTick = 0; /// <summary> /// 是否多卡读取 /// </summary> private bool _multiFlag = false; /// <summary> /// RFID数据 /// </summary> private readonly List<byte[]> _data = new List<byte[]>(); /// <summary> /// 数据锁 /// </summary> private readonly object _dataLock = new object(); /// <summary> /// 错误数量 /// </summary> private int _errorCount = 0; /// <summary> /// 只读 串口号 /// </summary> public int ComNo { get { return _comNo; } } /// <summary> /// 串口句柄 /// </summary> public IntPtr ComHadle { set; get; } /// <summary> /// 只读 时间间隔 毫秒级 /// </summary> public int TimeTick { get { return _timeTick; } } /// <summary> /// 是否多卡标志 /// </summary> public bool MultiFlag { set { _multiFlag = value; } get { return _multiFlag; } } /// <summary> /// 暂停读取标志 /// </summary> public bool StopReadFlag { set; get; } /// <summary> /// 出入串口 /// </summary> public PassCom PassCom { set; get; } /// <summary> /// 构造函数 /// </summary> /// <param name="comNo"></param> /// <param name="sleepTime"></param> public RfidDevice(int comNo,int sleepTime) { _comNo = comNo; _timeTick = sleepTime; _mManualReset = new ManualResetEvent(true); ComHadle = EPCSDKHelper.OpenComm(_comNo); if (ComHadle == new IntPtr()) { //输出系统日志 //throw new Exception("打开串口失败!"); LogInfo.Error("打开串口:" + comNo + "失败!" ); } } /// <summary> /// 构造函数 /// </summary> /// <param name="comNo"></param> /// <param name="sleepTime"></param> /// <param name="multiFlag"></param> public RfidDevice(int comNo, int sleepTime,bool multiFlag) { _comNo = comNo; _timeTick = sleepTime; MultiFlag = multiFlag; _mManualReset = new ManualResetEvent(true); ComHadle = EPCSDKHelper.OpenComm(_comNo); if (ComHadle == new IntPtr()) { //输出系统日志 //throw new Exception("打开串口失败!"); LogInfo.Error("打开串口:" + comNo + "失败!"); } } /// <summary> /// 构造函数 /// </summary> /// <param name="comNo"></param> /// <param name="sleepTime"></param> /// <param name="multiFlag"></param> /// <param name="passCom"></param> public RfidDevice(int comNo, int sleepTime, bool multiFlag,PassCom passCom) { _comNo = comNo; _timeTick = sleepTime; _multiFlag = multiFlag; MultiFlag = multiFlag; _mManualReset = new ManualResetEvent(true); this.PassCom = passCom; ComHadle = EPCSDKHelper.OpenComm(_comNo); #if DEBUG Console.WriteLine("串口号:" + this.ComNo.ToString() + " - " + ComHadle.ToString()); #endif if (ComHadle == new IntPtr()) { //输出系统日志 //throw new Exception("打开串口失败!"); LogInfo.Error("打开串口:" + comNo + "失败!"); } } /// <summary> /// 关闭串口 /// </summary> public void CloseComm() { EPCSDKHelper.CloseComm(this.ComHadle); LogInfo.Info("关闭串口:" + this.ComNo ); } /// <summary> /// 开始读取 /// </summary> public void Start() { if (_mThread != null) return; _mThread = new Thread(GetRfidTag) {IsBackground = true}; _mThread.Start(); } /// <summary> /// 暂停 /// </summary> public void ReStart() { _mManualReset.Set(); } /// <summary> /// 继续 /// </summary> public void Stop() { _mManualReset.Reset(); } /// <summary> /// 获取RFID标签现成 /// </summary> private void GetRfidTag() { while(true) { GcCollect(); try { Monitor.Enter(this._dataLock); _mManualReset.WaitOne(); byte[] ids; byte[] devNos; byte[] antennaNos; if (this._multiFlag) { ids = new byte[12 * 200]; devNos = new byte[200]; antennaNos = new byte[200]; //处理多卡读取模式 byte idNum = 0; if (EPCSDKHelper.IdentifyUploadedMultiTags(this.ComHadle, out idNum, ids, devNos, antennaNos)) { _errorCount = 0; var tmpids = new byte[idNum * 12]; Array.Copy(ids, 0, tmpids, 0, tmpids.Length); this._data.Add(tmpids); #if DEBUG Console.WriteLine("串口号:"+this.ComNo.ToString() + " - " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.yyy") + " - 02 - " + TextEncoder.ByteArrayToHexString(ids)); LogInfo.Info("串口号:" + this.ComNo.ToString() + " - " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.yyy") + " - 02 - " + TextEncoder.ByteArrayToHexString(ids)); #endif } } else { ids = new byte[12]; devNos = new byte[1]; antennaNos = new byte[1]; //处理单卡读取模式 if (EPCSDKHelper.IdentifyUploadedSingleTag(this.ComHadle, ids, devNos, antennaNos)) { _errorCount = 0; this._data.Add(ids); #if DEBUG Console.WriteLine("串口号:" + this.ComNo.ToString() + " - " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.yyy") + " - 01 - " + TextEncoder.ByteArrayToHexString(ids)); LogInfo.Info("串口号:" + this.ComNo.ToString() + " - " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.yyy") + " - 01 - " + TextEncoder.ByteArrayToHexString(ids)); #endif } } } catch (Exception er) { #if DEBUG Console.WriteLine("串口号:" + this.ComNo.ToString() + " - " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.yyy") + " Error: " + er.Message); LogInfo.Error("串口号:" + this.ComNo.ToString() + " - " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.yyy") + " Error: " + er.Message); #endif _errorCount++; if (_errorCount > 10) { //设备复位 } } finally { Monitor.Exit(this._dataLock); } Thread.Sleep(this._timeTick); } } /// <summary> /// 获取RFID数据标签 /// </summary> /// <returns></returns> public IList<byte[]> GetData() { try { Monitor.Enter(this._dataLock); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); var tmpData = new List<byte[]>(); tmpData.AddRange(_data); _data.Clear(); #if DEBUG Console.WriteLine("串口号:" + this.ComNo.ToString() + " - " + "_tmpData:" + tmpData.Count + " _data:" + _data.Count); LogInfo.Info("串口号:" + this.ComNo.ToString() + " - " + "_tmpData:" + tmpData.Count + " _data:" + _data.Count); #endif return tmpData; } finally { Monitor.Exit(this._dataLock); } } /// <summary> /// 数据回收 /// </summary> private static void GcCollect() { GC.WaitForFullGCComplete(); GC.Collect(); GC.WaitForFullGCComplete(); } } }
当然我们还需要一个设备管理类作为设备的监管。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using RfidService; using System.Diagnostics; using System.Threading; using RfidService.Common; namespace Rfid { public class RfidDevices : IDisposable { /// <summary> /// RFID设备集合 /// </summary> private IList<RfidDevice> _lstRfidDevice = new List<RfidDevice>(); private readonly RfidDataContext _oRfidDataContext = new RfidDataContext(); /// <summary> /// 添加RFID设备 /// </summary> /// <param name="rfidDevice"></param> public void Add(RfidDevice rfidDevice) { this._lstRfidDevice.Add(rfidDevice); } /// <summary> /// 移除RFID设备 /// </summary> /// <param name="rfidDevice"></param> public void Remove(RfidDevice rfidDevice) { foreach (var o in _lstRfidDevice.Where(o => o.ComHadle == rfidDevice.ComHadle && o.ComNo == rfidDevice.ComNo)) { _lstRfidDevice.Remove(o); break; } } public void DeviceClose() { foreach (var o in _lstRfidDevice) { try { o.CloseComm(); } catch(Exception er) { LogInfo.Error("设备监听关闭失败:" + o.ComNo); LogInfo.Error("设备监听关闭失败:" + er.Message); } } } public IList<RfidDevice> GetDevices() { return _lstRfidDevice; } readonly object _oLock = new object(); /// <summary> /// 获取所有设备数据 /// </summary> /// <returns></returns> public void GetData() { try { Monitor.Enter(_oLock); var sw = new Stopwatch(); sw.Start(); var lstByteArray = new List<byte[]>(); var serviceDateTime = DateTime.Now; foreach (var o in _lstRfidDevice) { try { var lstByt = o.GetData(); foreach (var byt in lstByt) { for (var i = 0; i < byt.Length; i = i + 12) { var buffer = new byte[4]; GcCollect(); Array.Copy(byt, i + 8, buffer, 0, 4); var id = ((buffer[0]) + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 32)).ToString(); //处理自己的业务把 } } } catch (Exception er) { Console.WriteLine(er.Message + "\t\n" + er.StackTrace.ToString()); LogInfo.Info(er.Message); LogInfo.Info(er.StackTrace.ToString()); } } sw.Stop(); Console.WriteLine("操作数据库执行时间:" + sw.ElapsedMilliseconds.ToString()); LogInfo.Info("操作数据库执行时间:" + sw.ElapsedMilliseconds.ToString()); } finally { Monitor.Exit(_oLock); } } public void Dispose() { _lstRfidDevice.Clear(); _lstRfidDevice = null; GcCollect(); } public void GcCollect() { GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); } } }
通过以上几个类我们可以对设备的记录读写了。 在设备处理方法中你可以自行处理自己的业务逻辑。
其实从整体上看RFID的处理还是很简单的。 跟处理串口没什么却别。发送数据-> 读取接收的数据->解析->处理业务入库。
分享是种美德,要提倡!