Fundamentos de MQTT

Topics $SYS de MQTT: lo que te cuentan los topics de sistema del broker

Una guía práctica del árbol de topics $SYS: de dónde viene, por qué los comodines lo omiten, qué publican ahí los brokers al estilo Mosquitto y cómo vigilar el estado de conexión de los clientes en ConnectMQ.

Ilustración de los topics SYS de MQTT que se ramifican desde un broker en estadísticas de conexiones, clientes y mensajes
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

Los topics SYS de MQTT son la rama $SYS/... del árbol de topics en la que un broker publica información sobre sí mismo en lugar de datos de aplicación. En este artículo aprenderás de dónde viene la convención, por qué una suscripción simple a # nunca los muestra, qué expone ahí un broker típico y cómo usar el único topic de sistema que publica ConnectMQ para seguir el estado de conexión de los clientes.

¿Qué son los topics SYS de MQTT?

La especificación de MQTT reserva los topics que empiezan por $ para uso específico del broker. Se supone que los clientes no deben publicar datos de aplicación en ellos, y la especificación deja su contenido por completo en manos de la implementación. Con los años, $SYS/ se convirtió en el prefijo de facto para la telemetría del broker: tiempo de actividad, versión, número de clientes conectados, contadores de mensajes y bytes, y datos de mantenimiento similares.

La palabra importante es "de facto". No existe una lista estándar de topics $SYS, ni un formato de payload estándar, ni garantía alguna de que un broker concreto publique alguno de ellos. Mosquitto popularizó un árbol amplio, otros brokers publican un subconjunto o una estructura diferente, y muchos brokers MQTT gestionados sustituyen la mayor parte por dashboards y APIs. Trata cada topic $SYS como un detalle de implementación del broker concreto al que estás conectado.

Por qué una suscripción a # no los muestra

Esto sorprende a casi todo el mundo la primera vez. Si te suscribes a # recibes todos los mensajes de aplicación del broker, pero nada de $SYS. Es así por diseño. La especificación de MQTT en mqtt.org establece que un filtro de topic que empieza con un comodín (# o +) no debe coincidir con nombres de topic que empiezan por $.

La regla protege a los suscriptores "atrapalotodo" habituales de verse inundados con estadísticas del broker, y evita que las herramientas que replican # vuelvan a publicar por accidente datos del sistema. Para leer los topics de sistema tienes que nombrar explícitamente el prefijo $SYS:

#                  -> solo topics de aplicación, nunca $SYS
$SYS/#             -> todo lo que hay bajo $SYS (si el broker lo permite)
$SYS/broker/+/+    -> una profundidad concreta bajo $SYS/broker
+/broker/uptime    -> NO coincide con $SYS/broker/uptime

El mismo razonamiento se aplica a las reglas de los comodines en los topics MQTT en general: los comodines funcionan nivel a nivel, y el nivel inicial con $ queda simplemente excluido de la coincidencia de comodines en la primera posición.

Un árbol $SYS típico (ejemplo con Mosquitto)

Mosquitto es la referencia más habitual, así que es una buena forma de ver qué pueden contener los topics de sistema. Con la configuración por defecto, publica una instantánea de sus contadores cada pocos segundos. El intervalo se controla en mosquitto.conf:

# mosquitto.conf
# Publica actualizaciones de $SYS cada 10 segundos (0 desactiva las actualizaciones periódicas)
sys_interval 10

Una selección de los topics que verás en una instancia local de Mosquitto:

Topic Significado
$SYS/broker/version Cadena de versión del broker
$SYS/broker/uptime Segundos desde que arrancó el broker
$SYS/broker/clients/connected Clientes conectados actualmente
$SYS/broker/clients/disconnected Sesiones persistentes cuyo cliente está offline
$SYS/broker/messages/received Total de mensajes recibidos desde el arranque
$SYS/broker/messages/sent Total de mensajes enviados desde el arranque
$SYS/broker/subscriptions/count Suscripciones activas
$SYS/broker/retained messages/count Mensajes retenidos almacenados
$SYS/broker/load/messages/received/1min Media móvil de mensajes recibidos
$SYS/broker/bytes/received Total de bytes recibidos

Para observarlos en tu propio broker Mosquitto, pon el topic entre comillas para que tu shell no expanda $SYS:

mosquitto_sub -h localhost -p 1883 -i sys-watcher-01 -t '$SYS/#' -v

