话说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的处理还是很简单的。 跟处理串口没什么却别。发送数据-> 读取接收的数据->解析->处理业务入库。

  

  分享是种美德,要提倡!

C# RFID windows 服务 串口方式的更多相关文章

  1. C# RFID windows 服务 网络协议方式

    上篇话说是串口方式操作RFID设备. 下面介绍网络协议方式. 设备支持断线重连. 那我们的服务也不能差了不是. 所以这个服务类也是支持的哦. 不解释上代码: namespace Rfid { /// ...

  2. C#程序安装为windows服务的方式

    项目开发中,需要将采集程序以windows服务的形式进行部署,可分为定时采集程序以及监控采集程序. 1.定时采集程序 采用Quartz.net框架实现定时任务,针对该种情形,可采用批处理文件的形式进行 ...

  3. InChatter系统之服务端的Windows服务寄宿方式(三)

    为了部署的方便,我们开发Windows服务的服务寄宿程序,这样我们的服务便可以作为系统服务,随着系统的启动和关闭而启动和关闭,而避免了其他的设置,同时在服务的终止时(如系统关闭等)能及时处理服务的关闭 ...

  4. kafka 以windows服务的方式在windows下安装并自启动

    准备工作: 下载kafka http://apache.fayea.com/kafka/0.10.0.0/kafka_2.10-0.10.0.0.tgz 解压kafka至D:\bigdata\kafk ...

  5. 以Windows服务方式运行ASP.NET Core程序

    我们对ASP.NET Core的使用已经进行了相当一段时间了,大多数时候,我们的Web程序都是发布到Linux主机上的,当然了,偶尔也有需求要发布到Windows主机上,这样问题就来了,难道直接以控制 ...

  6. 以Windows服务方式运行ASP.NET Core程序【转载】

    我们对ASP.NET Core的使用已经进行了相当一段时间了,大多数时候,我们的Web程序都是发布到Linux主机上的,当然了,偶尔也有需求要发布到Windows主机上,这样问题就来了,难道直接以控制 ...

  7. [转帖]以Windows服务方式运行ASP.NET Core程序

    以Windows服务方式运行ASP.NET Core程序 原作者blog: https://www.cnblogs.com/guogangj/p/9198031.htmlaspnet的blog 需要持 ...

  8. 以windows服务方式快速部署免安装版Postgres数据库

    目录 以windows服务方式快速部署免安装版Postgres数据库 1.下载Postgresql数据库免安装包 2.安装环境准备及验证 解压文件 测试环境依赖 3.创建并初始化数据目录 创建数据目录 ...

  9. 玩转Windows服务系列——服务运行、停止流程浅析

    通过研究Windows服务注册卸载的原理,感觉它并没有什么特别复杂的东西,Windows服务正在一步步退去它那神秘的面纱,至于是不是美女,大家可要睁大眼睛看清楚了. 接下来研究一下Windows服务的 ...

随机推荐

  1. mybatis xml 大于 小于

    当我们需要通过xml格式处理sql语句时,经常会用到< ,<=,>,>=等符号,但是很容易引起xml格式的错误,这样会导致后台将xml字符串转换为xml文档时报错,从而导致程序 ...

  2. DB2环境设置

    作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ 1.级别对应 • Environment variables at the operating system l ...

  3. 【hadoop2.6.0】通过代码运行程序流程

    之前跑了一下hadoop里面自带的例子,现在顺一下如何通过源代码来运行程序. 我懒得装eclipse,就全部用命令行了. 整体参考官网上的:http://hadoop.apache.org/docs/ ...

  4. 【HTTP】WireShark中获取Content-Encoding: gzip时的响应内容

    GZIP格式 详见:http://blog.csdn.net/jison_r_wang/article/details/52068607 表述的很清楚 关键:GZIP头以0x1F8B开始 用WireS ...

  5. 如何让Table中的第一列和第二列的值相乘然后赋值给第三列

    因为需求的原因所以这样做,不废话了,直接上代码,我用的GridView绑定的数据,table也一样,因为GridView通过浏览器编译后的代码就是table.下面是aspx页面的Html代码: < ...

  6. gcc提供的原子操作函数

    gcc从4.1.2提供了__sync_*系列的built-in函数,用于提供加减和逻辑运算的原子操作.其声明如下: type __sync_fetch_and_add (type *ptr, type ...

  7. 检查C++内存泄露

    #ifdef _DEBUG #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__) #else #define DEBUG_ ...

  8. 解决安卓TextView异常换行,参差不齐等问题

    参考:http://blog.csdn.net/u012286242/article/details/28429267?utm_source=tuicool&utm_medium=referr ...

  9. Linux 查看 删除进程

    这东西,时间久不用总容易忘....记下来! 1. 在 LINUX 命令平台输入 1-2 个字符后按 Tab 键会自动补全后面的部分(前提是要有这个东西,例如在装了 tomcat 的前提下, 输入 to ...

  10. NYOJ题目34韩信点兵

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAskAAAHiCAIAAACV1MbSAAAgAElEQVR4nO3dPXLjONeG4W8TyrUQx1 ...