Web浏览器485通讯读取RFID卡号js JavaScript

本示例使用设备:485通讯液显带键盘RFID打菲计件读卡器工位机串口可二次开发编程-淘宝网 (taobao.com) 

<!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" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Web Serial Api串口读卡器485工控机示例 </title><script>		window.onload = function() {document.getElementById('butt_openserial').hidden=true;document.getElementById('butt_closeserial').hidden=true;}if ('serial' in navigator){}else{alert('您的浏览器不支持 Web Serial API,暂无法使用以下功能!');}		navigator.serial.onconnect =function event(){console.log("Serial port connected: ", event.target);}navigator.serial.ondisconnect =function event(){console.log("Serial port disconnected: ", event.target);}var port = null;var reader = null;var reading = false;const getdata=new Uint8Array(1000);     //接收串口返回的数据var DataPoint=0;                        //接收数据指针var SendCode=0;                         //已发送的指令代码var connecting = false;                 //正在通讯var time1;var datetimestr=""var weekday=0 ;setInterval(showTime, 1000);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 showTime() {const now = new Date();const hours = now.getHours().toString().padStart(2, '0');const minutes = now.getMinutes().toString().padStart(2, '0');const seconds = now.getSeconds().toString().padStart(2, '0');const timeString = `${hours}:${minutes}:${seconds}`;const day = now.getDate().toString().padStart(2, '0');const month = (now.getMonth() + 1).toString().padStart(2, '0');const year = now.getFullYear();const dateString = `${year}-${month}-${day}`;weekday=now.getDay();datetimestr=dateString+" "+ timeString+" "+weekday.toString();        document.getElementById('label_datetime').innerText =datetimestr;}async function SelectSerial(){try{port =await navigator.serial.requestPort();  // 弹出系统串口列表对话框,选择一个串口进行连接ports =await navigator.serial.getPorts();    // 获取已连接的授权过的设备列表document.getElementById('butt_openserial').hidden=false;				}catch (e){console.log(e);}}function updateInputData(data) {let array = new Uint8Array(data); // event.data.buffer就是接收到的inputreport包数据了let hexstr = "";					for (const data of array) {hexstr += (Array(2).join(0) + data.toString(16).toUpperCase()).slice(-2) + " "; // 将字节数据转换成(XX )形式字符串getdata[DataPoint]=data;DataPoint=DataPoint+1;}ReceiveData.value += hexstr;var label_disp = document.getElementById('label_disp');if(SendCode==1 && DataPoint>4 ){ConnectOver();if(getdata[4]==getdata[2] ^ getdata[3]){deviceno.value=(getdata[2]+getdata[3]*256).toString();		            	            label_disp.innerText = "读取机号成功!";}}else if(SendCode==2 && DataPoint>=2 && getdata[0]==0x69 && getdata[1]==0xf0){		        	        label_disp.innerText = "设置新机号成功!";deviceno.value=newdeviceno.value;ConnectOver();	}else if(SendCode==3 && DataPoint>0){		        		        label_disp.innerText = "发卡器已响声!";ConnectOver();}else if(SendCode==4){if(getdata[0]==0){ConnectOver();		            label_disp.innerText = "未寻到卡!";}else if(getdata[0]==0x69 && DataPoint>7){ConnectOver();var dispinfo="";if(getdata[1]==0xd2 && getdata[2]^getdata[3]^getdata[4]^getdata[5]^getdata[6]==getdata[7]){		                cardnohex="";for(i=2;i<7;i++){cardnohex=cardnohex+(Array(2).join(0) + getdata[i].toString(16).toUpperCase()).slice(-2);}HLCode=cardnohex.substring(2,4)+cardnohex.substring(4,6)+cardnohex.substring(6,8)+cardnohex.substring(8,10);card8h10dz=parseInt("0x"+HLCode).toString().padStart(10, '0');cardwg26z=parseInt("0x"+cardnohex.substring(4,6)).toString().padStart(3, '0')+parseInt("0x"+cardnohex.substring(6,10)).toString().padStart(5, '0');cardwg34z=parseInt("0x"+cardnohex.substring(2,6)).toString().padStart(5, '0')+parseInt("0x"+cardnohex.substring(6,10)).toString().padStart(5, '0');		dispinfo=dispinfo+"读取16进制卡号:"+cardnohex+",转8H10D码:"+card8h10dz+",转WG34码:"+cardwg34z+",转WG26码:"+cardwg26z;}else{dispinfo=dispinfo+"卡号异或和校验错误,未能读取到正确的卡号!";}label_disp.innerText =dispinfo;}}else if(SendCode==5 ){if(getdata[0]==0x00 ){ConnectOver();	label_disp.innerText = "没有按键!";		            }else if(getdata[0]==0x69 && getdata[DataPoint-1]==0x0d){		            	 keystr="";for(i=2;i<DataPoint;i++){keystr=keystr+String.fromCharCode(getdata[i]);}label_disp.innerText = "读取键值:"+keystr;	ConnectOver();	}}else if(SendCode==6 ){if(getdata[0]==0x00 ){		            label_disp.innerText = "没有刷卡按键!";		            ConnectOver();	}else if(getdata[0]==0x69 && getdata[1]==0x69 && getdata[DataPoint-1]==getdata[DataPoint-2]^getdata[DataPoint-3]){		if(getdata[2]==0x01 && getdata[3]^getdata[4]^getdata[5]^getdata[6]^getdata[7]==getdata[8]){    //只有刷卡数据cardnohex="";for(i=3;i<8;i++){cardnohex=cardnohex+(Array(2).join(0) + getdata[i].toString(16).toUpperCase()).slice(-2);}HLCode=cardnohex.substring(2,4)+cardnohex.substring(4,6)+cardnohex.substring(6,8)+cardnohex.substring(8,10);card8h10dz=parseInt("0x"+HLCode).toString().padStart(10, '0');cardwg26z=parseInt("0x"+cardnohex.substring(4,6)).toString().padStart(3, '0')+parseInt("0x"+cardnohex.substring(6,10)).toString().padStart(5, '0');cardwg34z=parseInt("0x"+cardnohex.substring(2,6)).toString().padStart(5, '0')+parseInt("0x"+cardnohex.substring(6,10)).toString().padStart(5, '0');		label_disp.innerText="读取16进制卡号:"+cardnohex+",转8H10D码:"+card8h10dz+",转WG34码:"+cardwg34z+",转WG26码:"+cardwg26z;ConnectOver();	}else if(getdata[2]==0x02 && getdata[DataPoint-4]==0x0d){  //只有按键数据keystr="";for(i=4;i<DataPoint-4;i++){keystr=keystr+String.fromCharCode(getdata[i]);}label_disp.innerText = "读取键值:"+keystr;	ConnectOver();	}else if(getdata[2]==0x03  && getdata[DataPoint-4]==0x0d){ //卡号+按键值cardnohex="";for(i=3;i<8;i++){cardnohex=cardnohex+(Array(2).join(0) + getdata[i].toString(16).toUpperCase()).slice(-2);}HLCode=cardnohex.substring(2,4)+cardnohex.substring(4,6)+cardnohex.substring(6,8)+cardnohex.substring(8,10);card8h10dz=parseInt("0x"+HLCode).toString().padStart(10, '0');cardwg26z=parseInt("0x"+cardnohex.substring(4,6)).toString().padStart(3, '0')+parseInt("0x"+cardnohex.substring(6,10)).toString().padStart(5, '0');		                keystr="";for(i=10;i<DataPoint-4;i++){keystr=keystr+String.fromCharCode(getdata[i]);}label_disp.innerText="读取16进制卡号:"+cardnohex+",转8H10D码:"+card8h10dz+",转WG26码:"+cardwg26z+",按键值:"+keystr;ConnectOver();	}		           		           		  }}else if(SendCode==8 && DataPoint>=2 && getdata[0]==0x69 && getdata[1]==0x0f){label_disp.innerText = "设置新管理密码成功!";		        ConnectOver();		}else if(SendCode==11 && DataPoint>=2){label_disp.innerText = "读取设备状态成功!";		        ConnectOver();		}}		    		async function listenReceived(){if (reading){console.log("On reading.");return;}reading=true;while (port.readable && reading) {reader = port.readable.getReader();try {while (true) {const { value, done } = await reader.read();if (done) {// |reader| has been canceled.break;}// 需要特别注意的是:实际使用中即使对端是按一个个包发送的串口数据,接收时收到的也可能是分多段收到的updateInputData(value);}} catch (e) {alert(e);} finally {reader.releaseLock();}}await port.close(); // 关闭串口port = null;alert("串口已关闭!");var label_disp = document.getElementById('label_disp');label_disp.innerText = "请先选择并打开与读卡器相连的串口!";            }async function OpenSerial(){if (port==null){alert('请先选择要操作的串口号!');return;}else{document.getElementById('butt_closeserial').hidden=false;	var baudSelected = parseInt(document.getElementById("select_btn").value);await port.open({baudRate: baudSelected,					});	listenReceived();	alert('串口打开成功!');		var label_disp = document.getElementById('label_disp');label_disp.innerText = "串口已打开,可向串口发送指令!";   }			}async function CloseSerial(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}if (reading) {reading = false;reader?.cancel();}		document.getElementById('butt_openserial').hidden=true;document.getElementById('butt_closeserial').hidden=true;		}function ListSendData(senddata,datalen){  //显示串口发送的数据var sendhex="";for(i=0;i<datalen;i++){sendhex=sendhex+senddata[i].toString(16).padStart(2, '0').toUpperCase()+" ";}			SendData.value=sendhex;ReceiveData.value="";var label_disp = document.getElementById('label_disp');label_disp.innerText = "指令已发送...";}function ConnTimeout(){    //通讯超时处理if(connecting){ConnectOver()var label_disp = document.getElementById('label_disp');label_disp.innerText = "通讯超时!";}}function ConnectOver(){  //通讯已完成clearInterval(time1);connecting=false;SendCode=0;DataPoint=0;}async function getdevicenumber(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}var beepdelay=parseInt(document.getElementById("beepdelay").value);const outputData = new Uint8Array(5);outputData[0]=0xaa;     outputData[1]=0xaa;   outputData[2]=0x00;outputData[3]=0x00;outputData[4]=0xa5;ListSendData(outputData,5);SendCode=1;DataPoint=0;const writer = port.writable.getWriter();await writer.write(outputData);             // 发送数据writer.releaseLock();time1 = setInterval("ConnTimeout()", 100);  //开启100毫秒的通讯超时connecting=true;}async function editdevicenumber(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}var olddevicenum=parseInt(document.getElementById("deviceno").value);var newdevicenum=parseInt(document.getElementById("newdeviceno").value);const outputData = new Uint8Array(10);outputData[0]=0xaa;     outputData[1]=0xaa;   outputData[2]=olddevicenum % 256;outputData[3]=olddevicenum / 256;outputData[4]=0xf0;outputData[5]=newdevicenum % 256;outputData[6]=newdevicenum / 256;outputData[7]=outputData[5] ^ 0xff;outputData[8]=outputData[6] ^ 0xff;outputData[9]=0x00;ListSendData(outputData,10);SendCode=2;DataPoint=0;const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();time1 = setInterval("ConnTimeout()",100);  //开启100毫秒的通讯超时connecting=true;}async function beep(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}var devicenum=parseInt(document.getElementById("deviceno").value);var beepdelay=parseInt(document.getElementById("beepdelay").value);const outputData = new Uint8Array(8);outputData[0]=0xaa;     outputData[1]=0xaa;   outputData[2]=devicenum % 256;outputData[3]=devicenum / 256;outputData[4]=0xc3;outputData[5]=beepdelay / 256;outputData[6]=beepdelay % 256;outputData[7]=outputData[5] ^ outputData[6];ListSendData(outputData,8);SendCode=3;DataPoint=0;const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();//time1 = setInterval("ConnTimeout()", 100);  //开启100毫秒的通讯超时//connecting=true;}async function Request(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}			var devicenum=parseInt(document.getElementById("deviceno").value);const outputData = new Uint8Array(5);outputData[0]=0xaa;		outputData[1]=0xaa;     outputData[2]=devicenum % 256;outputData[3]=devicenum / 256;outputData[4]=0xd2;     ListSendData(outputData,5);SendCode=4;DataPoint=0;											const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();time1 = setInterval("ConnTimeout()", 100);  //开启100毫秒的通讯超时connecting=true;}async function ReadKey(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}			var devicenum=parseInt(document.getElementById("deviceno").value);const outputData = new Uint8Array(5);outputData[0]=0xaa;		outputData[1]=0xaa;     outputData[2]=devicenum % 256;outputData[3]=devicenum / 256;outputData[4]=0x87;     ListSendData(outputData,5);SendCode=5;DataPoint=0;											const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();time1 = setInterval("ConnTimeout()", 100);  //开启100毫秒的通讯超时connecting=true;}		async function ReadCardKey(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}			var devicenum=parseInt(document.getElementById("deviceno").value);const outputData = new Uint8Array(5);outputData[0]=0xaa;		outputData[1]=0xaa;     outputData[2]=devicenum % 256;outputData[3]=devicenum / 256;outputData[4]=0x69;     ListSendData(outputData,5);SendCode=6;DataPoint=0;											const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();time1 = setInterval("ConnTimeout()", 100);  //开启100毫秒的通讯超时connecting=true;}	async function DispBeep(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}		let devicenum=parseInt(document.getElementById("deviceno").value);let dispstr=document.getElementById("text_dispstr").value+"                                               ";  //加入空格是为了能满屏显示let beeplen=parseInt(document.getElementById("beeplen").value);let stoplen=parseInt(document.getElementById("stoplen").value);let beepcount=parseInt(document.getElementById("beepcount").value);dispasc=GetChineseCode(dispstr);		    var outputData = new Uint8Array(39);outputData[0]=0xaa;		outputData[1]=0xaa;     outputData[2]=devicenum % 256;outputData[3]=devicenum / 256;outputData[4]=0x5a;     for(i=0;i<30;i++){outputData[5+i]=parseInt(dispasc.substr(i*2,2),16);;}outputData[35]=beeplen / 20;     outputData[36]=stoplen / 20;     outputData[37]=beepcount;   let crc=0;for(i=5;i<=37;i++){crc=crc ^ outputData[i];}outputData[38]=crc;   ListSendData(outputData,39);SendCode=7;DataPoint=0;											const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();}async function editdevicepassword(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}		let devicenum=parseInt(document.getElementById("deviceno").value);let newpassword=document.getElementById("newpassword").value;if(newpassword.length!=6){alert("读卡器管理密码必须是6位数字!请输入正确的管理密码。");document.getElementById("newpassword").focus();document.getElementById("newpassword").select();return;}var outputData = new Uint8Array(9);outputData[0]=0xaa;		outputData[1]=0xaa;     outputData[2]=devicenum % 256;outputData[3]=devicenum / 256;outputData[4]=0xf;     for(i=0;i<3;i++){outputData[5+i]=parseInt(newpassword.substr(i*2,2),16);}outputData[8]=outputData[5]^outputData[6]^outputData[7];                ListSendData(outputData,9);SendCode=8;DataPoint=0;											const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();time1 = setInterval("ConnTimeout()", 100);  //开启100毫秒的通讯超时connecting=true;}async function SwitchOn(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}		let devicenum=parseInt(document.getElementById("deviceno").value);let switchdelay=parseInt(document.getElementById("switchdelay").value);var outputData = new Uint8Array(9);outputData[0]=0xaa;		outputData[1]=0xaa;     outputData[2]=devicenum % 256;outputData[3]=devicenum / 256;outputData[4]=0x1e;     outputData[5]=0xf1;     outputData[6]=switchdelay / 256;outputData[7]=switchdelay % 256;outputData[8]=outputData[5]^outputData[6]^outputData[7];                ListSendData(outputData,9);SendCode=9;DataPoint=0;											const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();}async function SwitchOff(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}		let devicenum=parseInt(document.getElementById("deviceno").value);var outputData = new Uint8Array(9);outputData[0]=0xaa;		outputData[1]=0xaa;     outputData[2]=devicenum % 256;outputData[3]=devicenum / 256;outputData[4]=0x1e;     outputData[5]=0xe1;     outputData[6]=0x00;outputData[7]=0x00;outputData[8]=outputData[5]^outputData[6]^outputData[7];                ListSendData(outputData,9);SendCode=10;DataPoint=0;											const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();}async function ReadStatus(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}		let devicenum=parseInt(document.getElementById("deviceno").value);if(devicenum==0){alert("请先输入要读取的机号!");document.getElementById("deviceno").focus();document.getElementById("deviceno").select();return;}var outputData = new Uint8Array(5);outputData[0]=0xaa;		outputData[1]=0xaa;     outputData[2]=devicenum % 256;outputData[3]=devicenum / 256;outputData[4]=0x2d;     ListSendData(outputData,5);SendCode=11;DataPoint=0;											const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();time1 = setInterval("ConnTimeout()", 100);  //开启100毫秒的通讯超时connecting=true;}async function SetDevDateTime(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}		let devicenum=parseInt(document.getElementById("deviceno").value);var outputData = new Uint8Array(13);outputData[0]=0xaa;		outputData[1]=0xaa;     outputData[2]=devicenum % 256;outputData[3]=devicenum / 256;outputData[4]=0x4b;outputData[5]=parseInt(datetimestr.substr(17,2),16);outputData[6]=parseInt(datetimestr.substr(14,2),16);outputData[7]=parseInt(datetimestr.substr(11,2),16);outputData[8]=parseInt(datetimestr.substr(8,2),16);outputData[9]=parseInt(datetimestr.substr(5,2),16);outputData[10]=weekday;outputData[11]=parseInt(datetimestr.substr(2,2),16);let crc=0;for(i=5;i<=11;i++){crc=crc ^ outputData[i];}outputData[12]=crc;   ListSendData(outputData,13);SendCode=12;DataPoint=0;											const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();}</script><style>th {font-family:楷体;background-color:#F6FAFF;		color:blue;}td {font-family:楷体;background-color:#F6FAFF;		}  </style>    </head><body>
<table width="950" height="423"  align="center"><tr><td width="120" height="50">    <input  name="btnSelect"  type="submit" id="btnSelect" style="width:100%" onclick="SelectSerial()" value="选择串口" /></td><td width="800">波特率:<label for="select_btn"></label><select name="select_btn" id="select_btn"><option>1200</option><option>4800</option><option>9600</option><option>14400</option><option selected="selected">19200</option><option>38400</option><option>43000</option><option>57600</option><option>115200</option><option>128000</option><option>230400</option><option>256000</option><option>460800</option><option>921600</option><option>1382400</option></select>&nbsp;数据位:<select name="select_btn2" id="select_data"><option>8</option><option>7</option><option>6</option><option>5</option></select>&nbsp;停止位:<select name="select_btn3" id="select_stop"><option>1</option><option>1.5</option><option>2</option></select>&nbsp;校验位:<select name="select_btn4" id="select_mark"><option>None  无</option><option>Odd   奇</option><option>Even  偶</option><option>Mask  常1</option><option>Space 常0</option></select>&nbsp;<input  name="butt_openserial"  type="submit" id="butt_openserial" style="width:80px" onclick="OpenSerial()" value="打开串口" /><input  name="butt_closeserial"  type="submit" id="butt_closeserial" style="width:80px" onclick="CloseSerial()" value="关闭串口" /></td></tr><tr><td height="36"><input name="butt_getdevnum" type="submit" id="butt_getdevnum" style="width:100%" onclick="getdevicenumber()" value="读取在线设备机号" /></td><td>设备机号:<input style="color:red;text-align:center;" name="deviceno" type="text" id="deviceno" value="0" size="5" maxlength="5" onkeyup="this.value=this.value.replace(/\D/g,'')" /></td></tr><tr><td height="36" ><input name="butt_beep"  type="submit" id="butt_beep" style="width:100%" onclick="beep()" value="驱动发卡器响声" /></td><td>响声延时:<input style="color:blue;text-align:center;" name="beepdelay" type="text" id="beepdelay" value="30" size="5" maxlength="4" onkeyup="this.value=this.value.replace(/\D/g,'')"/>毫秒 &nbsp;&nbsp;<input name="butt_changedevnum" type="submit" id="butt_changedevnum" style="width:120px" onclick="editdevicenumber()" value="修改在线设备机号" />新机号:<input style="color:blue;text-align:center;" name="newdeviceno" type="text" id="newdeviceno" value="2" size="5" maxlength="5" onkeyup="this.value=this.value.replace(/\D/g,'')" />&nbsp;&nbsp;<input name="butt_changepassword" type="submit" id="butt_changepassword" style="width:150px" onclick="editdevicepassword()" value="修改在线设备管理密码" />密码:<input style="color:blue;text-align:center;" name="newpassword" type="text" id="newpassword" value="123456" size="5" maxlength="6" onkeyup="this.value=this.value.replace(/\D/g,'')" /></td></tr><tr><td height="36"><input name="butt_request"  type="submit" id="butt_request" style="width:100%" onclick="Request()" value="驱动读卡器读一次卡" /></td><td><label style="color:red;" name="label_disp" id="label_disp">请先选择并打开与读卡器相连的串口!</label></td></tr><tr><td height="36"></td><td></td></tr>  <tr><td height="36"><input name="butt_readcardkey" type="submit" id="butt_readcardkey" style="width:170px" onclick="ReadCardKey()" value="驱动读卡器读卡号+按键值" /></td><td><input name="butt_readkey" type="submit" id="butt_readkey" style="width:160px" onclick="ReadKey()" value="驱动读卡器读取按键值" />&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <input name="butt_setdatetime" type="submit" id="butt_setdatetime" style="width:120px" onclick="SetDevDateTime()" value="设置读卡器时钟" /><label style="color:red;" name="label_datetime" id="label_datetime">2024-07-11 10:08:00</label></td></tr><tr><td height="36"><input name="butt_disp_beep" type="submit" id="butt_disp_beep" style="width:100%" onclick="DispBeep()" value="驱动读卡器显示+响声" /></td><td>显示文字: <input style="color:blue;text-align:left;" name="text_dispstr" type="text" id="text_dispstr" value="感谢您选用我们 的读卡器!" size="34" maxlength="34" /> 声长: <input style="color:blue;text-align:center;" name="beeplen" type="text" id="beeplen" value="100" size="5" maxlength="4" onkeyup="this.value=this.value.replace(/\D/g,'')" /> 停顿: <input style="color:blue;text-align:center;" name="stoplen" type="text" id="stoplen" value="100" size="5" maxlength="4" onkeyup="this.value=this.value.replace(/\D/g,'')" /> 次数: <input style="color:blue;text-align:center;" name="beepcount" type="text" id="beepcount" value="1" size="5" maxlength="4" onkeyup="this.value=this.value.replace(/\D/g,'')" /> </td></tr><tr><td height="36"><input name="butt_switchon" type="submit" id="butt_switchon" style="width:100%" onclick="SwitchOn()" value="驱动读卡器开启继电器" /></td><td>开启延时:<input style="color:blue;text-align:center;" name="switchdelay" type="text" id="switchdelay" value="30" size="5" maxlength="4" onkeyup="this.value=this.value.replace(/\D/g,'')" />毫秒 &nbsp;&nbsp; <input name="butt_switchoff" type="submit" id="butt_switchoff" style="width:120px" onclick="SwitchOff()" value="关闭已开启继电器" />&nbsp;&nbsp; <input name="butt_readstatus" type="submit" id="butt_readstatus" style="width:120px" onclick="ReadStatus()" value="读取设备当前状态" /></td></tr>    <tr><td height="70" scope="row"><p align="center">发送的数据</p></td><td><textarea style="width:800px;color:blue;" name="SendData" id="SendData" cols="100" rows="4" ></textarea></td></tr><tr><td height="70" scope="row"><p align="center">接收的数据</p></td><td><textarea style="width:800px" name="ReceiveData" id="ReceiveData" cols="100" rows="4" ></textarea></td></tr>
</table></body>
</html>

