zoukankan      html  css  js  c++  java
  • C# RFID windows 服务 串口方式

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

      

      分享是种美德,要提倡!

  • 相关阅读:
    d2admin框架学习
    手机访问本地配置域名下的项目
    laydate 限制结束日期不能大于起始日期
    学习MVC之租房网站(十一)-定时任务和云存储
    学习MVC之租房网站(十)-预约和跟单
    学习MVC之租房网站(九)-房源显示和搜索
    学习MVC之租房网站(八)- 前台注册和登录
    学习MVC之租房网站(七)-房源管理和配图上传
    《程序员修炼之道》笔记(九)
    《程序员修炼之道》笔记(八)
  • 原文地址:https://www.cnblogs.com/liuyunsheng/p/3739605.html
Copyright © 2011-2022 走看看