Firmware Architecture
Relevant source files
The following files were used as context for generating this wiki page:
The Muse Gadget firmware architecture provides a robust system for connecting ESP32-compatible hardware to the Muse cloud infrastructure. It manages encrypted communication sessions, handles hardware-specific peripherals like displays and LEDs, and provides a command dispatch system for remote interaction.
The firmware operates on the ESP-IDF v6.0.1 framework and utilizes a multi-tasking approach to separate concerns between network management, cloud synchronization, and user interface updates.
Sources: AGENTS.md:25-28, app.c:1340-1345, README.md:126-128
Core System Components
The firmware is structured into several key modules that interact to maintain the gadget's state and connectivity.
| Component | Responsibility |
|---|---|
App Logic (app.c) | Coordinates high-level state transitions, pairing, and overall system initialization. |
Noise Control (noise_control.cpp) | Manages the encrypted Noise protocol session, WebSocket framing, and daemon communication. |
LED/Status (led_status.c) | Drives visual feedback via RGB LEDs or on-screen status bars and animations. |
Wi-Fi Manager (wifi_mgr.c) | Handles Wi-Fi scanning, connection persistence, and channel hinting. |
BLE Server (ble_server.c) | Provides the interface for initial provisioning and developer mode interactions. |
Sources: app.c:1340-1480, noise_control.cpp:89-105, led_status.c:750-780, CMakeLists.txt:18-42
System Task Flow
The following diagram illustrates the initialization and main loop sequence of the firmware.
This diagram shows the path from boot to the steady-state heartbeat loop.
Sources: app.c:1340-1530, noise_control.cpp:1085-1110
Communication and Security
Communication with the Muse backend (typically hatch.metaaivm.com) is established over a WebSocket connection secured by the Noise protocol. This ensures that all data, including home-network tunnel traffic and remote commands, is encrypted.
Noise Session Establishment
The noise_control module performs a multi-step handshake to establish a secure link.
- TLS Connect: Establishes a standard TLS link to the backend on port 443.
- WebSocket Upgrade: Sends an HTTP request with an Authorization bearer token to upgrade the connection to a WebSocket.
- Noise Handshake: Performs a 3-message Noise protocol handshake (Initiator -> Responder -> Initiator) to establish encryption keys.
- Link Registration: Sends a
link.registerJSON message to identify the node and its capabilities to the daemon.
Sources: noise_control.cpp:92-95, noise_control.cpp:325-340, noise_control.cpp:465-510, noise_control.cpp:590-630
Command Dispatch System
Remote commands from Muse are received as JSON objects and dispatched through on_ws_command.
This diagram demonstrates the asynchronous command execution pattern used for long-running operations like network discovery or image fetching.
Sources: noise_control.cpp:830-860, app.c:1130-1160, AGENTS.md:316-325
Hardware Abstraction and UI
The firmware supports a wide variety of boards through an overlay system and a flexible LED/Display backend.
LED and Display States
The led_status module translates internal system states into visual indicators. The visual feedback differs based on whether the board has a simple RGB LED or a full LCD.
| State | LED Color | Meaning |
|---|---|---|
LED_STATE_BLE_ADVERTISING | Orange (Breathing) | Ready for BLE setup |
LED_STATE_PAIRING_CONFIRM_REQUIRED | Blue (Breathing) | Awaiting physical button press |
LED_STATE_WS_CONNECTED | Green | Encrypted tunnel and control session are live |
LED_STATE_WS_DISCONNECTED | Yellow (Blinking) | Connection lost; retrying |
LED_STATE_ERROR | Red (Blinking) | System error or storage failure |
Sources: app.c:158-175, led_status.c:820-860, README.md:143-152
Display Rendering Architecture
For boards with screens, the UI includes:
- Status Bars: Colored bars at the top and bottom representing the connection state.
- Pixel Animation: A central animation (e.g., "Happy Anim") that loops during idle states.
- Image Overlays: A mechanism for Muse to draw remote images using
display.draw_url. - Title Text: A single line of pixel-font text shown above the animation.
Sources: led_status.c:150-170, led_status.c:665-680, led_status.c:980-995
State Management and Persistence
The firmware relies on ESP32 Non-Volatile Storage (NVS) to persist critical configuration data.
Persistent Data Keys
| Key | Type | Description |
|---|---|---|
ssid / password | String | Wi-Fi credentials |
access_token | String | Used for WebSocket Authorization and Noise auth |
refresh_token | String | Used to obtain new access tokens proactively or reactively |
vm_url | String | The specific VM target the gadget is pinned to |
setup_complete | Boolean | Marker indicating the device has finished initial provisioning |
Sources: app.c:1515-1550, app.c:460-480, app.c:560-580
Setup Reset Procedure
A 5-second hold of the BOOT button triggers a full system reset. The firmware:
- Disconnects existing WebSocket and Wi-Fi sessions.
- Erases pairing and Wi-Fi credentials from NVS.
- Restarts the ESP32 to return to a clean "advertising" state.
Sources: app.c:265-295, app.c:990-1010, AGENTS.md:278-282
Summary
The Muse Gadget Firmware Architecture implements a secure, task-oriented system designed for persistent cloud connectivity. By separating network handling (Noise Control) from application logic and UI rendering, it maintains responsiveness while handling complex encrypted data streams and varied hardware peripherals. The use of NVS for state persistence and a controlled command dispatch system allows for reliable remote management and extensibility.
Sources: README.md:16-25, AGENTS.md:25-30, app.c:1570-1580