源码下载:JavaScript前端485通讯读取RFID卡号资源-CSDN文库

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

零基础做项目---五子棋对战---day02

用户模块 完成注册登录&#xff0c;以及用户分数管理~使用数据库来保存上述用户信息. 使用 MyBatis来连接并操作数据库了 主要步骤: 1.修改 Spring的配置文件,使数据库可以被连接上. 2.创建实体类&#xff0c;用户, User 3.创建Mapper接口~ 4.实现MyBatis 的相关xml配置…

初学SpringMVC之接收请求参数及数据回显

pom.xml 文件导入 lombok 的依赖 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version></dependency> Controller 表示这是一个控制器 RequestParam 表示从前端接收…

小巧低调的黑盒子,打造个性化音乐体验,欧尼士ONIX Alpha小尾巴上手

欧尼士ONIX的产品很有辨识度&#xff0c;这家来自英国的品牌&#xff0c;有着鲜明的黑金设计色彩&#xff0c;以及低调奢华的质感&#xff0c;当然最重要的是&#xff0c;欧尼士的音质表现非常出色&#xff0c;因此深受音乐爱好者的喜爱。在以手机等设备为载体的流媒体音乐盛行…

前端-Cookie篇

文章目录 一、由来什么是Cookie&#xff1f;特点Cookie的类型 二、原理三、Cookie生成机制客户端设置案例 四、属性五、缺陷最后分享一段自己工作中封装的一些关于cookie的公众方法✒️总结 前端Cookie是Web开发中非常重要的一部分&#xff0c;它是服务器发送到用户浏览器并保存…

