首页 > 代码库 > C# RFID windows 服务 串口方式

C# RFID windows 服务 串口方式

话说RFID以前很火所以整理一下一年前自己处理的RFID程序,放源码.

一开始觉得他是个很神奇的东西。 包含串口通讯和网络通讯。 由于网络通讯设备太贵,所以国内的设备基本上都是在外置一个比较便宜的模块在里面。  

本案例应该适用于大多数的RFID模块。

首先我们先放上RFID API:如下 

+ View Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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他还是一串口方式打开的。

  我们要记录每个设备的信息所以我们需要一个设备类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
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 = http://www.mamicode.com/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 = http://www.mamicode.com/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();
        }
 
    }
}

  当然我们还需要一个设备管理类作为设备的监管。

+ View Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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的处理还是很简单的。 跟处理串口没什么却别。发送数据-> 读取接收的数据->解析->处理业务入库。 

  

  分享是种美德,要提倡!