Skip to main content

Overview

The AutoLight V3 REST API provides comprehensive HTTP endpoints for controlling and monitoring LED systems. The API is served by the APIServerManager on port 8000 via AsyncWebServer with FreeRTOS task-based execution. Base URL: http://{device-ip}:8000/api/v1
Default IP (AP Mode): 192.168.4.1
Default IP (mDNS): als.local
Protocol: HTTP
Response Format: Plain text

Quick Start

# Get current mode
curl http://192.168.4.1:8000/api/v1/data/get/mode

# Set mode to 5
curl "http://192.168.4.1:8000/api/v1/data/set/mode?value=5"

# Get device name
curl http://192.168.4.1:8000/api/v1/data/get/device/name

# Set delay to 100ms
curl "http://192.168.4.1:8000/api/v1/data/set/delay?value=100"

API Endpoints

Device Information

GET /api/v1/data/get/device/name
endpoint
Get the device name (SSID in AP mode)Response: Plain text stringExample:
curl http://192.168.4.1:8000/api/v1/data/get/device/name
# Response: "AutoLight-A1B2"
Implementation: APIServerManager.cpp:238
api_.on("/api/v1/data/get/device/name", HTTP_GET, [this](AsyncWebServerRequest *request) {
    auto creds = ConfigManager::getInstance().getCredentials();
    request->send(200, "text/plain", creds.ssid);
});
GET /api/v1/data/get/device/serial
endpoint
Get the device serial numberResponse: Plain text stringExample:
curl http://192.168.4.1:8000/api/v1/data/get/device/serial
# Response: "AL3-001234"
Implementation: APIServerManager.cpp:247
api_.on("/api/v1/data/get/device/serial", HTTP_GET, [this](AsyncWebServerRequest *request) {
    auto creds = ConfigManager::getInstance().getCredentials();
    request->send(200, "text/plain", creds.serial);
});
GET /api/v1/data/get/device/ch
endpoint
Get the device channel countResponse: Plain text integer (1-64)Example:
curl http://192.168.4.1:8000/api/v1/data/get/device/ch
# Response: "12"
Implementation: APIServerManager.cpp:243
api_.on("/api/v1/data/get/device/ch", HTTP_GET, [this](AsyncWebServerRequest *request) {
    request->send(200, "text/plain", String(config_->getChannel()));
});

Device State

GET /api/v1/data/get/mode
endpoint
Get the current LED sequence modeResponse: Plain text integer (0-15)
  • 0 - OFF
  • 1 - Static ON
  • 2-15 - LED sequences
Example:
curl http://192.168.4.1:8000/api/v1/data/get/mode
# Response: "5"
Implementation: APIServerManager.cpp:267
api_.on("/api/v1/data/get/mode", HTTP_GET, [this](AsyncWebServerRequest *request) {
    request->send(200, "text/plain", String(led_->getSequenceIndex()));
});
GET /api/v1/data/get/delay
endpoint
Get the current timing delay in millisecondsResponse: Plain text integer (30-300)Example:
curl http://192.168.4.1:8000/api/v1/data/get/delay
# Response: "50"
Implementation: APIServerManager.cpp:283
api_.on("/api/v1/data/get/delay", HTTP_GET, [this](AsyncWebServerRequest *request) {
    request->send(200, "text/plain", String(led_->getDelayTime()));
});

Device Control

GET /api/v1/data/set/mode
endpoint
Set the LED sequence modeParameters:
  • value (required) - Mode number (0-15)
Response: Plain text confirmationExample:
curl "http://192.168.4.1:8000/api/v1/data/set/mode?value=7"
# Response: "Berhasil Set Mode : 7"
Implementation: APIServerManager.cpp:271
api_.on("/api/v1/data/set/mode", HTTP_GET, [this](AsyncWebServerRequest *request) {
    if (request->hasArg("value")) {
        String modeValue = request->arg("value");
        int modeValueInt = modeValue.toInt();
        Serial.println("API Set Mode: " + String(modeValueInt));
        led_->changeModeApp(modeValueInt);
        request->send(200, "text/plain", "Berhasil Set Mode : " + modeValue);
    } else {
        request->send(400, "text/plain", "Parameter 'value' is missing");
    }
});
Validation:
  • Value must be 0-15
  • Invalid values default to mode 0 (OFF)
GET /api/v1/data/set/delay
endpoint
Set the timing delay in millisecondsParameters:
  • value (required) - Delay in milliseconds (30-300)
Response: Plain text confirmationExample:
curl "http://192.168.4.1:8000/api/v1/data/set/delay?value=100"
# Response: "Berhasil Set delay : 100"
Implementation: APIServerManager.cpp:287
api_.on("/api/v1/data/set/delay", HTTP_GET, [this](AsyncWebServerRequest *request) {
    if (request->hasArg("value")) {
        String delayValue = request->arg("value");
        led_->setInitDelay(delayValue.toInt());
        request->send(200, "text/plain", "Berhasil Set delay : " + delayValue);
    } else {
        request->send(400, "text/plain", "Parameter 'value' is missing");
    }
});
Validation:
  • Recommended range: 30-300ms
  • Values below 30ms may cause timing issues
  • Values above 300ms create sluggish patterns
GET /api/v1/data/set/device/name
endpoint
Set the device name (requires restart to take effect)Parameters:
  • value (required) - New device name (URL encoded)
Response: Plain text confirmationExample:
curl "http://192.168.4.1:8000/api/v1/data/set/device/name?value=MyAutoLight"
# Response: "Berhasil Set device : MyAutoLight"
Implementation: APIServerManager.cpp:252
api_.on("/api/v1/data/set/device/name", HTTP_GET, [this](AsyncWebServerRequest *request) {
    if (request->hasArg("value")) {
        String deviceName = request->arg("value");
        ConfigManager::getInstance().updateCredentials(deviceName, "");
        auto creds = ConfigManager::getInstance().getCredentials();
        credentials_ = creds;
        request->send(200, "text/plain", "Berhasil Set device : " + creds.ssid);
    } else {
        request->send(400, "text/plain", "Parameter 'value' is missing");
    }
});
Device name changes are persisted to EEPROM but require a restart to take effect for WiFi AP SSID.

LED Sequence Modes

The mode parameter controls which LED sequence is active:
ModeNameDescription
0OFFComplete OFF state - all channels disabled
1Static ONAll channels continuously high
2Blink AllAll channels blink simultaneously
3Fill CenterFill from two points (center outward)
4Fill RightFill from right to left
5Fill EndsFill from both ends inward
6SequentialBlink one LED at a time sequentially
7Two LED FillBlink two LEDs while filling
8SnakeSnake pattern with reverse
9RandomRandom LED activation
10WaveWave propagation effect
11Multi-PatternComplex multi-pattern coordination
12MatrixAdvanced pattern matrix
13Custom BlinkCustom blink patterns
14AdvancedAdvanced pattern combinations
15All SequencesAll sequences in rotation

API Server Configuration

WiFi Modes

The API server operates in two WiFi modes:
Default mode for standalone operation
// Default AP configuration
WiFi.mode(WIFI_AP);
WiFi.softAP(credentials_.ssid, credentials_.password);
Settings:

Server Initialization

The APIServerManager initializes two AsyncWebServer instances:
class APIServerManager {
private:
    AsyncWebServer server_;  // Port 80 - Static files from SD card
    AsyncWebServer api_;     // Port 8000 - REST API endpoints
    
public:
    APIServerManager(BaseChannel *led, BaseConfig *config)
        : server_(80), api_(8000) {
        // Constructor
    }
};
Initialization sequence: APIServerManager.cpp:73-110
1

Load Credentials

initCredentials();
auto creds = ConfigManager::getInstance().getCredentials();
2

Initialize SD Card

initSDCard();
if (!SD.begin(5)) {
    Serial.println("Card Mount Failed");
}
3

Start WiFi

initWiFi();
// Automatically handles AP or STA mode
4

Setup Routes

setupRoutes();
// Register all API endpoints
5

Configure CORS

setDefaultHeaders();
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
6

Start Servers

server_.begin();  // Port 80
api_.begin();     // Port 8000
7

Start mDNS

MDNS.begin("als");
// Available at http://als.local

CORS Configuration

The API automatically enables CORS for cross-origin requests:
void APIServerManager::setDefaultHeaders() {
    DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "content-type");
    DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
}
This allows the web client to be hosted on a different domain while still communicating with the device API.

Error Handling

HTTP Status Codes

CodeMeaningExample
200SuccessRequest completed successfully
400Bad RequestMissing required parameter
404Not FoundInvalid endpoint
500Server ErrorInternal server error

Common Errors

Cause: Required value parameter not provided
curl http://192.168.4.1:8000/api/v1/data/set/mode
# Response: "Parameter 'value' is missing"
Solution: Include the value parameter
curl "http://192.168.4.1:8000/api/v1/data/set/mode?value=5"
Cause: Device not reachable on networkTroubleshooting:
  1. Verify device IP address
  2. Check WiFi connection (AP or STA mode)
  3. Ping the device: ping 192.168.4.1
  4. Check firewall settings
  5. Try mDNS: curl http://als.local:8000/api/v1/data/get/mode
Cause: Browser blocking cross-origin requestNote: CORS is automatically enabled on the server side. If you still see CORS errors:
  1. Check browser console for specific error
  2. Verify API server is running on port 8000
  3. Use browser dev tools to inspect headers
  4. Try direct API call with cURL to verify server

Integration Examples

Web Client Integration

React/TypeScript Example (from AutoLight Web Client):
// lib/api/device.ts
const baseURL = `${protocol}://${host}:${port}/api/v1`

export async function getDeviceMode(): Promise<number> {
  try {
    const response = await fetch(`${baseURL}/data/get/mode`)
    if (!response.ok) throw new Error('Failed to get mode')
    return parseInt(await response.text())
  } catch (error) {
    console.error('Error getting device mode:', error)
    throw error
  }
}

export async function setDeviceMode(mode: number): Promise<void> {
  try {
    const response = await fetch(`${baseURL}/data/set/mode?value=${mode}`)
    if (!response.ok) throw new Error('Failed to set mode')
  } catch (error) {
    console.error('Error setting device mode:', error)
    throw error
  }
}

// Usage with React hook
function useLEDControl() {
  const [mode, setMode] = useState(0)
  
  useEffect(() => {
    // Poll device every 2 seconds
    const interval = setInterval(async () => {
      const currentMode = await getDeviceMode()
      setMode(currentMode)
    }, 2000)
    
    return () => clearInterval(interval)
  }, [])
  
  const updateMode = async (newMode: number) => {
    await setDeviceMode(newMode)
    setMode(newMode)
  }
  
  return { mode, updateMode }
}

Python Integration

import requests
import time

class AutoLightAPI:
    def __init__(self, host='192.168.4.1', port=8000):
        self.base_url = f'http://{host}:{port}/api/v1'
    
    def get_mode(self):
        """Get current LED mode"""
        response = requests.get(f'{self.base_url}/data/get/mode')
        return int(response.text)
    
    def set_mode(self, mode):
        """Set LED mode (0-15)"""
        if not 0 <= mode <= 15:
            raise ValueError('Mode must be between 0 and 15')
        requests.get(f'{self.base_url}/data/set/mode?value={mode}')
    
    def get_delay(self):
        """Get current timing delay in ms"""
        response = requests.get(f'{self.base_url}/data/get/delay')
        return int(response.text)
    
    def set_delay(self, delay):
        """Set timing delay (30-300ms)"""
        if not 30 <= delay <= 300:
            raise ValueError('Delay must be between 30 and 300ms')
        requests.get(f'{self.base_url}/data/set/delay?value={delay}')
    
    def get_device_info(self):
        """Get device information"""
        name = requests.get(f'{self.base_url}/data/get/device/name').text
        serial = requests.get(f'{self.base_url}/data/get/device/serial').text
        channels = int(requests.get(f'{self.base_url}/data/get/device/ch').text)
        
        return {
            'name': name,
            'serial': serial,
            'channels': channels
        }

# Usage example
api = AutoLightAPI(host='192.168.4.1')

# Get device info
info = api.get_device_info()
print(f"Device: {info['name']}")
print(f"Serial: {info['serial']}")
print(f"Channels: {info['channels']}")

# Cycle through modes
for mode in range(2, 16):
    api.set_mode(mode)
    time.sleep(2)

# Turn off
api.set_mode(0)

Arduino/ESP32 Client

#include <WiFi.h>
#include <HTTPClient.h>

class AutoLightClient {
private:
    String baseURL;
    HTTPClient http;
    
public:
    AutoLightClient(const char* host, int port = 8000) {
        baseURL = String("http://") + host + ":" + String(port) + "/api/v1";
    }
    
    int getMode() {
        String url = baseURL + "/data/get/mode";
        http.begin(url);
        int httpCode = http.GET();
        
        if (httpCode == 200) {
            String payload = http.getString();
            return payload.toInt();
        }
        return -1;
    }
    
    bool setMode(int mode) {
        String url = baseURL + "/data/set/mode?value=" + String(mode);
        http.begin(url);
        int httpCode = http.GET();
        return (httpCode == 200);
    }
    
    int getDelay() {
        String url = baseURL + "/data/get/delay";
        http.begin(url);
        int httpCode = http.GET();
        
        if (httpCode == 200) {
            String payload = http.getString();
            return payload.toInt();
        }
        return -1;
    }
    
    bool setDelay(int delayMs) {
        String url = baseURL + "/data/set/delay?value=" + String(delayMs);
        http.begin(url);
        int httpCode = http.GET();
        return (httpCode == 200);
    }
};

// Usage
AutoLightClient led("192.168.4.1");

void setup() {
    Serial.begin(115200);
    WiFi.begin("YourSSID", "YourPassword");
    
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    
    // Get current mode
    int mode = led.getMode();
    Serial.println("Current mode: " + String(mode));
    
    // Set to mode 5
    led.setMode(5);
    
    // Set delay to 100ms
    led.setDelay(100);
}

void loop() {
    // Control logic
}

Performance Considerations

Rate Limiting

The API does not enforce rate limiting, but excessive requests may impact LED sequence execution.Recommended polling interval: 1-2 seconds for state monitoring

Concurrent Requests

AsyncWebServer handles concurrent requests efficiently:
  • Multiple clients can connect simultaneously
  • FreeRTOS task-based execution prevents blocking
  • Web server (port 80) and API (port 8000) run independently

Response Times

Typical response times:
EndpointAverage Response Time
GET device info5-15ms
GET mode/delay5-10ms
SET mode/delay10-20ms
SET device name50-100ms (EEPROM write)

Next Steps

Web Client

Explore the Next.js web interface using this API

AutoLight V3

Learn about firmware architecture

Pattern Builder

Create custom LED sequences

Back to Overview

Return to AutoLight overview

Build docs developers (and LLMs) love