<!DOCTYPE html>
<html>
<head>
<meta charset=" utf-8">
<title>串口</title>
</head>
<body>
<button id="btnRequest">请求访问串口</button><p/><p/><p/>
<select id="sltPort" style="width: 152px; height: 24px;"></select> <button id="btnOpen">打开串口</button><p/><p/><p/>
<textarea id="txtIn" style="width: 512px; height: 256px;"></textarea><p/><p/><p/><p/>
<textarea id="txtOut" style="width: 256px; height: 24px;">020004A23100009303</textarea><p/><button id="btnSend">发送</button>
<script type="text/javascript">
var g_ports;
var g_portIndex;
var g_isOpen = false;
var g_closed;
var g_keepReading;
var g_reader;
// 定义打开/关闭串口函数
async function openPort(portIndex, isOpen) {
// 打开串口
let port = g_ports[portIndex];
if (!isOpen) {
// 关闭串口
g_keepReading = false;
g_reader.cancel();
await g_closed;
g_portIndex = portIndex;
g_isOpen = isOpen;
} else {
await port.open({
baudRate: "115200",
dataBits: "8",
stopBits: "1",
parity: "none",
flowControl: "none",
});
g_portIndex = portIndex;
g_isOpen = isOpen;
g_keepReading = true;
g_closed = readUntilClosed(portIndex);
}
document.getElementById("btnOpen").textContent = isOpen ? '关闭串口' : '打开串口';
}
// 定义读串口函数
async function readUntilClosed(portIndex) {
let port = g_ports[portIndex];
while (port.readable && g_keepReading) {
g_reader = port.readable.getReader();
try {
while (true) {
const { value, done } = await g_reader.read();
console.log(value, '已接收');
let txtIn = document.getElementById("txtIn");
let content = txtIn.value + '\n';
value.map((item, index) => {
content = content + ' ' + item.toString(16).toLocaleUpperCase();
});
console.log(content);
txtIn.value = content;
if (done) {
console.log('done');
break;
}
}
} catch (error) {
console.log(error.message);
} finally {
g_reader.releaseLock();
}
}
await port.close();
}
// 定义写串口函数
function portWrite(value) {
return new Promise(async (resolve, reject) => {
if (!g_isOpen) {
console.log("串口未打开");
reject();
return;
} else {
let port = g_ports[g_portIndex];
const writer = port.writable.getWriter();
await writer.write(new Uint8Array(value));
writer.releaseLock();
resolve(value);
}
});
}
// 选择端口 事件处理
var sltPort = document.getElementById("sltPort");
sltPort.addEventListener('onchange', function() {
g_portIndex = sltPort.selectedIndex;
});
// 请求端口 事件处理
const btnRequest = document.getElementById("btnRequest");
btnRequest.addEventListener('click', async function() {
// Prompt user to select any serial port.
const port = await navigator.serial.requestPort();
// Wait for the serial port to open.
g_ports = await navigator.serial.getPorts();
// VID_1A86&PID_7523
g_ports.map((port, index) => {
const { usbProductId, usbVendorId } = port.getInfo();
if (usbProductId === undefined || usbVendorId === undefined) {
sltPort.options.add(new Option("未知设备", index));
} else {
sltPort.options.add(new Option("VID_" + usbVendorId.toString(16).toUpperCase() + "&PID_" + usbProductId.toString(16).toUpperCase(), index));
}
g_portIndex = index;
});
});
// 打开端口 事件处理
const btnOpen = document.getElementById("btnOpen");
btnOpen.addEventListener('click', function() {
// 设置串口
if (g_portIndex === undefined) {
alert("请选择串口");
return;
}
openPort(g_portIndex, !g_isOpen);
});
// 发送数据 事件处理
const btnSend = document.getElementById("btnSend");
btnSend.addEventListener('click', async function() {
const txtOut = document.getElementById("txtOut");
const content = txtOut.value.trim();
const value = content.trim();
if (value.length != 0) {
let arr = [];
if (/^[0-9A-Fa-f]+$/.test(value) && value.length % 2 === 0) {
for (let i = 0; i < value.length; i = i + 2) {
arr.push(parseInt(value.substring(i, i + 2), 16));
}
} else {
alert("格式错误");
return;
}
portWrite(arr).then((res) => {
console.log(arr, '已发送');
});
} else {
alert("请输入");
}
});
</script>
</body>
</html>