各位靓仔靓女们,早上好/下午好/晚上好!我是今天的主讲人,咱们今天要聊聊Web USB API,这玩意儿能让你在浏览器里直接跟USB设备“谈恋爱”,是不是听起来就有点小激动? 别怕,其实没那么玄乎,咱们争取用大白话把它说明白。
一、啥是Web USB API?(这名字听着就高大上)
简单说,Web USB API就是浏览器提供的一套接口,让你的网站(准确说是Web应用)可以直接访问连在电脑上的USB设备。以前这事儿只能客户端程序干,现在浏览器也能插一脚了,是不是感觉世界都美好了?
-
为啥要用它?
- 免驱动安装: 很多USB设备都需要安装驱动才能用,Web USB API可以让用户直接在浏览器里用,省去了安装驱动的麻烦。
- 跨平台: 只要浏览器支持,你的Web应用就能在各种操作系统上访问USB设备,不用为不同平台写不同的代码。
- 安全性: 浏览器会控制Web应用对USB设备的访问权限,避免恶意网站搞破坏。
- 便捷性: 用户插上USB设备,打开你的网站,就能直接使用,简直不要太方便!
-
能干啥?
- 硬件调试: 直接在浏览器里调试你的硬件设备,比如单片机、传感器等等。
- 自定义HID设备: 控制各种奇奇怪怪的HID设备,比如游戏手柄、键盘、鼠标等等。
- 数据采集: 从USB设备上采集数据,比如温度、湿度、压力等等。
- 固件升级: 直接在浏览器里给你的USB设备升级固件。
- 打印机/扫描仪: 理论上,只要设备支持,就能在浏览器里控制打印机/扫描仪。
二、怎么用?(代码才是王道!)
想跟USB设备“谈恋爱”,总得先认识一下吧?下面咱们就一步一步来,看看怎么用Web USB API。
-
获取USB设备列表
首先,你需要让用户选择要连接的USB设备。这可以通过
navigator.usb.requestDevice()
方法来实现。async function connectUSB() { try { const device = await navigator.usb.requestDevice({ filters: [ { vendorId: 0x2341, productId: 0x8036 }, // Arduino Uno { vendorId: 0x046d, productId: 0xc52b } // Logitech Mouse ] }); console.log("USB Device selected:", device); // 连接设备 await device.open(); console.log("Device opened successfully."); //选择 configuration if(device.configuration === null){ await device.selectConfiguration(1); } // Claim interface await device.claimInterface(0); console.log("Interface claimed successfully."); //接下来就可以进行数据传输了 //... } catch (error) { console.error("Error connecting to USB device:", error); } }
navigator.usb.requestDevice()
:会弹出一个窗口,让用户选择USB设备。filters
:是一个数组,用于过滤USB设备。每个对象包含vendorId
(厂商ID)和productId
(产品ID)。这两个ID可以在设备的硬件信息里找到。vendorId
和productId
:一定要填对,不然用户可能选不到你的设备。await
:因为requestDevice()
是个异步函数,所以要用await
等待它执行完成。device.open()
: 打开设备,准备进行通信。device.selectConfiguration(1)
: 选择配置。通常情况下,USB设备只有一个配置(configuration 1),但有些设备可能有多个配置。选择正确的配置很重要,否则可能无法正常通信。device.claimInterface(0)
: 声明接口。USB设备通常有多个接口(interface),每个接口负责不同的功能。你需要声明你要使用的接口,才能进行数据传输。通常情况下,接口0是主要的接口。
-
打开USB设备并声明接口
拿到设备对象后,就可以打开设备并声明要使用的接口了。
//假设device是上面获取到的设备对象
-
数据传输
打开设备并声明接口后,就可以进行数据传输了。Web USB API提供了
transferIn()
和transferOut()
方法,用于接收和发送数据。-
发送数据(transferOut)
async function sendData(device, endpoint, data) { try { const result = await device.transferOut(endpoint, data); console.log("Data sent:", result); } catch (error) { console.error("Error sending data:", error); } } // 举例:向endpoint 1 发送数据 const data = new Uint8Array([0x01, 0x02, 0x03, 0x04]); sendData(device, 1, data);
endpoint
:是USB端点的地址。每个USB接口都有若干个端点,用于数据传输。你需要知道你要使用的端点的地址。一般来说,端点地址是1到127之间的整数。data
:是要发送的数据,必须是一个Uint8Array
对象。result
:是一个对象,包含了传输的结果信息,比如传输的字节数。
-
接收数据(transferIn)
async function receiveData(device, endpoint, length) { try { const result = await device.transferIn(endpoint, length); console.log("Data received:", result.data); return result.data; } catch (error) { console.error("Error receiving data:", error); return null; } } // 举例:从endpoint 2 接收64字节的数据 const receivedData = await receiveData(device, 2, 64); if (receivedData) { // 处理接收到的数据 const decoder = new TextDecoder(); const text = decoder.decode(receivedData); console.log("Received text:", text); }
length
:是要接收的数据的长度,单位是字节。result.data
:是一个DataView
对象,包含了接收到的数据。TextDecoder
:用于将DataView
对象转换为字符串。
-
-
关闭USB设备
用完USB设备后,一定要记得关闭它,释放资源。
async function disconnectUSB(device) { try { await device.releaseInterface(0); //释放接口 await device.close(); console.log("USB Device disconnected."); } catch (error) { console.error("Error disconnecting USB device:", error); } } // 举例: disconnectUSB(device);
device.releaseInterface(0)
:释放之前声明的接口。device.close()
:关闭设备。
三、实战演练(来点真家伙!)
光说不练假把式,咱们来个小例子,用Web USB API控制一个Arduino Uno开发板上的LED灯。
-
硬件准备
- Arduino Uno开发板
- LED灯
- 220欧姆电阻
- 杜邦线
把LED灯的正极通过220欧姆电阻连接到Arduino Uno的数字引脚13,LED灯的负极连接到GND。
-
Arduino代码
void setup() { pinMode(13, OUTPUT); // 设置数字引脚13为输出模式 Serial.begin(115200); // 初始化串口通信 } void loop() { if (Serial.available() > 0) { int command = Serial.read(); // 读取串口数据 if (command == '1') { digitalWrite(13, HIGH); // 点亮LED灯 Serial.println("LED ON"); } else if (command == '0') { digitalWrite(13, LOW); // 关闭LED灯 Serial.println("LED OFF"); } } }
把这段代码烧录到你的Arduino Uno开发板上。
-
Web页面代码
<!DOCTYPE html> <html> <head> <title>Web USB Arduino LED Control</title> </head> <body> <h1>Web USB Arduino LED Control</h1> <button id="connectButton">Connect USB</button> <button id="ledOnButton" disabled>LED ON</button> <button id="ledOffButton" disabled>LED OFF</button> <script> const connectButton = document.getElementById("connectButton"); const ledOnButton = document.getElementById("ledOnButton"); const ledOffButton = document.getElementById("ledOffButton"); let device = null; connectButton.addEventListener("click", async () => { try { device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341, productId: 0x8036 }], // Arduino Uno }); console.log("USB Device selected:", device); await device.open(); console.log("Device opened successfully."); if(device.configuration === null){ await device.selectConfiguration(1); } await device.claimInterface(0); console.log("Interface claimed successfully."); connectButton.disabled = true; ledOnButton.disabled = false; ledOffButton.disabled = false; } catch (error) { console.error("Error connecting to USB device:", error); } }); ledOnButton.addEventListener("click", async () => { await sendData(device, 1, new Uint8Array([0x31])); // 发送 '1' }); ledOffButton.addEventListener("click", async () => { await sendData(device, 1, new Uint8Array([0x30])); // 发送 '0' }); async function sendData(device, endpoint, data) { try { const result = await device.transferOut(endpoint, data); console.log("Data sent:", result); } catch (error) { console.error("Error sending data:", error); } } </script> </body> </html>
把这段代码保存为一个HTML文件,用浏览器打开。
-
操作步骤
- 把Arduino Uno开发板连接到电脑上。
- 点击Web页面上的"Connect USB"按钮,浏览器会弹出一个窗口,让你选择Arduino Uno设备。
- 选择Arduino Uno设备,点击"连接"。
- 如果连接成功,"LED ON"和"LED OFF"按钮会变成可用状态。
- 点击"LED ON"按钮,Arduino Uno上的LED灯会被点亮。
- 点击"LED OFF"按钮,Arduino Uno上的LED灯会被关闭。
四、注意事项(雷区警告!)
使用Web USB API的时候,要注意以下几点:
- HTTPS: Web USB API只能在HTTPS协议下使用,因为涉及到安全问题。
- 用户授权: 每次连接USB设备都需要用户授权,不能偷偷摸摸地连接。
- 设备兼容性: 并不是所有的USB设备都支持Web USB API,需要设备厂商的支持。
- 浏览器兼容性: 目前只有Chrome、Edge等少数浏览器支持Web USB API。
- 权限问题: 一些操作系统可能会限制Web应用对USB设备的访问权限。
- 错误处理: Web USB API可能会抛出各种异常,一定要做好错误处理。
五、常见问题(排坑指南!)
-
Q:为什么我的设备没有出现在设备选择窗口里?
- A:检查你的
vendorId
和productId
是否正确。 - A:检查你的设备是否支持Web USB API。
- A:检查你的浏览器是否支持Web USB API。
- A:检查你的
-
Q:为什么我连接设备后无法发送或接收数据?
- A:检查你是否正确地打开了设备并声明了接口。
- A:检查你的
endpoint
是否正确。 - A:检查你的数据格式是否正确。
-
Q:为什么我的代码在Chrome里能用,在Edge里不能用?
- A:不同的浏览器对Web USB API的实现可能略有差异,需要做一些兼容性处理。
- A:检查你的浏览器版本是否过低。
六、一些建议(老司机经验!)
- 多看文档: Web USB API的官方文档是最好的学习资料。
- 多看例子: 网上有很多Web USB API的例子,可以参考一下。
- 多调试: 调试是解决问题的最好方法。
- 多交流: 遇到问题可以到社区里提问,大家一起讨论。
七、Web Serial API和Web Bluetooth API (拓展)
除了Web USB API,浏览器还提供了Web Serial API和Web Bluetooth API,用于与串口设备和蓝牙设备进行通信。
- Web Serial API 允许网站通过串口与设备通信,例如与微控制器、3D打印机等连接。
- Web Bluetooth API 允许网站与蓝牙设备进行通信,例如与心率监测器、智能家居设备等连接。
它们与Web USB API类似,都是为了让Web应用能够直接与硬件设备进行交互。
八、总结
Web USB API是一个强大的工具,可以让你在浏览器里直接跟USB设备“谈恋爱”。虽然有一些坑,但是只要你掌握了正确的方法,就能轻松驾驭它。希望今天的讲座能帮助你入门Web USB API,开启你的硬件探索之旅! 祝各位玩得开心!
API 名称 | 功能 | 适用场景 |
---|---|---|
Web USB API | 与 USB 设备直接通信 | 硬件调试、自定义 HID 设备、数据采集、固件升级、打印机/扫描仪等 |
Web Serial API | 通过串口与设备通信 | 与微控制器、3D 打印机等连接 |
Web Bluetooth API | 与蓝牙设备通信 | 与心率监测器、智能家居设备等连接 |
安全性 | 需要 HTTPS 协议和用户授权 | 所有 API 都需要在 HTTPS 协议下运行,并需要用户授权才能访问设备 |
浏览器兼容性 | Chrome、Edge 等少数浏览器支持 | Chrome、Edge 等浏览器支持,但不同浏览器对 API 的实现可能略有差异 |
权限管理 | 操作系统可能限制 Web 应用对 USB 设备的访问权限 | 操作系统和浏览器都会对 Web 应用访问硬件设备进行权限管理,例如需要用户授权、限制访问频率等 |
错误处理 | 需要做好错误处理 | 所有 API 在使用过程中都可能抛出异常,例如设备未连接、权限不足等,需要做好错误处理 |
学习资源 | 官方文档、示例代码、社区论坛 | 官方文档是最好的学习资料,网上有很多示例代码可以参考,社区论坛可以交流问题 |
使用建议 | 多看文档、多看例子、多调试、多交流 | 充分利用各种学习资源,遇到问题及时调试和交流 |