Node-RED

Node-RED Worldmap: seguimiento de dispositivos GPS por MQTT

Convierte mensajes GPS de MQTT en marcadores en movimiento con node-red-contrib-web-worldmap. Incluye un simulador de vehículos, la función de conversión, la gestión de dispositivos inactivos, trazas y consejos para integrar el mapa en Dashboard 2.0.

Node-RED Worldmap mostrando marcadores de vehículos con rumbo moviéndose por el mapa de una ciudad a partir de datos GPS de MQTT
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

El nodo worldmap de Node-RED convierte en pocos minutos un flujo de mensajes GPS de MQTT en marcadores que se mueven sobre un mapa interactivo. En este tutorial simularás tres vehículos, convertirás sus posiciones JSON en marcadores de worldmap con rumbo y colores, señalarás los dispositivos que dejan de informar y dibujarás sus trazas. Al terminar tendrás un rastreador en vivo funcional que podrás apuntar a hardware GPS real.

Cómo funciona el nodo Worldmap de Node-RED

El paquete node-red-contrib-web-worldmap añade un nodo worldmap que sirve un mapa basado en Leaflet en http://<node-red-host>:1880/worldmap. Cada mensaje que envías al nodo describe un objeto:

  • msg.payload.name es el ID único. Enviar una nueva posición con el mismo nombre mueve el marcador existente.
  • msg.payload.lat y msg.payload.lon son la posición en grados decimales.
  • Las propiedades opcionales controlan la apariencia y el comportamiento.
Propiedad Ejemplo Efecto
icon car, bus, fa-truck Iconos de vehículo integrados o un icono de Font Awesome
iconColor green, #d33 Color del marcador (en los iconos que lo admiten)
bearing 87 Gira los iconos direccionales según el rumbo
label "Van 2" Texto permanente junto al marcador
layer "Vans" Agrupa marcadores en una capa que puedes mostrar u ocultar
ttl 300 Elimina el marcador tras ese número de segundos sin actualizaciones
deleted true Elimina el marcador inmediatamente
cualquier otra clave speed: 42 Se muestra en la ventana emergente del marcador

Como cualquier propiedad adicional acaba en la ventana emergente, puedes pasar valores de sensores, nombres de conductores o niveles de batería sin configuración extra. Los comandos usan el mismo nodo: un mensaje con msg.payload.command, como { "lat": 41.01, "lon": 28.97, "zoom": 12 }, desplaza y amplía el mapa.

Instala el nodo Worldmap

Desde el editor, abre Manage palette → Install y busca node-red-contrib-web-worldmap. O instálalo desde la línea de comandos:

cd ~/.node-red
npm install node-red-contrib-web-worldmap
# then restart Node-RED

El mapa descarga las teselas de servidores de teselas en línea, así que el navegador que lo visualiza necesita acceso a internet. Si eres nuevo en Node-RED y MQTT, el tutorial de Node-RED y MQTT explica primero la instalación y la configuración del broker.

Simula dispositivos GPS por MQTT

Cada vehículo publica una posición JSON en su propio topic: connectmq/demo/a7f3k2/fleet/<vehicle>/gps. Poner el ID del vehículo en el topic, y no solo en el payload, permite a los suscriptores elegir un vehículo o usar el comodín + para todos. Este script mueve tres vehículos en bucles alrededor del centro de una ciudad y publica en broker.connectmq.com, el servidor MQTT público gratuito. Sustituye a7f3k2 por tu propia cadena aleatoria; las posiciones en el servidor público son visibles para cualquiera, así que usa allí solo datos simulados.

# pip install "paho-mqtt>=2.0"
import json
import math
import random
import time
import uuid

import paho.mqtt.client as mqtt

PREFIX = "connectmq/demo/a7f3k2/fleet"
CENTER_LAT, CENTER_LON = 41.0082, 28.9784

vehicles = {
    "van1": {"angle": 0.0, "radius": 0.020, "speed": 0.010},
    "van2": {"angle": 2.0, "radius": 0.030, "speed": 0.007},
    "truck1": {"angle": 4.0, "radius": 0.045, "speed": 0.005},
}

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=f"gps-sim-{uuid.uuid4().hex[:8]}")
client.connect("broker.connectmq.com", 1883, keepalive=60)
client.loop_start()

try:
    while True:
        for vid, v in vehicles.items():
            v["angle"] += v["speed"] * random.uniform(0.8, 1.2)
            lat = CENTER_LAT + v["radius"] * math.sin(v["angle"])
            lon = CENTER_LON + v["radius"] * 1.3 * math.cos(v["angle"])
            # Heading is tangent to the circle, in degrees clockwise from north
            dlat = math.cos(v["angle"])
            dlon = -1.3 * math.sin(v["angle"])
            heading = (math.degrees(math.atan2(dlon, dlat)) + 360) % 360
            payload = {
                "lat": round(lat, 6),
                "lon": round(lon, 6),
                "heading": round(heading),
                "speed": round(random.uniform(25, 55), 1),
                "ts": int(time.time() * 1000),
            }
            client.publish(f"{PREFIX}/{vid}/gps", json.dumps(payload), qos=0)
        time.sleep(3)
except KeyboardInterrupt:
    pass
finally:
    client.loop_stop()
    client.disconnect()

QoS 0 es una elección razonable para posiciones frecuentes: si se pierde una actualización, la siguiente llega unos segundos después. Usa QoS 1 para eventos que no puedes perderte, como las alarmas de geocerca. La guía sobre rastreo de vehículos con MQTT trata con más profundidad el diseño de topics y payloads para flotas, y el tutorial de rastreador GPS con ESP32 muestra el lado del dispositivo con hardware real.

Construye el flujo de Node-RED Worldmap

Paso 1: suscríbete a todos los vehículos

Añade un nodo mqtt in con una configuración de broker que apunte a broker.connectmq.com:1883 y un client ID único. Pon como topic connectmq/demo/a7f3k2/fleet/+/gps y como salida "a parsed JSON object".

Paso 2: convierte los payloads MQTT en marcadores

Añade un nodo function entre el nodo mqtt in y un nodo worldmap:

// Function node "gps to worldmap marker"
const p = msg.payload;
const lat = Number(p.lat);
const lon = Number(p.lon);

// Reject missing or impossible coordinates (and the classic 0,0 "no fix")
if (!Number.isFinite(lat) || !Number.isFinite(lon) ||
    Math.abs(lat) > 90 || Math.abs(lon) > 180 || (lat === 0 && lon === 0)) {
    return null;
}

// connectmq/demo/a7f3k2/fleet/van1/gps -> van1
const id = msg.topic.split("/")[4];
const isTruck = id.startsWith("truck");
const speed = Number(p.speed) || 0;

msg.payload = {
    name: id,
    lat: lat,
    lon: lon,
    bearing: Number(p.heading) || 0,
    icon: isTruck ? "fa-truck" : "car",
    iconColor: speed > 50 ? "orange" : "green",
    layer: isTruck ? "Trucks" : "Vans",
    label: id,
    speed: speed + " km/h",
    lastSeen: new Date(p.ts || Date.now()).toLocaleTimeString(),
    ttl: 120
};
return msg;

Despliega y abre http://localhost:1880/worldmap. Aparecen tres marcadores que se mueven cada tres segundos. Haz clic en uno para ver la velocidad y la hora de la última señal en la ventana emergente. Si un vehículo deja de publicar, su marcador desaparece a los dos minutos gracias a ttl.

Paso 3: centra el mapa al arrancar

Añade un nodo inject configurado para inject once after 1 second con un payload JSON {"command": {"lat": 41.0082, "lon": 28.9784, "zoom": 12}} y conéctalo al mismo nodo worldmap. Ten en cuenta que los comandos se aplican cuando llegan; un navegador que se conecte más tarde empieza en la vista por defecto a menos que también reenvíes el comando al conectarse. El nodo worldmap in emite un evento de conexión que puedes usar para ello.

Paso 4: dibuja las trazas

El paquete también incluye un nodo worldmap tracks. Colócalo entre tu nodo function y el nodo worldmap y fija el número de puntos que se conservan, por ejemplo 50. Añade una línea detrás de cada marcador en movimiento, lo que hace evidentes de un vistazo las rutas y los bucles.

Gestión de dispositivos inactivos y desconectados

Eliminar marcadores con ttl es sencillo, pero a menudo preferirás mantener el marcador y mostrar que está desactualizado. Dos patrones funcionan bien:

  1. Color según la antigüedad. Guarda el último mensaje de cada vehículo en el contexto del flujo, ejecuta un inject cada 30 segundos y reenvía cada vehículo con iconColor: "grey" si su marca de tiempo supera un umbral.
  2. Usa Last Will and Testament. Cada dispositivo configura un mensaje de última voluntad retenido, como offline, en .../fleet/<vehicle>/status. Si su conexión se cae, el broker publica ese mensaje y un segundo nodo mqtt in actualiza el marcador. Al ser un estado retenido, un Node-RED recién arrancado sabe al instante qué vehículos están desconectados.

