gpsnmeawebusb

Reading GPS Receiver using WebUSB


I am trying to use WebUSB to read GPS coordinates from a USB-connected GPS receiver from within javascript.

I have been able to connect to the receiver; however, I am unsure how to use WebUSB to access the NMEA messages.

So far, I have the following proof-of-concept code:

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

The transferOut statement allows me to read the Vendor name from the device. So, I know I'm connected and can communicate with it. I just don't know what specific command(s) are needed to access the lat/lon from the device.

UPDATE: Below is a snapshot of the device config info enter image description here


Solution

  • I have finally solved this problem. The answer (for me, anyway) was to purchase a different GPS receiver that implemented the CDC-ACM interface since there seems to be more examples and better docs for this protocol.

    The following proof-of-concept code is working:

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