話說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的處理還是很簡單的。 跟處理串口沒什么卻別。發送數據-> 讀取接收的數據->解析->處理業務入庫。
分享是種美德,要提倡!