大吉大利杯_RE

A-Maze-In 一道比较新颖的 maze 题吧&#xff0c; 地图长度是 256 32 * 8 &#xff1f; 不知道了 0.0 难崩&#xff0c;看了一下 wp 说map长度什么的都有&#xff0c;应该就是 16 * 16的 看了一圈&#xff0c;感觉还是要把 DFS&#xff0c;BFS 算法学一下&#xff0c;直接跑…

视频太大怎么压缩变小?这几种压缩方法值得收藏!

视频太大怎么压缩变小&#xff1f;在数字化浪潮汹涌的时代&#xff0c;处理大型视频文件已不再仅仅是存储空间的挑战&#xff0c;我们身处于数据洪流之中&#xff0c;数据的安全与隐私的保护已然成为了我们不得不面对的重大议题&#xff0c;特别是随着视频内容的井喷式增长及其…

MySQL 中的 DDL、DML、DQL 和 DCL

文章目录 1. 数据定义语言&#xff08;DDL&#xff09;2. 数据操作语言&#xff08;DML&#xff09;3. 数据查询语言&#xff08;DQL&#xff09;4. 数据控制语言&#xff08;DCL&#xff09;总结 在 MySQL 数据库管理系统中&#xff0c;SQL 语句可以根据其功能分为不同的类别&…

