R2P2ESP32

File Transfer

Three ways to get files onto the device — from the Web Terminal, with a Rake task, or baked into the build.

There are three ways to get files onto the device:

  • With the Web Terminal — upload from the browser over an existing connection, without rebuilding or reflashing anything.
  • With a Rake task — upload (or download) from your host’s command line, also without rebuilding or reflashing anything.
  • At build time — place files under the project’s storage/ directory before building, so they’re baked into the firmware image itself.

With the Web Terminal

Use the Web Terminal’s File Editor (or any serial connection) — like uploading hello.rb in Quick Start. Fast to iterate with, but whatever you upload this way is lost if you erase and reflash the device.

With a Rake task

rakelib/picomodem.rake provides tasks that transfer files over the serial connection from your host’s command line, using the PicoModem client that ships with picoruby-picomodem. It runs on the host picoruby built by rake setup_<target> (or the one named by the PICORUBY environment variable, or one on your PATH).

# Upload: REMOTE defaults to LOCAL's basename
rake "picomodem:put[hello.rb,/home/hello.rb]"

# Download: LOCAL defaults to REMOTE's basename
rake "picomodem:get[/home/hello.rb,hello.rb]"
  • Quote the task name so your shell doesn’t interpret the [...].
  • Set PORT to choose the serial port, as with rake flash (the client’s default is /dev/ttyACM0), e.g. PORT=/dev/ttyUSB0 rake "picomodem:put[...]".
  • The device’s shell must be sitting at its prompt, and no other program (such as a serial monitor or the Web Terminal) may hold the port.

Like the Web Terminal, this is lost if you erase and reflash the device.

At build time

The storage/ directory at the project root becomes the device’s own filesystem. It currently has two subdirectories:

storage/
├── etc/
└── home/

At build time, main/CMakeLists.txt packs the entire storage/ directory into a LittleFS image via littlefs_create_partition_image, targeting the storage partition defined in partitions.csv (1 MB). Because that call includes FLASH_IN_PROJECT, idf.py flash (and rake flash, see Flash and Monitor) writes this image alongside the app automatically — no separate step needed.

On boot, main_task.rb mounts it as the root volume:

Shell.setup_root_volume(:flash, label: 'storage')

From there, storage/home becomes /home and storage/etc becomes /etc in the running picoruby-shell — the same /home/hello.rb path you saw in Quick Start.

This is useful for shipping a default /home/app.rb (see mrblib/main_task.rb — it auto-loads /home/app.mrb or /home/app.rb if present) or committing configuration your firmware depends on.

Example: WiFi auto-connect config

rake gen_wifi_config (see Enabling WiFi) writes an encrypted storage/etc/network/wifi.yml, which main_task.rb reads on boot to auto-connect — a concrete example of the build-time approach above.

Careful: because the storage image is built with FLASH_IN_PROJECT, the default rake flash (see Flash and Monitor) rewrites it along with the app — any files you uploaded at runtime (via the Web Terminal or Rake task) are replaced with whatever is currently in your local storage/ directory. To update just the app and leave on-device storage alone, use rake flash_factory instead, which only touches the factory/app partition.