Public Access
The documentation had kept up feature page by feature page and nowhere else. Now also: - the home page's App cards (notes of any size, pictures, sharing) and its note (the Shell, the VPN, the screenshot key); - the guide: VPN in the Status Bar and in Settings, the three keys that work everywhere, screenshots of the Shell, a picture, sharing, the VPN page and the help panel; - three how-tos: move files with your phone, set up the VPN, take a screenshot; where the files are and what things cost in memory; - the FAQ: screenshots, and what listens on the network; - the README's opening: what the firmware does today; - the glossary: Tunnel, Sharing, Screenshot; - every milestone's status line, with the version each thing shipped in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
64 lines
4.2 KiB
Markdown
64 lines
4.2 KiB
Markdown
+++
|
|
title = "Files, screenshots and the SD card"
|
|
description = "Copy files to and from the card, take a screenshot, fetch a core dump and restart the device, all over Wi-Fi, with checksums."
|
|
weight = 3
|
|
[extra]
|
|
tag = "Console"
|
|
+++
|
|
|
|
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.
|
|
|
|
**Without a PC,** the device does both by itself now: <kbd>Fn</kbd> + <kbd>p</kbd> saves a screenshot to the card ([how-to](/howto/screenshot/)), and <kbd>w</kbd> in the Storage App serves the card to a browser ([how-to](/howto/phone-files/)). What follows is the scripted way, with checksums.
|
|
|
|
## `get`: card to PC
|
|
|
|
```sh
|
|
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
|
|
|
|
```sh
|
|
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 answers `put: ready <size>` or `put: 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 `.part` file**, 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`, or `put: 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
|
|
|
|
```sh
|
|
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](/guide/) and the [devlog](/devlog/), were taken this way.
|
|
- **With a number, it saves to the card instead:** `screenshot 5` (or `screenshot 0`) writes a PNG to `/screenshots` on the SD card after that many seconds, as the [Shell](/guide/shell/) does. A bare `screenshot` over the console is the binary one above.
|
|
- Its main use is in a loop: send a key, wait a moment, take a screenshot, look. See [Drive the UI](/dev/debug/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](/dev/debug/crashes/).
|
|
|
|
## `reset`: restart now
|
|
|
|
```sh
|
|
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.)
|