【thingsbord源码编译】 显示node内存不足

编译thingsbord显示报错 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory问题原因分析 重新安装java版本 编译通过

【Vue3】使用vite创建vue项目

一、安装Nodejs 参考文章https://blog.csdn.net/DX390609/article/details/140305585?spm1001.2014.3001.5502 二、创建项目 在要创建的目录下打开命令行输入&#xff1a; npm create vuelatestvue项目创建成功&#xff1a; 三、安装vue插件 vscode打开项目文件夹&…

RAG理论:ES混合搜索BM25+kNN(cosine)以及归一化

接前一篇:RAG实践:ES混合搜索BM25+kNN(cosine) https://blog.csdn.net/Xin_101/article/details/140230948 本文主要讲解混合搜索相关理论以及计算推导过程, 包括BM25、kNN以及ES中使用混合搜索分数计算过程。 详细讲解: (1)ES中如何通过BM25计算关键词搜索分数; (2)…

C++:组合和继承的区别

组合介绍以及与继承对比 什么是组合 (1)composition&#xff0c;组合&#xff0c;就是在一个class内使用其他多个class的对象作为成员 (2)用class tree做案例讲解 (3)组合也是一种代码复用方法&#xff0c;本质也是结构体包含 #include <iostream> #include <vector…

曹操的五色棋布阵 - 工厂方法模式

