/

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.

Firmware minimo 0.9.63Revisione 26 agosto 2026HTTP / JSON / LAN

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.

Documentazione statica

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.

MethodRouteDescrizione
GET/api/auth/statusPubblico: indica soltanto se è richiesto lo sblocco.
POST/api/auth/loginPubblico, massimo 512 B. Scambia la password con una sessione RAM revocabile.
POST/api/auth/passwordImposta, cambia o rimuove la password locale e revoca le sessioni esistenti.
POST/api/tokensCrea 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/state

Token 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..5 per LED mono PWM, con misura INA219 per canale.
  • Gruppi RGB/RGBW/CCT con base 0 o 3, secondo il layout.
  • Strip indirizzabili S1/S2 come gruppi virtuali 6 e 7; usano alimentazione esterna e non hanno misura di potenza.
  • Scene scenarios, switch a muro 1..2 e zone/sensori.
MethodRouteRisultato
GET/api/stateStato completo: canali, gruppi, strip, scene, switch, Wi-Fi, OTA, temperatura, potenze e api.auth_required.
GET/api/devicesAltri LUMA rilevati nella rete.
GET/api/channels/mapMappa dal canale logico al LEDC fisico.
GET/api/wifi/scanScansione asincrona: {scanning, networks[]} oppure array.
GET/api/config/exportBackup 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

MethodRouteBody
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.

Limiti elettrici

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.

MethodRouteBody
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>/white0..100: intensità W RGBW o posizione CCT, da 2700 K a 6500 K.
POST/api/group/<base>/effectstatic, 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

MethodRouteUso
GET/api/scenariosElenco completo; ID stabili 0..15.
POST/api/scenariosCrea una scena con lo schema di /api/state → scenarios[].
POST/api/scenarios/<id>Aggiorna la scena.
POST/api/scenarios/<id>/runEsegue 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

MethodRouteBody / result
POST/api/device/name{"name":"..."}
POST/api/setup/completeCommit atomico del wizard; richiede nome e layout validi.
GET/api/zonesSnapshot completo, escluso dal polling di /api/state.
POST/api/zonesCrea una zona lux con payload completo.
POST/api/zones/<id>Aggiorna la zona; l'ID è immutabile.
POST/api/zones/<id>/calibrateAvvia 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/importBackup JSON completo.
GET/api/config/exportBackup schema 2 sanitizzato.
POST/api/config/factory-resetCancella 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

MethodRouteDescrizione
GET/api/energy/historyOggi, 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-energyAzzera 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-price

9 / Programmazioni locali

MethodRouteUso
GET/api/schedulesElenco con ID, configurazione e prossima esecuzione.
POST/api/schedulesCrea 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/locationPosizione privata per alba e tramonto.
POST/api/prefs/timezoneTimezone 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

MethodRoutePurpose
GET/api/ota/info · /api/ota/logStato partizioni e log non sensibile.
POST/api/ota/check · /api/ota/rollbackVerifica 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.

MethodRouteBody
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/mappingsArray 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.

MethodRouteBody / result
GET/api/mqtt/userConfigurazione 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-passwordCancella la password memorizzata.
POST/api/mqtt/user/clear-caCancella il certificato CA personalizzato.
POST/api/mqtt/user/publish-nowPubblica subito stato e telemetria.
POST/api/mqtt/user/testTesta 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.

MethodRouteBody / result
GET/api/home-assistantOpt-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.
  • 400 JSON/tipo/URL non valido; 401 autenticazione mancante o scaduta; 404 risorsa assente; 409 conflitto; 422 configurazione impossibile; 500 persistenza fallita; 503 sottosistema 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 404 da /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.

Factory reset

POST /api/config/factory-reset cancella NVS e riavvia il dispositivo.

Import configurazione

POST /api/config/import sostituisce la configurazione corrente con il backup validato.

OTA rollback

POST /api/ota/rollback cambia la partizione firmware attiva.

Eliminazione scene e programmazioni

DELETE /api/scenarios/<id> / DELETE /api/schedules/<id>

Revoca token

DELETE /api/tokens/<id> interrompe immediatamente l'integrazione che usa quel token.

Nessuna sezione corrisponde alla ricerca.