Skip to main content

Python package for OTA updating the bootloader on nrf chips

Project description

Tests PyPI Python Version

nrf-ota

Flash firmware to Nordic nRF5x devices over BLE from Python. Implements the Nordic Legacy DFU protocol (nRF5 SDK ≤ 15.x) and works on Linux, macOS, and Windows.

Installation

pip install nrf-ota

CLI

No install required — run directly with uvx:

uvx nrf-ota firmware.zip                                  # interactive device picker
uvx nrf-ota https://example.com/firmware.zip              # download then flash
uvx nrf-ota firmware.zip --device OD216205                # select by name
uvx nrf-ota firmware.zip --device FC:06:1C:C8:DE:47       # select by address

Accepts a local ZIP path or an HTTP(S) URL. Scans for nearby BLE devices, lets you pick one, and flashes the firmware. If the device is running application firmware the bootloader is triggered automatically.

Library

import asyncio
from nrf_ota import perform_dfu, scan_for_devices

async def main():
    devices = await scan_for_devices(timeout=5.0)

    # local file
    await perform_dfu("firmware.zip", devices[0], on_progress=lambda pct: print(f"\r{pct:.0f}%", end=""))

    # or a URL — downloads and flashes in one call
    await perform_dfu("https://example.com/firmware.zip", devices[0])

asyncio.run(main())

API

perform_dfu(zip_path, device, *, on_progress=None, on_log=None, packets_per_notification=...)

Performs a full OTA update — triggers the bootloader if needed, waits for the device to reboot into DFU mode, transfers the firmware, and activates it.

Parameter Type Description
zip_path str | DFUZipInfo Local path, HTTP(S) URL, or pre-parsed DFUZipInfo
device BLEDevice | str Device from scan_for_devices, or a raw Bluetooth address
on_progress Callable[[float], None] Called with percentage (0–100) as firmware is sent
on_log Callable[[str], None] Called with status messages
packets_per_notification int Packets sent per receipt notification. Default: 8 on macOS, 10 elsewhere.

Raises DFUError on failure, DeviceNotFoundError if the bootloader can't be found after reboot.

DFUZipInfo

Named tuple returned by parse_dfu_zip. Can be passed directly to perform_dfu to skip re-parsing:

from nrf_ota import perform_dfu, parse_dfu_zip

info = parse_dfu_zip("firmware.zip")
print(f"{info.bin_file}  {len(info.firmware):,} bytes")
await perform_dfu(info, device)

scan_for_devices(timeout=5.0) -> list[BLEDevice]

Scans for nearby named BLE devices and returns a list of bleak.BLEDevice objects.

Exceptions

Exception Description
DFUError Base exception for all DFU failures
DeviceNotFoundError Bootloader not found after reboot

Platform notes

Works on Linux, macOS, and Windows via bleak. On macOS, the default packets_per_notification is lowered to 8 (from 10) to stay within CoreBluetooth's write-without-response flow control limits.

Development

git clone https://github.com/OpenDisplay-org/nrf-ota.git
cd nrf-ota
uv sync --all-extras

uv run pytest tests/ -v
uv run ruff check .
uv run mypy src/nrf_ota

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nrf_ota-0.3.0.tar.gz (76.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nrf_ota-0.3.0-py3-none-any.whl (22.0 kB view details)

Uploaded Python 3

File details

Details for the file nrf_ota-0.3.0.tar.gz.

File metadata

  • Download URL: nrf_ota-0.3.0.tar.gz
  • Upload date:
  • Size: 76.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nrf_ota-0.3.0.tar.gz
Algorithm Hash digest
SHA256 d0010efbb193057cbf0921cb748056b482c16445638a2f6fd9560d96ec9b2dea
MD5 2a45371284ae29a1326c8cc7ea0a952f
BLAKE2b-256 64c5ecdb03b45f0d64d43894898120a775a9bd77ba6d8fc56cd1cbb5a142e7d3

See more details on using hashes here.

Provenance

The following attestation bundles were made for nrf_ota-0.3.0.tar.gz:

Publisher: release.yml on OpenDisplay-org/nrf-ota

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nrf_ota-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: nrf_ota-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 22.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nrf_ota-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f4eaf7a3f05974c4430b640782eaae98d0d36bdef60e118db00d70309722de01
MD5 ae3ad63474804e784c70f7e2eadf142d
BLAKE2b-256 dcda5141bc9288a46a133e7644e188dc2c667b2e23f90a59003b6ca043c1d6a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for nrf_ota-0.3.0-py3-none-any.whl:

Publisher: release.yml on OpenDisplay-org/nrf-ota

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page