定场诗 “兵无常势&#xff0c;水无常形&#xff0c;能因敌变化而取胜者&#xff0c;谓之神。” 在三国的战场上&#xff0c;兵法如棋&#xff0c;布阵如画。曹操的五色棋布阵&#xff0c;不正是今日软件设计中工厂方法模式的绝妙写照吗&#xff1f;让我们从这个神奇的布阵之…

srs直播内网拉流带宽飙升问题记录

问题背景 srs部署在云服务器上&#xff0c;32核cpu&#xff0c;64G内存&#xff0c;带宽300M. 客户端从srs拉流&#xff0c;发现外网客户端拉流&#xff0c;cpu和带宽都正常。然而内网客户端拉流&#xff0c;拉流人数超过5人以上&#xff0c;带宽就会迅速飙升。 排查 用srs…

【爬虫】爬虫基础

目录 一、Http响应与请求1、Http请求2、Http响应3、状态码 二、Requests库1、发起GET请求2、发起POST请求3、处理请求头 三、BeautifulSoup库1、解析HTML文档2、查找和提取数据Ⅰ、查找单个元素Ⅱ、查找所有元素Ⅲ、使用CSS选择器Ⅳ、获取元素属性 四、爬取豆瓣电影榜 一、Http…

Desktop docker 部署 WordPress

