# Lighting Controller REST API - Frontend Documentation ## Overview Complete REST API for controlling the LED lighting system. **No WebSocket required** - all operations use simple HTTP requests. **Base URL:** `http://10.42.0.1:8765` **Local Testing:** `http://localhost:8765` --- ## Table of Contents 1. [Quick Start](#quick-start) 2. [Pattern Control](#pattern-control) 3. [Color Palette](#color-palette) 4. [Parameters](#parameters) 5. [System State](#system-state) 6. [Tempo Control](#tempo-control) 7. [Complete Examples](#complete-examples) --- ## Quick Start ### Load Initial State ```javascript // Get everything in one call const response = await fetch('http://10.42.0.1:8765/api/state'); const state = await response.json(); console.log(state.pattern); // Current pattern console.log(state.parameters); // All parameters console.log(state.color_palette); // 8 colors + 2 selected console.log(state.beat_index); // Current beat number ``` ### Change Pattern ```javascript await fetch('http://10.42.0.1:8765/api/pattern', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({pattern: 'alternating'}) }); ``` ### Change Color ```javascript await fetch('http://10.42.0.1:8765/api/color-palette', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({selected_indices: [2, 5]}) // Blue and Cyan }); ``` --- ## Pattern Control ### GET /api/pattern Get the currently active pattern. **Request:** ```http GET /api/pattern HTTP/1.1 ``` **Response:** ```json { "pattern": "alternating" } ``` --- ### POST /api/pattern Change the active pattern. **Request:** ```http POST /api/pattern HTTP/1.1 Content-Type: application/json { "pattern": "alternating" } ``` **Available Patterns:** - `"on"` / `"o"` - Solid color - `"off"` / `"f"` - All LEDs off - `"flicker"` / `"f"` - Flickering effect - `"fill_range"` / `"fr"` - Fill effect - `"n_chase"` / `"nc"` - Chase pattern - `"alternating"` / `"a"` - Alternating on/off - `"pulse"` / `"p"` - Pulsing effect - `"rainbow"` / `"r"` - Rainbow cycle - `"specto"` / `"s"` - Spectograph effect - `"radiate"` / `"rd"` - Radiate from center - `"segmented_movement"` / `"sm"` - Moving segments **Response:** ```json { "status": "ok", "pattern": "alternating" } ``` **JavaScript Example:** ```javascript async function setPattern(patternName) { const response = await fetch('http://10.42.0.1:8765/api/pattern', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({pattern: patternName}) }); return await response.json(); } // Usage await setPattern('alternating'); await setPattern('rainbow'); ``` --- ## Color Palette ### GET /api/color-palette Get the 8-color palette and selected colors. **Response:** ```json { "palette": [ {"r": 255, "g": 0, "b": 0}, // Slot 0: Red {"r": 0, "g": 255, "b": 0}, // Slot 1: Green {"r": 0, "g": 0, "b": 255}, // Slot 2: Blue {"r": 255, "g": 255, "b": 0}, // Slot 3: Yellow {"r": 255, "g": 0, "b": 255}, // Slot 4: Magenta {"r": 0, "g": 255, "b": 255}, // Slot 5: Cyan {"r": 255, "g": 128, "b": 0}, // Slot 6: Orange {"r": 255, "g": 255, "b": 255} // Slot 7: White ], "selected_indices": [0, 1] // [0] = pattern color, [1] = reserved } ``` **Important:** The **first selected color** (index 0) is used for all patterns! --- ### POST /api/color-palette Update palette colors and/or selected colors. **Request (Change Selected Colors):** ```json { "selected_indices": [2, 5] // Use slot 2 (Blue) for patterns } ``` **Request (Update a Color):** ```json { "palette": [ {"r": 255, "g": 0, "b": 0}, {"r": 0, "g": 255, "b": 0}, {"r": 128, "g": 0, "b": 128}, // Changed to purple // ... all 8 colors (must send complete array) ] } ``` **Response:** ```json { "status": "ok", "palette": { "palette": [...], "selected_indices": [2, 5] } } ``` **JavaScript Example:** ```javascript // Change pattern color to slot 5 (Cyan) async function selectColor(slotIndex) { const response = await fetch('http://10.42.0.1:8765/api/color-palette', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({selected_indices: [slotIndex, 1]}) }); return await response.json(); } // Edit a color in the palette async function updatePaletteColor(slotIndex, r, g, b) { // First get current palette const current = await fetch('http://10.42.0.1:8765/api/color-palette') .then(res => res.json()); // Update the specific slot const newPalette = [...current.palette]; newPalette[slotIndex] = {r, g, b}; // Send updated palette await fetch('http://10.42.0.1:8765/api/color-palette', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({palette: newPalette}) }); } // Usage await selectColor(2); // Use blue for patterns await updatePaletteColor(3, 128, 0, 128); // Change slot 3 to purple ``` --- ## Parameters ### GET /api/parameters Get all current parameter values. **Response:** ```json { "brightness": 100, // 0-100 "delay": 50, // milliseconds "n1": 10, // Pattern parameter 1 "n2": 5, // Pattern parameter 2 "n3": 2, // Pattern parameter 3 (forward movement) "n4": 1 // Pattern parameter 4 (backward movement) } ``` --- ### POST /api/parameters Update one or more parameters. Only send the parameters you want to change. **Request:** ```json { "brightness": 75, "n1": 15 } ``` **Response:** ```json { "status": "ok", "parameters": { "brightness": 75, "delay": 50, "n1": 15, "n2": 5, "n3": 2, "n4": 1 } } ``` **Parameter Descriptions:** | Parameter | Range | Description | |-----------|-------|-------------| | `brightness` | 0-100 | LED brightness percentage | | `delay` | 1-1000 | Pattern speed (milliseconds) | | `n1` | 0-255 | Pattern-specific (e.g., segment length) | | `n2` | 0-255 | Pattern-specific (e.g., spacing) | | `n3` | 0-255 | Pattern-specific (e.g., forward steps) | | `n4` | 0-255 | Pattern-specific (e.g., backward steps) | **JavaScript Example:** ```javascript async function setBrightness(value) { const response = await fetch('http://10.42.0.1:8765/api/parameters', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({brightness: value}) }); return await response.json(); } async function setSpeed(delayMs) { await fetch('http://10.42.0.1:8765/api/parameters', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({delay: delayMs}) }); } // Usage await setBrightness(75); // Set to 75% await setSpeed(100); // Slow down pattern ``` --- ## System State ### GET /api/state Get complete system state in a single call. Perfect for initial UI load. **Response:** ```json { "pattern": "alternating", "parameters": { "brightness": 100, "delay": 50, "n1": 10, "n2": 5, "n3": 2, "n4": 1 }, "color_palette": { "palette": [...8 colors...], "selected_indices": [0, 1] }, "beat_index": 42 } ``` **JavaScript Example:** ```javascript // Load all state when UI starts async function loadInitialState() { const response = await fetch('http://10.42.0.1:8765/api/state'); const state = await response.json(); // Update UI with current state updatePatternButtons(state.pattern); updateColorPalette(state.color_palette); updateSliders(state.parameters); return state; } ``` --- ## Tempo Control ### POST /api/tempo/reset Reset the tempo/beat detection in the sound system. **Request:** ```http POST /api/tempo/reset HTTP/1.1 ``` **Response:** ```json { "status": "ok", "message": "Tempo reset sent" } ``` **JavaScript Example:** ```javascript async function resetTempo() { const response = await fetch('http://10.42.0.1:8765/api/tempo/reset', { method: 'POST' }); return await response.json(); } // Usage: Call this when tempo detection seems off await resetTempo(); ``` --- ## Complete Examples ### Example 1: Full UI Controller Class ```javascript class LightingController { constructor(baseUrl = 'http://10.42.0.1:8765') { this.baseUrl = baseUrl; } // Load complete state async loadState() { const response = await fetch(`${this.baseUrl}/api/state`); return await response.json(); } // Pattern control async setPattern(pattern) { const response = await fetch(`${this.baseUrl}/api/pattern`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({pattern}) }); return await response.json(); } // Color selection async selectColor(slotIndex) { const response = await fetch(`${this.baseUrl}/api/color-palette`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({selected_indices: [slotIndex, 1]}) }); return await response.json(); } // Brightness control async setBrightness(value) { const response = await fetch(`${this.baseUrl}/api/parameters`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({brightness: value}) }); return await response.json(); } // Pattern parameters async setParameters(params) { const response = await fetch(`${this.baseUrl}/api/parameters`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(params) }); return await response.json(); } } // Usage const lights = new LightingController(); // On page load const state = await lights.loadState(); // User interactions await lights.setPattern('rainbow'); await lights.selectColor(2); // Blue await lights.setBrightness(75); ``` --- ### Example 2: React Component ```jsx import { useState, useEffect } from 'react'; function LightingControl() { const [state, setState] = useState(null); const BASE_URL = 'http://10.42.0.1:8765'; // Load initial state useEffect(() => { fetch(`${BASE_URL}/api/state`) .then(res => res.json()) .then(setState); }, []); // Change pattern const handlePatternChange = async (pattern) => { await fetch(`${BASE_URL}/api/pattern`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({pattern}) }); // Reload state const newState = await fetch(`${BASE_URL}/api/state`).then(r => r.json()); setState(newState); }; // Change color const handleColorSelect = async (slotIndex) => { await fetch(`${BASE_URL}/api/color-palette`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({selected_indices: [slotIndex, 1]}) }); const newState = await fetch(`${BASE_URL}/api/state`).then(r => r.json()); setState(newState); }; // Change brightness const handleBrightnessChange = async (value) => { await fetch(`${BASE_URL}/api/parameters`, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({brightness: value}) }); }; if (!state) return
Loading...
; return (

Pattern: {state.pattern}

Colors

{state.color_palette.palette.map((color, i) => (
handleColorSelect(i)} style={{ background: `rgb(${color.r}, ${color.g}, ${color.b})`, border: state.color_palette.selected_indices[0] === i ? '3px solid gold' : '1px solid black', width: 50, height: 50, display: 'inline-block', cursor: 'pointer' }} /> ))}
handleBrightnessChange(e.target.value)} />
); } ``` --- ### Example 3: Simple HTML + Vanilla JS ```html Lighting Controller

