Files
SmartSpeaker/API.md
T

12 KiB

ESP32-S3 Audio Board - WebSocket API Specification

This document serves as the official protocol source of truth for developing the host server (Dev Gateway / Monitor Dashboard) and client (ESP32-S3 device) software.

All communications over the WebSocket connection use JSON text frames.


Commands are sent from the server to control the device's state. The message structure is:

{
  "command": "<command_name>",
  "value": <command_value>
}

1.1. Set Volume (set_volume)

Sets the output gain level on the ES8311 mono DAC audio codec.

  • Payload:
    {
      "command": "set_volume",
      "value": 85
    }
    
  • Parameters: value must be an integer between 0 (mute) and 100 (max amplification).

1.2. Query State (query_state)

Requests the device to compile and send its complete state telemetry payload immediately.

  • Payload:
    {
      "command": "query_state"
    }
    
  • Parameters: None. The device will reply immediately with a state_report payload (see Section 2).

1.3. Set LED Mode (set_led)

Sets the active visual feedback preset mode on the WS2812B LED ring.

  • Payload:
    {
      "command": "set_led",
      "value": "rainbow"
    }
    
  • Parameters: value must be a string: "rainbow" (moving rainbow), "connecting" (flashing orange), "failed" (solid red), "idle" (off), or "updating" (breathing blue - OTA flash).

1.4. Play Audio Track (play_audio)

Triggers the ES8311 DAC codec to play an internal chime asset file from flash SPIFFS.

  • Payload:
    {
      "command": "play_audio",
      "value": "startup"
    }
    
  • Parameters: value must be a string: "startup", "wifi_connecting", or "wifi_connected".

1.5. Set LED Brightness (set_brightness)

Sets the overall brightness coefficient for the WS2812B LED ring.

  • Payload:
    {
      "command": "set_brightness",
      "value": 0.25
    }
    
  • Parameters: value must be a float between 0.0 (completely dark) and 1.0 (maximum intensity).

1.6. Set Haptic Vibration (set_haptics) [PROTO-1 Only]

Sets the PWM vibration intensity on the GPIO 5 haptic motor.

  • Payload:
    {
      "command": "set_haptics",
      "value": 50
    }
    
  • Parameters: value must be an integer between 0 (off) and 100 (max vibration).

The device reports its complete operational state to the server.

  • Trigger Conditions:

    1. Periodic Telemetry: Broadcasted automatically every 5 seconds.
    2. Event-Driven: Broadcasted immediately when a state changes (e.g. volume adjustment, LED mode transition, or a hardware button press).
    3. On-Demand: Sent in direct response to a query_state command.
  • State Report Payload:

    {
      "type": "state_report",
      "deviceId": "ESP32-S3-A2D4",
      "timestamp": "2026-06-28T05:12:00Z",
      "system": {
        "mac_address": "A0:F2:62:E3:5C:F0",
        "model": "DEV-1",
        "firmware_version": "v1.0.0",
        "idf_version": "v6.0.1",
        "cpu_freq_mhz": 240,
        "flash_size_mb": 16,
        "psram_size_mb": 8
      },
      "health": {
        "uptime_seconds": 1205,
        "free_heap_bytes": 3842420,
        "min_free_heap_bytes": 3720100,
        "reset_reason": "POWERON_RESET"
      },
      "network": {
        "wifi_connected": true,
        "wifi_ssid": "ExampleWiFi",
        "wifi_rssi": -47,
        "ip_address": "192.0.2.10",
        "websocket_connected": true
      },
      "peripherals": {
        "audio": {
          "volume": 85,
          "player_state": "idle",
          "current_track": "none"
        },
        "led_ring": {
          "state_id": 5,
          "state_name": "rainbow",
          "brightness_coef": 0.2
        },
        "buttons": {
          "btn_play": false,
          "btn_mute": false,
          "btn_vol_up": false,
          "btn_vol_down": false
        },
        "haptic_intensity": 50,
        "ambient_light": 2048,
        "touch_active": false
      }
    }
    

2.1. Payload Field Definitions

System Info (system)

  • mac_address (string): Globally unique MAC address of the device network interface.
  • model (string): Physical hardware configuration model identifier ("DEV-1" or "PROTO-1").
  • firmware_version (string): Compiled application version.
  • idf_version (string): ESP-IDF framework version.
  • cpu_freq_mhz (integer): Dual-core clock speed in MHz (typically 240).
  • flash_size_mb / psram_size_mb (integer): Total sizes of physical flash and PSRAM chips.

Health (health)

  • uptime_seconds (integer): Elapsed seconds since device boot.
  • free_heap_bytes (integer): Available dynamic DRAM size.
  • min_free_heap_bytes (integer): Lowest free memory watermark (critical for memory leak analysis).
  • reset_reason (string): Hardware restart source code (e.g. POWERON_RESET, SW_RESET).

Network (network)

  • wifi_connected (boolean): true if connected to Wi-Fi.
  • wifi_ssid (string): Connected Wi-Fi AP name.
  • wifi_rssi (integer): Wi-Fi Signal Strength in dBm (e.g., -50 is strong, -85 is weak).
  • ip_address (string): Device local IP.
  • websocket_connected (boolean): true if active control socket link is connected.

