Gurglee Premium

Manda le misure a Gurglee dal tuo impianto

Se hai già una sonda che legge la temperatura o il pH, non c'è motivo di ribattere quei numeri a mano. Gurglee ti dà un indirizzo e una chiave: quello che sa fare una chiamata HTTP può scriverci dentro.

Da leggere prima di tutto il resto: non è un'integrazione con SmartLife o Tuya. Quei servizi vogliono un contratto commerciale per l'uso in produzione, e per andare noi a leggere i tuoi sensori dovremmo custodire le tue credenziali di quei cloud — una responsabilità che non vogliamo prenderci per una funzione da pochi euro al mese.

Quello che c'è, invece, funziona con qualunque sistema: Home Assistant, Node-RED, ESPHome, un controller da acquario, uno script su un Raspberry, perfino un'automazione che parte dall'app SmartLife. Il pezzo che collega il tuo sensore a Gurglee lo scrivi tu — sotto ci sono gli esempi già pronti, ed è questione di cinque righe.

1 · Come ottenere la chiave

Serve il piano Premium e un account Gurglee (le misure arrivano al tuo profilo, e da lì scendono su tutti i tuoi dispositivi).

  1. Nell'app, Menu → Strumenti → «API e integrazioni».
  2. Accendi l'interruttore API attiva.
  3. Tocca Crea una chiave e dalle un nome che ti ricordi dove finirà («Home Assistant», «ESP sala»).
  4. Copiala subito. La vedi una volta sola: sul server ne resta solo un'impronta, quindi non possiamo rimostrartela. Se la perdi, la revochi e ne fai un'altra.

La chiave comincia per glk_ e va nell'header Authorization, come un normale bearer token. Puoi averne fino a 5 attive insieme: una per sistema, così ne revochi una senza spegnere le altre.

Nella stessa schermata c'è il bottone «Prova la chiamata»: manda una richiesta vera con la tua chiave vera, ma non salva niente. È il modo più rapido per scoprire che hai sbagliato il nome della vasca, invece di guardare i log del tuo Home Assistant.

2 · Gli endpoint

Base: https://cyykgbgeswcflhxjgsag.supabase.co/functions/v1/api/v1

GET /tanks — cosa posso scrivere

La chiamata da fare per prima: dice come si chiamano le tue vasche, quali parametri seguono, con che unità, e i limiti in vigore.

curl -H "Authorization: Bearer glk_LA_TUA_CHIAVE" \
  https://cyykgbgeswcflhxjgsag.supabase.co/functions/v1/api/v1/tanks
{
  "ok": true,
  "tanks": [
    {
      "id": "0f0b…",
      "name": "Reef",
      "type": "reef",
      "volumeLiters": 300,
      "parameters": [
        { "key": "temperature", "unit": "°C", "accepts": ["°C", "°F", "K"] },
        { "key": "ph",          "unit": "pH", "accepts": ["pH"] }
      ]
    }
  ],
  "limits": { "requestsPerDay": 500, "minIntervalMinutes": { "temperature": 60, "default": 1440 } }
}

POST /readings — mandare una misura

CampoObbligatorioCos'è
tankL'id, il nome o un alias della vasca. Il nome è più comodo; se due vasche si chiamano uguale la richiesta viene respinta con l'elenco degli id, invece di indovinare.
parameterLa chiave del parametro (temperature, ph, kh…): l'elenco è nella tabella qui sotto. Valgono anche i parametri personalizzati che hai creato tu.
valueIl numero. Si accetta anche come stringa e con la virgola decimale ("24,6"), perché è quello che produce un template con la lingua italiana.
unitnoSe manca si assume l'unità canonica del parametro. Le forme scritte sono generose: C, celsius, °C, mg/L, uS/cm.
measuredAtnoQuando è stata presa, in ISO 8601 (2026-08-11T18:30:00Z) o come epoch. Se manca, adesso.
notenoFino a 500 caratteri, come nel form dell'app.
dryRunnotrue controlla tutto e non salva nulla. È quello che usa il bottone di prova.

La risposta di una scrittura andata a buon fine è un 201:

{
  "ok": true,
  "message": "Reading stored. It will show up in the app at the next sync.",
  "reading": {
    "id": "…", "tank": { "id": "0f0b…", "name": "Reef" },
    "parameter": "temperature", "value": 77, "unit": "°F",
    "valueCanonical": 25, "canonicalUnit": "°C",
    "measuredAt": "2026-08-11T18:30:00.000Z", "minIntervalMinutes": 60
  }
}

Come vedi il valore viene convertito nell'unità canonica del parametro, esattamente come quando lo digiti nell'app: manda pure i gradi Fahrenheit se il tuo sensore parla così.

3 · Parametri e unità

ChiaveCanonicaUnità accettate
temperature°C°C, °F, K
phpHpH
ammonia, nitrite, nitrateppmppm (= mg/L)
khdKHdKH, meq/L, ppm
ghdGHdGH, ppm, meq/L
tdsppmppm, µS/cm, mS/cm
salinitypptppt, SG, mS/cm
orpmVmV
calcium, magnesium, phosphate, co2, iron, potassium, silicate, copper, oxygenppmppm

Un parametro personalizzato creato nell'app funziona con la sua chiave e la sua unità: conversioni non ne conosciamo, quindi accetta solo quella.

Non serve che la vasca segua già quel parametro perché la misura venga accettata — ma per vederla nei grafici e nella panoramica conviene aggiungerlo ai parametri seguiti dell'acquario.

4 · Ogni quanto si può mandare

ParametroUna misura ogni
temperature60 minuti
tutti gli altri24 ore

Non è avarizia di spazio: un valore ogni dieci secondi non aggiunge informazione, riempie lo storico e rende i grafici illeggibili. La temperatura fa eccezione perché è l'unico valore che una sonda misura davvero in continuo e di cui interessa l'andamento nella giornata.

Se mandi prima del tempo ricevi un 429 con scritto quanti secondi mancano (anche nell'header Retry-After): la tua automazione può semplicemente riprovare al giro dopo. Il conteggio guarda solo le misure arrivate dall'API: quello che inserisci a mano nell'app non blocca il sensore.

C'è anche un tetto di 500 richieste al giorno per chiave, valide o sbagliate che siano. Serve a fermare un ciclo impazzito, non a limitare l'uso normale: con i tempi qui sopra, una vasca ben strumentata ne consuma qualche decina.

5 · Esempi pronti

Terminale (curl)

curl -X POST https://cyykgbgeswcflhxjgsag.supabase.co/functions/v1/api/v1/readings \
  -H "Authorization: Bearer glk_LA_TUA_CHIAVE" \
  -H "Content-Type: application/json" \
  -d '{"tank": "Reef", "parameter": "temperature", "value": 25.4, "unit": "°C"}'

Home Assistant

In configuration.yaml, un rest_command più un'automazione che lo chiama ogni ora:

rest_command:
  gurglee_temperatura:
    url: "https://cyykgbgeswcflhxjgsag.supabase.co/functions/v1/api/v1/readings"
    method: POST
    headers:
      Authorization: "Bearer glk_LA_TUA_CHIAVE"
      Content-Type: "application/json"
    payload: >-
      {"tank": "Reef", "parameter": "temperature",
       "value": {{ states("sensor.temperatura_acquario") }} }

automation:
  - alias: "Gurglee — temperatura ogni ora"
    trigger:
      - platform: time_pattern
        hours: "/1"
    condition:
      # Non mandare "unknown" quando il sensore non risponde: finirebbe
      # rifiutato con un 400 e riempirebbe il log di errori.
      - condition: template
        value_template: "{{ states('sensor.temperatura_acquario') not in ['unknown', 'unavailable'] }}"
    action:
      - service: rest_command.gurglee_temperatura

Node-RED

Un nodo function che prepara il messaggio, seguito da un http request (POST) verso l'endpoint:

msg.headers = {
  "Authorization": "Bearer glk_LA_TUA_CHIAVE",
  "Content-Type": "application/json"
};
msg.payload = {
  tank: "Reef",
  parameter: "temperature",
  value: msg.payload            // il numero che arriva dal sensore
};
return msg;

Python / Raspberry Pi

import requests

requests.post(
    "https://cyykgbgeswcflhxjgsag.supabase.co/functions/v1/api/v1/readings",
    headers={"Authorization": "Bearer glk_LA_TUA_CHIAVE"},
    json={"tank": "Reef", "parameter": "ph", "value": 8.12},
    timeout=20,
)

ESPHome

Direttamente dall'ESP, senza passare da Home Assistant:

http_request:
  useragent: esphome/gurglee
  timeout: 10s

sensor:
  - platform: dallas_temp
    name: "Acquario"
    id: temp_acquario
    update_interval: 60min
    on_value:
      - http_request.post:
          url: "https://cyykgbgeswcflhxjgsag.supabase.co/functions/v1/api/v1/readings"
          headers:
            Authorization: "Bearer glk_LA_TUA_CHIAVE"
            Content-Type: "application/json"
          json:
            tank: "Reef"
            parameter: "temperature"
            value: !lambda "return id(temp_acquario).state;"

PowerShell

Invoke-RestMethod -Method Post `
  -Uri "https://cyykgbgeswcflhxjgsag.supabase.co/functions/v1/api/v1/readings" `
  -Headers @{ Authorization = "Bearer glk_LA_TUA_CHIAVE" } `
  -ContentType "application/json" `
  -Body '{"tank":"Reef","parameter":"temperature","value":25.4}'

6 · SmartLife, Tuya e simili

È la domanda che arriva per prima, quindi rispondiamo per esteso.

Perché non c'è un'integrazione diretta. Il piano gratuito delle API cloud di Tuya — quello su cui gira SmartLife e buona parte dei termometri WiFi economici, Inkbird compresi — è dichiaratamente «solo per sviluppo»: per usarlo in produzione serve un contratto commerciale, con costi fuori scala per un'app da pochi euro al mese. E anche potendolo pagare, per leggere i tuoi sensori dovremmo tenere le tue credenziali di quel cloud sui nostri server: più dati sensibili di tutto il resto di Gurglee messo insieme.

Come si colma la distanza. Serve qualcosa che stia in mezzo, e quasi sempre è già in casa:

Se un giorno l'integrazione diretta diventerà sostenibile la faremo, e chi nel frattempo ha usato l'API non perderà nulla: le misure sono già dentro Gurglee, con la stessa forma.

7 · Errori

Ogni errore è un JSON con un error stabile (per il codice) e un message in inglese leggibile (per te che stai guardando i log).

HTTPerrorCosa fare
401missing_tokenManca l'header Authorization.
401invalid_tokenChiave sconosciuta o revocata. Fanne un'altra dall'app.
403api_disabledL'interruttore è spento: riaccendilo in «API e integrazioni».
403premium_requiredL'abbonamento collegato a quella chiave non è attivo.
400unknown_tank · ambiguous_tankLa risposta elenca le vasche con i loro id: usa l'id.
400unknown_parameter · bad_unit · bad_valueLa risposta dice cosa è accettato per quel parametro.
400bad_measured_atData illeggibile, nel futuro o più vecchia di un anno (di solito un epoch in secondi letto come millisecondi).
429too_soonTroppo presto per quel parametro: retryAfterSeconds dice quanto manca.
429daily_capSuperate le 500 richieste della giornata. Il contatore riparte a mezzanotte UTC.
500server_errorColpa nostra: riprova più tardi.

8 · Sicurezza e privacy

Qualcosa non torna, o hai collegato un sistema che qui non è elencato e vorresti vederlo comparire? Scrivici: [email protected].