LED Lighting Control

``` --- ## API Endpoint Summary | Method | Endpoint | Purpose | |--------|----------|---------| | `GET` | `/api/state` | Get complete system state | | `GET` | `/api/pattern` | Get current pattern | | `POST` | `/api/pattern` | Change pattern | | `GET` | `/api/color-palette` | Get color palette | | `POST` | `/api/color-palette` | Update palette/selection | | `GET` | `/api/parameters` | Get all parameters | | `POST` | `/api/parameters` | Update parameters | | `POST` | `/api/tempo/reset` | Reset tempo detection | --- ## Error Handling All endpoints return standard HTTP status codes: - `200 OK` - Success - `400 Bad Request` - Invalid request data - `500 Internal Server Error` - Server error **Error Response Format:** ```json { "status": "error", "message": "Pattern name required" } ``` **JavaScript Error Handling Example:** ```javascript async function safeApiCall(url, options) { try { const response = await fetch(url, options); const data = await response.json(); if (data.status === 'error') { console.error('API Error:', data.message); return null; } return data; } catch (error) { console.error('Network Error:', error); return null; } } // Usage const result = await safeApiCall('http://10.42.0.1:8765/api/pattern', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({pattern: 'rainbow'}) }); ``` --- ## Testing ### Test All Endpoints ```bash # Get state curl http://10.42.0.1:8765/api/state | jq # Change pattern curl -X POST http://10.42.0.1:8765/api/pattern \ -H "Content-Type: application/json" \ -d '{"pattern": "rainbow"}' # Change color curl -X POST http://10.42.0.1:8765/api/color-palette \ -H "Content-Type: application/json" \ -d '{"selected_indices": [2, 5]}' # Update brightness curl -X POST http://10.42.0.1:8765/api/parameters \ -H "Content-Type: application/json" \ -d '{"brightness": 75}' # Reset tempo curl -X POST http://10.42.0.1:8765/api/tempo/reset ``` --- ## Notes - **No WebSocket needed** - Everything uses simple HTTP REST API - **CORS**: Not currently enabled. Host UI on same domain or add CORS middleware - **Persistence**: Color palette persists to `lighting_config.json` - **Real-time**: Changes take effect immediately (within one beat cycle) - **Pattern Color**: First selected color (index 0) is used for all patterns --- ## Support Files - Full API details: `COLOR_PALETTE_API.md` - Migration notes: `AIOHTTP_MIGRATION.md` - Test results: `PATTERN_COLOR_TEST_RESULTS.md`