RFIDAuto.cs 10.5 KB
using log4net; 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Asa.RFID
{
    public class RFIDAuto
    {
        public static readonly ILog LOGGER = LogManager.GetLogger("TheRFID");

        private string IP = "";
        private byte addr;
        private int portIndex;
        private bool IsConnect = false;
        private byte[] lastData = new byte[8];

        /// <summary>
        /// 接收事件
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="buff"></param>
        public delegate void Received_Event(string ip, byte[] buff);
        /// <summary>
        /// 接收数据
        /// </summary>
        public event Received_Event Received;

        public RFIDAuto(string ip)
        {
            this.IP = ip;
        }

        public int StopAutoScan()
        {
            try
            {
                IsConnect = false;
                byte scanMode = 0;
                int ErrCode = SetAutoScanMode(addr, scanMode);
                LOGGER.Info("Close RFID [" + IP + "] ScanMode:" + ErrCode);
                ErrCode = ReaderA.StaticClassReaderA.CloseNetPort(portIndex);
                LOGGER.Info("Close RFID [" + IP + "]:" + ErrCode);
                return ErrCode;
            }
            catch (Exception e)
            {
                LOGGER.Error("Close RFID[" + IP + "] has error", e);
            }
            return -1;
        }


        public int StartAutoScan(Received_Event OnReceive)
        {
            if (IsConnect)
            {
                LOGGER.Warn(" RFID [" + IP+"] is already connected, no need to start again");
                return 0;
            }
            this.Received = OnReceive;
            //IP合法
            string pattern = @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$";
            bool rtn = System.Text.RegularExpressions.Regex.IsMatch(IP, pattern);
            if (!rtn) {
                LOGGER.Error(IP + " is error");
                return -1;
            }

            string[] arr = IP.Split('.');
            if (arr.Length != 4)
            {
                LOGGER.Error(IP + " length is not 4");
                return -1;
            }
            addr = Convert.ToByte(arr[3]);
            int port = 6000 + Convert.ToInt32(arr[3]);
            portIndex = 0;

            int ErrCode = ReaderA.StaticClassReaderA.OpenNetPort(port, IP, ref addr, ref portIndex);
            LOGGER.Info("Connect [" + IP + "] :" + ErrCode);
            if (ErrCode == 0)
            {
                ErrCode = OpenAutoScanMode(addr);
                LOGGER.Info(" [" + IP + "]  Open Auto Scan Mode:" + ErrCode);
                Task.Factory.StartNew(AutoScan);
            }
            return ErrCode;
        }

        private int SetAutoScanMode(byte addr, byte scanMode)
        {
            byte[] scanModeData = new byte[11];

            //bit0: 0停止扫描,1开始扫描
            //bit1: 0正常数据扫描,1EAS扫描
            //bit2: 0正常灵敏度,1高灵敏度
            //bit3: 0禁止输入同步,1允许输入同步
            //bit4: 0禁止指令同步,1允许指令同步
            //bit5: 0禁止扫描提示,1允许扫描提示
            //bit6: 0禁止EAS探测提示,1允许EAS探测提示
            //bit7: 0禁止EAS消息输出提示,1允许EAS消息输出提示
            scanModeData[0] = scanMode;

            //bit0: 0不发送comAddr,1发送comAddr
            //bit1: 0不带UID,1带UID
            //bit2: 0不包含指定块,1包含指定块
            //bit3: 0不带安全状态字,1带安全状态字
            //bit4: 0 ASCII,1 HEX
            //bit5: 0不进行开关射频场,1进行开关射频场
            //bit6: 0无操作,1停止扫描关闭射频场
            //bit7: 0无,1鸣叫闪烁
            scanModeData[1] = 255;

            scanModeData[2] = 0;  //起始块号
            scanModeData[3] = 2;  //块总数          之前是28
            scanModeData[4] = 1;  //块的起始字节
            scanModeData[5] = 4;  //块的字节数

            //1   CR+LF      0x0D 0x0A
            //2   CR         0x0D
            //4   LF         0x0A
            //8   BEL        0x07
            //16  :(分号)    0x3B
            //32  ,(逗号)    0x2C
            //64  " "(空格)  0x20
            //128 自定义
            scanModeData[6] = 8;  //间隔符
            scanModeData[7] = 0;  //自定义间隔符,[6] = 128

            //1   CR+LF      0x0D 0x0A
            //2   CR         0x0D
            //4   LF         0x0A
            //8   BEL        0x07
            //16  :(分号)    0x3B
            //32  ,(逗号)    0x2C
            //64  " "(空格)  0x20
            //128 自定义
            scanModeData[8] = 8;  //结束符
            scanModeData[9] = 0;  //自定义间隔符,[8] = 128

            scanModeData[10] = 0x00;

            int ErrCode = ReaderA.StaticClassReaderA.SetScanMode(ref addr, scanModeData, portIndex);
            return ErrCode;
        }
        private DateTime LastOkTime = DateTime.Now;
        private void AutoScan()
        {
            IsConnect = true;

            byte[] dataBuffer = new byte[0];

            while (IsConnect)
            {
                try
                {
                    byte[] data = new byte[100];
                    int len = 0;
                    int ErrCode = ReaderA.StaticClassReaderA.ReadScanModeData(data, ref len, portIndex);

                    if (ErrCode == 0)
                    {
                        LastOkTime = DateTime.Now;
                        string dataStr = byteToStr(data, len);
                        LOGGER.Debug(IP + " Receive Code: " + ErrCode + " Len: " + len + " Data:" + dataStr);
                        byte[] temp = new byte[dataBuffer.Length + len];

                        Array.Copy(dataBuffer, temp, dataBuffer.Length);
                        Array.Copy(data, 0, temp, dataBuffer.Length, len);

                        byte[] bb = new byte[10];
                        int idx = -1;
                        bool start = false;
                        bool end = false;
                        int endIndex = -1;
                        for (int i = 0; i < temp.Length; i++)
                        {
                            byte b = temp[i];
                            if (b == 0x5A)
                            {
                                start = true;
                                idx = 0;
                                //bb[idx++] = result;
                            }
                            else if (b == 0x4A && start)
                            {
                                start = false;
                                end = true;
                                endIndex = i;
                                bb[idx++] = b;
                            }

                            if (start)
                            {
                                if (idx + 1 == bb.Length)
                                {
                                    start = false;
                                    end = false;
                                }
                                else
                                {
                                    bb[idx++] = b;
                                }
                            }

                            if (end)
                            {
                                byte[] _buff = new byte[8];
                                _buff[0] = bb[0];
                                _buff[1] = bb[1];
                                _buff[2] = bb[2];
                                _buff[3] = bb[3];
                                _buff[4] = bb[5];
                                _buff[5] = bb[6];
                                _buff[6] = 0;
                                _buff[7] = 0;
                                end = false;
                                string itemStr = byteToStr(_buff, _buff.Length);
                                lastData = _buff;
                                LOGGER.Debug("[" + IP + "] Item:" + itemStr);
                                Received?.Invoke(IP, _buff);
                            }
                        }

                        endIndex++;
                        if (endIndex < temp.Length)
                        {
                            dataBuffer = new byte[temp.Length - endIndex];
                            Array.Copy(temp, endIndex, dataBuffer, 0, temp.Length - endIndex);

                            dataStr = byteToStr(dataBuffer, dataBuffer.Length);
                            LOGGER.Debug(IP + " Receive Code:  剩余 Length: " + dataBuffer.Length + " Data:" + dataStr);
                        }
                    }
                    else if (ErrCode == 14 && IsConnect)
                    {
                        LOGGER.Error(IP + " Receive Code: " + ErrCode + "  进行重连");
                      //  LogUtil.error(IP + " Receive Code: " + ErrCode + "  进行重连");
                        StopAutoScan();
                        StartAutoScan(this.Received);
                        break;
                    }
                    else
                    {
                        TimeSpan span = DateTime.Now - LastOkTime;
                        if (span.TotalMinutes > 2)
                        {
                            LastOkTime = DateTime.Now;
                            string dataStr = byteToStr(data, len);
                            LOGGER.Debug(IP + " Receive Code: " + ErrCode + " Len: " + len + " Data:" + dataStr);
                        }
                    }
                    System.Threading.Thread.Sleep(60);
                }
                catch (Exception e)
                {
                    LOGGER.Error("ReadScanModeData Error:", e);
                }

            }
        }

        public byte[] ReadAndClear()
        {
            byte[] data = lastData;
            lastData = new byte[8];
            LOGGER.Info("Read and clear RFID[" + IP + "] data:" + byteToStr(data, data.Length));
            return data;
        }

        public byte[] Read()
        {
            return lastData;
        }

        private int OpenAutoScanMode(byte addr)
        {
            byte scanMode = 1;
            return SetAutoScanMode(addr, scanMode);
        }
        
        private string byteToStr(byte[] data, int len)
        {
            string s = "";
            for (int i = 0; i < len; i++)
            {
                s += data[i].ToString("X2") + " ";
            }
            return s;
        }
    }
}