How to Deploy 65 WASM Edge Modules on ESP32 Using WASM3 Runtime with RuView

Deploy 65 WebAssembly edge modules to an ESP32-S3 by compiling them to wasm32-unknown-unknown, flashing the WASM3-enabled firmware, and uploading binaries via the HTTP API on port 8032.

RuView provides a Tier-3 programmable-sensing layer that runs hot-loadable WASM edge modules directly on ESP32-S3 microcontrollers using the lightweight WASM3 interpreter. This architecture allows you to deploy up to 65 distinct edge modules—such as the reference "6S" collection including sig_flash_attention and spt_micro_hnsw—for sub-5 millisecond on-device inference without rebooting the hardware.


Build WASM Edge Modules for ESP32 Deployment

Install the WASM32 Target

Before compiling the RuView edge modules, add the WebAssembly target to your Rust toolchain:

rustup target add wasm32-unknown-unknown

Compile the Edge Module Collection

RuView organizes its 65 WASM modules within the wifi-densepose-wasm-edge crate. Build the entire collection or specific subsets using Cargo:

cargo build \
    --release \
    --package wifi-densepose-wasm-edge \
    --target wasm32-unknown-unknown

The compiler outputs .wasm binaries to:


target/wasm32-unknown-unknown/release/

Key modules in the 6S reference set include:


Flash ESP32 Firmware with WASM3 Runtime

Enable WASM Support in ESP-IDF

The RuView firmware located in firmware/esp32-csi-node requires the WASM3 component. Enable it via menuconfig:

cd firmware/esp32-csi-node

idf.py menuconfig

# Navigate to: Component config → WASM3 → Enable (CONFIG_WASM_ENABLE=y)

The WASM3 interpreter is fetched and compiled via components/wasm3/CMakeLists.txt, which pulls the upstream source and links it into the ESP32 image.

Build and Flash the Firmware

Compile the firmware and flash it to the ESP32-S3:

idf.py build flash monitor

Critical runtime components include:

  • main/wasm_runtime.c – Initializes the WASM3 environment, allocates 160 KB PSRAM arenas per module slot, and dispatches process_frame calls at approximately 20 Hz
  • main/wasm_upload.c – Implements the HTTP REST API on port 8032 for module management

After flashing, the device listens for WASM uploads on TCP port 8032.


Deploy WASM Modules to the ESP32 Edge

Upload Binaries via HTTP API

RuView exposes a lightweight HTTP API for hot-loading modules. You can deploy using the provided Python helper or manual curl commands.

Using the Python deployment script:

python scripts/esp32_wasm_test.py \
    --port /dev/ttyUSB0 \
    --modules \
        target/wasm32-unknown-unknown/release/sig_flash_attention.wasm \
        target/wasm32-unknown-unknown/release/sig_coherence_gate.wasm \
        target/wasm32-unknown-unknown/release/spt_micro_hnsw.wasm \
        target/wasm32-unknown-unknown/release/spt_spiking_tracker.wasm \
        target/wasm32-unknown-unknown/release/tmp_pattern_sequence.wasm \
        target/wasm32-unknown-unknown/release/tmp_goap_autonomy.wasm

Manual upload with curl:

ESP_IP="192.168.1.42"
ESP_PORT="8032"

for module in sig_flash_attention sig_coherence_gate spt_micro_hnsw \
              spt_spiking_tracker tmp_pattern_sequence tmp_goap_autonomy; do
    curl -X POST "http://${ESP_IP}:${ESP_PORT}/wasm/upload?name=${module}" \
         -H "Content-Type: application/octet-stream" \
         --data-binary @target/wasm32-unknown-unknown/release/${module}.wasm
done

Start and Manage Modules

After uploading, activate individual modules using the start endpoint:


# Start a specific module

curl -X POST "http://${ESP_IP}:${ESP_PORT}/wasm/start?name=sig_flash_attention"

# Verify running modules

