using BPA.Helper; using System.Text.RegularExpressions; namespace BPASmartClient.Nfc { public class NFCHelper { private volatile static NFCHelper _Instance; public static NFCHelper GetInstance => _Instance ?? (_Instance = new NFCHelper()); private NFCHelper() { } public ReadResult GetReadResult { get; set; } = new ReadResult(); public Action Update { get; set; } //转换卡号专用 private byte[] convertSNR(string str, int keyN) { string regex = "[^a-fA-F0-9]"; string tmpJudge = Regex.Replace(str, regex, ""); //长度不对,直接退回错误 if (tmpJudge.Length != 12) return null; string[] tmpResult = Regex.Split(str, regex); byte[] result = new byte[keyN]; int i = 0; foreach (string tmp in tmpResult) { result[i] = Convert.ToByte(tmp, 16); i++; } return result; } //数据输入判断函数2个 private string formatStr(string str, int num_blk) { string tmp = Regex.Replace(str, "[^a-fA-F0-9]", ""); //长度不对直接报错 //num_blk==-1指示不用检查位数 if (num_blk == -1) return tmp; //num_blk==其它负数,为-1/num_blk if (num_blk < -1) { if (tmp.Length != -16 / num_blk * 2) return null; else return tmp; } if (tmp.Length != 16 * num_blk * 2) return null; else return tmp; } private void convertStr(byte[] after, string before, int length) { for (int i = 0; i < length; i++) { after[i] = Convert.ToByte(before.Substring(2 * i, 2), 16); } } //显示命令执行结果 private string showStatue(int Code) { string msg = ""; switch (Code) { case 0x00: msg = "命令执行成功"; break; case 0x01: msg = "命令操作失败"; break; case 0x02: msg = "地址校验错误"; break; case 0x03: msg = "找不到已选择的端口"; break; case 0x04: msg = "读写器返回超时"; break; case 0x05: msg = "数据包流水号不正确"; break; case 0x07: msg = "接收异常"; break; case 0x0A: msg = "参数值超出范围"; break; case 0x80: msg = "参数设置成功"; break; case 0x81: msg = "参数设置失败"; break; case 0x82: msg = "通讯超时"; break; case 0x83: msg = "卡不存在"; break; case 0x84: msg = "接收卡数据出错"; break; case 0x85: msg = "未知的错误"; break; case 0x87: msg = "输入参数或者输入命令格式错误"; break; case 0x89: msg = "输入的指令代码不存在"; break; case 0x8A: msg = "在对于卡块初始化命令中出现错误"; break; case 0x8B: msg = "在防冲突过程中得到错误的序列号"; break; case 0x8C: msg = "密码认证没通过"; break; case 0x8F: msg = "读取器接收到未知命令"; break; case 0x90: msg = "卡不支持这个命令"; break; case 0x91: msg = "命令格式有错误"; break; case 0x92: msg = "在命令的FLAG参数中,不支持OPTION 模式"; break; case 0x93: msg = "要操作的BLOCK不存在"; break; case 0x94: msg = "要操作的对象已经别锁定,不能进行修改"; break; case 0x95: msg = "锁定操作不成功"; break; case 0x96: msg = "写操作不成功"; break; default: msg = "未知错误2"; break; } return msg; } /// /// 结果显示 /// /// /// /// /// private string showData(byte[] data, int s, int e) { string res = string.Empty; //非负转换 for (int i = 0; i < e; i++) { if (data[s + i] < 0) data[s + i] = Convert.ToByte(Convert.ToInt32(data[s + i]) + 256); } for (int i = 0; i < e; i++) { res += data[s + i].ToString("X2") + " "; } return res; } public void Init() { TaskManage.GetInstance.StartLong(new Action(() => { Read(); if (GetReadResult.ErrorInfo.Length > 0) MessageLog.GetInstance.Show(GetReadResult.ErrorInfo); Thread.Sleep(1000); }), "NFC数据读取"); } public void Read(ReadKeyEnum readKeyEnum = ReadKeyEnum.KeyA, ReadTypeEnum readTypeEnum = ReadTypeEnum.Idle, byte ReadStart = 16, byte ReadNum = 1) { //数据是一个64位的长整形,读取块的数量就是指第几个字 if (ReadStart < 0 || ReadStart > 63) return; if (ReadNum <= 0 || ReadNum > 4) return; byte mode1 = (readKeyEnum == ReadKeyEnum.KeyB) ? (byte)0x01 : (byte)0x00; byte mode2 = (readTypeEnum == ReadTypeEnum.All) ? (byte)0x01 : (byte)0x00; byte mode = (byte)((mode1 << 1) | mode2); byte blk_add = ReadStart; byte num_blk = ReadNum; //秘钥: //第一组:FF FF FF FF FF FF //第二组:B0 B1 B2 B3 B4 B5 //第三组:A0 A1 A2 A3 A4 A5 byte[] snr = new byte[6]; snr = convertSNR("FF FF FF FF FF FF", 6); if (snr == null) { GetReadResult.ErrorInfo = "序列号无效!"; return; } byte[] buffer = new byte[16 * num_blk]; try { int nRet = Reader.MF_Read(mode, blk_add, num_blk, snr, buffer); GetReadResult.StatueCode = showStatue(nRet); if (nRet != 0) { GetReadResult.StatueCode = showStatue(buffer[0]); GetReadResult.CardNum = string.Empty; GetReadResult.Data = string.Empty; } else { GetReadResult.CardNum = showData(snr, 0, 4); GetReadResult.Data = showData(buffer, 0, 16 * num_blk); } } catch (Exception ex) { GetReadResult.CardNum = string.Empty; GetReadResult.Data = string.Empty; MessageLog.GetInstance.Show(ex.ToString()); } finally { Update?.Invoke(); } } } }