Combinar ambos ofrece a los operadores una imagen clara: los marcadores verdes en movimiento están bien, los grises van con retraso y los marcados como desconectados han perdido la conexión. Enrutar esos mensajes de estado es un buen trabajo para el nodo switch de Node-RED.

Integrar el mapa en Dashboard 2.0

El worldmap tiene su propia página, pero también puedes mostrarlo dentro de un panel. En Dashboard 2.0, añade un widget ui-template cuya plantilla contenga un iframe que apunte a /worldmap, dimensionado al grupo. Así el mapa queda junto a indicadores y alertas en una sola pantalla. El tutorial de Dashboard 2.0 explica los grupos y la maquetación.

Lista de comprobación para solucionar problemas

  1. No hay marcadores. Confirma con un nodo debug que llegan mensajes; comprueba que name, lat y lon existen y son números, no cadenas.
  2. Los marcadores saltan al golfo de Guinea. Es la posición 0,0, la salida típica de "sin fix GPS". La función anterior la filtra.
  3. Todos los vehículos comparten un marcador. Todos los mensajes tienen el mismo name. Derívalo del topic o de un ID de dispositivo.
  4. El mapa aparece gris y vacío. El navegador no puede llegar al servidor de teselas; revisa el acceso a internet o la configuración del proxy.
  5. Los iconos no giran. Solo los iconos direccionales respetan bearing; cambia a un icono de vehículo como car.
  6. Las posiciones van por detrás de la realidad. Revisa el intervalo de publicación del dispositivo y el keep-alive, y evita encolar posiciones antiguas con QoS 2 en mapas en vivo.

Llevar el seguimiento GPS a producción

En muchos contextos los datos de ubicación son datos personales, así que nunca deben viajar por un broker público en producción. Pasa los dispositivos y Node-RED a un broker privado con TLS en el puerto 8883 y credenciales por dispositivo. Con ConnectMQ, el portal genera un usuario, una contraseña y un client ID por broker, y los intentos de inicio de sesión fallidos repetidos desde una IP provocan su bloqueo, lo que ayuda frente a intentos de adivinar credenciales en dispositivos de campo. Los dispositivos con conexión celular, como los de una flota de reparto en Bogotá o Santiago, se benefician de un broker MQTT gestionado con un endpoint público estable, ya que solo se conectan hacia fuera. Si quieres comparar primero opciones de alojamiento, lee qué hace un broker MQTT y en qué se diferencian los brokers en autenticación y límites.

Rastrea tus dispositivos en ConnectMQ

Regístrate en app.connectmq.com y empieza con el plan gratuito Serverless, sin tarjeta de crédito. Crea un broker, graba las credenciales en tus rastreadores, apunta el nodo de configuración de Node-RED al puerto 8883 con TLS y tu worldmap funcionará en vivo con un flujo privado y cifrado. El explorador de topics en vivo de ConnectMQ es una forma rápida de confirmar que el topic GPS de cada vehículo se está actualizando.

Preguntas frecuentes

¿Qué URL usa el worldmap de Node-RED?

Por defecto, el mapa se sirve en http://<node-red-host>:1880/worldmap. La ruta puede cambiarse en la configuración del nodo worldmap.

¿Cómo muevo un marcador en lugar de crear uno nuevo?

Envía un nuevo mensaje con el mismo name. El nodo worldmap trata name como el ID del marcador y actualiza su posición y sus propiedades.

¿Cómo elimino un vehículo del mapa?

Envía un mensaje con el name del vehículo y deleted: true, o configura ttl para que los marcadores desaparezcan automáticamente cuando cesen las actualizaciones.

¿Puede el worldmap mostrar datos distintos de la posición GPS?

Sí. Cualquier propiedad adicional del payload, como la velocidad, la batería o la temperatura, aparece en la ventana emergente del marcador, y la propiedad layer te permite agrupar los marcadores por tipo.

Artículos relacionados

Cliente OPC UA en Node-RED hacia MQTT con topics ISA-95

Usa node-red-contrib-opcua para suscribirte a variables OPC UA de un PLC o de un servidor de simulación, asignar los node IDs a topics MQTT de estilo ISA-95 y publicar los valores con calidad y marcas de tiempo.

10 min de lectura

Node-RED Dashboard 2.0 con MQTT: indicadores, gráficos y controles

Un tutorial práctico de Node-RED Dashboard 2.0: suscríbete a telemetría MQTT en directo, muéstrala en indicadores y en un gráfico de líneas, y controla un dispositivo con un interruptor que publica comandos y refleja el estado real.

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.