curl http://${ESP_IP}:${ESP_PORT}/wasm/list

The list endpoint returns JSON metadata:

{
  "modules": [
    {"name": "sig_flash_attention", "size": 12345, "status": "running"},
    {"name": "spt_micro_hnsw", "size": 9876, "status": "running"}
  ]
}

To stop or remove modules:


# Stop a module

curl -X POST "http://${ESP_IP}:${ESP_PORT}/wasm/stop?name=sig_flash_attention"

# Delete a module

curl -X POST "http://${ESP_IP}:${ESP_PORT}/wasm/delete?name=sig_flash_attention"

Runtime Architecture and Memory Constraints

RuView’s WASM3 integration enforces strict resource budgets suitable for ESP32-S3 constraints. Each deployed module operates within a 160 KB PSRAM arena allocated by wasm_runtime.c, ensuring isolation between the 65 potential edge modules.

The runtime invokes each module’s process_frame function at the DSP tick rate (approximately 20 Hz). Latency annotations in the source code—such as "Budget: S (< 5 ms)" in sig_flash_attention.rs—guarantee that modules complete inference within their allocated time slices. The WASM3 interpreter’s Tier-3 classification indicates these are hot-loadable, sandboxed algorithms that execute directly on the edge device without cloud dependency.

Host API functions exposed to WASM modules include csi_get_frame for accessing pre-processed CSI data and csi_emit_event for publishing results back to the RuView pipeline, as implemented in the runtime glue layer.


Summary

  • RuView enables deployment of 65 WASM edge modules on ESP32-S3 microcontrollers using the WASM3 interpreter for sub-5 ms on-device inference.
  • Build modules by compiling the wifi-densepose-wasm-edge crate to wasm32-unknown-unknown and locating outputs in target/wasm32-unknown-unknown/release/.
  • Flash firmware from firmware/esp32-csi-node with CONFIG_WASM_ENABLE=y to embed the WASM3 runtime and HTTP upload API on port 8032.
  • Deploy binaries using scripts/esp32_wasm_test.py or direct curl POST requests to /wasm/upload, then activate via /wasm/start.
  • Each module runs in an isolated 160 KB PSRAM arena with guaranteed latency budgets, invoked at 20 Hz through the process_frame host API.

Frequently Asked Questions

How many WASM modules can run simultaneously on ESP32-S3?

RuView supports up to 65 distinct WASM edge modules in the collection, with the runtime capable of loading multiple modules simultaneously depending on available PSRAM. Each active module consumes a 160 KB PSRAM arena allocated by wasm_runtime.c, so practical limits depend on your ESP32-S3’s total PSRAM capacity and the specific subset of modules deployed.

What is the maximum binary size for each WASM edge module?

While the RuView architecture does not enforce a hardcoded binary size limit, modules must fit within the 160 KB PSRAM arena allocated per slot at runtime, as defined in firmware/esp32-csi-node/main/wasm_runtime.c. Additionally, modules must adhere to their annotated latency budgets—typically sub-5 ms for standard modules and sub-2 ms for lightweight gates—to maintain the 20 Hz DSP tick rate.

Can I hot-swap WASM modules without rebooting the ESP32?

Yes. The HTTP API implemented in firmware/esp32-csi-node/main/wasm_upload.c supports hot-loading via the /wasm/upload, /wasm/start, /wasm/stop, and /wasm/delete endpoints. You can upload new binaries, start additional modules, or replace running instances dynamically without reflashing the firmware or power-cycling the device, enabling true Tier-3 programmable sensing at the edge.

Which Rust target is required for RuView edge modules?

All RuView edge modules must compile to the wasm32-unknown-unknown target. This target produces bare-metal WebAssembly binaries without system dependencies, suitable for the WASM3 interpreter running on ESP32-S3. Add the target via rustup target add wasm32-unknown-unknown and build using cargo build --release --target wasm32-unknown-unknown as specified in docs/build-guide.md.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →