Web Hid Api浏览器读取IC卡号Js源码,无需插件支持

news2024/10/19 12:46:12

本示例使用的读卡器:https://item.taobao.com/item.htm?spm=a21dvs.23580594.0.0.52de2c1bW5eU3X&ft=t&id=615391857885

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Web HID Api IC卡读卡器Demo</title>

    <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="寻卡失败,有多张卡在读卡器感应区!";
		                        break;
		                    default:
		                        textarea.value="寻卡失败,错误代码:"+databuff[4].toString();
		                        break;
		                }
		                break;
		            default:

		        }
		    }
		}

		async function selectdev() {
		    try{
		        const devices = await navigator.hid.requestDevice({
		            filters: [{
		                vendorId: 0x0801,    // 根据VID进行过滤
		                productId: 0x2011,   // 根据PID进行过滤
		            },],
		        });

		        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);    
		        };
		    }
			catch (e){
		        console.log(e);
		    }
        }			

        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;
            outputData[4]=0x00;
            outputData[5]=0x00;
            outputData[6]=0x00;
            outputData[7]=0x00;
		    
            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;
            outputData[4]=0x00;
            outputData[5]=0x00;
            outputData[6]=0x00;
            outputData[7]=0x00;
		    
            await device.sendReport(0, outputData); // 发送数据,第一个参数为reportId,填0表示不使用reportId
        }
		
        function request_loop() {
            if (!device?.opened) {
                alert("请先选择已连接的读卡器!");
                return;
            }
            if (document.getElementById('butt_readloop').value == '轮询读取IC卡卡号') {
                document.getElementById('butt_readloop').value = '停止轮询';
                ButtonDisable();
                time1 = setInterval("piccrequest()", 500);             //开启间隔500毫秒寻一次卡
            } else {
                document.getElementById('butt_readloop').value = '轮询读取IC卡卡号';
                clearInterval(time1);
                ButtonEnabled();
            }
		}
						
		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="60" scope="row"><input style="width:120px" name="butt_selectdev" type="submit" id="butt_selectdev" onclick="selectdev()" value="选择连接的读卡器" /></th>
        <td width="716">
            
        </td>
    </tr>

  <tr>
    <th width="124" height="60" scope="row"><input style="width:120px" name="butt_beep" type="submit" id="butt_beep" onclick="beep()" value="驱动读卡器响声" /></th>
    <td width="716"><input name="butt_getdevnum" type="submit" id="butt_getdevnum" onclick="getdevicenumber()" value="获取读卡器唯一出厂序列号" />
      设备编号:
        <input style="color:red;text-align:center;" name="serialnumber" type="text" id="serialnumber" size="8" maxlength="8" /></td>
  </tr>
  
  <tr>
    <th height="80" scope="row">
        <input style="width:120px" name="butt_piccrequest" type="submit" id="butt_piccrequest" onclick="piccrequest()" value="读取IC卡卡号" />
      <br /><br />    
        <input name="butt_readloop" type="submit" id="butt_readloop" style="width:120px" onclick="request_loop()" value="轮询读取IC卡卡号" />
    </th>
    <td>原始16进制卡号:
      <input style="color:red;text-align:center;" name="carduid" type="text" id="carduid" size="8" maxlength="8" />
      ,转8H10D正码:
      <input style="color:red;text-align:center;" name="card8h10dz" type="text" id="card8h10dz" size="10" maxlength="10" />
      ,8H10D反码:
      <input style="color:red;text-align:center;" name="card8h10df" type="text" id="card8h10df" size="10" maxlength="10" /></td>
  </tr>

  <tr>
    <th height="120" scope="row"><p>&nbsp;</p>
      <p>操作提示</p>
    <p>&nbsp;</p></th>
    <td><textarea style="color:blue;" name="textarea" id="textarea" cols="100" rows="8" ></textarea></td>
  </tr>


</table>
</body>
</html>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2218478.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【R语言】gadm全球行政区划数据库

我R语言不熟、也不是学GIS的。仅用于记录。 文章目录 一、gadm 数据库简介二、R 语言示例三、sf 包的函数 一、gadm 数据库简介 GADM&#xff08;全称Database of Global Administrative Areas&#xff09;是一个高精度的全球行政区划数据库&#xff0c;它包含了全球所有国家和…

数字图像处理:图像去噪

图像去噪–总变差去噪&#xff08;TV&#xff09; 引用资料&#xff1a; 1.全变分图像去噪算法&#xff08;TV&#xff09; 2.TV去噪的理解 总变差去噪 (Total Variation Denoising) 是一种经典的图像去噪方法&#xff0c;能够有效减少噪声&#xff0c;同时保留图像的边缘细节…

单例模式(自动加载)

目录 介绍 使用 在脚本中写一个函数 让一个「自定义场景」作为单例「自动加载」 介绍 单例模式是编程中的一种设计思想&#xff0c;是为了解决某些编程语言中没有全局变量概念而产生的这对于实现某种模块非常好用 比如玩家信息&#xff0c;有时候&#xff0c;游戏中的很多…

以太网交换安全:MAC地址漂移与检测(实验:二层环路+网络攻击)

一、什么是MAC地址漂移&#xff1f; MAC地址漂移是指网络中设备的MAC地址在运行过程中发生变化的现象。 MAC地址是用于唯一标识网络中的设备。 MAC地址漂移是指交换机上一个VLAN内有两个端口学习到同一个MAC地址&#xff0c;后学习到的MAC地址表项覆盖原MAC地址表项的现象。…

Jsoup在Java中:解析京东网站数据

对于电商网站如京东来说&#xff0c;其页面上的数据包含了丰富的商业洞察。对于开发者而言&#xff0c;能够从这些网站中提取有价值的信息&#xff0c;进行分析和应用&#xff0c;无疑是一项重要的技能。本文将介绍如何使用Java中的Jsoup库来解析京东网站的数据。 Jsoup简介 …

