前言 之前寫了一個vue+django的一個通過串口控制的上位機系統。但是實際生產中,不如部署到伺服器上,這樣可以更好的節約成本。但是這樣就需要弄一個客戶端來控制處理串口信息。那我就在想能不能通過網頁直接拿到客戶端的串口信息。所以問了萬能的chatgpt,得到了以下答案: 是的,前端可以使用 Web ...
前言
之前寫了一個vue+django的一個通過串口控制的上位機系統。但是實際生產中,不如部署到伺服器上,這樣可以更好的節約成本。但是這樣就需要弄一個客戶端來控制處理串口信息。那我就在想能不能通過網頁直接拿到客戶端的串口信息。所以問了萬能的chatgpt,得到了以下答案:
是的,前端可以使用 Web SerialAPI直接與客戶端機器的串口通信,而Diango只需要負責存儲數據。當客戶端機器發送數據時,前端可以將數據發送到 Diango伺服器,Diango 伺服器再將數據存儲到資料庫中。當需要讀取數據時,前端可以從 Django伺服器中獲取數據並顯示在頁面上。
所以我去研究了下Web Serial Api
一、什麼是Web Serial Api
官方:https://wicg.github.io/serial/#open-method
Web Serial API 是一個用於訪問串列設備的 Web API,它允許 web 應用程式與串列設備(如 Arduino、感測器、GPS 接收器等)進行通信。使用 Web Serial API,你可以在 web 應用程式中讀取和寫入串列數據,就像使用本地應用程式一樣。
Web Serial API 是由 W3C Web 原生設備和感測器工作組開發的,它已經成為標準的一部分,目前已經在主流瀏覽器中得到了支持,包括 Chrome、Edge、Firefox 和 Opera。
使用 Web Serial API,你可以在 web 應用程式中執行以下操作:
- 請求用戶授權訪問串列埠
- 打開和關閉串列埠
- 讀取和寫入串列數據
- 監聽來自串列設備的數據
- 設置串列埠的參數,例如波特率、數據位、停止位、奇偶校驗等。
Web Serial API 的優點在於它可以在沒有任何插件或安裝軟體的情況下訪問串列設備,因此它非常適合用於構建基於 web 的物聯網應用程式。
二、vite項目運行在https協議
如果想使用Web Serial Api就需要把項目運行在https模式下
其實可以簡單驗證下:
if ("serial" in navigator) {
console.log("Web Serial API is supported!");
} else {
console.log("Web Serial API is not supported!");
}
正常在http模式下是不成功的。
首先需要把項目在https模式運行,這裡先用簡單證書去處理。
錯誤示範:
直接加--https 運行時在https上 但是會報錯:
這個時候需要自己獲取SSL證書
Windows使用mkcert頒發證書及應用
1、下載:
https://github.com/FiloSottile/mkcert/releases/tag/v1.4.4
在下載好的文件下
打開cd 找到文件 輸入mkcert-v1.4.3-windows-amd64.exe -install(根據你實際包來)
這個時候我們就看到2個pem文件了
Vite配置
把上面生成的兩個文件放到項目根目錄keys文件夾
在vite.config.ts中修改為(請根據情況按需修改):
import * as fs from 'fs'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.join(__dirname, 'src')
}
},
server:{
host:"192.168.149.1",
port:8080,
open:true,
https:{
key:fs.readFileSync(path.join(__dirname, 'key/install-key.pem')),
cert:fs.readFileSync(path.join(__dirname, 'key/install.pem')),
},
},
})
選擇高級
這樣我們的項目就運行在
這樣就解決了這個問題。
三、Web Serial Api簡單使用
串口的選擇
<script>
const port = await navigator.serial.requestPort();
await port.open({baudRate:9600});
const reader = port.readable.getReader();
</script>
<template>
</template>
<style scoped>
</style>
串口接受消息
// 提示用戶選擇一個串口
const port = await navigator.serial.requestPort();
await port.open({baudRate:9600});
const reader = port.readable.getReader();
let buffer = ''; // 緩衝區
// 監聽來自串口的數據
while (true) {
const { value } = await reader.read();
if (value) {
const textDecoder = new TextDecoder('utf-8');
const str = textDecoder.decode(value);
buffer += str; // 將讀取到的數據添加到緩衝區中
// 判斷緩衝區中是否存在完整的數據包
const completePacketIndex = buffer.indexOf('\n');
if (completePacketIndex !== -1) {
const completePacket = buffer.substring(0, completePacketIndex);
buffer = buffer.substring(completePacketIndex + 1);
// 處理完整的數據包
console.log(completePacket);
}
}
}
串口發送消息
const writer = port.writable.getWriter();
const data = new Uint8Array([104, 101, 108, 108, 111]); // hello
setInterval(async () => {
await writer.write(data);
}, 2000);