Files
MeshCore-Solo/tools
JakubandClaude Opus 5.5 c5bb4752d0 feat: per-contact actions, device settings, a companion CLI and your contact's QR code
- Nodes: telemetry permissions per contact, reset path, share nearby
  (L1 options menu; L2 node card with "Can ask for" switches)
- Settings > Privacy: fixed position (typed in, from a waypoint, cleared)
  and the Bluetooth PIN; Settings > System: factory reset, asked twice
- Companion CLI (CMD_RUN_CLI_COMMAND 66 / RESP_CODE_CLI_REPLY 29, as
  upstream; FIRMWARE_VER_CODE 14): upstream's command names plus a key for
  every schema setting (get / set / keys)
- Screenshots move to 0x7E; tools/screenshot.py falls back to 66 / 29
- Your contact as a QR code (meshcore://contact/add): Status > System on
  ui-new, Settings > About on the L2; Nayuki's qrcodegen made header-only

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:59:35 +02:00
..

Host-side tools

Helper scripts that run on your computer, not on the device.

Tool Purpose
screenshot.py capture the device display over USB serial and save it as a PNG
trail_export.py capture a GPX track from the device over USB serial
gpx-downloader/index.html the same GPX capture in a browser, via Web Serial
bdf2gfx.py convert a BDF bitmap font to an Adafruit-GFX header

Python dependencies are managed with uv — run the scripts with uv run tools/<script>.py from the repository root.

Tip

The USB tools on the Solo site do both screenshots and GPX export with nothing to install (Chrome or Edge), and are the easiest option for most people. The scripts here are the offline equivalents.

Important

USB serial is suspended while a BLE connection is active, so disconnect the companion app from BLE before using any of these. If the app is connected over USB, disconnect it too — the raw stream would otherwise disrupt its frame protocol.


Display screenshot

All solo firmware environments are built with -D ENABLE_SCREENSHOT, so no special build is needed. On other environments (repeater, room server, the non-solo companion builds) add the flag yourself:

PLATFORMIO_BUILD_FLAGS="-D ENABLE_SCREENSHOT" pio run -e <env> -t upload

Usage:

  1. Connect the device over USB, with no companion app attached

  2. Run the tool:

    uv run tools/screenshot.py
    

    Options:

    • --port PORT — serial port to use (default: auto-detect)
    • --scale SCALE — upscale factor for the output image (1 = none; default: 1)
  3. Press S in the tool's interactive menu to capture

  4. The PNG lands in tools/pngs/ with a timestamped filename

How it works:

  • The tool sends CMD_GET_SCREENSHOT (66) to the device
  • The device replies with RESP_CODE_SCREENSHOT (29) carrying the framebuffer
  • The framebuffer arrives in chunks (a 128 × 64 display is 1024 bytes, split across several frames), which the tool reassembles into a PNG
  • A colour screen (Wio Tracker L2) sends a freshly rendered frame as RGB565 (display type 2): 320 × 240 is 150 KB, about a second over USB

GPX trail export

  1. Connect the device over USB, with no companion app attached

  2. Start the listener:

    uv run tools/trail_export.py
    

    Options:

    • --port PORT — serial port to use (default: auto-detect)
    • --out OUT — output file (default: a timestamped file in tools/gpx/)
  3. On the device: Tools › Trail › Hold Enter › Export (live) or Export (saved)

  4. The script captures the GPX 1.1 XML stream and writes it to disk


Font conversion

uv run tools/bdf2gfx.py <font.bdf> <first_hex> <last_hex> <VarPrefix> > out.h

Emits a contiguous glyph table over the given codepoint range, with empty placeholders for codepoints the BDF does not define, so the renderer can index by cp - first. This is how src/helpers/ui/MiscFixedFont.h — the unified 6×9 Latin/Greek/Cyrillic display font — was generated from 6x9.bdf.