Peripherals (peripherals)

  • audio (object): DAC output status:
    • volume (integer): Gain scaling (0 to 100).
    • player_state (string): Current player thread status ("idle", "playing", "paused", "stopped").
    • current_track (string): Active file URI (e.g. file://spiffs/startup.mp3) or "none".
  • led_ring (object): WS2812B visual task status:
    • state_id (integer): Numeric preset state enum value:
      • 0: LED_STATE_OFF (Off)
      • 1: LED_STATE_WIFI_CONNECTING (Flashing Red)
      • 2: LED_STATE_WIFI_FAILED (Solid Red)
      • 3: LED_STATE_SERVER_CONNECTING (Flashing Orange)
      • 4: LED_STATE_SERVER_FAILED (Solid Orange)
      • 5: LED_STATE_CONNECTED (Rainbow Rotate)
      • 6: LED_STATE_UPDATING (Pulse Blue slowly - OTA flashing)
    • state_name (string): Visual pattern tag name ("rainbow", "connecting", "failed", "idle", "updating").
    • brightness_coef (float): Active brightness coefficient between 0.0 and 1.0.
  • buttons (object): Realtime physical state of the TCA9555 IO expander button pins (true if key is pressed down).
  • haptic_intensity (integer) [PROTO-1 Only]: Active haptic vibration level (0 to 100).
  • ambient_light (integer) [PROTO-1 Only]: Measured ambient light intensity (0 to 4095).
  • touch_active (boolean) [PROTO-1 Only]: true if capacitive/digital touch sensor is active.

3. Monitor Dashboard Commands (Dashboard ➔ Server)

Commands sent by the Monitor Dashboard client to the Dev Gateway server to manage connected device sessions. These differ from Section 1 commands in that they are server-side operations — the server acts on them directly rather than forwarding them to a device.

{
  "type": "<command_type>",
  "targetId": "<client_id>"
}

3.1. Boot Device (boot_device)

Forces a connected device to disconnect by closing its WebSocket connection server-side. Used to simulate a disconnect event, trigger device reconnection logic, or evict a misbehaving client.

  • Sender: Monitor Dashboard
  • Receiver: Dev Gateway Server (not forwarded to device)
  • Payload:
    {
      "type": "boot_device",
      "targetId": "esp32-a2d4f1"
    }
    
  • Parameters: targetId (string) — the unique client session ID of the device to disconnect.
  • Server Behaviour: The server locates the WebSocket for targetId, sends a close frame (1000 Normal Closure), logs a boot event, and broadcasts an updated status_update to all monitors.
  • Device Behaviour: The device's WebSocket client receives the close event and triggers its reconnect logic (up to 5 retries with backoff).

3.2. Control Device (control_device)

Routes a downlink command (from Section 1) from the Monitor Dashboard through the server to a specific target device.

  • Sender: Monitor Dashboard
  • Receiver: Dev Gateway Server → forwarded to target device
  • Payload:
    {
      "type": "control_device",
      "targetId": "esp32-a2d4f1",
      "payload": {
        "command": "set_volume",
        "value": 70
      }
    }
    
  • Parameters: targetId (string), payload (object) — any valid Section 1 command object.

3.3. Trigger OTA Update (trigger_ota)

Instructs the server to push a firmware binary (previously uploaded via HTTP POST /ota/upload) to a target device and begin the OTA flash process.

  • Sender: Monitor Dashboard
  • Receiver: Dev Gateway Server → forwards start_ota downlink to target device
  • Payload:
    {
      "type": "trigger_ota",
      "targetId": "esp32-a2d4f1",
      "version": "latest"
    }
    
  • Parameters:
    • targetId (string) — the ID of the target ESP32 device.
    • version (string, optional) — select which firmware version to deploy:
      • "latest" (default): Deploys the latest catalog release built by release.ps1.
      • "<semver>" (e.g. "v0.0.32-4471303"): Deploys a specific catalog release version.
      • "custom" (or omitted): Deploys the manually uploaded binary from /ota/firmware.bin.
  • Server Behaviour: Resolves target URL (either /releases/firmware-vX.Y.Z.bin or /ota/firmware.bin), sends a start_ota command (Section 4.1) to target device. Updates metadata.otaStatus to "pending" and broadcasts to monitors.

4. OTA Firmware Update Protocol

Server instructs the device to begin an OTA firmware download and flash.

{
  "command": "start_ota",
  "url": "https://example.com/releases/firmware-v0.0.37-proto1.bin",
  "cert_pem": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
}
  • Parameters:
    • url (string) — HTTP/HTTPS URL from which the device should fetch the firmware binary.
    • cert_pem (string, optional) — PEM-formatted CA certificate used to verify the HTTPS server. If omitted, the device falls back to validating the HTTPS server certificate using the built-in ESP x509 Certificate Bundle.
  • Device Behaviour: Spawns an OTA task. Downloads the binary in chunks. Validates the image. Writes to the inactive OTA partition. On success, commits the new partition and reboots. On failure, rolls back and reports an error.

Device reports download/flash progress.

{
  "type": "ota_progress",
  "percent": 45,
  "bytes_written": 204800,
  "bytes_total": 450000
}

Device reports successful flash before rebooting.

{ "type": "ota_complete" }
  • Device reboots ~500ms after sending this message to apply the new firmware.

Device reports a failure during download or flash.

{ "type": "ota_error", "reason": "HTTP connection failed: -1" }
  • Device continues running the existing firmware after an OTA error. No rollback is needed.

4.5. Server HTTP Endpoints (OTA)

Method Path Description
POST /ota/upload Upload a .bin firmware file (multipart/form-data, field: firmware)
GET /ota/firmware.bin Serve the most recently uploaded firmware binary
GET /ota/status Return current OTA metadata: filename, size, upload time
GET /ota/catalog Return the full catalog JSON (firmware-catalog.json) generated by release.ps1
GET /releases/* Serve versioned release binaries (e.g. /releases/firmware-vX.Y.Z.bin)