Files, screenshots and the SD card
Copy files to and from the card, take a screenshot, fetch a core dump and restart the device, all over Wi-Fi, with checksums.
These are the binary commands: a text header line, then raw bytes. The console task answers them itself, so they keep working when the main loop is stuck. scripts/rdbg.py handles each one on the PC side; the protocol is given too, for your own tools.
get: card to PC
scripts/rdbg.py get /gnss/tracks/20261004-142530.gpx # saved here, under its own name
scripts/rdbg.py get /captures/lora/capture.pcap my-capture.pcap
The device answers get: data <size>, then exactly <size> bytes, then get: end. A path it cannot open (missing, or a folder) gives get: error cannot open <path>. The script prints the size and the speed.
put: PC to card
scripts/rdbg.py put roro9stack-v0.12.0.ota # to /updates/roro9stack-v0.12.0.ota
scripts/rdbg.py put notes.txt /notes/from-the-pc.txt # to a path you choose
The default destination is /updates/<name>, so this is also the way to install an update from the SD card without touching the device: put the .ota file, then scripts/rdbg.py install /updates/<name>.
The device does a few things you want from a file transfer:
- the PC sends the size and the SHA-256 first (
put <path> <size> <sha256>); the device answersput: ready <size>orput: error <why>(no card, not enough space: it wants the size plus 64 KB free, or a path or size it refuses); - it writes to a temporary
.partfile, creating missing folders, and only renames it into place after the whole file has been read back from the card and its SHA-256 matches: the checksum covers what is on the card, not what arrived; - a write the card refuses is retried up to 3 times, cutting the file back to the last good byte, and gives up rather than leave a hole in the middle;
- it ends with
put: done <path> <size> B, orput: error <why>and a closed connection (so the rest of the file is never read as commands). A failed transfer leaves nothing on the card.
Speed is about 300 KB/s. The same transfer exists over USB serial, for a device with no Wi-Fi: scripts/sd_put.sh <file> [card path] (about 30 seconds for 1.6 MB, with the card left in).
screenshot: the screen as a PNG
scripts/rdbg.py screenshot ui.png # 480x270: the 240x135 screen at 2x
The device sends screenshot: rgb332 <width> <height> and then one byte per pixel: the frame the UI composed off-screen, in RGB332 (RRRGGGBB), the way M5GFX stores an 8-bit sprite. The script expands it and doubles it into a PNG.
- It is read as it stands, while the UI may be drawing, so it can tear. It is for looking at, not for pixel-exact comparison.
- It is the real thing: the screenshots on this site, in the user guide and the devlog, were taken this way.
- Its main use is in a loop: send a key, wait a moment, take a screenshot, look. See Drive the UI.
coredump get: the crash dump
The raw contents of the core dump partition: coredump: data <size>, the bytes, coredump: end, or coredump: none. scripts/rdbg.py coredump fetches and decodes it in one go: see Crashes and Safe Mode.
reset: restart now
scripts/rdbg.py reset
The console prints debug: restarting now and restarts the chip after a moment. It does not go through the main loop, so it works when the loop is stuck. (The text command reboot does go through the main loop: a clean restart. boot other restarts into the other app slot: a manual rollback.)