← Volver al blog

Receta: conectar una ESP32-CAM y datos IoT

Transmití cuadros MJPEG desde una cámara de dos dólares por una sola WebSocket, mandá lecturas de sensores por la misma conexión, ingerí MQTT de tu flota, y convertí cualquiera de esos en un trigger de flujo.

4 min de lectura
Read in English

Por qué ingesta IoT

Una ESP32-CAM cuesta un par de dólares y no tiene codificador H.264, así que la vía RTMP habitual necesita un salto de transcode. La ingesta por WebSocket de StreamHub toma los cuadros MJPEG crudos de la cámara directamente — y deja que el mismo dispositivo mande datos de sensores por el mismo socket. Sumá MQTT-in para el resto de tu flota, y cada lectura se vuelve un evento sobre el que podés automatizar.

La arquitectura en palabras

El dispositivo abre una WebSocket a /ingest/ws, autenticada con una clave wsk_, y manda cuadros JPEG completos como mensajes binarios. Los espectadores tiran esos cuadros como MJPEG sin relay y sin transcode. Por el mismo socket el dispositivo puede mandar cuadros de texto data, y un suscriptor MQTT-in aparte tira mensajes de tu broker; ambos convergen en un único evento iot.data que se reparte a webhooks y a Streamflow.

1. Aprovisionar una cámara WebSocket

export BASE="https://your-server.example.com/api/v1"
export TOKEN="sk_...."

curl -s -X POST $BASE/apps/iot/ws-ingest -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"room":"cam1","identity":"porton-norte"}'

La respuesta devuelve un id (wsi_…), una streamKey (wsk_…), y las wsUrl, mjpegUrl y playerUrl.

2. Apuntar el dispositivo al socket

La ESP32 conecta y transmite cuadros JPEG:

wss://your-server.example.com/ingest/ws?app=iot&room=cam1&key=wsk_...

Cada mensaje binario es un JPEG completo (FF D8 … FF D9). Al conectar, el servidor manda un cuadro ready con los límites que va a aplicar (maxFps 15, maxFrameBytes, y los topes de cuadros de datos).

3. Mandar datos de sensores por la misma conexión

El dispositivo manda un cuadro de texto para publicar una lectura:

{ "type": "data", "topic": "door", "data": { "open": true, "battery": 87 } }

Eso se vuelve un evento iot.data { topic, deviceId, data, source: "ws" }. Límites de cuadros de datos (de features.ws_ingest): max_data_bytes 16384, max_data_per_sec 5 — un cuadro de datos sobredimensionado se descarta (solo un JPEG sobredimensionado cierra el socket).

4. Ingerir MQTT del resto de la flota

Agregá una lista subscribe a la config mqtt de la app para que los mensajes del broker se vuelvan el mismo evento:

mqtt:
  enabled: true
  url: "mqtt://broker.example.com:1883"
  subscribe:
    - topic: devices/#

Cada mensaje entrante despacha iot.data { topic, data, source: "mqtt" } (JSON si es válido, si no la cadena cruda), con tope de 64 suscripciones y 64 KB por mensaje.

5. Mirar la cámara y disparar un flujo

Mirá el MJPEG en vivo sin token cuando la reproducción pública está activa:

https://your-server.example.com/live/iot/cam1/mjpeg
https://your-server.example.com/live/iot/cam1/frame.jpg

Después, en Streamflow, una caja trigger.mqtt que dispara ante el tema door (coincidido desde el cuadro de datos WS o desde MQTT-in) puede capturar una foto y avisarte en el instante en que se abre el portón.

Qué deberías ver

Los cuadros de la cámara aparecen en la URL MJPEG a segundos de que el dispositivo conecta; cada lectura de sensor y cada mensaje del broker aparece como un evento iot.data en tu log de webhooks; y un flujo de Streamflow atado al tema corre en el momento justo.

Resolución de problemas

  • El socket cierra al instante — verificá que la clave, la app y la sala coincidan con la cámara aprovisionada; un desajuste cierra con 4401, una función deshabilitada o cuota excedida con 4403.
  • Cuadros rechazados — un JPEG por encima de max_frame_kb (256 KB por defecto) cierra con 4413; bajá la resolución/calidad de la cámara.
  • Sin audio, sin grabación — la ingesta WS v1 es solo video y datos: sin audio (la cámara no tiene micrófono), sin grabación MP4/HLS, sin bitrate adaptativo. Para medio completo, usá la vía de relay ffmpeg a RTMP.
  • ¿Datos de salida? — recibir datos de vuelta en el dispositivo por el socket todavía no está implementado; esta etapa es solo datos de entrada.

Cierre

Cámaras y sensores baratos, transmitidos y automatizados en tu propio servidor — esa es la historia IoT sin una nube de dispositivos. Si querés firmware, un flujo de aprovisionamiento de flota, o los flujos cableados de punta a punta, nuestro equipo los construye alrededor de la ingesta open source como servicio de consultoría.