Desktop Docker 部署 WordPress 之前都是在Linux里面玩的&#xff0c;今天看到别人在windwos下安装docker&#xff0c;一时兴起装了一个试试&#xff0c;效果一般&#xff0c;很吃硬盘空间和内存。 首先在docker官方下载桌面版&#xff0c;安装下一步一直到完成。 安装完docke…

一招杜绝 | 网站被劫持强制植入广告的问题

在我们日常上网过程中&#xff0c;经常会遇到打开一个网页&#xff0c;网页都还没有显示出来&#xff0c;一堆广告就弹出来的现象。或者网页刚刚打开&#xff0c;没几分钟 就会弹出来某游戏广告&#xff0c;注册领豪华坐骑等等的小广告。这些广告不仅仅会让我们对网站的真实性产…

强烈推荐!!李沐老师《动手学深度学习》最新Pytorch版!

动手学深度学习(PyTorch版)》是由李沐、Aston Zhang和孔德威共同编写的教材&#xff0c;专为深度学习初学者和实践者设计。本书使用PyTorch作为主要的深度学习框架&#xff0c;全面系统地介绍了深度学习的基本理论、常见模型和实际应用技巧。 书中内容包括深度学习的基础知识、…

逻辑回归(纯理论)

1.什么是逻辑回归&#xff1f; 逻辑回归是一种常用的统计学习方法&#xff0c;主要用于解决分类问题。尽管名字中包含"回归"&#xff0c;但它实际上是一种分类算法 2.为什么机器学习需要使用逻辑回归 1.二元分类 这是逻辑回归最基本和常见的用途。它可以预测某个事…

短视频矩阵:批量发布的秘密揭秘

在数字化时代&#xff0c;短视频已经成为一种广受欢迎的媒体形式。无论是用于品牌推广、产品营销还是个人创作&#xff0c;短视频都提供了一种直观、生动的方式来吸引观众的注意力。然而&#xff0c;有效地制作、管理和发布短视频对于许多创作者和企业来说是一个挑战。 为此&am…

unity3d:Shader知识点,矩阵,函数,坐标转换,Tags,半透明,阴影,深度,亮度,优化

基本结构 Shader "MyShaderName" {Properties {// 属性}SubShader {// 针对显卡A的SubShaderPass {// 设置渲染状态和标签Tags { "LightMode""ForwardBase" }// 开始Cg代码片段CGPROGRAM// 该代码片段的编译指令&#xff0c;例如&#xff1a;#p…