Los sistemas IoT de monitorización de ganado permiten a los ganaderos vigilar los animales, el agua y las condiciones de los alojamientos sin recorrer cada parcela dos veces al día, ya sea en una estancia de la pampa argentina, un hato lechero en Colombia o una dehesa en España. En esta guía diseñarás una instalación completa: collares y sensores LoRaWAN en el campo, un servidor de red que decodifica los uplinks y un broker MQTT que convierte esas lecturas en un árbol de topics que tus paneles y alertas pueden usar. También obtendrás un puente funcional en Python y un patrón de alertas que puedes probar hoy mismo en el servidor MQTT público gratuito.
Qué mide realmente la monitorización de ganado con IoT
La mayoría de los problemas de un rebaño se manifiestan primero como un cambio en unas pocas señales sencillas. Un buen sistema no intenta medirlo todo; mide el puñado de cosas que, de otro modo, exigirían que alguien saliera en quad.
| Qué monitorizas | Sensor típico | Por qué importa | Intervalo de envío |
|---|---|---|---|
| Posición del animal | Collar GPS o crotal LoRaWAN | Animales escapados, patrones de pastoreo, localizar una vaca a punto de parir | 15–60 min, más rápido con movimiento |
| Actividad | Acelerómetro en el collar o el crotal | Detección de celo, cojeras, enfermedad (menos movimiento) | Agregado cada 15–60 min |
| Nivel del bebedero | Sensor de nivel ultrasónico o de presión | Un bebedero seco en verano es una emergencia | 10–30 min |
| Válvula de boya / caudal | Caudalímetro de pulsos en la línea de suministro | Detecta válvulas rotas y fugas | Totales cada 15 min |
| Temperatura y humedad del establo | Sensor de clima (a menudo con cálculo de THI) | Estrés térmico en alojamientos de vacuno de leche y avicultura | 5–10 min |
| Amoniaco / CO2 | Sensor de gases en el establo | Problemas de ventilación, salud respiratoria | 5–10 min |
| Tensión del pastor eléctrico | Monitor de cerca eléctrica | Una cerca cortocircuitada deja salir a los animales | 15 min |
Los intervalos importan porque casi todos estos dispositivos funcionan con baterías y con los límites de ciclo de trabajo de LoRaWAN. Un collar que informa cada minuto agotará pronto la batería y, en muchas regiones, también superará lo que la red debería transportar. Planifica uplinks lentos y regulares, más mensajes activados por eventos cuando algo cambia.
Por qué LoRaWAN en el campo y MQTT detrás
Los pastos son extensos y rara vez tienen Wi-Fi o cobertura móvil fiable a ras de suelo. LoRaWAN encaja bien porque un único gateway en el tejado del establo o en un poste puede cubrir una gran superficie, y los sensores pueden funcionar mucho tiempo con una batería. El inconveniente es el ancho de banda: los payloads son diminutos, normalmente una docena de bytes de binario empaquetado.
LoRaWAN no entrega los datos directamente a tu aplicación. La cadena es así:
- El collar o el sensor del bebedero envía un uplink por radio.
- Uno o varios gateways lo reenvían a un servidor de red LoRaWAN, como The Things Stack o ChirpStack.
- El servidor de red decodifica el payload con un códec (una pequeña función JavaScript) y publica un evento JSON.
- Tu integración toma ese evento y lo pone a disposición de paneles, alertas y almacenamiento.
Los dos principales servidores de red exponen los uplinks por MQTT, pero sus topics son específicos de cada red y están llenos de metadatos de radio. Un patrón práctico es ejecutar un pequeño puente que se suscribe al servidor de red y republica un mensaje limpio, orientado a la explotación, en tu propio broker MQTT. Todo lo que hay aguas abajo (paneles, Home Assistant, Node-RED, una app móvil) habla entonces con un árbol de topics estable que no cambia si cambias de servidor de red. Las guías sobre la integración MQTT de The Things Network y ChirpStack MQTT cubren en detalle la parte del servidor de red.
Si el concepto de un centro de mensajes central es nuevo para ti, merece la pena leer la breve explicación de qué hace un broker MQTT antes de continuar.
Diseño del árbol de topics
Nombra los topics según la explotación, no según la radio. Un árbol que sigue el orden instalación, zona y activo es fácil de leer y de suscribir con comodines:
farm1/pasture-north/animals/cow-0412/position
farm1/pasture-north/animals/cow-0412/activity
farm1/pasture-north/troughs/trough-03/level
farm1/barn-a/climate/env-01/telemetry
farm1/barn-a/fence/energizer-1/voltage
farm1/status/bridge
Unas pocas reglas lo mantienen manejable:
- Usa ID estables (número de crotal, número de bebedero) en los topics, no DevEUI. Conserva el DevEUI en el payload para la resolución de problemas.
- Retén la última lectura de bebederos, clima y tensión de la cerca, para que un panel que se abra a las 5 de la mañana muestre al instante el estado actual.
- No retengas las alarmas como comandos. Las alertas son eventos; una alarma retenida que se reproduce en cada reconexión genera confusión.
- Mantén los payloads como JSON pequeño con una marca de tiempo del servidor de red, porque lo que importa es la hora del uplink, no la hora a la que tu puente lo procesó.
Ejemplo de mensaje de bebedero:
{
"ts": "2026-10-16T05:42:10Z",
"level_pct": 18,
"level_cm": 9.4,
"battery_v": 3.52,
"rssi": -112,
"snr": -4.5,
"dev_eui": "a84041000181c2f1"
}
Construcción del puente: del servidor de red a MQTT
El siguiente puente se suscribe a los eventos de uplink de ChirpStack v4, extrae el campo decodificado object, asigna cada dispositivo a un topic de la explotación y lo republica. Para la primera prueba publica en el área pública de broker.connectmq.com, que no necesita cuenta pero que cualquiera puede leer, así que usa un prefijo aleatorio y solo datos de prueba.
Instala la biblioteca:
pip install "paho-mqtt>=2.0"
import json
import time
import uuid
import paho.mqtt.client as mqtt
# ChirpStack v4 (local o alojado) - ajústalo a tu servidor de red
LNS_HOST = "chirpstack.local"
LNS_PORT = 1883
LNS_TOPIC = "application/+/device/+/event/up"
# Broker de destino - primero el área pública de pruebas, credenciales después
DEST_HOST = "broker.connectmq.com"
DEST_PORT = 1883
PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:8]}/farm1"
# DevEUI -> (zona, tipo, id del activo)
DEVICES = {
"a84041000181c2f1": ("pasture-north", "troughs", "trough-03"),
"70b3d57ed005a1b2": ("pasture-north", "animals", "cow-0412"),
"a84041000181d004": ("barn-a", "climate", "env-01"),
}
dest = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"farm-bridge-{uuid.uuid4().hex[:6]}")
dest.will_set(f"{PREFIX}/status/bridge", "offline", qos=1, retain=True)
dest.connect(DEST_HOST, DEST_PORT, keepalive=60)
dest.loop_start()
dest.publish(f"{PREFIX}/status/bridge", "online", qos=1, retain=True)
def on_connect(client, userdata, flags, reason_code, properties):
print("Connected to network server:", reason_code)
client.subscribe(LNS_TOPIC, qos=1)
def on_message(client, userdata, msg):
try:
event = json.loads(msg.payload)
except json.JSONDecodeError:
return
dev_eui = event.get("deviceInfo", {}).get("devEui", "").lower()
if dev_eui not in DEVICES:
print("Unknown device", dev_eui)
return
area, kind, asset = DEVICES[dev_eui]
decoded = event.get("object") or {}
rx = (event.get("rxInfo") or [{}])[0]
out = dict(decoded)
out["ts"] = event.get("time")
out["dev_eui"] = dev_eui
out["rssi"] = rx.get("rssi")
out["snr"] = rx.get("snr")
leaf = {"troughs": "level", "animals": "position",
"climate": "telemetry"}.get(kind, "telemetry")
topic = f"{PREFIX}/{area}/{kind}/{asset}/{leaf}"
retain = kind != "animals"
dest.publish(topic, json.dumps(out), qos=1, retain=retain)
print("->", topic, out)
lns = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"farm-lns-{uuid.uuid4().hex[:6]}")
lns.on_connect = on_connect
lns.on_message = on_message
lns.connect(LNS_HOST, LNS_PORT, keepalive=60)
print("Publishing under", PREFIX)
try:
lns.loop_forever()
except KeyboardInterrupt:
dest.publish(f"{PREFIX}/status/bridge", "offline", qos=1, retain=True)
time.sleep(0.5)
Observa el resultado desde cualquier equipo:
mosquitto_sub -h broker.connectmq.com -p 1883 -i farm-viewer-7731 -t "connectmq/demo/<your-id>/farm1/#" -v
El servidor público admite 8 niveles de topic, así que connectmq/demo/<id>/farm1/pasture-north/troughs/trough-03/level, con exactamente 8 niveles, es el máximo; para árboles más profundos, elimina el nivel farm1 durante las pruebas. La página del servidor MQTT público gratuito enumera los demás límites.
Alertas a las que los ganaderos realmente responden
Los paneles son útiles, pero en una explotación el valor está en las alertas. Empieza con una lista corta y ajústala para que la gente no aprenda a ignorar las notificaciones.
- Nivel del bebedero por debajo del 25 por ciento en dos lecturas consecutivas (una sola lectura puede deberse a un animal bebiendo).
- Ningún uplink de un sensor de bebedero o de cerca durante 3 intervalos, lo que suele indicar una batería agotada o un sensor dañado.
- Tensión de la cerca por debajo de tu umbral (muchos ganaderos usan unos pocos kilovoltios) en dos lecturas.
- Animal fuera de una geocerca, evaluado en los mensajes de posición.
- Índice de temperatura-humedad del establo por encima de tu límite de estrés térmico en alojamientos de vacuno de leche o avicultura.
- Caída de actividad respecto a la media reciente del propio animal, señalada para inspección y no como emergencia.
Para umbrales numéricos como el nivel del bebedero o la temperatura del establo, el portal de ConnectMQ incluye reglas de alerta por umbral y un registro de alertas, de modo que puedes configurar "level_pct por debajo de 25" en un topic sin escribir código. Las geocercas y las comprobaciones de "sin datos durante 3 intervalos" requieren algo de lógica, que puedes ejecutar en Node-RED o en un pequeño suscriptor en Python que se conecta como un cliente MQTT normal:
def inside_fence(lat, lon, fence):
# fence = (min_lat, min_lon, max_lat, max_lon) - rectángulo delimitador simple
return fence[0] <= lat <= fence[2] and fence[1] <= lon <= fence[3]
Un rectángulo delimitador es tosco pero robusto; las geocercas poligonales son mejores para parcelas irregulares, y una biblioteca como Shapely lo hace sencillo.
Problemas habituales en el campo y cómo evitarlos
- Precisión del GPS y batería. Los collares que calculan la posición en cada uplink se agotan rápido. Prefiere dispositivos que informen con menos frecuencia en reposo y más a menudo cuando el acelerómetro detecta movimiento.
- Ubicación del gateway. La altura es lo que más cuenta. Un gateway en la cumbrera del establo con una antena exterior adecuada suele cubrir mucho más que uno dentro de un edificio.
- Deriva del códec. Si un fabricante cambia el firmware, los nombres de los campos decodificados pueden cambiar. Mantén la asignación del puente en un único lugar y registra los campos desconocidos.
- Confianza en el reloj. Usa la marca de tiempo del servidor de red. De lo contrario, los puentes que se reinician pueden crear huecos o duplicados en tu historial.
- Almacenamiento. El broker es un centro en tiempo real, no un histórico. Envía las lecturas a una base de datos con Telegraf o Node-RED si necesitas el historial de toda una temporada para analizar el pastoreo.
- No publiques datos de la explotación en abierto. La ubicación de los animales revela dónde está el ganado valioso. El servidor público es solo para pruebas y prototipos, no para datos de producción.
De la prueba al despliegue en la explotación
Cuando el puente funcione, cambia el destino a un broker privado con credenciales y TLS. Con un broker MQTT gestionado no tienes que ejecutar ni parchear el broker tú mismo, algo importante cuando la persona responsable del sistema también lo es de los partos. En ConnectMQ, crea un broker en el portal, copia el usuario, la contraseña y el client ID generados y cambia la conexión de destino:
DEST_HOST = "broker.connectmq.com" # o el host que aparece en tu portal
DEST_PORT = 8883
dest = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="YOUR_CLIENT_ID")
dest.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
dest.tls_set() # el paquete de CA del sistema valida el certificado de Let's Encrypt
El plan gratuito Serverless admite hasta 25 conexiones, lo que cubre holgadamente un puente, un panel, una instancia de Node-RED y algunos teléfonos. Las explotaciones más grandes con muchas sedes pueden pasar a un plan de pago con más conexiones y suscripciones compartidas para consumidores con balanceo de carga. Para una visión más amplia de la automatización agrícola, incluidos el riego y los invernaderos, consulta la guía de IoT para agricultura inteligente y la guía de automatización IoT.
Conecta los sensores de tu explotación a ConnectMQ
ConnectMQ ofrece a tu puente LoRaWAN, tus paneles y tus herramientas de alertas un lugar seguro donde encontrarse, con TLS, credenciales generadas y alertas por umbral integradas en el portal. Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y apunta a él tu puente en pocos minutos.
Preguntas frecuentes
¿Necesito LoRaWAN para la monitorización de ganado con IoT?
No siempre. Los establos con Wi-Fi pueden usar sensores Wi-Fi o Ethernet que publiquen MQTT directamente, pero en pastos abiertos LoRaWAN o el IoT celular suelen ser la única opción práctica por la distancia y la duración de la batería.
¿Pueden los collares GPS publicar MQTT directamente?
La mayoría de los collares LoRaWAN no pueden; envían uplinks a un servidor de red, que es quien publica MQTT. Los collares celulares a veces publican MQTT o HTTP directamente, y en ambos casos un puente puede normalizar los datos en tu árbol de topics.
¿Con qué frecuencia deben informar los sensores de bebedero?
Cada 10 a 30 minutos es un equilibrio habitual entre duración de la batería y aviso temprano. Combínalo con una alerta ante dos lecturas bajas consecutivas para evitar falsas alarmas cuando los animales beben.
¿Es seguro el servidor MQTT público gratuito para datos reales de la explotación?
No. Cualquiera puede leer el área pública de broker.connectmq.com, que está pensada para pruebas. Usa un broker privado con credenciales y TLS para los datos de producción, especialmente la ubicación de los animales.



