发布于 

使用 Chrome 浏览器连接 USB 设备

使用 Chrome 浏览器连接 USB 设备的一些总结。

项目地址

https://github.com/RinChanNOWWW/web_usb_connector

前言

在公司 mentor 给我说来了一个需求,想要能够通过 Web 配置终端设备的一些设置,让我看看怎么用浏览器通过 USB 连接到设备。

好巧不巧的是,作为一个街机音游狗,接触了各种黑科技的我还真用过这种 Web 配置工具。我使用的一款手台就是通过这样的方式进行配置的,而且作者还将所有代码完全开源了:PocketVoltex/Software/WebConfig,于是我按照作者 mon 的做法将连接 USB 设备并进行配置的代码框架提取了出来。

我也找了 Github 上其他项目看了看,大多数都是连接 Arduino 的,而且都没有 mon 的这个简单好学。

编写 Javascript

将浏览器提供的 usb API 封装起来

将连接 usb 的方法封装起来赋值给 window 以便全局使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// usb.js
(function(window, navigator) {
"use strict";
var USBWrapperInit = function() {
var UsbWrapper = new function() {
this.hasUSB = navigator && navigator.usb;
if (!this.hasUSB) {
console.log('Your browser does not support usb')
return;
}
this.connect = () => {
return navigator.usb
.requestDevice({filters: []})
.catch(e => {
console.log(e);
return null;
});
};
this.usb = navigator.usb;
};
window.USBWrapper = UsbWrapper;
};
window.USBWrapperInit = USBWrapperInit;
})(window, navigator);

编写 Config 类

本应用的逻辑是新建一个 Config 的同时连接到想要配置的 USB 设备,这样就能将一个连接对应到一个配置上。同样的,把 Config 类赋值给 window 以便全局使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// config.js
(function(window, document) {
"use strict";
var device;
const genLog = function(html) {
var log = document.getElementById('log');
log.innerHTML += html + '<br/>';
log.scrollTop = log.scrollHeight;
}
const clearLog = function() {
var log = document.getElementById('log');
log.innerHTML = "USB CONFIG TEST"
}
class Config {
constructor() {
genLog("USB CONFIG TEST")
}

connect(selectedDevice) {
console.log(selectedDevice);
device = selectedDevice;
genLog("Opening Device...");
return device.open()
.then(() => {
genLog(`${device.productName}(${device.manufacturerName}) connected.`)
})
.catch(err => {
genLog(err);
if (device && device.opened) {
device.close();
}
})
}

newConnection() {
return window.USBWrapper.connect()
.then(device => {
if (!device) {
return Promise.reject("No device selected");
}
this.connect(device);
})
}

close() {
if (!device || !device.opened) {
return Promise.reject("Device not opened");
}
genLog("Closing Device...");
return device.close()
.then(() => {
genLog('Device closed.')
})
}
};
window.Config = Config;
window.genLog = genLog;
window.clearLog = clearLog;
})(window, document);

编写 html 页面并加载上面两个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html>
<head>
<title>usb test</title>
<script type="text/javascript" src="js/usb.js"></script>
<script type="text/javascript" src="js/config.js"></script>
<script type="text/javascript">
window.addEventListener("load", function() {
USBWrapperInit();
if(USBWrapper.hasUSB) {
config = new Config();
navigator.usb.getDevices()
.then(devices => {
if(devices.length) {
config.connect(devices[0]);
}
});
navigator.usb.addEventListener('connect', event => {
config.connect(event.device);
});
}
});
</script>
</head>
<body>
<div>
<div id="log" class="hidden"></div>
<button id="connectBtn" onclick="config.newConnection()">connect</button>
<button id="disconnectBtn" onclick="config.close()">disconnect</button>
<button id="clearBtn" onclick="window.clearLog()">clear log</button>
</div>
</body>
</html>

后续

实现以上的代码,就已经可以通过网页连接到 USB 设备了。可以打开 Chrome 的控制台查看连接后生成的 USBDevice 对象,里面有符合 USB 协议的各种信息。

接下来就是如何进行配置操作了。为了完成这一点,还需要设备端编写 USB 驱动程序并运行在设备的内核才行。怎么样传数据,就自己和设备端那边商量就行了。

对于这个 Web 应用,还需要做的就是给 Config 类添加各种配置的方法,其核心是调用

1
2
var promise = USBDevice.transferIn(endpointNumber, length)
var promise = USBDevice.transferOut(endpointNumber, data)

这两个方法,进行 USB 的数据读取与写入操作。只要和设备端协商好了,接下来的就都好说了。

写在最后

虽然我是在后台岗位实习,但是是着实干了很多前端的活啊。。。这两天也看了不少 HTML、CSS、Javascript、Typescript 的东西。。。感觉学到的都是一些奇奇怪怪的东西(针对于我想学更多后端的东西而言)。

对于 USB 协议与 Web 更深层次的东西我就不懂了,本项目也只是浅尝辄止。如果上面写的有什么错误或者可以提升的地方,您可以联系我(虽然我觉得应该不会有人看到我的博文),非常感谢。

最后的最后

API 文档