Getting started with Web Bluetooth

published on 08 March 2022

This post guides you through the process of reading the battery level from your phone using Web Bluetooth. So far, we published guides on Python + Bleak and Node + Noble. Web Bluetooth stands out because it uses your computer's Bluetooth hardware by way of your internet browser. This allows you to create web apps, which have all the notorious advantages associated with developing in the cloud.

Installation

Installation gets a little complicated with Web Bluetooth. Essentially, starting a web bluetooth project requires setting up a web app. Luckily, there are some bare-bones web app setup options available. If you're new to web app development, start by following this tutorial blindly. Work your way backwards based on what peaks your interest after you've completed the project. This tutorial avoids using any complex web app frameworks. Instead, it uses a 'vanilla' configuration. It uses the most basic combination of Javascript and HTML. Hopefully, the stripped down nature of the configuration makes the tutorial easy to follow.

Start off by setting up a node repository. The basis for the basic web app will be a Node packaging library called Parcel. Install the Parcell library into the project folder.

npm install --save-dev parcel

Create an index.html and index.js file in the directory. Feel free to organize them as show in this screenshot.

Screen Shot 2022-03-05 at 11.13.07 PM-iuzme

Next, create the index.html file in the project's root directory. Add the code as follows.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <title>My First Web Bluetooth App</title>
  </head>
  <body>
    <div id="app"></div>
  </body>
  <script type="module" src="src/index.js"></script>
</html>

Create an index.js file in a root/src for the directory. The code:

document.getElementById("app").innerHTML = `
<h1>Hello Wavecake!</h1>
<div>
  <button id='start button'>
    Start
  </button>
</div>
`;

var start = document.getElementById("start button");

start.addEventListener("click", async () => {
  console.log("click");
});

Return to the terminal and run another command. This runs parcel which sets up a local server.

npx parcel index.html

The page should look like this.

Screen Shot 2022-03-07 at 9.22.41 PM-b0aqf

The start button on the website should log the word 'click.' Open up the developer tools view to see the log output.

Screen Shot 2022-03-07 at 9.23.27 PM-h95lc

This webpage and the start button will serve as a sandbox for running javascript in the web browser. 

Preparing the phone

Now we need to prepare the battery service. The preparation will be different for different phones. I'll be setting this up on an iPhone. I recommend using the nRF Connect app. You can find it for Android and iPhone in the app stores. 

First, navigate to the Peripheral tab. Then, add an advertiser.

IMG_4837-ifnlw

Next, add the battery service.

IMG_4838_small-ka2ah

The peripheral tab should look like this:

IMG_4839_small-fwy4z

Last, select the switch to enable advertising the battery service.

IMG_4840_small-eoj6o

Read Battery Level

Pull the battery level code from the following example. Insert the code into the button callback function.

document.getElementById("app").innerHTML = `
<h1>Hello Wavecake!</h1>
<div>
  <button id='start button'>
    Start
  </button>
</div>
`;

var start = document.getElementById("start button");

start.addEventListener("click", async () => {
  console.log("click");
  try {
    console.log("Requesting Bluetooth Device...");
    const device = await navigator.bluetooth.requestDevice({
      filters: [{ services: ["battery_service"] }]
    });

    console.log("Connecting to GATT Server...");
    const server = await device.gatt.connect();

    console.log("Getting Battery Service...");
    const service = await server.getPrimaryService("battery_service");

    console.log("Getting Battery Level Characteristic...");
    const characteristic = await service.getCharacteristic("battery_level");

    console.log("Reading Battery Level...");
    const value = await characteristic.readValue();

    console.log("> Battery Level is " + value.getUint8(0) + "%");
  } catch (error) {
    console.log("Argh! " + error);
  }
});

When you click the start button, the webpage will read the battery level of the device you select. It will print the results in the log. The logs should match the following output.

Screen Shot 2022-03-07 at 10.04.26 PM-k9eeg

For new projects going forward, visit this site or this site from the Web Bluetooth core group for more examples.

Conclusion

The setup for web bluetooth will be strange territory for a lot of developers that are more familiar normal python or node scripting. Despite the problems with getting started, there are advantages that make it worth the effort for some use cases. Hosting the web app can make it easy to share code with team mates. Using HTML and Javascript, you can create user interfaces that feel more intuitive. Disadvantages include less permissions. Web Bluetooth can effectively manage most BLE use cases, but the permission structure takes getting used to. When you develop natively, you get hit less road blocks when it comes to searching devices.

About Wavecake

Completing the same experiment in Wavecake takes less than 1 minute. Sign up on our home page to get an invitation to the private beta.

Read more