Files
system-control/firmware/README-API.md
2026-01-01 17:40:23 +01:00

18 KiB

System Control - API Documentation

This document describes all REST API endpoints and WebSocket messages required for the ESP32 firmware implementation.

Table of Contents


REST API Endpoints

Capabilities

Get Device Capabilities

Returns the device capabilities. Used to determine which features are available.

  • URL: /api/capabilities
  • Method: GET
  • Response:
{
  "thread": true
}
Field Type Description
thread boolean Whether Thread/Matter features are enabled

Notes:

  • If thread is true, the UI shows Matter device management and Scenes
  • If thread is false or the endpoint is unavailable, these features are hidden
  • The client can also force-enable features via URL parameter ?thread=true

WiFi

Scan Networks

Scans for available WiFi networks.

  • URL: /api/wifi/scan
  • Method: GET
  • Response:
[
  {
    "ssid": "NetworkName",
    "rssi": -45
  },
  {
    "ssid": "AnotherNetwork",
    "rssi": -72
  }
]
Field Type Description
ssid string Network name (SSID)
rssi number Signal strength in dBm

Save WiFi Configuration

Saves WiFi credentials and initiates connection.

  • URL: /api/wifi/config
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "ssid": "NetworkName",
  "password": "SecretPassword123"
}
Field Type Required Description
ssid string Yes Network name
password string No Network password
  • Response: 200 OK on success, 400 Bad Request on error

Get WiFi Status

Returns current WiFi connection status.

  • URL: /api/wifi/status
  • Method: GET
  • Response:
{
  "connected": true,
  "ssid": "NetworkName",
  "ip": "192.168.1.100",
  "rssi": -45
}
Field Type Description
connected boolean Whether connected to a network
ssid string Connected network name (if connected)
ip string Assigned IP address (if connected)
rssi number Signal strength in dBm (if connected)

Light Control

Set Light Power

Turns the main light on or off.

  • URL: /api/light/power
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "on": true
}
Field Type Required Description
on boolean Yes true = on, false = off
  • Response: 200 OK on success

Set Light Mode

Sets the lighting mode.

  • URL: /api/light/mode
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "mode": "simulation"
}
Field Type Required Description
mode string Yes One of: day, night, simulation
  • Response: 200 OK on success

Set Active Schema

Sets the active schema for simulation mode.

  • URL: /api/light/schema
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "schema": "schema_01.csv"
}
Field Type Required Description
schema string Yes Schema filename: schema_01.csv, schema_02.csv, etc.
  • Response: 200 OK on success

Get Light Status

Returns current light status (alternative to WebSocket).

  • URL: /api/light/status
  • Method: GET
  • Response:
{
  "on": true,
  "mode": "simulation",
  "schema": "schema_01.csv",
  "color": {
    "r": 255,
    "g": 240,
    "b": 220
  }
}
Field Type Description
on boolean Current power state
mode string Current mode (day/night/simulation)
schema string Active schema filename
color object Current RGB color being displayed

LED Configuration

Get LED Configuration

Returns the current LED segment configuration.

  • URL: /api/wled/config
  • Method: GET
  • Response:
{
  "segments": [
    {
      "name": "Main Light",
      "start": 0,
      "leds": 60
    },
    {
      "name": "Accent Light",
      "start": 60,
      "leds": 30
    }
  ]
}
Field Type Description
segments array List of LED segments
segments[].name string Optional segment name
segments[].start number Start LED index (0-based)
segments[].leds number Number of LEDs in this segment

Save LED Configuration

Saves the LED segment configuration.

  • URL: /api/wled/config
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "segments": [
    {
      "name": "Main Light",
      "start": 0,
      "leds": 60
    },
    {
      "name": "Accent Light",
      "start": 60,
      "leds": 30
    }
  ]
}
Field Type Required Description
segments array Yes List of LED segments (can be empty)
segments[].name string No Optional segment name
segments[].start number Yes Start LED index (0-based)
segments[].leds number Yes Number of LEDs in this segment
  • Response: 200 OK on success, 400 Bad Request on validation error

Notes:

  • Segments define how the LED strip is divided into logical groups
  • Changes are persisted to NVS (non-volatile storage)
  • Each segment can be controlled independently in the light schema

Schema

Load Schema

Loads a schema file.

  • URL: /api/schema/{filename}
  • Method: GET
  • URL Parameters:
    • filename: Schema file name (e.g., schema_01.csv)
  • Response: CSV text data
255,240,220,0,100,250
255,230,200,0,120,250
...

The CSV format has 48 rows (one per 30-minute interval) with 6 values per row:

Column Description Range
1 Red (R) 0-255
2 Green (G) 0-255
3 Blue (B) 0-255
4 Value 1 (V1) - custom value 0-255
5 Value 2 (V2) - custom value 0-255
6 Value 3 (V3) - custom value 0-255

Save Schema

Saves a schema file.

  • URL: /api/schema/{filename}
  • Method: POST
  • Content-Type: text/csv
  • URL Parameters:
    • filename: Schema file name (e.g., schema_01.csv)
  • Request Body: CSV text data (same format as above)
  • Response: 200 OK on success

Devices

Scan for Devices

Scans for available Matter devices to pair.

  • URL: /api/devices/scan
  • Method: GET
  • Response:
[
  {
    "id": "matter-001",
    "type": "light",
    "name": "Matter Lamp"
  },
  {
    "id": "matter-002",
    "type": "sensor",
    "name": "Temperature Sensor"
  }
]
Field Type Description
id string Unique device identifier
type string Device type: light, sensor, unknown
name string Device name (can be empty)

Pair Device

Pairs a discovered device.

  • URL: /api/devices/pair
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "id": "matter-001",
  "name": "Living Room Lamp"
}
Field Type Required Description
id string Yes Device ID from scan
name string Yes User-defined device name
  • Response: 200 OK on success

Get Paired Devices

Returns list of all paired devices.

  • URL: /api/devices/paired
  • Method: GET
  • Response:
[
  {
    "id": "matter-001",
    "type": "light",
    "name": "Living Room Lamp"
  }
]
Field Type Description
id string Unique device identifier
type string Device type: light, sensor, unknown
name string User-defined device name

Update Device Name

Updates the name of a paired device.

  • URL: /api/devices/update
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "id": "matter-001",
  "name": "New Device Name"
}
Field Type Required Description
id string Yes Device ID
name string Yes New device name
  • Response: 200 OK on success

Unpair Device

Removes a paired device.

  • URL: /api/devices/unpair
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "id": "matter-001"
}
Field Type Required Description
id string Yes Device ID
  • Response: 200 OK on success

Toggle Device

Toggles a device (e.g., light on/off).

  • URL: /api/devices/toggle
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "id": "matter-001"
}
Field Type Required Description
id string Yes Device ID
  • Response: 200 OK on success

Scenes

Get All Scenes

Returns all configured scenes.

  • URL: /api/scenes
  • Method: GET
  • Response:
[
  {
    "id": "scene-1",
    "name": "Evening Mood",
    "icon": "🌅",
    "actions": {
      "light": "on",
      "mode": "simulation",
      "schema": "schema_02.csv",
      "devices": [
        {
          "id": "matter-001",
          "state": "on"
        }
      ]
    }
  },
  {
    "id": "scene-2",
    "name": "Night Mode",
    "icon": "🌙",
    "actions": {
      "light": "on",
      "mode": "night"
    }
  }
]

Scene Object:

Field Type Description
id string Unique scene identifier
name string Scene name
icon string Emoji icon for the scene
actions object Actions to execute (see below)

Actions Object:

Field Type Optional Description
light string Yes "on" or "off"
mode string Yes "day", "night", or "simulation"
schema string Yes Schema filename (e.g., schema_01.csv)
devices array Yes Array of device actions (see below)

Device Action Object:

Field Type Description
id string Device ID
state string "on" or "off"

Create/Update Scene

Creates a new scene or updates an existing one.

  • URL: /api/scenes
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "id": "scene-1",
  "name": "Evening Mood",
  "icon": "🌅",
  "actions": {
    "light": "on",
    "mode": "simulation",
    "schema": "schema_02.csv",
    "devices": [
      {
        "id": "matter-001",
        "state": "on"
      }
    ]
  }
}
  • Response: 200 OK on success

Delete Scene

Deletes a scene.

  • URL: /api/scenes
  • Method: DELETE
  • Content-Type: application/json
  • Request Body:
{
  "id": "scene-1"
}
Field Type Required Description
id string Yes Scene ID
  • Response: 200 OK on success

Activate Scene

Executes all actions of a scene.

  • URL: /api/scenes/activate
  • Method: POST
  • Content-Type: application/json
  • Request Body:
{
  "id": "scene-1"
}
Field Type Required Description
id string Yes Scene ID
  • Response: 200 OK on success

WebSocket

Connection

  • URL: ws://{host}/ws or wss://{host}/ws
  • Protocol: JSON messages

The WebSocket connection is used for real-time status updates. The client should reconnect automatically if the connection is lost (recommended: 3 second delay).


Client to Server Messages

Request Status

Requests the current system status.

{
  "type": "getStatus"
}

Server to Client Messages

Status Update

Sent in response to getStatus or when status changes.

{
  "type": "status",
  "on": true,
  "mode": "simulation",
  "schema": "schema_01.csv",
  "color": {
    "r": 255,
    "g": 240,
    "b": 220
  }
}
Field Type Description
type string Always "status"
on boolean Light power state
mode string Current mode (day/night/simulation)
schema string Active schema filename
color object Current RGB color (optional)

Color Update

Sent when the current color changes (during simulation).

{
  "type": "color",
  "r": 255,
  "g": 200,
  "b": 150
}
Field Type Description
type string Always "color"
r number Red value (0-255)
g number Green value (0-255)
b number Blue value (0-255)

WiFi Status Update

Sent when WiFi connection status changes.

{
  "type": "wifi",
  "connected": true,
  "ip": "192.168.1.100",
  "rssi": -45
}
Field Type Description
type string Always "wifi"
connected boolean Whether connected to a network
ip string Assigned IP address (if connected)
rssi number Signal strength in dBm (if connected)

Static Files

The web interface files should be served from the /storage/www/ directory:

Path Description
/ Serves index.html (or captive.html in AP mode)
/index.html Main HTML file (full interface)
/captive.html Captive portal (WiFi setup only)
/css/shared.css Shared styles for all pages
/css/index.css Styles for main interface
/css/captive.css Styles for captive portal
/js/wifi-shared.js Shared WiFi configuration logic
/js/*.js JavaScript modules

Captive Portal

When the ESP32 is in Access Point (AP) mode (no WiFi configured or connection failed), it should serve the captive portal:

Behavior

  1. AP Mode Activation:

    • ESP32 creates an access point (e.g., "marklin-setup")
    • DNS server redirects all requests to the ESP32's IP (captive portal detection)
  2. Captive Portal Detection:

    • Respond to common captive portal detection URLs:
      • /generate_204 (Android)
      • /hotspot-detect.html (Apple)
      • /connecttest.txt (Windows)
    • Return redirect or serve captive.html
  3. Serving Files in AP Mode:

    • /captive.html
    • /captive.html → Captive portal page
    • /js/wifi-shared.js → WiFi functions
    • API endpoints remain the same (/api/wifi/*)
  4. After Successful Configuration:

    • ESP32 attempts to connect to the configured network
    • If successful, switch to Station mode and serve index.html
    • If failed, remain in AP mode
Setting Value
SSID marklin-setup
Password None (open) or marklin
IP Address 192.168.4.1
Gateway 192.168.4.1
Subnet 255.255.255.0

Error Handling

All endpoints should return appropriate HTTP status codes:

Code Description
200 Success
400 Bad Request (invalid input)
404 Not Found (resource doesn't exist)
500 Internal Server Error

Error responses should include a JSON body with an error message:

{
  "error": "Description of what went wrong"
}