La mayoría de los valores se publican como mensajes retenidos, así que un suscriptor nuevo recibe la última instantánea de inmediato en lugar de esperar al siguiente intervalo. Los contadores se reinician cuando el broker se reinicia, lo que importa si los representas en gráficas: una caída a cero significa un reinicio, no una hora tranquila.

Errores comunes con los datos de $SYS

  • Dar por hecha la portabilidad. Un dashboard construido sobre los topics $SYS de Mosquitto se rompe en cuanto te pasas a otro broker. Mantén la lógica de parseo en un único lugar.
  • Olvidarte de la shell. En bash, "$SYS/#" con comillas dobles expande $SYS a una variable vacía y te suscribes a /#. Usa comillas simples.
  • Exponerlo públicamente. En un broker autoalojado, los topics de sistema revelan el número de clientes y las versiones. Restríngelos con las reglas de autorización de tu broker si es accesible desde internet.
  • Consultar con demasiada frecuencia. Un sys_interval muy corto añade tráfico sin aportar mucho. Entre diez y sesenta segundos es más que suficiente para gráficas operativas.

Topics SYS de MQTT en un broker MQTT gestionado

En un broker MQTT gestionado normalmente no necesitas un árbol $SYS amplio, porque el operador ya recoge las métricas del broker y te las muestra. Ese es el enfoque de ConnectMQ. La información a nivel de broker, como las conexiones y el tráfico, se presenta en el dashboard del portal, y el explorador de topics en directo te permite ver qué topics están activos, así que no hace falta parsear contadores de los topics de sistema.

Publica exactamente un topic de sistema:

$SYS/broker/connection/{clientId}/state

Informa del estado de conexión de un client ID concreto. Este es el dato de $SYS que el código de aplicación necesita de verdad: "¿está el dispositivo X online ahora mismo?". Todo lo demás, como el número de clientes y las tasas de mensajes, pertenece a la monitorización y no a tu flujo de datos MQTT.

Cómo vigilar el estado de conexión de un cliente

El ejemplo siguiente usa Python paho-mqtt 2.x para suscribirse al topic de estado de un dispositivo en tu broker privado. Sustituye los marcadores por las credenciales generadas en el portal y fija DEVICE_ID con el client ID del dispositivo que quieras vigilar.

import ssl
import paho.mqtt.client as mqtt

BROKER = "YOUR_BROKER_HOST"      # se muestra en el portal
PORT = 8883
DEVICE_ID = "YOUR_DEVICE_CLIENT_ID"
STATE_TOPIC = f"$SYS/broker/connection/{DEVICE_ID}/state"

def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code.is_failure:
        print(f"Connect failed: {reason_code}")
        return
    print("Connected, subscribing to", STATE_TOPIC)
    client.subscribe(STATE_TOPIC, qos=1)

def on_subscribe(client, userdata, mid, reason_code_list, properties):
    for rc in reason_code_list:
        print("SUBACK:", rc)

def on_message(client, userdata, msg):
    print(f"{msg.topic} -> {msg.payload.decode(errors='replace')}")

client = mqtt.Client(
    mqtt.CallbackAPIVersion.VERSION2,
    client_id="YOUR_CLIENT_ID",
    protocol=mqtt.MQTTv5,
)
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set(cert_reqs=ssl.CERT_REQUIRED)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message

client.connect(BROKER, PORT, keepalive=60)
client.loop_forever()

Ejecútalo y después apaga y enciende el dispositivo o detén su cliente. Verás cómo cambia el topic de estado cuando el dispositivo se desconecta y se reconecta. Antes de escribir la lógica de parseo, mira el payload real en el cliente MQTT integrado en el navegador del portal, para que tu código se ajuste a lo que envía el broker y no a lo que supones.

Estado en $SYS frente a Last Will

Puede que ya estés siguiendo la presencia con un mensaje Last Will and Testament. Ambos enfoques se complementan:

Enfoque Quién publica Ventaja Limitación
Last Will más mensaje "online" retenido El dispositivo y el broker en su nombre Funciona en cualquier broker; el topic y el payload son tuyos El dispositivo debe configurarlo bien; un cliente mal configurado nunca informa
$SYS/broker/connection/{clientId}/state El broker No requiere código en el dispositivo; refleja lo que el broker ve realmente Estructura de topic específica del broker

Un patrón sensato es mantener el Last Will para los consumidores de aplicación que ya entienden tu árbol de topics, y usar el topic de estado del broker para las herramientas de operaciones y para verificar que los dispositivos sin Will se comportan correctamente. La guía sobre el estado online de dispositivos MQTT explica en detalle el patrón basado en el Will.

