WebUSB API 允许网页与 USB 设备进行交互,但出于安全考虑,浏览器要求在调用 requestDevice 方法(用于请求用户选择一个 USB 设备并授予网页访问权限)时,必须是在处理用户手势(例如点击按钮)的过程中进行。这是为了防止网页在用户不知情的情况下擅自请求访问 USB 设备,从而保护用户的隐私和安全。
代码演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebUSB Correct Example</title>
</head>
<body>
<button id="connectButton">Connect to USB Device</button>
<script>
const connectButton = document.getElementById('connectButton');
connectButton.addEventListener('click', async () => {
try {
const device = await navigator.usb.requestDevice({ filters: [] });
console.log('Selected device:', device);
} catch (error) {
console.error('Error:', error);
}
});
</script>
</body>
</html>
WebUSB 是一项 Web API 技术,它允许网页直接与 USB 设备进行通信,打破了以往网页在访问本地设备方面的限制,为网页开发者提供了更强大的功能和更丰富的交互场景。以下是关于 WebUSB 的详细介绍:
基本概念
WebUSB 是由万维网联盟(W3C)制定的标准,它使得基于浏览器的网页应用能够发现、连接和与 USB 设备进行数据传输。在没有 WebUSB 之前,网页与本地设备的交互通常需要借助插件或本地应用程序,而 WebUSB 让这一过程可以直接在网页中实现,提高了开发的便利性和用户体验。
主要特点
简化开发流程:开发者无需编写复杂的本地应用程序,只需使用 JavaScript 就可以在网页中实现与 USB 设备的通信,降低了开发门槛和成本。
跨平台兼容性:只要浏览器支持 WebUSB 标准,无论在桌面端还是移动端,都可以实现网页与 USB 设备的交互,具有良好的跨平台性。
增强用户体验:用户无需安装额外的软件,直接通过浏览器就能使用网页应用与 USB 设备进行交互,操作更加便捷。
安全可靠:为了保护用户的隐私和安全,WebUSB 有严格的权限管理机制。例如,在请求访问 USB 设备时,必须在用户的明确手势(如点击按钮)触发下进行,并且设备的选择和授权过程都需要用户手动确认。
工作原理
设备发现:网页通过调用 navigator.usb.requestDevice() 方法,弹出设备选择对话框,让用户选择要连接的 USB 设备。该方法可以接受一个过滤器参数,用于筛选符合特定条件的设备。
设备连接:用户选择设备并授权后,网页可以调用 device.open() 方法打开设备连接,建立与设备的通信通道。
数据传输:连接建立后,网页可以使用 device.transferIn() 和 device.transferOut() 方法进行数据的读取和写入操作,实现与 USB 设备的数据交互。
设备断开:当不再需要与设备通信时,网页可以调用 device.close() 方法关闭设备连接,释放资源。
应用场景
硬件控制:可以用于控制各种 USB 接口的硬件设备,如 3D 打印机、机器人、传感器等。通过网页应用,用户可以方便地对这些设备进行参数设置、数据采集和控制操作。
数据采集:与 USB 数据采集设备(如数据记录仪、万用表等)进行通信,实时获取设备采集的数据,并在网页中进行显示和分析。
教育领域:在教学过程中,学生可以通过网页应用直接与 USB 实验设备进行交互,进行实验操作和数据采集,提高学习的趣味性和效果。
物联网应用:作为物联网的一种接入方式,WebUSB 可以让网页应用与各种物联网设备进行通信,实现设备的远程监控和管理。
WebUSB 提供了一系列 API 用于实现网页与 USB 设备的交互,下面为你介绍一些常用的 API。
1. navigator.usb
这是 WebUSB API 的入口点,它是 USB 对象的实例,通过它可以访问 WebUSB 的各种功能。
示例代码
if ('usb' in navigator) {
// 浏览器支持 WebUSB
console.log('WebUSB is supported.');
} else {
console.log('WebUSB is not supported.');
}
- 2. navigator.usb.requestDevice()
该方法用于请求用户选择一个 USB 设备,并授予网页访问该设备的权限。它返回一个 Promise,当用户选择设备并授权后,Promise 会被解析为选中的 USBDevice 对象。
参数
options:一个对象,包含 filters 属性,用于筛选符合特定条件的设备。filters 是一个数组,每个元素是一个包含设备信息的对象,如 vendorId、productId 等。
示例代码
const filters = [
{ vendorId: 0x1234, productId: 0x5678 }
];
navigator.usb.requestDevice({ filters })
.then(device => {
console.log('Selected device:', device);
})
.catch(error => {
console.error('Error:', error);
});
3. USBDevice 对象
当用户选择并授权一个 USB 设备后,会得到一个 USBDevice 对象,通过该对象可以对设备进行各种操作。
3.1 USBDevice.open()
用于打开与 USB 设备的连接。返回一个 Promise,当连接成功打开时,Promise 会被解析。
示例代码
navigator.usb.requestDevice({ filters: [] })
.then(device => {
return device.open();
})
.then(() => {
console.log('Device opened successfully.');
})
.catch(error => {
console.error('Error:', error);
});
3.2 USBDevice.selectConfiguration()
用于选择 USB 设备的配置。USB 设备可能有多种配置,需要选择合适的配置才能进行通信。返回一个 Promise,当配置选择成功时,Promise 会被解析。
参数
configurationValue:一个整数,表示要选择的配置值。
示例代码
navigator.usb.requestDevice({ filters: [] })
.then(device => {
return device.open();
})
.then(device => {
return device.selectConfiguration(1);
})
.then(() => {
console.log('Configuration selected successfully.');
})
.catch(error => {
console.error('Error:', error);
});
3.3 USBDevice.claimInterface()
用于声明对 USB 设备某个接口的使用权限。在进行数据传输之前,需要先声明使用的接口。返回一个 Promise,当接口声明成功时,Promise 会被解析。
参数
interfaceNumber:一个整数,表示要声明的接口编号。
示例代码
navigator.usb.requestDevice({ filters: [] })
.then(device => {
return device.open();
})
.then(device => {
return device.selectConfiguration(1);
})
.then(device => {
return device.claimInterface(0);
})
.then(() => {
console.log('Interface claimed successfully.');
})
.catch(error => {
console.error('Error:', error);
});
3.4 USBDevice.transferIn()
用于从 USB 设备读取数据。返回一个 Promise,当数据读取成功时,Promise 会被解析为一个包含读取数据的对象。
参数
endpointNumber:一个整数,表示要读取数据的端点编号。
length:一个整数,表示要读取的数据长度。
示例代码
navigator.usb.requestDevice({ filters: [] })
.then(device => {
return device.open();
})
.then(device => {
return device.selectConfiguration(1);
})
.then(device => {
return device.claimInterface(0);
})
.then(device => {
return device.transferIn(1, 64);
})
.then(result => {
const data = new DataView(result.data.buffer);
console.log('Received data:', data);
})
.catch(error => {
console.error('Error:', error);
});
3.5 USBDevice.transferOut()
用于向 USB 设备写入数据。返回一个 Promise,当数据写入成功时,Promise 会被解析。
参数
endpointNumber:一个整数,表示要写入数据的端点编号。
data:要写入的数据,可以是 ArrayBuffer、TypedArray 或 DataView 类型。
示例代码
const data = new Uint8Array([0x01, 0x02, 0x03]);
navigator.usb.requestDevice({ filters: [] })
.then(device => {
return device.open();
})
.then(device => {
return device.selectConfiguration(1);
})
.then(device => {
return device.claimInterface(0);
})
.then(device => {
return device.transferOut(2, data);
})
.then(() => {
console.log('Data sent successfully.');
})
.catch(error => {
console.error('Error:', error);
});
3.6 USBDevice.close()
用于关闭与 USB 设备的连接。返回一个 Promise,当连接成功关闭时,Promise 会被解析。
示例代码
navigator.usb.requestDevice({ filters: [] })
.then(device => {
return device.open();
})
.then(device => {
// 进行一些操作
return device.close();
})
.then(() => {
console.log('Device closed successfully.');
})
.catch(error => {
console.error('Error:', error);
});
这些 API 是 WebUSB 中比较常用的部分,通过它们可以实现网页与 USB 设备的基本通信功能。