简体   繁体   中英

Web Bluetooth: Can't pair BLE device with Mobile Device with Live Server VS Code extension

I'm a beginner in the Web Development world. I want to pair a BLE device (NRF52840 DK) with my mobile device through a web page. I tested an example for Web Bluetooth and it works fine on my PC as you can see on the following image:

Pairing my PC (Chrome) with a BLE device successfully

在此处输入图像描述

I did it through the popular extension Live Server on VS Code. When I tried to access to that page on my mobile (Android) using my IP and port, and pressed the button nothing happened.

Pairing my mobile (Chrome) with a BLE device unsuccessfully

在此处输入图像描述

Is there something that I'm not taking into consideration?

Here is the HTML & JS code:

<!DOCTYPE html>
<html>
    <head>
        <title>BLE WebApp</title>
    </head>
    <body>
        <form>
            <button>Connect with BLE device</button>
        </form>

        <script>
            var deviceName = 'Nordic_HRM'

            function isWebBluetoothEnabled() {
                if (!navigator.bluetooth) {
                    console.log('Web Bluetooth API is not available in this browser!')
                    return false
                }
                return true
            }

            function getDeviceInfo() {
                let chosenHeartRateService = null;
            
                console.log('Requesting Bluetooth Device...')
                navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
                .then(device => device.gatt.connect())
                .then(server => {
                    console.log("Getting HR Service…")
                    return server.getPrimaryService('heart_rate');
                })
                .then(service => {
                    chosenHeartRateService = service;
                    return Promise.all([
                        service.getCharacteristic('heart_rate_measurement')
                        .then(handleHeartRateMeasurementCharacteristic),
                    ]);
                })
            }

            function handleHeartRateMeasurementCharacteristic(characteristic) {
            return characteristic.startNotifications()
            .then(char => {
                characteristic.addEventListener('characteristicvaluechanged',
                                                onHeartRateChanged);
            });
            }

            function onHeartRateChanged(event) {
                const characteristic = event.target;
                console.log(parseHeartRate(characteristic.value));
            }

            function parseHeartRate(data) {
                const flags = data.getUint8(0);
                const rate16Bits = flags & 0x1;
                const result = {};
                let index = 1;
                if (rate16Bits) {
                    result.heartRate = data.getUint16(index, /*littleEndian=*/true);
                    index += 2;
                } else {
                    result.heartRate = data.getUint8(index);
                    index += 1;
                }
                const contactDetected = flags & 0x2;
                const contactSensorPresent = flags & 0x4;
                if (contactSensorPresent) {
                    result.contactDetected = !!contactDetected;
                }
                const energyPresent = flags & 0x8;
                if (energyPresent) {
                    result.energyExpended = data.getUint16(index, /*littleEndian=*/true);
                    index += 2;
                }
                const rrIntervalPresent = flags & 0x10;
                if (rrIntervalPresent) {
                    const rrIntervals = [];
                    for (; index + 1 < data.byteLength; index += 2) {
                    rrIntervals.push(data.getUint16(index, /*littleEndian=*/true));
                    }
                    result.rrIntervals = rrIntervals;
                }
                return result;
            }

            document.querySelector('form').addEventListener('submit', function(event) {
                event.stopPropagation()
                event.preventDefault()
            
                if (isWebBluetoothEnabled()) {
                    getDeviceInfo()
                }
            })
        </script>
    </body>
</html>

I don't think it's possible in the way you describe it. Web Bluetooth only works on pages which has HTTPS enabled. It works on localhost too for testing purposes. Since you access the web application via an IP-address which doesn't have HTTPS enabled, Web Bluetooth is not available.

https://web.dev/bluetooth/#https-only

You can test this by adding a text to the page with a boolean or other text which will show if web bluetooth is available.

function isWebBluetoothEnabled() {
    if (!navigator.bluetooth) {
        console.log('Web Bluetooth API is not available in this browser!')
        document.getElementById('bluetoothState').innerText = 'Not available'
        return false
    }
    document.getElementById('bluetoothState').innerText = 'Available'
    return true
}

use mkcert to create a certificate usage:

mkcert 127.0.0.1 localhost 0.0.0.0 192.168.0.X

use the files generated to add it to settings.json file in.vscode directory (create if doesn't exist)

{
    "liveServer.settings.https": {
        "enable": true,
        "cert": "/full/path/to/file/192.168.0.108+3.pem",
        "key": "/full/path/to/file/192.168.0.108+3-key.pem",
        "passphrase": ""
    }
}

this will create a warning once due to the nature of self signed certificates, but it'll make sure almost all features of https work. The issue I faced using this method is that it is considered not secure enough to install a PWA on a local device by chrome.

@Joey yes, web bluetooth can only be accessed on HTTPS enabled sites. I am working on a web app and it is hosted on heroku. I am facing the similar problem. i can access web Bluetooth on my PC when accessing the site, but cannot when I access the site on my android phone (Oneplus 7T with chrome version 79). Do you have any idea why it is so?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM