使用 WebUSB 读取 GPS 接收器
Reading GPS Receiver using WebUSB
我正在尝试使用 WebUSB 从 javascript.
内的 USB 连接的 GPS 接收器读取 GPS 坐标
我已经可以连接到接收器;但是,我不确定如何使用 WebUSB 访问 NMEA 消息。
到目前为止,我有以下概念验证代码:
<html>
<head>
<title>WebUSB Serial Sample Application</title>
</head>
<body>
<a href="#" id = "click">Connect</a><br>
<a href="#" id = "send">Send Data</a><br>
<a href="#" id = "read">Read Data</a><br>
<script>
let y;
let device;
var connectButton = document.getElementById('click')
connectButton.addEventListener('click', function() {
navigator.usb.requestDevice({
filters: [{}]
}).then((selectedDevice) => {
device = selectedDevice;
return device.open()
.then(() => device.selectConfiguration(1))
.then(() => device.claimInterface(device.configuration.interfaces[0].interfaceNumber))
.then(() => device.selectAlternateInterface(device.configuration.interfaces[0].interfaceNumber, 0))
.then(() => {
y = device;
})
});
})
var sendButton = document.getElementById('send')
var sendDecoder = new TextDecoder()
sendButton.addEventListener('click', async () => {
y.controlTransferOut({
requestType: 'class',
recipient: 'interface',
request: 0x22,
value: 0x01,
index: 0x00});
y.controlTransferIn({
requestType: 'standard',
recipient: 'device',
request: 0x06,
value: 0x0302,
index: 0x409
}, 255)
.then(result => {
let decoder = new TextDecoder()
console.log(sendDecoder.decode(result.data));
console.log('sent req');
}).catch(error => {
console.log(error);
});
});
</script>
</body>
</html>
transferOut 语句允许我从设备中读取供应商名称。所以,我知道我已经连接并且可以与之通信。我只是不知道从设备访问 lat/lon 需要什么特定命令。
更新:
下面是设备配置信息的快照
为了实现您的目标,您需要了解几个层次。首先是设备实现的USB接口。
在您发布的示例代码中,有两个向设备发送命令的调用。第一个是 controlTransferOut(),它向设备发送标准 USB CDC-ACM SET_CONTROL_LINE_STATE 请求 (0x22) 以启用 DTR 信号 (0x01)。如果您的设备实现了 USB CDC-ACM 协议,那么这就是写入操作,因为它向设备发出主机软件已准备好接收数据的信号。如果您的设备未实现此协议,则该命令将被忽略或失败。您已经声明了第一个接口,要了解接口实现的 USB 协议,您应该检查 device.configuration.interfaces[0].alternates[0].interfaceClass
和 device.configuration.interfaces[1].alternates[0].interfaceClass
。 USB CDC-ACM 设备将有一个接口 class 2 和一个接口 class 10。Class 2 用于控制接口,而 class 10 是数据接口。如果您的设备没有这两个接口,那么它可能没有实现 USB CDC-ACM 协议,您必须先弄清楚它使用的是什么协议。
您进行的第二个调用是 controlTransferIn(),它发送标准 USB GET_DESCRIPTOR 请求 (0x06) 以从设备读取字符串描述符。传递 0x0302 要求它读取索引 2 处的字符串描述符(类型 3)。这适用于任何 USB 设备(假设索引正确),因此不会告诉您是否已经弄清楚接口支持什么协议。
假设这是一个 USB CDC-ACM 接口,那么您需要查看 device.configuration.interfaces[1].alternates[0].endpoints
并找出 IN 和 OUT 端点的端点编号。这些是您将传递给 transferIn()
和 transferOut()
以从设备发送和接收数据的内容。
一旦你弄清楚了所有这些,你就需要弄清楚如何让设备开始发送 NMEA 消息。如果你幸运的话,在默认模式下它会自动发送它们,你可以开始调用 transferIn()
来接收它们。否则,您将不得不弄清楚向设备发送什么命令以将其置于正确的模式。如果您有该设备的文档或用支持该设备的其他语言编写的示例代码,那么这将非常有助于解决这个问题。
我终于解决了这个问题。答案(无论如何对我来说)是购买一个实现 CDC-ACM 接口的不同 GPS 接收器,因为似乎有更多示例和更好的文档适用于此协议。
以下概念验证代码正在运行:
<html>
<head>
<title>WebUSB Serial Sample Application</title>
</head>
<body>
<a href="#" id = "click">Connect</a><br>
<a href="#" id = "read">Read Data</a><br>
<script>
let y;
let device;
var connectButton = document.getElementById('click')
connectButton.addEventListener('click', function() {
navigator.usb.requestDevice({
filters: [{}]
})
.then((selectedDevice) => {
device = selectedDevice;
return device.open();
})
.then(() => device.selectConfiguration(1))
.then(() => device.claimInterface(device.configuration.interfaces[0].interfaceNumber))
.then(() => device.claimInterface(device.configuration.interfaces[1].interfaceNumber))
.then(() => device.selectAlternateInterface(device.configuration.interfaces[0].interfaceNumber, 0))
.then(() => device.selectAlternateInterface(device.configuration.interfaces[1].interfaceNumber, 0))
.then(() => {
y = device;
})
})
var readButton = document.getElementById('read')
var readDecoder = new TextDecoder()
var readLoop = () => {
y.transferIn(2,64)
.then(result => {
let decoder = new TextDecoder()
console.log(readDecoder.decode(result.data.buffer));
readLoop();
}).catch(error => {
console.log(error);
});
};
readButton.addEventListener('click', async () => {
readLoop();
});
</script>
</body>
</html>
我正在尝试使用 WebUSB 从 javascript.
内的 USB 连接的 GPS 接收器读取 GPS 坐标我已经可以连接到接收器;但是,我不确定如何使用 WebUSB 访问 NMEA 消息。
到目前为止,我有以下概念验证代码:
<html>
<head>
<title>WebUSB Serial Sample Application</title>
</head>
<body>
<a href="#" id = "click">Connect</a><br>
<a href="#" id = "send">Send Data</a><br>
<a href="#" id = "read">Read Data</a><br>
<script>
let y;
let device;
var connectButton = document.getElementById('click')
connectButton.addEventListener('click', function() {
navigator.usb.requestDevice({
filters: [{}]
}).then((selectedDevice) => {
device = selectedDevice;
return device.open()
.then(() => device.selectConfiguration(1))
.then(() => device.claimInterface(device.configuration.interfaces[0].interfaceNumber))
.then(() => device.selectAlternateInterface(device.configuration.interfaces[0].interfaceNumber, 0))
.then(() => {
y = device;
})
});
})
var sendButton = document.getElementById('send')
var sendDecoder = new TextDecoder()
sendButton.addEventListener('click', async () => {
y.controlTransferOut({
requestType: 'class',
recipient: 'interface',
request: 0x22,
value: 0x01,
index: 0x00});
y.controlTransferIn({
requestType: 'standard',
recipient: 'device',
request: 0x06,
value: 0x0302,
index: 0x409
}, 255)
.then(result => {
let decoder = new TextDecoder()
console.log(sendDecoder.decode(result.data));
console.log('sent req');
}).catch(error => {
console.log(error);
});
});
</script>
</body>
</html>
transferOut 语句允许我从设备中读取供应商名称。所以,我知道我已经连接并且可以与之通信。我只是不知道从设备访问 lat/lon 需要什么特定命令。
更新:
下面是设备配置信息的快照
为了实现您的目标,您需要了解几个层次。首先是设备实现的USB接口。
在您发布的示例代码中,有两个向设备发送命令的调用。第一个是 controlTransferOut(),它向设备发送标准 USB CDC-ACM SET_CONTROL_LINE_STATE 请求 (0x22) 以启用 DTR 信号 (0x01)。如果您的设备实现了 USB CDC-ACM 协议,那么这就是写入操作,因为它向设备发出主机软件已准备好接收数据的信号。如果您的设备未实现此协议,则该命令将被忽略或失败。您已经声明了第一个接口,要了解接口实现的 USB 协议,您应该检查 device.configuration.interfaces[0].alternates[0].interfaceClass
和 device.configuration.interfaces[1].alternates[0].interfaceClass
。 USB CDC-ACM 设备将有一个接口 class 2 和一个接口 class 10。Class 2 用于控制接口,而 class 10 是数据接口。如果您的设备没有这两个接口,那么它可能没有实现 USB CDC-ACM 协议,您必须先弄清楚它使用的是什么协议。
您进行的第二个调用是 controlTransferIn(),它发送标准 USB GET_DESCRIPTOR 请求 (0x06) 以从设备读取字符串描述符。传递 0x0302 要求它读取索引 2 处的字符串描述符(类型 3)。这适用于任何 USB 设备(假设索引正确),因此不会告诉您是否已经弄清楚接口支持什么协议。
假设这是一个 USB CDC-ACM 接口,那么您需要查看 device.configuration.interfaces[1].alternates[0].endpoints
并找出 IN 和 OUT 端点的端点编号。这些是您将传递给 transferIn()
和 transferOut()
以从设备发送和接收数据的内容。
一旦你弄清楚了所有这些,你就需要弄清楚如何让设备开始发送 NMEA 消息。如果你幸运的话,在默认模式下它会自动发送它们,你可以开始调用 transferIn()
来接收它们。否则,您将不得不弄清楚向设备发送什么命令以将其置于正确的模式。如果您有该设备的文档或用支持该设备的其他语言编写的示例代码,那么这将非常有助于解决这个问题。
我终于解决了这个问题。答案(无论如何对我来说)是购买一个实现 CDC-ACM 接口的不同 GPS 接收器,因为似乎有更多示例和更好的文档适用于此协议。
以下概念验证代码正在运行:
<html>
<head>
<title>WebUSB Serial Sample Application</title>
</head>
<body>
<a href="#" id = "click">Connect</a><br>
<a href="#" id = "read">Read Data</a><br>
<script>
let y;
let device;
var connectButton = document.getElementById('click')
connectButton.addEventListener('click', function() {
navigator.usb.requestDevice({
filters: [{}]
})
.then((selectedDevice) => {
device = selectedDevice;
return device.open();
})
.then(() => device.selectConfiguration(1))
.then(() => device.claimInterface(device.configuration.interfaces[0].interfaceNumber))
.then(() => device.claimInterface(device.configuration.interfaces[1].interfaceNumber))
.then(() => device.selectAlternateInterface(device.configuration.interfaces[0].interfaceNumber, 0))
.then(() => device.selectAlternateInterface(device.configuration.interfaces[1].interfaceNumber, 0))
.then(() => {
y = device;
})
})
var readButton = document.getElementById('read')
var readDecoder = new TextDecoder()
var readLoop = () => {
y.transferIn(2,64)
.then(result => {
let decoder = new TextDecoder()
console.log(readDecoder.decode(result.data.buffer));
readLoop();
}).catch(error => {
console.log(error);
});
};
readButton.addEventListener('click', async () => {
readLoop();
});
</script>
</body>
</html>