Skip to content

bledev.filetransfer: CircuitPython's BLE file-transfer protocol on MicroPython - #86

Merged
bdbarnett merged 3 commits into
mainfrom
bledev-filetransfer
Sep 25, 2026
Merged

bdbarnett merged 3 commits into
mainfrom
bledev-filetransfer

Conversation

@bdbarnett

@bdbarnett bdbarnett commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

A MicroPython board can now serve files over Bluetooth using CircuitPython's own BLE file-transfer protocol, so one client reaches files on either interpreter. Stacked on #85 (bledev-midi); the diff is the three commits on top.

import bledev.filetransfer
bledev.filetransfer.start(password="...", name="rack")   # files and the REPL, from main.py

What's in it

  • bledev.filetransfer: read (with an offset), write (at an offset), delete (recursive), mkdir (with parents), listdir, move, and the free-space pacing on every write. FileServer is the protocol with no radio. The board serves it as a second service on bledev.repl's server (repl.start(files=True)). There's also a client built on the bledev contract, so it runs on bleak or on a board.
  • Locked like the REPL. It's opt-in and needs the REPL's password, written to one extra characteristic (ADAF0300-…, which CircuitPython doesn't have). One attempt per connection, and a wrong password gets hung up on. Until the password arrives, every command is answered with status 0x80. Logging in to the REPL on the same connection unlocks files too.
  • File work runs on the main thread. The esp32 BLE IRQ runs in NimBLE's task, which has only a few KB of stack, and a recursive delete there crashed the T-Embed. Now the IRQ only queues the bytes, and micropython.schedule plus the REPL's 5 ms timer do the file work.

Checks

  • tests/bledev_filetransfer.py passes 104 of 104 on CPython and on unix MicroPython. It runs at MTUs 23, 185 and 247 with windows from 512 to 4096 bytes. test_bledev_filetransfer.py also plants a flipped bit and a dropped packet, and both fail the run.
  • On the T-Embed from the laptop (bleak), tests/bledev_board/files_client.py passed: no password and a wrong password were refused, 20 KB went up and down byte for byte, and read-at-offset, listdir, move and recursive delete all worked. A bit flip planted on the client side and one planted on the board side both failed the run.
  • Adafruit's own FileTransferClient also worked against FileServer in-process. That was a one-off check; the details are in the internals doc.

Measured. This is what decides whether mpftp needs this. A 20 KB file, laptop to T-Embed, with throughput connection parameters:

Up Down
file transfer 0.83 s 0.30 s
raw REPL (mpremote) 15.6 s 10.6 s

mpftp's ble:// transport uses file transfer, and falls back to the REPL when a board doesn't serve it: PyDevices/mpftp#47.

Not done

  • No CircuitPython board has been tried with bledev's client, because CircuitPython's service needs pairing and bledev doesn't pair yet.
  • A board acting as the client hasn't been run on hardware. Only one S3 was free.

…d and client

The board serves it beside the REPL (bledev.repl.start(files=True)), locked
by the REPL's password through one extra characteristic. File work runs on
the main thread: in the BLE task's few-KB stack a recursive delete crashed
the T-Embed.
Base automatically changed from bledev-midi to main September 25, 2026 05:38
@bdbarnett
bdbarnett merged commit f467130 into main Sep 25, 2026
3 checks passed
@bdbarnett
bdbarnett deleted the bledev-filetransfer branch September 25, 2026 05:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant