Web Serial串口通信实现WEB浏览器读写M1卡

 本示例使用的设备:RS232串口RFID NFC IC卡读写器可二次开发编程发卡器USB转COM-淘宝网 (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串口读写器示例 </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 BLOCK0_EN = 0x01;//读第一块的(16个字节)var BLOCK1_EN = 0x02;//读第二块的(16个字节)var BLOCK2_EN = 0x04;//读第三块的(16个字节)var NEEDSERIAL = 0x08;//仅读指定序列号的卡var EXTERNKEY = 0x10;//用明码认证密码,产品开发完成后,建议把密码放到设备的只写区,然后用该区的密码后台认证,这样谁都不知道密码是多少,需要这方面支持请联系var NEEDHALT = 0x20; //读/写完卡后立即休眠该卡,相当于这张卡不在感应区。要相重新操作该卡必要拿开卡再放上去var port = null;var reader = null;var reading = false;const getdata=new Uint8Array(1000);     //接收串口返回的数据var DataPoint=0;                        //接收数据指针var SendCode=0;                         //已发送的指令代码function isUIntNum(val) {var testval = /^\d+$/; // 非负整数return (testval.test(val));}function isHex(val) {var testval = /^(\d|[A-F]|[a-f])+$/; // 十六进制数判断return (testval.test(val));}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;}var crc=0;for(i=1;i<DataPoint;i++){   //校验接收数据,同时也解决数据分包上传的问题crc=crc^getdata[i];}if (crc==0 && DataPoint>1){                let hexstr = "";for (i=0;i<DataPoint;i++){hexstr=hexstr+getdata[i].toString(16).padStart(2, '0').toUpperCase()+" ";}ReceiveData.value += hexstr;		        var dispstr="";var cardnohex="";var datahex="";switch (SendCode) {case 1:break;case 2:  //读取M1卡序列号的回应case 3:  //读取M1卡扇区数据的回应case 4:  //写M1卡扇区数据的回应case 5:  //修改M1卡扇区数密钥的回应switch (getdata[0]){case 1:  //返回有效数据长度为1switch (getdata[1]){case 8:dispstr = "未寻到卡!" ; break;case 9:dispstr = "两张以上卡片同时在感应区,发生冲突!" ; 										break;case 10:dispstr = "无法选择激活卡片!" ; break;case 11:dispstr = "密码装载失败,卡片序列号已知!" ; break;default:dispstr = "操作卡失败,返回代码:" + getdata[1].ToString() ; 		break;}var label_disp = document.getElementById('label_disp');label_disp.innerText = dispstr;break;		 case 5:  //返回有效数据长度为5								for(i=2;i<6;i++){cardnohex=cardnohex+getdata[i].toString(16).padStart(2, '0').toUpperCase();}if(SendCode==2){dispstr ="读卡序列号";}else if(SendCode==3){dispstr ="读扇区数据";}else if(SendCode==4){dispstr ="写扇区数据";}else if(SendCode==5){dispstr ="修改扇区密码";}	switch (getdata[1]){case 0:										dispstr=dispstr+"成功!卡号:"+cardnohexbreak;case 1:dispstr = dispstr+",密码认证成功,但读写扇区内容失败!卡号:" + cardnohex;break;	case 2:dispstr = dispstr+",第0块操作成功,但第1、2块操作失败,仅扇区内容前16个字节的数据有效!!卡号:" + cardnohex;break;	case 3:dispstr = dispstr+",第0、1块操作成功,但第2块操作失败,仅扇区内容前32个字节的数据有效!!卡号:" + cardnohex;break;	    case 12:dispstr = dispstr+",密码认证失败,卡号:" + cardnohex;break;default:dispstr = dispstr+",操作卡失败,返回代码:" + getdata[1].ToString() ; 		break;		}var label_disp = document.getElementById('label_disp');label_disp.innerText = dispstr;break;case 53:  //返回有效数据长度为53for(i=2;i<6;i++){cardnohex=cardnohex+getdata[i].toString(16).padStart(2, '0').toUpperCase();}dispstr = "读M1卡扇区数据成功,卡号:" + cardnohex;for(i=6;i<DataPoint-1;i++){datahex=datahex+getdata[i].toString(16).padStart(2, '0').toUpperCase()+" ";}var label_disp = document.getElementById('label_disp');label_disp.innerText = dispstr;RWM1Data.value=datahex;break;case 54:  //旧版本设备返回有效数据长度为54for(i=2;i<6;i++){cardnohex=cardnohex+getdata[i].toString(16).padStart(2, '0').toUpperCase();}dispstr = "读M1卡扇区数据成功,卡号:" + cardnohex;for(i=7;i<DataPoint-1;i++){datahex=datahex+getdata[i].toString(16).padStart(2, '0').toUpperCase()+" ";}var label_disp = document.getElementById('label_disp');label_disp.innerText = dispstr;RWM1Data.value=datahex;break;	}break;}DataPoint=0;}}		async function listenReceived(){if (reading){console.log("On reading.");return;}reading=true;await port.close(); // 关闭串口port = null;alert("串口已关闭!");}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('串口打开成功!');							}			}async function CloseSerial(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}if (reading) {reading = false;reader?.cancel();}			}async function beep(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}var beepdelay=parseInt(document.getElementById("beepdelay").value);const outputData = new Uint8Array(5);outputData[0]=0x03;     outputData[1]=0x0f;   outputData[2]=beepdelay % 256;outputData[3]=beepdelay / 256;outputData[4]=outputData[1] ^ outputData[2] ^outputData[3];var sendhex="";for(i=0;i<5;i++){sendhex=sendhex+outputData[i].toString(16).padStart(2, '0').toUpperCase()+" ";}			SendData.value=sendhex;ReceiveData.value="";SendCode=1;DataPoint=0;const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();}async function Request(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}			const outputData = new Uint8Array(3);outputData[0]=0x01;		//指令长度outputData[1]=0xf0;     //功能码outputData[2]=0xf0;		//校验码	var sendhex="";for(i=0;i<3;i++){sendhex=sendhex+outputData[i].toString(16).padStart(2, '0').toUpperCase()+" ";}			SendData.value=sendhex;ReceiveData.value="";SendCode=2;DataPoint=0;var label_disp = document.getElementById('label_disp');label_disp.innerText = "";const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();}async function ReadM1Card(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}			if (selinoutkey.selectedIndex==1){myctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY;    //外部密钥认证}else {myctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN;}			   //已装载到发卡器内部密钥认证myareano = selareano.selectedIndex;                       		   //指定为本次读取第8区,十进制authmode = selauthmode.selectedIndex;                              //指定密码模式,十进制,大于0表示用A密码认证,推荐用A密码认证mypiccserial = "00000000";         						           //指定本次操作的卡序列号,十六进制,未知时可指定为8个0mypicckey = authkey0.value.trim();                                 //指定卡片密码,十六进制,FFFFFFFFFFFF为卡片厂家出厂密码if (!isHex(mypicckey) || mypicckey.length!=12) {textarea.value = "认证密钥输入错误,请输入正确的12位16进制认证密钥!";authkey0.focus();authkey0.select();return;}            const outputData = new Uint8Array(16);outputData[0]=0x0e;			//指令长度outputData[1]=0x78;			//功能码outputData[2]=myctrlword;	//控制位		outputData[3]=0x00;			//四字节本次操作卡卡号,全部取0表示可操作任意卡outputData[4]=0x00;outputData[5]=0x00;outputData[6]=0x00;outputData[7]=myareano;		//扇区号outputData[8]=authmode;		//密钥认证方式	for(i=0;i<6;i++){           //6字节密钥outputData[9+i]=parseInt(mypicckey.substr(i*2,2),16);}var crc=0;for (i=1;i<15;i++){crc=crc^outputData[i];}outputData[15]=crc;	var sendhex="";for(i=0;i<16;i++){sendhex=sendhex+outputData[i].toString(16).padStart(2, '0').toUpperCase()+" ";}			SendData.value=sendhex;ReceiveData.value="";RWM1Data.value="";SendCode=3;DataPoint=0;var label_disp = document.getElementById('label_disp');label_disp.innerText = "";const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();			}async function WriteM1Card(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}			if (selinoutkey.selectedIndex==1){myctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY;    //外部密钥认证}else {myctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN;}			   //已装载到发卡器内部密钥认证myareano = selareano.selectedIndex;                       		   //指定为本次读取第8区,十进制authmode = selauthmode.selectedIndex;                              //指定密码模式,十进制,大于0表示用A密码认证,推荐用A密码认证mypiccserial = "00000000";         						           //指定本次操作的卡序列号,十六进制,未知时可指定为8个0mypicckey = authkey0.value.trim();                                 //指定卡片密码,十六进制,FFFFFFFFFFFF为卡片厂家出厂密码if (!isHex(mypicckey) || mypicckey.length!=12) {textarea.value = "认证密钥输入错误,请输入正确的12位16进制认证密钥!";authkey0.focus();authkey0.select();return;}     mypiccdata=RWM1Data.value.trim();mypiccdata=mypiccdata.replace(/\s/g, "");if (isHex(mypiccdata)){if(mypiccdata.length<96){if (confirm("写卡数据不足一扇区48个字节,是否要后面补0写入?")) {      while (mypiccdata.length<96){mypiccdata=mypiccdata+"0";}}else{return;}	}}else{alert("请输入96位16进制写卡数据!");return;}const outputData = new Uint8Array(64);outputData[0]=0x3e;			//指令长度outputData[1]=0x69;			//功能码outputData[2]=myctrlword;	//控制位		outputData[3]=0x00;			//四字节本次操作卡卡号,全部取0表示可操作任意卡outputData[4]=0x00;outputData[5]=0x00;outputData[6]=0x00;outputData[7]=myareano;		//扇区号outputData[8]=authmode;		//密钥认证方式	for(i=0;i<6;i++){           //6字节密钥outputData[9+i]=parseInt(mypicckey.substr(i*2,2),16);}for(i=0;i<48;i++){           //48字节写卡数据outputData[15+i]=parseInt(mypiccdata.substr(i*2,2),16);}var crc=0;for (i=1;i<63;i++){crc=crc^outputData[i];}outputData[63]=crc;	var sendhex="";for(i=0;i<64;i++){sendhex=sendhex+outputData[i].toString(16).padStart(2, '0').toUpperCase()+" ";}			SendData.value=sendhex;ReceiveData.value="";SendCode=4;DataPoint=0;var label_disp = document.getElementById('label_disp');label_disp.innerText = "";const writer = port.writable.getWriter();await writer.write(outputData);           // 发送数据writer.releaseLock();			}async function changecardkeyex(){if ((port == null) || (!port.writable)) {alert("请选择并打开与发卡器相连的串口!");return;}			if (selinoutkey.selectedIndex==1){myctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY;    //外部密钥认证}else {myctrlword = BLOCK0_EN + BLOCK1_EN + BLOCK2_EN;}			   //已装载到发卡器内部密钥认证myareano = selareano.selectedIndex;                       		   //指定为本次读取第8区,十进制authmode = selauthmode.selectedIndex;                              //指定密码模式,十进制,大于0表示用A密码认证,推荐用A密码认证mypiccserial = "00000000";         						           //指定本次操作的卡序列号,十六进制,未知时可指定为8个0mypicckey = authkey0.value.trim();                                 //指定卡片密码,十六进制,FFFFFFFFFFFF为卡片厂家出厂密码if (!isHex(mypicckey) || mypicckey.length!=12) {textarea.value = "认证密钥输入错误,请输入正确的12位16进制认证密钥!";authkey0.focus();authkey0.select();return;}     mypicckeyA = newkeya.value.trim();                             //新A密钥if (!isHex(mypicckeyA) || mypicckeyA.length!=12) {textarea.value = "新A密钥输入错误,请输入正确的12位16进制新A密钥!";newkeya.focus();newkeya.select();return;}			mypiccctr = cardctr.value.trim();                             //新控制位,出厂为FF078069,if (!isHex(mypiccctr) || mypiccctr.length!=8) {textarea.value = "新控制位输入错误,请输入正确的8位16进制控制位!";cardctr.focus();cardctr.select();return;}mypicckeyB = newkeyb.value.trim();                             //新B密钥if (!isHex(mypicckeyB) || mypicckeyB.length!=12) {textarea.value = "新B密钥输入错误,请输入正确的12位16进制新B密钥!";newkeyb.focus();newkeyb.select();return;}mypicckey_new=mypicckeyA+mypiccctr+mypicckeyB;switch (selchangekey.selectedIndex){case 0:mypicckey_new=mypicckey_new+"00";break;case 1:mypicckey_new=mypicckey_new+"02";break;					default:mypicckey_new=mypicckey_new+"03";break;					}						const outputData = new Uint8Array(33);outputData[0]=0x1f;			//指令长度outputData[1]=0xf1;			//功能码outputData[2]=myctrlword;	//控制位		outputData[3]=0x00;			//四字节本次操作卡卡号,全部取0表示可操作任意卡outputData[4]=0x00;outputData[5]=0x00;outputData[6]=0x00;outputData[7]=myareano;		//扇区号outputData[8]=authmode;		//密钥认证方式	for(i=0;i<6;i++){           //6字节密钥outputData[9+i]=parseInt(mypicckey.substr(i*2,2),16);}for(i=0;i<17;i++){           //6字节新A钥+4字节控制位+6字节新B钥+1字节密钥修改类型outputData[15+i]=parseInt(mypicckey_new.substr(i*2,2),16);}var crc=0;for (i=1;i<32;i++){crc=crc^outputData[i];}outputData[32]=crc;	var sendhex="";for(i=0;i<33;i++){sendhex=sendhex+outputData[i].toString(16).padStart(2, '0').toUpperCase()+" ";}			SendData.value=sendhex;ReceiveData.value="";SendCode=5;DataPoint=0;var label_disp = document.getElementById('label_disp');label_disp.innerText = "";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_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,'')"/>毫秒</td></tr><tr><td height="36"><input name="butt_request"  type="submit" id="butt_request" style="width:100%" onclick="Request()" value="仅读取M1卡序列号" /></td><td><label style="color:blue;" name="label_disp" id="label_disp"></label></td></tr><tr><td height="36"><input name="butt_readm1"  type="submit" id="butt_readm1" style="width:100%" onclick="ReadM1Card()" value="读取M1卡扇区数据" /></td><td><p>扇区号:<select style="color:blue;" name="selareano" id="selareano"><option selected="selected">第0扇区</option><option>第1扇区</option><option>第2扇区</option><option>第3扇区</option><option>第4扇区</option><option>第5扇区</option><option>第6扇区</option><option>第7扇区</option><option>第8扇区</option><option>第9扇区</option><option>第10扇区</option><option>第11扇区</option><option>第12扇区</option><option>第13扇区</option><option>第14扇区</option><option>第15扇区</option>        </select><label for="changeauthkey"></label><select style="color:blue;" name="selinoutkey" id="selinoutkey"><option>内部密钥认证</option><option selected="selected">外部密钥认证</option></select><label for="newkey"></label><select style="color:blue;" name="selauthmode" id="selauthmode"><option>B密钥认证</option><option selected="selected">A密钥认证</option>        </select>,认证密钥:<label for="authkey0"></label><input style="color:blue;text-align:center;" name="authkey0" type="text" id="authkey0" value="FFFFFFFFFFFF" size="12" maxlength="12" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F]/g,'')"/></p>    </td></tr><tr><td height="69"><input name="butt_writem1"  type="submit" id="butt_writem1" style="width:100%" onclick="WriteM1Card()" value="写数据到M1卡扇区" /></td><td><textarea style="width:800px;color:red;" name="RWM1Data" id="RWM1Data" cols="100" rows="4" ></textarea></td></tr>  <tr><td height="36"><input style="width:100%" name="butt_changecardkeyex" type="submit" id="butt_changecardkeyex" onclick="changecardkeyex()" value="修改M1卡扇区密钥" /></td><td><select style="color:blue;" name="selchangekey" id="selchangekey"><option>只修改A密钥</option><option>只修改AB密钥</option><option selected="selected">修改AB密钥及控制位</option></select>,新A密钥<input style="color:red;text-align:center;" name="newkeya" type="text" id="newkeya" value="FFFFFFFFFFFF" size="12" maxlength="12" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F]/g,'')"/>,控制位<input style="color:red;text-align:center;" name="cardctr" type="text" id="cardctr" value="FF078069" size="8" maxlength="8" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F]/g,'')"/>,B密钥<input style="color:red;text-align:center;" name="newkeyb" type="text" id="newkeyb" value="FFFFFFFFFFFF" size="12" maxlength="12" onkeyup="this.value=this.value.replace(/[^0-9a-fA-F]/g,'')"/></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>

源码下载:WebSerialapi浏览器串口通讯读写NFC标签资源-CSDN文库

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

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

相关文章

前端面试题-token的存放位置

哈喽小伙伴们大家好,本系列是一个专门针对前端开发岗的面试题系列,每周将会不定期分享一些面试题,希望对大家有所帮助. 面试官:token 一般在客户端存在哪儿 求职者:Token一般在客户端存在以下几个地方&#xff1a; (1)Cookie&#xff1a;Token可以存储在客户端的Cookie中。服…

61.应交税费的明细科目-待转销项税额

目录 1.变化 2.定义 3.科目设置的目的 4.会计处理 5.会计分录 1.变化 财会2016年22号文--《增值税会计处理规定》中对于应交税费的会计处理有了重大变化&#xff0c;引入了“待转销项税额”这一二级明细科目来核算一般纳税人销售货物、加工修理修配劳务、服务、无形资产…

优思学院|工厂的部门架构管理与精益生产

工厂内有不同部门&#xff0c;各部门之间必须协调合作才能发挥整体功能。工厂最主要的部分是制造产品的现场&#xff0c;这里安装了生产工具&#xff0c;还有操作员进行加工或生产制造。 制造时使用的材料或零组件&#xff0c;需要对外采购。对于加工组装型的工厂&#xff0c;…

短视频利器 ffmpeg (1)

使用FFmpeg切片视频有多种好处&#xff0c;尤其是在处理流媒体内容和优化视频分发时。以下是一些主要优点&#xff1a; 提高流媒体性能&#xff1a; 1、快速启动&#xff1a; 切片允许客户端更快地开始播放视频&#xff0c;因为它不需要等待整个文件下载完毕。客户端可以请求…

基于Boost和平均电流控制方法的APFC电路设计

通过学习无线充电相关知识&#xff0c;为更快熟悉APFC工作原理&#xff0c;通过实验得以掌握 技术要求&#xff1a; 1&#xff09;输入电压&#xff1a;AC 85V&#xff5e;265V&#xff1b; 2&#xff09;输出电压&#xff1a;400V1%&#xff1b; 3&#xff09;输出额定电流…

AI推介-信息抽取(information extraction,IE)论文速览(arXiv方向):2024.04.15-2024.06.01

文章目录~ 1.GAMedX: Generative AI-based Medical Entity Data Extractor Using Large Language Models2.Retrieval Augmented Structured Generation: Business Document Information Extraction As Tool Use3.BioBERT-based Deep Learning and Merged ChemProt-DrugProt for…

音视频开发30 FFmpeg 视频编码- 流程以及重要API,H264编码原理说明,该章节使用h264编码说明

一.H264编码原理 1 视频为什么需要进行编码压缩 ◼ 一张为 720x480 的图像&#xff0c;用 YUV420P 的格式来表示&#xff0c;其大小为&#xff1a; 720*480*1.5 约等于 0.5MB 。 ◼ 如果是 25 帧&#xff0c; 10 分钟的数据量 0.5M*10*60*25 7500MB -> 7GB 多 ◼ …

自学网络安全的三个必经阶段(含路线图)

一、为什么选择网络安全&#xff1f; 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地&#xff0c;网络安全行业地位、薪资随之水涨船高。 未来3-5年&#xff0c;是安全行业的黄金发展期&#xff0c;提前踏入…

blender 快捷键 常见问题

一、快捷键 平移视图&#xff1a;Shift 鼠标中键旋转视图&#xff1a;鼠标中键缩放视图&#xff1a;鼠标滚动框选放大模型&#xff1a;Shift B线框预览和材质预览切换&#xff1a;Shift Z 二、常见问题 问题&#xff1a;导入模型成功&#xff0c;但是场景中看不到。 解…

电路与数字逻辑期末复习重点整理!!

1.带无关项的卡诺图 2.置数法设计N进制电路 计数器&#xff1a;具有记忆输入脉冲个数功能的电路称为计数器。 按照各个触发器状态更新情况的不同可分为&#xff1a; 同步计数器&#xff1a;各触发器受同一时钟脉冲─输入计数脉冲控制&#xff0c;同步更新状态。异步计数器&a…

阿里云centos 7.9 使用宝塔面板部署.netcore 6.0

前言&#xff1a; 我有一个netcore6.0的系统接口和手机端程序的站点程序之前是部署在一台windows测试服务器的IIS站点中&#xff0c; 服务器最近压力太大扛不住了&#xff0c;买了一台centos7.9的阿里云服务器准备进行迁移。具体操作日记如下。 一、安装宝塔面板 这一步涉及…

堡垒机软件详细定义以及部分厂商汇总

随着大家对网络安全的重视&#xff0c;越来越多的企业开始采购堡垒机。堡垒机可以分为硬件堡垒机、软件堡垒机、软硬一体机。今天我们就来聊聊堡垒机软件详细定义以及部分厂商汇总。 堡垒机软件详细定义 堡垒机软件&#xff0c;又称为运维安全审计系统&#xff0c;其主要功能在…

顺序表--数据结构第一关

顺序表 数据结构概念 定义&#xff1a;数据结构是计算机存储、组织数据的⽅式 根据学过C语言的基础上&#xff0c;数组是最简单的数据结构 顺序表的底层就是数组 为什么呢&#xff1f; 例子如下&#xff1a; int arr[100]{1,2,3,4,5}; //修改某一个数据&#xff1a;arr[…

【Docker】docker 替换宿主与容器的映射端口和文件路径

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 docker 替换宿主与容器的映射端口和文件夹 1. 正文 1.1 关闭docker 服务 systemctl stop docker1.2 找到容器的配置文件 cd /var/lib/docker/contain…

掌握 Kubernetes 伸缩:HPA vs VPA 全面解析

前言 在 Kubernetes 中&#xff0c;水平 Pod 自动伸缩 (Horizontal Pod Autoscaler, HPA) 和垂直 Pod 自动伸缩 (Vertical Pod Autoscaler, VPA) 是两种关键的自动伸缩机制。它们在功能和用途上有显著区别&#xff0c;适用于不同的场景。本文将详细解析 HPA 和 VPA 的工作原理…

IAR嵌入式开发解决方案已全面支持矽力杰SA32系列车规MCU

IAR嵌入式开发解决方案已全面支持矽力杰SA32BXX系列车规ASIL-B MCU以及即将推出的SA32DXX系列ASIL-D MCU&#xff0c;共同推动汽车高品质应用的开发 中国上海&#xff0c;2024年6月26日 — 全球领先的嵌入式系统开发软件解决方案供应商IAR与矽力杰半导体&#xff08;以下简称“…

【AI生成】卫星系统海上通信应用及优缺点分析

卫星系统在海上通信中扮演着至关重要的角色&#xff0c;它为船舶、海上平台、搜救行动以及海洋研究等提供了可靠的通信手段。 应用 海上通信应用 1. 船舶通信&#xff1a;卫星通信系统为远洋航行的船舶提供语音、数据和互联网服务&#xff0c;确保船舶与岸上保持联系&#xf…

游戏爱好者将《超级马里奥64》移植到GBA掌机

GBA虽然在当年拥有多款马里奥系列游戏&#xff0c;不过你一定没有想到&#xff0c;N64的《超级马里奥64》也能被移植到这个游戏掌机。近日&#xff0c;一位名为Joshua Barretto的开发者就完成了这一挑战。 大家都知道&#xff0c;《超级马里奥64》于1996年登陆任天堂64主机&am…

入职必备-mac下载安装maven

1、Maven 下载 1.1、官网下载安装包 官网下载链接 历史版本下载&#xff1a; Index of /dist/maven/maven-3/3.8.8/binaries 注意 .bash_profile 文件中的符号可能会影响配置 1.2、解压文件 2、Maven 环境配置 2.1、Java JDK 依赖 配置 maven 环境变量需要先配置好 JDK …

第一视角:获取VC账号,是成为亚马逊供应商的全面准备与必要条件

在当今全球化、数字化的商业环境中&#xff0c;亚马逊作为全球最大的电子商务平台&#xff0c;为众多企业提供了无限的商业机会。然而&#xff0c;想要成功在亚马逊上立足&#xff0c;成为其优质供应商&#xff0c;并非易事。其中&#xff0c;VC(Vendor Central)账号&#xff0…