Windows】【DevOps】Windows Server 2022 采用WinSW 启动一个会创建新的控制台程序窗口的程序行为分析

WinSW使用参考 【Windows】【DevOps】Windows Server 2022 采用WinSW将一个控制台应用程序作为服务启动&#xff08;方便&#xff09;-CSDN博客 源码 调整ConsoleApp1程序源代码如下&#xff1a; using System; using System.Diagnostics; using System.IO; using System.R…

十、客户端与服务端进行通信

一、服务端 1、建立协议脚本 此处必须序列化才能转为二进制发送出去 IP为本地连接&#xff1b;端口随意&#xff1b;不要选择规定的端口 2、建立服务端连接脚本 这个的方法都是重写的dll文件中的代码 在Start代码中进行调用 二、客户端 1、与客户端连接代码 2、开始代码 三…

腰背肌筋膜炎有哪些治疗方法

腰背肌筋膜炎主要表现为腰背部的疼痛、酸胀、僵硬、活动受限等症状。在疾病初期&#xff0c;症状可能相对较轻&#xff0c;通过休息、保暖、适当的物理治疗等&#xff0c;往往可以缓解症状&#xff0c;此时病情不算严重。如果患者不重视&#xff0c;继续保持不良的生活习惯&…

Nexpose 6.6.273 发布,新增功能概览

Nexpose 6.6.273 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, released Oct 10, 2024 请访问原文链接&#xff1a;https://sysin.org/blog/nexpose-6/ 查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 您的本地…

微调小型Llama 3.2(十亿参数)模型取代GPT-4o

微调Llama VS GPT-4o 别忘了关注作者&#xff0c;关注后您会变得更聪明&#xff0c;不关注就只能靠颜值了 ^_^。 一位年轻的儿科医生与一位经验丰富的医师&#xff0c;谁更能有效治疗婴儿的咳嗽&#xff1f; 两者都具备治疗咳嗽的能力&#xff0c;但儿科医生由于专攻儿童医学…

数据中台业务架构图

数据中台的业务架构是企业实现数据驱动决策和业务创新的关键支撑。它主要由数据源层、数据存储与处理层、数据服务层以及数据应用层组成。 数据源层涵盖了企业内部各个业务系统的数据&#xff0c;如 ERP、CRM 等&#xff0c;以及外部数据来源&#xff0c;如社交媒体、行业数据…

2024年9月中国电子学会青少年软件编程(Python)等级考试试卷(一级)答案 + 解析

一、单选题 1、下列选项中关于 turtle.color(red) 语句的作用描述正确的是&#xff1f;&#xff08; &#xff09; A. 只设置画笔的颜色为红色 B. 只设置填充的颜色为红色 C. 设置画笔和填充的颜色为红色 D. 设置画笔的颜色为红色&#xff0c;设置画布背景的颜色为红色 正…

基于langchain.js快速搭建AI-Agent

基于langchain.js快速搭建AI-Agent 什么是AIAgent? 1. 替换默认请求地址为自定义API 构建基础会话大模型 import { ChatOpenAI } from langchain/openai;const chat new ChatOpenAI({model: gpt4o,temperature: 0,apiKey: ****,configuration: {baseURL: https://www.xx.co…

[含文档+PPT+源码等]精品大数据项目-基于python实现的社交媒体用户活跃时间预测系统

大数据项目——基于Python实现的社交媒体用户活跃时间预测系统的背景可以从以下几个方面进行详细阐述&#xff1a; 一、项目背景与意义 随着互联网技术的快速发展和社交媒体的普及&#xff0c;社交媒体平台已经成为人们日常生活中不可或缺的一部分。每天都有数以亿计的用户在…

Golang笔记_day08

Go面试题&#xff08;一&#xff09; 1、空切片 和 nil 切片 区别 空切片&#xff1a; 空切片是指长度和容量都为0的切片。它不包含任何元素&#xff0c;但仍然具有切片的容量属性。在Go语言中&#xff0c;可以使用内置的make函数创建一个空切片&#xff0c;例如&#xff1a;…

[Godot4] 水底气泡的 gdshader

水底气泡的 gdshader 来自 shadertoy 的代码 在这里&#xff0c;我添加了 x 方向和 y 方向上的 uv 位移 但是还是感觉太弱智 shader_type canvas_item; // Created by greenbird10 // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0uniform float bub…

C语言笔记(指针的进阶)

目录 1.字符指针 2.指针数组 3.数组指针 3.1.创建数组指针 3.2.&数组名和数组名 1.字符指针 int main() { char ch w;char* pc &ch;const char *p "abcdef";//常量字符串 产生的值就是首元素的地址//常量字符串不能被修改 因此需要加上一个…

go 环境安装

最近搭建AIGC大模型聚合平台&#xff0c;涉及到了go语言&#xff0c;随手整理一下环境安装步骤分享给大家。 1、安装 官网下载地址&#xff1a;https://go.dev/ 1.1 Linux 安装 yum install git -y yum install golang -y yum install gcc -y # 日志工具&#xff0c;如需要…

Web保存状态的手段(请求转发,Cookie的使用)

一&#xff0c;掌握请求转发 请求转发与重定向技术都是跳转页面的途径&#xff0c;但是这两个技术之间也有不同之处。 请求转发更倾向于servlet跳转jsp&#xff0c;而重定向更倾向于servlet跳转到servlet。 1. 常用页面跳转方法2:请求转发(重写URL) RequestDispatcher接口对…

基于SpringBoot+Vue+uniapp微信小程序的教学质量评价系统的详细设计和实现

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…