【问题标题】:Reading GPS Receiver using WebUSB使用 WebUSB 读取 GPS 接收器
【发布时间】:2021-02-05 23:52:29
【问题描述】:

我正在尝试使用 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 语句允许我从设备中读取供应商名称。所以,我知道我已经连接并且可以与之通信。我只是不知道从设备访问纬度/经度需要哪些特定命令。

更新: 下面是设备配置信息的快照

【问题讨论】:

    标签: gps nmea webusb


    【解决方案1】:

    为了实现您的目标,您需要了解几个层次。首先是设备实现的USB接口。

    在您发布的示例代码中,有两个调用向设备发送命令。第一个是 controlTransferOut(),它将标准 USB CDC-ACM SET_CONTROL_LINE_STATE 请求 (0x22) 发送到设备以启用 DTR 信号 (0x01)。如果您的设备实现了 USB CDC-ACM 协议,那么这是要执行的写入操作,因为它会向设备发出主机软件已准备好接收数据的信号。如果您的设备未实现此协议,则该命令将被忽略或失败。您已经声明了第一个接口,要了解该接口实现的 USB 协议,您应该检查device.configuration.interfaces[0].alternates[0].interfaceClassdevice.configuration.interfaces[1].alternates[0].interfaceClass。 USB CDC-ACM 设备将有一个 2 类接口和一个 10 类接口。2 类用于控制接口,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() 来接收它们。否则,您将不得不弄清楚向设备发送什么命令以使其处于正确模式。如果您有该设备的文档或以支持该设备的其他语言编写的示例代码,那么这将非常有助于弄清楚这一点。

    【讨论】:

    • 谢谢赖利。我只有一个接口和 class=255;因此,它不是 USB CDC-ACM 设备。 GPS 似乎正在使用 Prolific PL2303 芯片组……我在 StackOverflow 的其他地方发现了它。但是,使用其中一些示例代码(例如stackoverflow.com/questions/51605886/…)仍然不起作用。当我调用 transferIn ...时,一切都挂起,我再也没有收到 Promise。
    • 这样的调用不应该像那样冻结,而是返回一个 Promise。如果准确,那是一个非常严重的错误。你能用你的示例代码在 crbug.com 上打开一个问题吗?
    • 不确定我需要发送什么命令,因为该设备不使用 USB CDC-ACM。该设备是 GlobalSat (bu-353-s4) 的 GPS 接收器。它使用 Prolific PL2303 芯片组。在我选择一个配置后,声明唯一的接口并选择唯一的备用接口(alternates[0]),对端点 0(“in”,“interrupt”)的 transferIn 调用返回......但是“then”和“catch”语句永远被执行。当我尝试将 transferIn 发送到端点 3(显示为“bulk”和“in”)时,我得到 DOMException: The specified endpoint is not part of a claim and selected alternate interface。
    【解决方案2】:

    我终于解决了这个问题。答案(对我来说,无论如何)是购买一个不同的 GPS 接收器来实现 CDC-ACM 接口,因为这个协议似乎有更多的例子和更好的文档。

    以下概念验证代码正在运行:

    <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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-14
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多