Skip to content

microbit-foundation/microbit-connection

Repository files navigation

micro:bit connection library

This documentation is best viewed on the documentation site rather than GitHub or NPM package site.

A TypeScript library for connecting to micro:bit devices via USB and Bluetooth. Works in browsers (via WebUSB and Web Bluetooth) and in native iOS/Android apps (Bluetooth only, via Capacitor).

Available on NPM. Migrating from an earlier version? See the migration guide.

Demo apps

  • Demo app (source) — WebUSB, Web Bluetooth, and Capacitor for native mobile

Projects using this library

Platform support

Feature Web (browser) Native (Capacitor)
USB connection WebUSB Not supported
Bluetooth connection Web Bluetooth iOS and Android
Flash via USB Yes Not supported
Flash via Bluetooth Not supported iOS and Android

Entrypoints

The library is split into separate entrypoints for tree-shaking. Import shared types from the root and connection-specific code from subpaths:

Import path Contents
@microbit/microbit-connection Shared types and events (ConnectionStatus, DeviceConnection, FlashOptions, etc.)
@microbit/microbit-connection/bluetooth createBluetoothConnection and Bluetooth connection types
@microbit/microbit-connection/usb createUSBConnection and USB connection types
@microbit/microbit-connection/universal-hex createUniversalHexFlashDataSource (depends on @microbit/microbit-universal-hex)
@microbit/microbit-connection/radio-bridge Experimental. createRadioBridgeConnection for radio bridge via USB. Limited service support — see JSDoc for details.

Usage

Flash a micro:bit

Instantiate a WebUSB connection using {@link @microbit/microbit-connection/usb!createUSBConnection | createUSBConnection} and use it to connect to a micro:bit.

import { createUSBConnection } from "@microbit/microbit-connection/usb";

const usb = createUSBConnection();
await usb.connect();

console.log("Connection status: ", usb.status); // "Connected"

Flash a universal hex that supports both V1 and V2:

import { createUniversalHexFlashDataSource } from "@microbit/microbit-connection/universal-hex";

await usb.flash(createUniversalHexFlashDataSource(universalHexString), {
  partial: true,
  progress: (stage, percentage) => {
    console.log(stage, percentage);
  },
});

This code will also work for non-universal hex files so is a good default for unknown hex files.

Alternatively, you can create and flash a hex for a specific micro:bit version by providing a function that takes a {@link @microbit/microbit-connection!BoardVersion} and returns a hex. This can reduce download size or help integrate with APIs that produce a hex for a particular device version. This example uses the @microbit/microbit-fs library which can return a hex based on board id.

import { MicropythonFsHex, microbitBoardId } from "@microbit/microbit-fs";

const micropythonFs = new MicropythonFsHex([
  { hex: microPythonV1HexFile, boardId: microbitBoardId.V1 },
  { hex: microPythonV2HexFile, boardId: microbitBoardId.V2 },
]);
// Add files to MicroPython file system here (omitted for simplicity)
// Flash the device
await usb.flash(
  async (boardVersion) => {
    return micropythonFs.getIntelHex(microbitBoardId[boardVersion]);
  },
  {
    partial: true,
    progress: (stage, percentage) => {
      console.log(stage, percentage);
    },
  },
);

Post-flash connection state