Lista de comprobación de monitorización sin un gran árbol $SYS

Si vienes de un broker autoalojado en el que las gráficas de Grafana se alimentaban de $SYS, así puedes cubrir las mismas necesidades en un broker MQTT gestionado:

  1. Número de conexiones y tráfico. Usa el dashboard del broker en el portal en lugar de $SYS/broker/clients/connected.
  2. Qué topics están vivos. Usa el explorador de topics en directo en lugar de suscribirte a # desde un portátil.
  3. Presencia por dispositivo. Suscríbete a $SYS/broker/connection/{clientId}/state para los client IDs que te interesen, o usa un Last Will.
  4. Condiciones de umbral sobre los datos. Configura reglas de alerta en el portal para valores como la temperatura o la presión, y revisa el registro de alertas.
  5. Historial de métricas a largo plazo. Ejecuta tu propio suscriptor (Telegraf, un pequeño servicio en Python o Node-RED) que escriba los datos que necesitas en tu base de datos de series temporales.
  6. Control de cuotas. Vigila el reason code 0x97 de MQTT 5 (quota exceeded) en los logs de los clientes; indica que se ha alcanzado un límite del plan.

Pruebas en el servidor público

Si solo quieres experimentar con la estructura de topics, el servidor MQTT público gratuito en broker.connectmq.com acepta conexiones anónimas con cualquier client ID único y no vacío. Ten en cuenta que cualquiera puede leer el área pública, así que usa un prefijo único y nunca envíes datos sensibles ni de producción:

# Terminal 1: suscríbete a tu propio prefijo de demostración
mosquitto_sub -h broker.connectmq.com -p 1883 -i sys-demo-sub-7f3a \
  -t 'connectmq/demo/7f3a/#' -v

# Terminal 2: publica un mensaje de prueba
mosquitto_pub -h broker.connectmq.com -p 1883 -i sys-demo-pub-7f3a \
  -t 'connectmq/demo/7f3a/hello' -m 'hi'

Observa que la suscripción a # del terminal 1 ve tu mensaje, pero nada bajo $SYS, exactamente como exige la especificación. Para una visión más amplia de cómo encajan los topics, las suscripciones y el broker, el tutorial de MQTT es una buena lectura a continuación, y las convenciones de nombres de topics MQTT explican cómo mantener tu propio árbol tan ordenado como el árbol de sistema de un broker.

Empieza con ConnectMQ

¿Quieres métricas del broker sin parsear contadores de $SYS? Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito. En pocos minutos tendrás credenciales generadas, un dashboard, un explorador de topics en directo y el topic $SYS/broker/connection/{clientId}/state para la presencia de cada dispositivo.

Preguntas frecuentes

¿Por qué suscribirse a # no muestra los mensajes de $SYS?

La especificación de MQTT establece que los filtros de topic que empiezan con un comodín no deben coincidir con los topics que empiezan por $. Suscríbete explícitamente a $SYS/# si tu broker publica topics de sistema y te permite leerlos.

¿Están estandarizados los topics SYS de MQTT?

No. Solo está estandarizada la reserva de los topics con prefijo $. Los nombres de topic, los payloads y los intervalos de actualización varían entre brokers, así que el código que los lee es específico de cada broker.

¿Qué topic $SYS publica ConnectMQ?

ConnectMQ publica $SYS/broker/connection/{clientId}/state, que informa del estado de conexión de un cliente. Las métricas del broker, como las conexiones y el tráfico, se muestran en cambio en el dashboard del portal.

¿Puedo publicar mis propios mensajes en topics $SYS?

No deberías. El prefijo $ está reservado para el broker, y la mayoría de los brokers rechazan o ignoran las publicaciones de clientes en él. Pon tus propios datos de estado bajo el árbol de topics de tu aplicación.

Artículos relacionados

¿Quién inventó MQTT? La historia, de los oleoductos al IoT

MQTT lo inventaron en 1999 Andy Stanford-Clark, de IBM, y Arlen Nipper, de Arcom, para monitorizar oleoductos vía satélite. Sigue su camino hacia el open source, OASIS, ISO y los brokers MQTT gestionados en la nube de hoy.

8 min de lectura

Por qué tu cliente MQTT se desconecta constantemente (y cómo solucionarlo)

Los bucles de reconexión son uno de los problemas más habituales de MQTT. Conoce las cinco causas típicas, desde los client ID duplicados hasta los timeouts de keep alive y los paquetes demasiado grandes, y sigue un flujo de diagnóstico que localiza la tuya.

9 min de lectura

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.