LUMA-6CH / Open HTTP API
Documentazione API HTTP
Riferimento tecnico per integrare LUMA-6CH con applicazioni, sistemi di automazione e strumenti eseguiti nella rete locale.
1 / Base URL e accesso
L'API utilizza HTTP/1.1 nella rete locale ed è raggiungibile tramite http://luma.local oppure tramite l'indirizzo IP del dispositivo. Non esporre mai la porta 80 del dispositivo direttamente a Internet.
Questa pagina mostra esempi da copiare ma non comunica con il dispositivo. Evita così mixed content, CORS, Private Network Access e l'esposizione accidentale dei token.
- Richieste e risposte usano JSON con
Content-Type: application/json. - Le risposte API usano
Cache-Control: no-store. - I comandi riusciti restituiscono
{"ok":true}; gli errori usano uno status HTTP 4xx/5xx e, dove previsto,{"ok":false,"error":"..."}.
2 / Autenticazione locale
Quando api.auth_required è true, le route protette richiedono Authorization: Bearer . Solo le risorse di sblocco, GET /api/auth/status e POST /api/auth/login restano pubbliche.
| Method | Route | Descrizione |
|---|---|---|
| GET | /api/auth/status | Pubblico: indica soltanto se è richiesto lo sblocco. |
| POST | /api/auth/login | Pubblico, massimo 512 B. Scambia la password con una sessione RAM revocabile. |
| POST | /api/auth/password | Imposta, cambia o rimuove la password locale e revoca le sessioni esistenti. |
| POST | /api/tokens | Crea un token persistente di integrazione; il segreto viene mostrato una sola volta. |
| DELETE | /api/tokens/<id> | Revoca un token di integrazione. |
La password locale deve avere almeno 8 caratteri; una stringa vuota la rimuove. Le sessioni interattive vivono in RAM per 12 ore e vengono revocate al cambio password o al riavvio. Dopo cinque login falliti il dispositivo restituisce 429 try_later per 30 secondi. Il verificatore persistente usa PBKDF2-HMAC-SHA256 con salt casuale e costo versionato.
Sessione interattiva
read -s LUMA_PASSWORD
LUMA_TOKEN=$(curl -fsS -H 'Content-Type: application/json' \
-d "{\"password\":\"$LUMA_PASSWORD\"}" \
http://luma.local/api/auth/login | jq -er .token)
curl -fsS -H "Authorization: Bearer $LUMA_TOKEN" \
http://luma.local/api/stateToken persistente per integrazioni
Per Home Assistant, Node-RED, backend e automazioni crea una credenziale separata usando una sessione amministrativa. Conserva il campo secret in un secret store, mai nel repository.
INTEGRATION=$(curl -fsS -X POST \
-H "Authorization: Bearer $LUMA_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"label":"Home Assistant"}' \
http://luma.local/api/tokens)
LUMA_API_TOKEN=$(printf '%s' "$INTEGRATION" | jq -er .secret)
LUMA_TOKEN_ID=$(printf '%s' "$INTEGRATION" | jq -er .id)3 / Stato e modello dati
- Sei canali cablati
0..5per LED mono PWM, con misura INA219 per canale. - Gruppi RGB/RGBW/CCT con base
0o3, secondo il layout. - Strip indirizzabili S1/S2 come gruppi virtuali
6e7; usano alimentazione esterna e non hanno misura di potenza. - Scene
scenarios, switch a muro1..2e zone/sensori.
| Method | Route | Risultato |
|---|---|---|
| GET | /api/state | Stato completo: canali, gruppi, strip, scene, switch, Wi-Fi, OTA, temperatura, potenze e api.auth_required. |
| GET | /api/devices | Altri LUMA rilevati nella rete. |
| GET | /api/channels/map | Mappa dal canale logico al LEDC fisico. |
| GET | /api/wifi/scan | Scansione asincrona: {scanning, networks[]} oppure array. |
| GET | /api/config/export | Backup schema 2 privo di password, token, identità cloud e storico energetico. |
/api/state.system espone nvs_queue_overflows, nvs_queue_pending e nvs_flush_failures. Un contatore errori non nullo segnala un commit asincrono non arrivato in flash.
/api/state.inputEvents conserva in RAM gli ultimi 32 eventi SW1/SW2 in ordine, con sequence, timestamp, switchId e type. La sequenza riparte dopo il reboot e la coda non è persistente.
4 / Canali cablati 0–5
| Method | Route | Body |
|---|---|---|
| POST | /api/channel/<n> | {state?, pwm?, name?, effect?, gamma_active?, restore_after_power_loss?, dimming_ms?, max_voltage_v?, max_current_a?, max_power_w?} |
| POST | /api/channel/<n>/pwm | {"value": 0..100} |
| POST | /api/channel/<n>/effect | {"effect":"static|breathe|blink|strobe|fade|tube"} |
| POST | /api/channel/<n>/name | {"name":"..."} |
| POST | /api/channel/<n>/identify | {} |
pwm:0 non equivale allo spegnimento: usa {"state":false}, così il livello precedente viene ricordato. dimming_ms è il tempo della transizione completa 0→100%, intero 0..10000; zero è immediato.
I limiti utente non possono superare 25,5 V, 7,5 A e 180 W per canale. Il limite effettivo è 90 W a 12 V e 180 W a 24 V; il trip rapido indipendente resta 9 A. Il regolatore complessivo usa min(20,8333 A, 500 W / Vbus): 250 W a 12 V e 500 W a 24 V.
curl -fS -X POST -H "Authorization: Bearer $LUMA_TOKEN" \
-H 'Content-Type: application/json' \
http://luma.local/api/channel/0 -d '{"state":true,"pwm":60}'5 / Gruppi RGB, RGBW, CCT e strip
I gruppi analogici usano base 0 o 3; le strip S1/S2 usano base 6 e 7. Nei gruppi analogici i positivi dei canali devono essere ponticellati e i ritorni PWM restano separati. La potenza mostrata è la somma degli INA e il ramo più restrittivo governa il derating del gruppo.
| Method | Route | Body |
|---|---|---|
| POST | /api/group/<base> | {state?, brightness?, white?, color?, effect?, name?, restore_after_power_loss?} |
| POST | /api/group/<base>/color | {"color":"#rrggbb"} |
| POST | /api/group/<base>/brightness | {"value":0..100} |
| POST | /api/group/<base>/white | 0..100: intensità W RGBW o posizione CCT, da 2700 K a 6500 K. |
| POST | /api/group/<base>/effect | static, breathe, rainbow, cycle, chase, strobe, warm-mix, blink, fade, tube, cct-cycle |
| POST | /api/group/<base>/name | {"name":"..."} |
| POST | /api/strip/<port>/config | {enabled?, chip? (0..3), led_count? (1..1024), gamma?} |
| POST | /api/all | {"state":true|false} |
Per la configurazione strip, porta 0 = S1 e 1 = S2. Chip 0: WS2812/13/15/SK6812 RGB (GRB); 1: WS2811/UCS1903 RGB 800 kHz; 2: SK6812 RGBW; 3: APA102/SK9822. Il chip 3 usa S1 come data e S2 come clock, quindi esclude la seconda strip.
curl -fS -X POST -H "Authorization: Bearer $LUMA_TOKEN" \
-H 'Content-Type: application/json' \
http://luma.local/api/group/6 \
-d '{"state":true,"brightness":40,"color":"#ff0000","effect":"rainbow"}'6 / Scene e switch a muro
| Method | Route | Uso |
|---|---|---|
| GET | /api/scenarios | Elenco completo; ID stabili 0..15. |
| POST | /api/scenarios | Crea una scena con lo schema di /api/state → scenarios[]. |
| POST | /api/scenarios/<id> | Aggiorna la scena. |
| POST | /api/scenarios/<id>/run | Esegue la scena. |
| DELETE | /api/scenarios/<id> | Elimina la scena. |
| POST | /api/switch/<id> | {label?, input_type?, long_press_ms?, binding?, long_press_binding?} |
Le azioni scena sono {type:"channel"|"group"|"all", target, state, value, color?}. Per gli switch, channel_mask usa i bit 0–5 per i canali, 6/7 per S1/S2; zero significa tutto.
7 / Rete, zone e configurazione
| Method | Route | Body / result |
|---|---|---|
| POST | /api/device/name | {"name":"..."} |
| POST | /api/setup/complete | Commit atomico del wizard; richiede nome e layout validi. |
| GET | /api/zones | Snapshot completo, escluso dal polling di /api/state. |
| POST | /api/zones | Crea una zona lux con payload completo. |
| POST | /api/zones/<id> | Aggiorna la zona; l'ID è immutabile. |
| POST | /api/zones/<id>/calibrate | Avvia la calibrazione se canali e sensori sono disponibili. |
| POST | /api/wifi/connect | {"ssid":"...","password":"..."} |
| POST | /api/wifi/disconnect | {} |
| POST | /api/channels/map | [0,1,2,3,4,5] |
| POST | /api/config/import | Backup JSON completo. |
| GET | /api/config/export | Backup schema 2 sanitizzato. |
| POST | /api/config/factory-reset | Cancella NVS e riavvia; 409 durante OTA. |
/api/config/layout accetta: mono6, rgb_mono, mono_rgb, rgb2, rgbw_mono, cct_mono4, m_cct_m3, m2_cct_m2, m3_cct_m, mono4_cct, cct2_mono2, mono2_cct2, rgb_cct_m, cct_m_rgb, rgbw_cct.
8 / Energia e pricing
| Method | Route | Descrizione |
|---|---|---|
| GET | /api/energy/history | Oggi, mese, 366 giorni conclusi, 12 mesi conclusi, tariffa e costi non arrotondati. |
| POST | /api/prefs/kwh-price | {"value":0..1000} |
| POST | /api/prefs/currency | {"currency":"EUR","symbol":"€"} |
| POST | /api/prefs/reset-energy | Azzera solo il contatore giornaliero corrente. |
curl -fsS -H "Authorization: Bearer $LUMA_TOKEN" \
http://luma.local/api/energy/history | jq '.today, .month'
curl -fS -X POST -H "Authorization: Bearer $LUMA_TOKEN" \
-H 'Content-Type: application/json' -d '{"value":0.2845}' \
http://luma.local/api/prefs/kwh-price9 / Programmazioni locali
| Method | Route | Uso |
|---|---|---|
| GET | /api/schedules | Elenco con ID, configurazione e prossima esecuzione. |
| POST | /api/schedules | Crea e restituisce l'ID firmware con 201. |
| POST | /api/schedules/<id> | Sostituisce una programmazione. |
| DELETE | /api/schedules/<id> | Elimina una programmazione. |
| GET/POST | /api/prefs/location | Posizione privata per alba e tramonto. |
| POST | /api/prefs/timezone | Timezone POSIX nella whitelist firmware. |
| POST | /api/prefs/locale | {"locale":"en|it"} |
Massimo 16 programmazioni. Maschere canali 1..0x3f, giorni 1..0x7f (bit 0 = lunedì), minuti 0..1439, evento 0=fisso, 1=alba, 2=tramonto, offset solare -180..180. Payload impossibili restituiscono 422 invalid_schedule.
10 / OTA
| Method | Route | Purpose |
|---|---|---|
| GET | /api/ota/info · /api/ota/log | Stato partizioni e log non sensibile. |
| POST | /api/ota/check · /api/ota/rollback | Verifica aggiornamenti e rollback. Gli aggiornamenti sono firmati e provengono da ota.objex.cloud. |
11 / KNXnet/IP
La build corrente include il client KNXnet/IP tunnelling. Configurazione e mappature sono persistenti e tutte le route richiedono autenticazione.
| Method | Route | Body |
|---|---|---|
| POST | /api/knx/enabled | {"enabled":true|false} |
| POST | /api/knx/mode | {"mode":"tunnel"} |
| POST | /api/knx/gateway | {"gateway":"192.168.1.53"} |
| POST | /api/knx/port | {"port":3671} |
| POST | /api/knx/physical | {"physical":"1.1.250"} |
| POST | /api/knx/mappings | Array massimo 6 con canale e GA switch/dim/feedback. |
Gli indirizzi di gruppo sono main/middle/sub (0..31/0..7/0..255). I segreti KNX Secure non transitano nelle risposte.
12 / MQTT
Il client MQTT configurabile è separato dal collegamento privato OBJEX Cloud. Le route richiedono autenticazione locale; password e CA non vengono mai restituite.
| Method | Route | Body / result |
|---|---|---|
| GET | /api/mqtt/user | Configurazione non segreta, connessione, base topic e diagnostica. |
| POST | /api/mqtt/user | {enabled, transport, host, port, clientId, username, password, prefix, caPem} |
| POST | /api/mqtt/user/clear-password | Cancella la password memorizzata. |
| POST | /api/mqtt/user/clear-ca | Cancella il certificato CA personalizzato. |
| POST | /api/mqtt/user/publish-now | Pubblica subito stato e telemetria. |
| POST | /api/mqtt/user/test | Testa la sessione: 409 se disabilitata, 503 se non connessa. |
Campi segreti vuoti conservano il valore esistente; usa le route dedicate per cancellarli. Il trasporto mqtt richiede allowPlaintext:true. I comandi MQTT passano sempre dallo stato canonico e non aggirano le protezioni elettriche o termiche.
13 / Home Assistant
L'integrazione diretta è indipendente da MQTT: usa Zeroconf e REST HTTP nella LAN. L'inventario segue il Channel setup e presenta mono, RGB, RGBW, CCT e strip come entità logiche.
| Method | Route | Body / result |
|---|---|---|
| GET | /api/home-assistant | Opt-in, trasporto local_http, versione API, identità stabile e inventario. |
| POST | /api/home-assistant | {"enabled":true|false} |
Non creare manualmente switch REST YAML. Abilita Settings → Protocols → Home Assistant, installa il componente luma e completa il pairing in Settings → Devices & services. La password viene usata una volta; il componente conserva solo il token dedicato.
14 / Limiti, errori e concorrenza
- Body ordinari: massimo 8 KB e 4 s; login: 512 B; import autenticato: 64 KB e 10 s.
400JSON/tipo/URL non valido;401autenticazione mancante o scaduta;404risorsa assente;409conflitto;422configurazione impossibile;500persistenza fallita;503sottosistema non pronto.- Import, mappa canali, scene, programmazioni e zone ripristinano lo snapshot precedente in caso di errore.
- Non inviare comandi concorrenti sullo stesso campo aspettandoti un merge: prevale l'ultimo comando valido e lo stato firmware resta la fonte di verità.
15 / Disponibilità delle funzioni
- Gli endpoint DALI
/api/dali/*sono feature-gated e assenti dalla build corrente. - KNX è abilitato. Una build che lo escluda restituisce
404da/api/knx/*senza modificare la configurazione. - MQTT cloud è gestito automaticamente e non espone comandi HTTP manuali. Il client MQTT pubblico usa credenziali e namespace indipendenti.
- L'API può crescere con il firmware; in caso di dubbio
/api/stateè lo specchio fedele delle funzioni disponibili.
16 / Operazioni distruttive
Queste operazioni possono cancellare dati, interrompere il servizio o revocare l'accesso. Esporta la configurazione e verifica il target prima di eseguirle.
POST /api/config/factory-reset cancella NVS e riavvia il dispositivo.
POST /api/config/import sostituisce la configurazione corrente con il backup validato.
POST /api/ota/rollback cambia la partizione firmware attiva.
DELETE /api/scenarios/<id> / DELETE /api/schedules/<id>
DELETE /api/tokens/<id> interrompe immediatamente l'integrazione che usa quel token.
Nessuna sezione corrisponde alla ricerca.