2026-02-09

測試 Web Serial API

之前,在下曾經使用 WebHID API 與 HID 通訊,發現以 網頁技術 來存取 硬件裝置 非常簡單。
此外,使用網頁技術開發 圖形介面 也較為方便。
既然在下需要製作 微控制器專案,因此在下嘗試以 網頁技術 來實現 微控制器 的 序列資料 發送 及 接收 功能。

由於這只是一個簡單的測試,因此在下沒有擷取太多圖像。

// rgb_led_test.ino
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel rgb(1, 16);
void setup() {
	Serial.begin(115200);
	rgb.begin();
	rgb.clear();
}
void loop() {
	if (Serial.available() > 0) {
		String command = Serial.readStringUntil('\n');
		Serial.println(command);
		if (command == "black") {
			rgb.setPixelColor(0, 0x000000);
			rgb.show();
		} else if (command == "red") {
			rgb.setPixelColor(0, 0xFF0000);
			rgb.show();
		} else if (command == "green") {
			rgb.setPixelColor(0, 0x00FF00);
			rgb.show();
		} else if (command == "blue") {
			rgb.setPixelColor(0, 0x0000FF);
			rgb.show();
		} else if (command == "yellow") {
			rgb.setPixelColor(0, 0xFFFF00);
			rgb.show();
		} else if (command == "magenta") {
			rgb.setPixelColor(0, 0xFF00FF);
			rgb.show();
		} else if (command == "cyan") {
			rgb.setPixelColor(0, 0x00FFFF);
			rgb.show();
		} else if (command == "white") {
			rgb.setPixelColor(0, 0xFFFFFF);
			rgb.show();
		}
	}
}

在下使用 Arduino IDE 製作 Sketch,讓兼容 Arduino 的開發板可以接收 序列資料 ,並根據接收到的序列資料執行相應的操作。

// web-serial.js
class WebSerial {
	#port;
	constructor() {
	}
	async connect(baudrate) {
		try {
			this.#port = await navigator.serial.requestPort();
			await this.#port.open({
				"baudRate": baudrate
			});
		} catch (error) {
			throw error;
		}
	}
	async sendData(data) {
		try {
			let writer = this.#port.writable.getWriter();
			await writer.write(new Uint8Array(data));
			writer.releaseLock();
		} catch (error) {
			throw error;
		}
	}
	async retrieveData() {
		try {
			let reader = this.#port.readable.getReader();
			let data = await reader.read();
			reader.releaseLock();
			return [...new Uint8Array(data.value)];
		} catch (error) {
			throw error;
		}
	}
	async disconnect() {
		try {
			this.#port.close();
		} catch (error) {
			throw error;
		}
	}
}

為了方便使用 Web Serial API,在下編寫了 WebSerial類別 ,將功能整合在一起。
這樣可以根據不同的情況擴展 WebSerial類別 ,製作針對特定情況的類別。

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
		<title></title>
		<script src="web-serial.js"></script>
		<script>
// <!--
let webSerial = new WebSerial();
window.addEventListener("load", function(loadEvent) {
	document.getElementById("serial-connector").addEventListener("click", async function(clickEvent) {
		await webSerial.connect(115200);
	});
	document.getElementById("serial-text").addEventListener("keyup", async function(keyupEvent) {
		if (keyupEvent.keyCode == 13) {
			this.select();
			let text = this.value;
			let data = [];
			for (let i = 0; i < text.length; i++) {
				data.push(text.charCodeAt(i));
			}
			await webSerial.sendData(data);
			data = await webSerial.retrieveData();
			console.log(data);
		}
	});
});
// -->
</script>
	</head>
	<body>
		<div>
			<button id="serial-connector">Serial Connector</button>
		</div>
		<div>
			<input id="serial-text" type="text"/>
		</div>
	</body>
</html>

最後,在下製作了一個測試用的網頁,以測試 Web Serial API 的功能。

測試使用 Web Serial API 經 基於 Chromium 的網頁瀏覽器 向 序列裝置 發送 序列資料 。

總結

以前,通常需要安裝特定軟件,甚至安裝特定驅動程式才能與硬件裝置通訊。
然而,隨著網頁技術的進步,現在能夠直接在網頁上與硬件通訊,而無需安裝額外的軟件和驅動程式。
最重要是能夠直接在宿主電腦上執行,不需要建立網頁伺服器就能運作。
不過,部分 Web API 技術目前僅能在基於 Chromium 的網頁瀏覽器中使用。

由於在下偏好使用 Firefox,因此在查找 Firefox 為何未支援這些功能時發現,
Firefox 認為某些 Web API 具有潛在的安全風險,因此並未實作這些 API,或者將曾經實作的API移除。

基於 Chromium 的網頁瀏覽器能夠支援這些功能,這可能是因為 Google 的 Chrome OS 的緣故。
由於 Chrome OS 的操作介面就是 Chrome 網頁瀏覽器,因此必須允許 Chrome 網頁瀏覽器存取硬件設備以協助設定 Chrome OS。

希望 Firefox 官方能讓使用者自行決定啟用或停用這些相關功能,例如預設情況下停用相關功能,
並能讓使用者在 about:config 中自行設定,或者允許使用者自行編譯 Firefox 來啟用這些功能。

參考資料

沒有留言 :

張貼留言