The connection state after flashing differs between USB and Bluetooth because they connect to different parts of the micro:bit hardware:

  • USB connects to the interface chip (running DAPLink firmware), which is separate from the application processor that runs user code. Flashing does not affect the interface chip, so the USB connection remains in "Connected" state and serial communication is automatically reinitialised.

  • Bluetooth connects directly to the application processor (the Nordic nRF51/nRF52 running the user's program and BLE stack). This processor reboots after flashing, so the Bluetooth connection is necessarily lost. The connection is always left in "Disconnected" state and callers must call connect() again after flashing.

Tab visibility and the Paused state

By default, a USB connection is automatically paused when the browser tab becomes hidden and reconnected when the tab becomes visible again. This frees the USB interface for other tabs or processes while the user isn't looking at the page. During this time the connection status is "Paused".

If reconnection fails when the tab becomes visible again (for example, because another process has claimed the USB interface), the connection transitions to "Disconnected".

To disable this behaviour, pass pauseOnHidden: false:

const usb = createUSBConnection({ pauseOnHidden: false });

For more examples see the demo app source.

Connect via Bluetooth

By default, the micro:bit's Bluetooth service is not enabled. Visit our Bluetooth tech site page to download a hex file that would enable the bluetooth service.

Instantiate a Bluetooth connection using {@link @microbit/microbit-connection/bluetooth!createBluetoothConnection | createBluetoothConnection} class and use it to connect to a micro:bit.

import { createBluetoothConnection } from "@microbit/microbit-connection/bluetooth";

const bluetooth = createBluetoothConnection();
await bluetooth.connect();

console.log("Connection status: ", bluetooth.status); // "Connected"

For more examples see the demo app source.

Error handling

Methods that interact with device features (reading sensors, writing to LEDs, serial communication, etc.) throw a {@link @microbit/microbit-connection!DeviceError | DeviceError} with code "not-connected" if called without an active connection:

import { DeviceError } from "@microbit/microbit-connection";

try {
  const data = await bluetooth.getAccelerometerData();
} catch (e) {
  if (e instanceof DeviceError && e.code === "not-connected") {
    console.log("Connect to a micro:bit first");
  }
}

Known limitations

Bluetooth

Open link security mode hex file already on micro:bit

Open link hex files are not common. The most common source is the micro:bit CreateAI. Known issues:

  • iOS DFU classroom collision risk with open-link firmware: When performing DFU on iOS with open-link security firmware (no bonding), the Nordic DFU library scans for the bootloader by DFU service UUID and connects to the first matching device. If multiple micro:bits are in bootloader mode simultaneously, the wrong device could be targeted. This does not affect bonded firmware (where the bootloader uses whitelist-filtered advertising) or Android (which reconnects by MAC address).

  • V1 Android PIN dialog with open-link firmware: On Android with micro:bit V1, calling createBond triggers a passkey entry dialog because the V1 DAL declares IO_CAPS_DISPLAY_ONLY even in open-link mode. The micro:bit displays a PIN that the user must enter. This is a bug in the V1 DAL (V2 correctly uses IO_CAPS_NONE). There is no BLE-visible indicator of the security mode, so the library cannot detect this situation to avoid it. On V2 you get a harmless (but somewhat pointless) "just works" pairing dialog.

No suitable services on the micro:bit to flash

  • Hex with no partial flashing or DFU control service (V1): Some older CreateAI data-collection hex files for micro:bit V1 fall into this category. There's nothing that can be done via Bluetooth. Workaround: flash via WebUSB or drag and drop from a computer. The equivalent V2 hex does have the Secure DFU service (but not partial flashing) which we support.

Hardware testing

The hardware test app is a human-in-the-loop test runner for USB flashing. It covers partial and full flash, flash fallback paths, serial data integrity after flash, and reconnection after unplug. Run it with:

cd apps/hardware-test
npm run dev

The tests prompt you for physical actions (plugging/unplugging) and verify the results automatically.

License

This software is under the MIT open source license.

SPDX-License-Identifier: MIT

We use dependencies via the NPM registry as specified by the package.json file under common Open Source licenses.

Full details of each package can be found by running license-checker:

$ npx license-checker --direct --summary --production

Omit the flags as desired to obtain more detail.

Code of conduct

Trust, partnership, simplicity and passion are our core values we live and breathe in our daily work life and within our projects. Our open-source projects are no exception. We have an active community which spans the globe and we welcome and encourage participation and contributions to our projects by everyone. We work to foster a positive, open, inclusive and supportive environment and trust that our community respects the micro:bit code of conduct. Please see our code of conduct which outlines our expectations for all those that participate in our community and details on how to report any concerns and what would happen should breaches occur.

About

JavaScript package for micro:bit web browser connectivity (WebUSB, Web Bluetooth)

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages