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()
{
ThreadManage.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();
}
}
}
}