JS调用web hid api接口驱动RFID读卡器读取IC卡号

`
<script language="javascript">
var time1;
let device; // 需要连接或已连接的设备
if ('hid' in navigator){
}else{
alert('您的浏览器不支持 Web Hid API,暂无法使用以下功能!');
}
navigator.hid.onconnect = function event() {
console.log("hid device connected: ", event.target);
}
navigator.hid.ondisconnect = function event() {
console.log("hid device disconnected: ", event.target);
}
function ParsedReturnData(databuff){
var datahex="";
if(databuff[0]==0x78 && databuff[1]==0x68 && databuff.length>4){
switch ( databuff[3]) {
case 0x0f:
textarea.value="读卡器已接受响声指令!";
break;
case 0x1E:
textarea.value="读取设备编号成功!";
for (i=5;i<9;i++){datahex=datahex+databuff[i].toString(16).padStart(2, '0').toUpperCase();}
serialnumber.value=datahex;
break;
case 0xF0:
switch(databuff[4]){
case 0x00:
textarea.value="读取IC卡号成功!";
for (i=5;i<9;i++){datahex=datahex+databuff[i].toString(16).padStart(2, '0').toUpperCase();}
carduid.value=datahex;
card8h10dz.value = parseInt("0x" + datahex).toString().padStart(10, '0');
LHCode = datahex.substring(6, 8) + datahex.substring(4, 6) + datahex.substring(2, 4) + datahex.substring(0, 2);
card8h10df.value = parseInt("0x" + LHCode).toString().padStart(10, '0');
break;
case 0x08:
textarea.value="寻卡失败,请重新将卡片放在读卡器感应区!";
break;
case 0x09:
textarea.value="选卡失败,此卡可能不是Mifare卡或感应区内有多张卡!";
break;
default:
textarea.value="寻卡失败,错误代码:"+databuff[4].toString();
break;
}
break;
case 0x10:
switch(databuff[4]){
case 0x00:
textarea.value="读取Ntag卡UID成功!";
for (i=5;i<12;i++){datahex=datahex+databuff[i].toString(16).padStart(2, '0').toUpperCase();}
ntaguid.value=datahex;
break;
case 0x08:
textarea.value="寻卡失败,请重新将Ntag卡放在读卡器感应区!";
break;
case 0x09:
textarea.value="选卡失败,此卡可能不是Ntag卡或感应区内有多张卡!";
break;
default:
textarea.value="寻卡失败,错误代码:"+databuff[4].toString();
break;
}
break;
case 0x21:
switch(databuff[4]){
case 0x00:
textarea.value="读取15693卡UID成功!";
for (i=7;i<15;i++){datahex=datahex+databuff[i].toString(16).padStart(2, '0').toUpperCase();}
uid15693.value=datahex;
break;
case 0x08:
textarea.value="寻卡失败,请重新将15693卡放在读卡器感应区!";
break;
case 0x09:
textarea.value="选卡失败,此卡可能不是15693卡!";
break;
default:
textarea.value="寻卡失败,错误代码:"+databuff[4].toString();
break;
}
break;
case 0x50:
switch(databuff[4]){
case 0x00:
textarea.value="读取二代证UID成功!";
for (i=5;i<13;i++){datahex=datahex+databuff[i].toString(16).padStart(2, '0').toUpperCase();}
sfzuid.value=datahex;
break;
case 0x08:
textarea.value="寻卡失败,请重新将二代证卡放在读卡器感应区!";
break;
default:
textarea.value="寻卡失败,错误代码:"+databuff[4].toString();
break;
}
break;
case 0x51:
switch(databuff[4]){
case 0x00:
textarea.value="读取iCLASS卡UID成功!";
for (i=5;i<13;i++){datahex=datahex+databuff[i].toString(16).padStart(2, '0').toUpperCase();}
iclassuid.value=datahex;
break;
case 0x08:
textarea.value="寻卡失败,请重新将iCLASS卡片放在读卡器感应区!";
break;
default:
textarea.value="寻卡失败,错误代码:"+databuff[4].toString();
break;
}
break;
default:
}
}
}
async function selectdev() {
try{
//const devices = await navigator.hid.requestDevice({ filters: [] });
//if (devices.length == 0) {
// console.log("No device selected\n\n");
// return;
//}
const devices = await navigator.hid.requestDevice({
filters: [{
vendorId: 0x0801, // 根据VID进行过滤
productId: 0x2011, // 根据PID进行过滤
//usagePage: 0x0c, // 根据usagePage进行过滤
//usage: 0x01, // 根据usage进行过滤
},],
});
device = devices[0]; // 选择列表中第一个设备
if (!device.opened) { // 检查设备是否打开
await device.open(); // 打开设备
}
device.oninputreport = (event) => { // 电脑接收到来自设备的消息回调
console.log(event); // event中包含device、reportId、data等内容
let array = new Uint8Array(event.data.buffer); // event.data.buffer就是接收到的inputreport包数据了
ParsedReturnData(array);
//let hexstr = "";
//for (const data of array) {
// hexstr += (Array(2).join(0) + data.toString(16).toUpperCase()).slice(-2) + " "; // 将字节数据转换成(XX )形式字符串
//}
//textarea.value += hexstr;
};
}
catch (e){
console.log(e);
}
}
function isUIntNum(val) {
var testval = /^\d+$/; // 非负整数
return (testval.test(val));
}
function isHex(val) {
var testval = /^(\d|[A-F]|[a-f])+$/; // 十六进制数判断
return (testval.test(val));
}
function ButtonDisable() { //删除按键的 onclick 事件,防止重复执行指令
document.getElementById("butt_beep").setAttribute("onclick", null);
document.getElementById("butt_getdevnum").setAttribute("onclick", null);
document.getElementById("butt_piccrequest").setAttribute("onclick", null);
//document.getElementById("butt_readloop").setAttribute("onclick", null);
}
async function beep() { //驱动发卡器响声令
if (!device?.opened) {
alert("请先选择已连接的读卡器!");
return;
}
textarea.value = "";
const outputData = new Uint8Array(32);
outputData[0]=0x78;
outputData[1]=0x68;
outputData[2]=0x04;
outputData[3]=0x0f;
outputData[4]=0x1e;
outputData[5]=0x00;
outputData[6]=0xe9;
outputData[7]=0x00;
await device.sendReport(0, outputData); // 发送数据,第一个参数为reportId,填0表示不使用reportId
}
async function getdevicenumber() { //读取发卡器唯一出厂序号,可以当加密狗使用
if (!device?.opened) {
alert("请先选择已连接的读卡器!");
return;
}
textarea.value = "";
serialnumber.value="";
const outputData = new Uint8Array(32);
outputData[0]=0x78;
outputData[1]=0x68;
outputData[2]=0x01;
outputData[3]=0x1e;
await device.sendReport(0, outputData); // 发送数据,第一个参数为reportId,填0表示不使用reportId
}
async function piccrequest() {
if (!device?.opened) {
alert("请先选择已连接的读卡器!");
return;
}
textarea.value = "";
carduid.value="";
card8h10dz.value="";
card8h10df.value="";
const outputData = new Uint8Array(32);
outputData[0]=0x78;
outputData[1]=0x68;
outputData[2]=0x01;
outputData[3]=0xf0;
await device.sendReport(0, outputData); // 发送数据,第一个参数为reportId,填0表示不使用reportId
}
function request_loop() {
if (!device?.opened) {
alert("请先选择已连接的读卡器!");
return;
}
if (document.getElementById('butt_readloop').value == '轮询读取M1卡UID') {
document.getElementById('butt_readloop').value = '停止轮询';
ButtonDisable();
time1 = setInterval("piccrequest()", 500); //开启间隔500毫秒寻一次卡
} else {
document.getElementById('butt_readloop').value = '轮询读取M1卡UID';
clearInterval(time1);
ButtonEnabled();
}
}
async function sfzrequest() {
if (!device?.opened) {
alert("请先选择已连接的读卡器!");
return;
}
textarea.value = "";
sfzuid.value="";
const outputData = new Uint8Array(32);
outputData[0]=0x78;
outputData[1]=0x68;
outputData[2]=0x01;
outputData[3]=0x50;
await device.sendReport(0, outputData); // 发送数据,第一个参数为reportId,填0表示不使用reportId
}
async function iclassrequest() {
if (!device?.opened) {
alert("请先选择已连接的读卡器!");
return;
}
textarea.value = "";
sfzuid.value="";
const outputData = new Uint8Array(32);
outputData[0]=0x78;
outputData[1]=0x68;
outputData[2]=0x01;
outputData[3]=0x51;
await device.sendReport(0, outputData); // 发送数据,第一个参数为reportId,填0表示不使用reportId
}
async function ntagrequest() {
if (!device?.opened) {
alert("请先选择已连接的读卡器!");
return;
}
textarea.value = "";
ntaguid.value="";
const outputData = new Uint8Array(32);
outputData[0]=0x78;
outputData[1]=0x68;
outputData[2]=0x01;
outputData[3]=0x10;
await device.sendReport(0, outputData); // 发送数据,第一个参数为reportId,填0表示不使用reportId
}
async function iso15693request(){
if (!device?.opened) {
alert("请先选择已连接的读卡器!");
return;
}
textarea.value = "";
uid15693.value="";
const outputData = new Uint8Array(32);
outputData[0]=0x78;
outputData[1]=0x68;
outputData[2]=0x0d;
outputData[3]=0x21;
outputData[4]=0x16;
outputData[15]=0xdd;
await device.sendReport(0, outputData); // 发送数据,第一个参数为reportId,填0表示不使用reportId
}
function ButtonEnabled() { //恢复各button 的onclick事件
document.getElementById("butt_beep").setAttribute("onclick", "beep()");
document.getElementById("butt_getdevnum").setAttribute("onclick", "getdevicenumber()");
document.getElementById("butt_piccrequest").setAttribute("onclick", "piccrequest()");
//document.getElementById("butt_readloop").setAttribute("onclick", "request_loop()");
}
window.onerror = function (e) {
ButtonEnabled(); //恢复按键的onclick事件
clearInterval(time1);
document.getElementById('butt_readloop').value = '轮询读取IC卡卡号';
alert("不好意思,出错了!");
return true;//屏蔽系统事件
}
</script>
<style>
th {
background-color:#F6FAFF;
color: blue;
font-family:楷体;
}
td {
background-color:#F6FAFF;
font-family:楷体;
}
</style>
</head>
<body>
<table width="866" height="346" align="center">
<tr>
<th width="124" height="45" scope="row"><input style="width:120px" name="butt_selectdev" type="submit" id="butt_selectdev" onclick="selectdev()" value="选择连接的读卡器" /></th>
<td width="716">
</td>
</tr>
设备编号:
原始16进制卡号: ,转8H10D正码: ,8H10D反码:
<tr>
<th width="124" height="45" scope="row"><input style="width:120px" name="butt_sfzrequest" type="submit" id="butt_sfzrequest" onclick="sfzrequest()" value="读取二代证UID" /></th>
<td >原始16进制卡号:<input style="color:red;text-align:center;" name="sfzuid" type="text" id="sfzuid" size="16" maxlength="16" />
</td>
</tr>
<tr>
<th width="124" height="45" scope="row"><input style="width:120px" name="butt_iclassrequest" type="submit" id="butt_iclassrequest" onclick="iclassrequest()" value="读取iCLASS卡UID" /></th>
<td>
原始16进制卡号:<input style="color:red;text-align:center;" name="iclassuid" type="text" id="iclassuid" size="16" maxlength="16" />
</td>
</tr>
<tr>
<th width="124" height="45" scope="row"><input style="width:120px" name="butt_ntagrequest" type="submit" id="butt_ntagrequest" onclick="ntagrequest()" value="读取Ntag卡UID" /></th>
<td>
原始16进制卡号:<input style="color:red;text-align:center;" name="ntaguid" type="text" id="ntaguid" size="16" maxlength="16" />
</td>
</tr>
<tr>
<th width="124" height="45" scope="row"><input style="width:120px" name="butt_15693request" type="submit" id="butt_15693request" onclick="iso15693request()" value="读取15693卡UID" /></th>
<td>
原始16进制卡号:<input style="color:red;text-align:center;" name="uid15693" type="text" id="uid15693" size="16" maxlength="16" />
</td>
</tr>
操作提示
以上功能使用Web HID API技术,请使用支持Web HID API的浏览器!
`
浙公网安备 33010602011771号