Topics MQTT, payloads y ejemplo ESP32

Convención de topics + JSON payloads + código MicroPython funcional + fallback HTTP.

Convención de topics MQTT

Reemplaza {device_id} por el UUID de tu dispositivo y {code} por el code de tu sensor o actuador.

DirecciónTopicQuién publica
Device → Abiorabior/{device_id}/sensors/{code}Tu firmware (lectura de sensor)
Device → Abiorabior/{device_id}/stateTu firmware (heartbeat online/offline)
Device → Abiorabior/{device_id}/ack/{cmd_id}Tu firmware (confirmar comando recibido)
Abior → Deviceabior/{device_id}/commands/{code}Servidor (al disparar regla/quehacer/procedpaso)

Payloads JSON

Lectura de sensor (sensors/<code>):

{"value": 25.5, "ts": "2026-04-29T14:30:00Z"}

ts es opcional — si se omite, Abior usa la hora de recepción.

Estado del device (state):

{"online": true, "fw_version": "1.0.3"}

Comando del servidor (commands/<code>):

{"cmd_id": "uuid-del-comando", "ts": "2026-04-29T14:30:00Z", "accion": "on", "valor": 80}

ACK del device (ack/<cmd_id>):

{"ok": true, "result": {"estado_final": "on"}}

Ejemplo completo MicroPython (ESP32)

import network, ssl, ujson, time
from umqtt.simple import MQTTClient

WIFI_SSID = "MiRed"
WIFI_PASS = "supersecreto"
DEVICE_ID = "uuid-de-tu-dispositivo-en-abior"
API_TOKEN = "tu-api-token-key"  # GET /api/desar/dispositivos/{id}/api-tokens/

# 1. WiFi
wlan = network.WLAN(network.STA_IF); wlan.active(True)
wlan.connect(WIFI_SSID, WIFI_PASS)
while not wlan.isconnected(): time.sleep(0.5)

# 2. MQTT con TLS al broker publico Abior
client = MQTTClient(
    client_id=DEVICE_ID,
    server="abior.art",
    port=8883,
    user=API_TOKEN,
    password="token",
    keepalive=60,
    ssl=True,
    ssl_params={"server_hostname": "abior.art"},
)

# 3. Suscribirse a comandos
def on_command(topic, msg):
    cmd = ujson.loads(msg)
    cmd_id = cmd.get("cmd_id")
    code = topic.decode().split("/")[-1]
    print("Comando recibido:", code, cmd)
    # ... ejecutar (p.ej. encender relay) ...
    client.publish(
        f"abior/{DEVICE_ID}/ack/{cmd_id}",
        ujson.dumps({"ok": True}),
    )

client.set_callback(on_command)
client.connect()
client.subscribe(f"abior/{DEVICE_ID}/commands/+")

# 4. Heartbeat
client.publish(f"abior/{DEVICE_ID}/state", ujson.dumps({"online": True}))

# 5. Loop: leer sensor cada 30s + escuchar comandos
while True:
    temperatura = leer_dht22()  # tu funcion
    client.publish(
        f"abior/{DEVICE_ID}/sensors/temp",
        ujson.dumps({"value": temperatura}),
    )
    for _ in range(30):
        client.check_msg()  # non-blocking
        time.sleep(1)

Fallback HTTP (sin MQTT)

Si tu device no soporta MQTT pero sí HTTP, usa los webhooks REST:

curl -X POST https://abior.art/api/iot/webhook/<DEVICE_ID>/sensor/temp/ \
  -H "Authorization: Token <API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"value": 25.5}'

Endpoints disponibles:

EndpointMétodoUso
/api/iot/webhook/{device_id}/sensor/{code}/POSTReportar lectura
/api/iot/webhook/{device_id}/state/POSTHeartbeat
/api/iot/webhook/{device_id}/ack/{cmd_id}/POSTConfirmar comando

Comandos del servidor en modo HTTP: Abior los encola y tu device los pollea con GET /api/iot/webhook/{device_id}/comandos-pendientes/ (cada N segundos).

Verificar que funciona

Tras publicar tu primera lectura, deberías verla en:

curl https://abior.art/api/desar/lecturas/?sensor=<SENSOR_UUID> \
  -H "Authorization: Token <TU_USER_TOKEN>"

O en la app Android, en el detalle del dispositivo → tab Sensores → gráfica.

Siguiente paso: Reglas reactivas

Una vez que las lecturas llegan, puedes crear Reglas: "si temp > 28 °C entonces encender ventilador". Ver el módulo IoT en /caracteristica-iot o el detalle de tu dispositivo.

Volver al capítulo completo

Topics MQTT, payloads y ejemplo ESP32 — Conectar dispositivos IoT a Abior — guía técnica para makers — Abior | Abior