网页串口 webSerial

index.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title></title>
		<script type="text/javascript">
			if(isIE() || isFirefox()){
				alert('当前浏览器(IE浏览器、火狐浏览器)不支持网页串口!请使用Edge或谷歌浏览器访问!')
			}
			else{
				window.location.href = "./b.html"
			}
			
			//判断是否为IE浏览器
			function isIE(){
				if(!!window.ActiveXObject || "ActiveXObject" in window){//ie浏览器不支持
					return true;
				}else{
					return false;
				}
			}
			
			// 判断是否为火狐浏览器
			function isFirefox(){
				str = navigator.userAgent;
				if(str.indexOf("Firefox") >= 0){
					return true
				}
				else{
					return false
				}
			}
		</script>
	</head>
	<body>
		
	</body>
</html>

b.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<link rel="stylesheet" href="css/bootstrap.min.css">
		<script src="jQuery/jquery-1.10.2.min.js"></script>
		<script src="js/bootstrap.min.js"></script>
		
		<script type="text/javascript" charset="UTF-8">
			console.log(window.location.href)  //http://172.16.4.131/wwx/webSerial/6.html
			let reader, textEncoder, writer
			let KeepReading=true
			let port
			let isOpen = false//当前串口是否打开;false代表未打开串口
			let res = ''//保存返回结果
			
			//连接串口
			async function myconnect(){
				if ("serial" in navigator) {
					var baudRate=$("#baudRate option:selected").text();
					var dataBits=$("#dataBits option:selected").text();
					var stopBits=$("#stopBits option:selected").text();
					var parity=$("#parity option:selected").text();
					
					// 提示用户选择一个串口。
					 port = await navigator.serial.requestPort();
					 var open_val = {baudRate:Number(baudRate),dataBits:Number(dataBits),stopBits:Number(stopBits),parity:parity,flowControl:'none', bufferSize:16}
					 
					 // 等待串口打开  SerialOptions
					 await port.open(open_val)//使用前端传的串口参数
					 isOpen = true;
					 $('#openBtn').hide()
					 $('#closeBtn').show()
					 $('#sendBtn').show()
					 
					 // 創建一個讀取器並將流鎖定到它。當流被鎖定時,在釋放此讀取器之前無法獲取其他讀取器
					 reader = port.readable.getReader();
					 //调用port.readable.getReader()创建一个读取器并将其锁定为readable。当可读被锁定时,串口不能被关闭。
				}
				else{
					alert("当前浏览器(IE浏览器、火狐浏览器)不支持网页串口!无法使用网页进行串口通讯!请使用Edge或谷歌浏览器访问!")
				}
			}
			
			// 发送指令并读取数据
			async function mysend(){
				var myendStr = $("input[name='end']:checked").val();//是否以\r结束
				res  = ''
				var sendMsg = $("#send").val(); 
				if(sendMsg==''){
					alert('请输入指令!')
				}
				else{//8 位无符号整数值的类型化数组  Uint8Array 对象
					//23 30 31 0D
					// uart.write(b'\x7b\x46\x30\x30\x52\x44\x44\x5b\x0d')   //高温高湿机
					// cmd = b'\x01\x03\x00\x00\x00\x03'  #讀振動傳感器值命令
					// 发送文本指令
					textEncoder = new TextEncoderStream();//轉換流,它抓取所有Uint8Array塊並將它們轉換為字符串。
					writableStreamClosed = textEncoder.readable.pipeTo(port.writable);
					writer = textEncoder.writable.getWriter();
					console.log('sendMsg=='+sendMsg)
					
					if(myendStr=='N'){
						await writer.write(sendMsg)
					}else{
						await writer.write(sendMsg + "\r")
					}
					// await writer.write("#01\r")
					await  writer.close()
					writer.releaseLock();// 允许稍后关闭串口
					$('#receive').val('');//清空上次返回数据
					
					//读取串口数据
					while (port.readable && KeepReading) {
						// 創建一個讀取器並將流鎖定到它。當流被鎖定時,在釋放此讀取器之前無法獲取其他讀取器
						// reader = port.readable.getReader();
						//调用port.readable.getReader()创建一个读取器并将其锁定为readable。当可读被锁定时,串口不能被关闭。
						try {
							while (true) {//监听来自串行设备的数据
							// 当使用循环从串行设备连续读取数据时,端口Readable将一直被锁定,直到遇到错误。在这种情况下,调用reader.cancel()将强制reader.read()
							// 立即解析为{value: undefined, done: true},从而允许循环调用reader.releaseLock()
							const { value, done } = await reader.read();
							if (done) {//如果done为真,则串行端口已经关闭,或者没有更多的数据输入。
								break;
							}
					      if (value) {
							  console.log(value)
							  // res += value
							  res += Uint8ArrayToString(value).toString()
							  $('#receive').val(res)
					      }
					    }
						} catch (error) {//只要错误是非致命的,一个新的ReadableStream就会自动创建。如果发生致命错误,如串行设备被删除,则端口。可读的变成了零。
					    // TODO: 处理非致命的读错误。
							console.log(error)
							console.log("处理非致命的读错误");
							alert("数据读取失败")
						}finally{
							// 允许稍后关闭串口。
							reader.releaseLock();
							await port.close()
							console.log('串口已关闭')
							myclose()
							isOpen = false
					  }
					}
				}
			}
			
			// 关闭串口
			async function myclose(){
				if(isOpen){
					window.location.href = "./b.html"
					// KeepReading = false;
					// reader.cancel();
					console.log('关闭reader')
					$('#openBtn').show()
					$('#closeBtn').hide()
					$('#sendBtn').hide()
				}
				else{
					alert("串口未打开,无需关闭串口!")
				}
			}
			
			// 数组转字符串
			function Uint8ArrayToString(fileData){
			  var dataString = "";
			  for (var i = 0; i < fileData.length; i++) {
			    dataString += String.fromCharCode(fileData[i]);
			  }
			  return dataString;
			}
			
			// 字符串转数组
			function toUint8Arr(str) {
				const buffer = [];
				for (let i of str) {
				    const _code = i.charCodeAt(0);
				    if (_code < 0x80) {
				        buffer.push(_code);
				    } else if (_code < 0x800) {
				        buffer.push(0xc0 + (_code >> 6));
				        buffer.push(0x80 + (_code & 0x3f));
				    } else if (_code < 0x10000) {
				        buffer.push(0xe0 + (_code >> 12));
				        buffer.push(0x80 + (_code >> 6 & 0x3f));
				        buffer.push(0x80 + (_code & 0x3f));
				    }
				}
				return Uint8Array.from(buffer); 
			}
			
			// 字符串转换UTF8字节
			function strToUtf8Bytes(str) {
				const utf8 = [];
				  for (let ii = 0; ii < str.length; ii++) {
					let charCode = str.charCodeAt(ii);
					if (charCode < 0x80) utf8.push(charCode);
					else if (charCode < 0x800) {
					  utf8.push(0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f));
					} else if (charCode < 0xd800 || charCode >= 0xe000) {
					  utf8.push(0xe0 | (charCode >> 12), 0x80 | ((charCode >> 6) & 0x3f), 0x80 | (charCode & 0x3f));
					} else {
					  ii++;
					  charCode = 0x10000 + (((charCode & 0x3ff) << 10) | (str.charCodeAt(ii) & 0x3ff));
					  utf8.push(
						0xf0 | (charCode >> 18),
						0x80 | ((charCode >> 12) & 0x3f),
						0x80 | ((charCode >> 6) & 0x3f),
						0x80 | (charCode & 0x3f),
					  );
					}
				  }
				  //兼容汉字,ASCII码表最大的值为127,大于127的值为特殊字符
				  for(let jj=0;jj<utf8.length;jj++){
					  var code = utf8[jj];
					  if(code>127){
						  utf8[jj] = code - 256;
					  }
				  }
				  return utf8;
			}
		
			// 根据返回字节码进行16进制转换
			function strToHexCharCode(str){
					var hexCharCode = [];
					var chars = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"];
					for(var i = 0; i < str.length; i++) {
						  var bit = (str[i] & 0x0f0) >> 4;
						  hexCharCode.push(chars[bit]);
						  var bit = str[i] & 0x0f;
						  hexCharCode.push(chars[bit]);
					}
				   return hexCharCode.join("");
			}

		</script>
	</head>
	<body>
		<table border="0" width="50%" align="center">
			<tr align="center"><td colspan="4"><h1>网页串口工具</h3></td></tr>
			<tr>
				<td style="padding: 5px;" colspan="1">
					波特率
					<select name="" id="baudRate" class="form-control ">
						<option value ="110">110</option>
						<option value ="300">300</option>
						<option value ="600">600</option>
						<option value ="1200">1200</option>
						<option value ="2400">2400</option>
						<option value ="4800">4800</option>
						<option value ="9600">9600</option>
						<option value ="14400">14400</option>
						<option value ="19200">19200</option>
						<option value ="38400">38400</option>
						<option value ="56000">56000</option>
						<option value ="57600">57600</option>
						<option value ="115200">115200</option>
					</select></td>
				<td style="padding: 5px;" colspan="1">
				奇偶校验模式
				<select name="" id="parity" class="form-control ">
					<option value="none">none</option>
					<option value="even">even</option>
					<option value="odd">odd</option>
				</select>
				</td><td style="padding: 5px;" colspan="1">数据位
				<select name="" id="dataBits" class="form-control ">
					<option value="7">7</option>
					<option value="8">8</option>
				</select></td>
				<td style="padding: 5px;" colspan="1">停止位
				<select name="" id="stopBits" class="form-control ">
					<option value="1">1</option>
					<option value="2">2</option>
				</select></td>
			</tr>
			<tr align="">
				<td colspan="1" style="padding: 5px;">发送指令(不包含\r)
				<textarea rows="3" cols="5" id="send" class="form-control "></textarea></td>
				<td colspan="3" style="padding: 5px;">接收内容
					<textarea rows="3" cols="5" id="receive" class="form-control "></textarea></td></tr>
			<tr align="">
				<td>是否以\r结束
				<input type="radio" checked="checked" name="end" value="Y"/>是
				<input type="radio"  name="end" value="N"/>否</td>
			</tr>
			<tr align="center">
				<td align="center" style="padding: 5px;" colspan="4">
					<button id="openBtn" type="button" onclick="myconnect()" class="btn-xs btn-primary" >打开串口</button>
					<button id="closeBtn" type="button" onclick="myclose()" class="btn-xs btn-primary" style="display: none;">关闭串口</button>
					<button id="sendBtn" type="button" onclick="mysend()" class="btn-xs btn-primary"  style="display: none;">发送指令</button> </td></tr>
		</table>
	</body>
</html>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值