El conector Generic MQTT de Crimson publica los tags de Red Lion como JSON en el tópico MQTT que elijas, en Crimson 3.1 y 3.2. Con Ubidots, apúntalo al broker de Ubidots o a una UbiFunction que primero transforme cada mensaje. Usa el conector Generic MQTT en lugar del conector Ubidots MQTT integrado en Crimson cuando necesites tus propios tópicos, tags de texto o varios dispositivos por conector.
Cuándo usar Generic MQTT en lugar del conector de Ubidots
El conector Ubidots MQTT de Crimson necesita tres ajustes: un host, un nombre de dispositivo y un token. El conector Generic MQTT, en cambio, expone el tópico MQTT, el inicio de sesión y el formato del mensaje, así que sirve para configuraciones que el conector de Ubidots no permite. El manual Crimson 3.2 Software Guide (LP1153, capítulo 24) lista los ajustes de ambos conectores. Para tags numéricos que van a un solo dispositivo, la guía del conector Ubidots MQTT es más corta.
Necesidad | Conector Ubidots MQTT | Conector Generic MQTT |
Tópico MQTT | Se construye a partir del Device Name | Cualquier Publication Topic, más un Topic Suffix por tag set en Crimson 3.2 |
Inicio de sesión | Access Token | User Name y Password, que las UbiFunctions necesitan |
Tags de texto | No se envían | Se envían como texto JSON; una UbiFunction los guarda en el contexto del dot |
Formato del mensaje | Fijo | Force Into Root, Data Encoding, Label Set, Tag Structure, Site Name |
Builds de Crimson | 3.2.0014.0 y 3.1.3119.001 o posteriores | También builds anteriores |
Escrituras de Ubidots a los tags | Tag Writes en el tag set | No se cubre aquí: la suscripción espera el formato JSON propio de Crimson |
Dos rutas hacia Ubidots
La ruta A publica directamente en el broker de Ubidots, en industrial.api.ubidots.com. La ruta B publica en una UbiFunction en functions.ubidots.com, que convierte cada mensaje de Crimson y lo escribe en Ubidots. La ruta A tiene menos piezas; la ruta B conserva más datos.
Ruta A: broker de Ubidots | Ruta B: UbiFunction | |
Variables | Una por tag numérico, más connected y una variable timestamp con la hora de Crimson en segundos Unix | Una por tag, más connected |
Tags de texto | Se descartan | Se guardan como texto en el contexto del dot |
Hora de cada valor | Hora de llegada a Ubidots | La marca de tiempo de Crimson, así que los datos del buffer conservan su hora original |
Varios dispositivos | Un conector por dispositivo (Crimson 3.2) | Un conector, con un Topic Suffix por tag set |
Probada en hardware | Sí, Crimson 3.1 en un CR3000 | No, consulta Solución de problemas |
Requisitos
Un dispositivo Red Lion programado con Crimson 3.1 o 3.2 y software Group 2 o superior, por ejemplo un FlexEdge, un HMI Graphite o CR3000, o un DA30D. Descarga Crimson desde la página de Crimson de HMS Networks.
Una cuenta de Ubidots, tu token de Ubidots y, para la ruta B, tu nombre de usuario de Ubidots.
Una red que permita al dispositivo llegar a industrial.api.ubidots.com (ruta A) o a functions.ubidots.com (ruta B) por el puerto 8883 con TLS, o 1883 sin TLS, con gateway predeterminado y servidores DNS.
1. Crea los tags y activa el conector Generic MQTT
El conector Generic MQTT publica los tags de datos que pongas en sus tag sets. Crea tus tags en Data Tags; el ejemplo de esta guía usa cuatro tags numéricos de un HMI CR3000. Luego abre Communications, selecciona Generic MQTT en Connectors y pon Enable Agent en Yes en la pestaña Service.
En Diagnostics, escribe en Status el nombre de un tag nuevo, como connectionStatus. Crimson ofrece crear el tag; haz clic en Yes. El conector escribe su estado en este tag, de 0 a 4.
En la pestaña Device Data, pon Transfer Mode en Disabled. El bloque del dispositivo contiene marcadores de posición, no datos.
En la pestaña Tag Set 1, deja Transfer Mode en Periodic, configura el Update Rate y arrastra tus tags hasta Contents. Usa más tag sets para los tags que necesiten otra frecuencia.
2A. Ruta A: publica en el broker de Ubidots
En la ruta A, el conector Generic MQTT publica en un tópico de dispositivo de Ubidots, y el broker convierte cada clave numérica en una variable. El mensaje por defecto de Crimson anida los tags y envía algunos valores como texto, que el broker no puede leer, así que Force into Root y Numeric Only deben estar activados. Configura la pestaña Service así.
Campo | Valor |
Host Name 1 | industrial.api.ubidots.com |
Client ID | Cualquier nombre único para este dispositivo, por ejemplo line-1-cr3000 |
Publication Topic | /v1.6/devices/<device-label>, por ejemplo /v1.6/devices/line-1, en minúsculas |
Subscription Topic | Déjalo vacío |
Use Dollar Sign | No |
Force into Root | Enabled |
Data Encoding | Numeric Only |
User Name | Tu token de Ubidots |
Password | Déjalo vacío |
En la pestaña Network, pon Transport Protocol en TLS y Connect via Port en 8883, y luego descarga la base de datos al dispositivo. Para alimentar varios dispositivos de Ubidots en Crimson 3.2, agrega en Connectors un conector Generic MQTT por dispositivo, cada uno con su propio Publication Topic.
2B. Ruta B: publica en una UbiFunction
En la ruta B, el conector Generic MQTT publica el JSON completo de Crimson en una UbiFunction, y la función escribe los valores en Ubidots. La función conserva los tags de texto como texto, usa la marca de tiempo de Crimson como la hora de cada valor y lee la etiqueta del dispositivo desde el tópico. La ruta B no se ha probado en hardware Red Lion; lee primero la nota sobre reconexiones en Solución de problemas.
Crea la función decodificadora
En Ubidots, ve a Dev Center → Functions y haz clic en +.
Pon crimson-decoder en Name, POST en Method y Python 3.14 Lite en Runtime.
Reemplaza el código de ejemplo por el código de abajo, pon tu token de Ubidots en TOKEN y guarda la función.
Copia la etiqueta de la función desde el final de la URL de su endpoint HTTPS, /prv/<your-username>/<function-label>. La etiqueta puede ser distinta del nombre, por ejemplo con guiones bajos.
import json
import re
from datetime import datetime
import requests
BASE_URL = "https://industrial.api.ubidots.com"
TOKEN = "PUT-YOUR-TOKEN-HERE"
DEFAULT_DEVICE = "crimson"
# Crimson agrega estas claves a cada mensaje; no son tags.
SKIP = {"device", "cid"}
def label(name):
# Etiquetas de Ubidots: minúsculas, números, - y _. "Group1.Tag1" -> "group1-tag1", "Tag2 [0]" -> "tag2-0"
text = re.sub(r"[^a-z0-9_-]+", "-", str(name).lower())
return text.strip("-")[:50]
def to_number(value):
if isinstance(value, bool):
return int(value)
if isinstance(value, (int, float)):
return value
if isinstance(value, str) and value.lower() in ("true", "false"):
return 1 if value.lower() == "true" else 0
return None
def timestamp_ms(value):
# Numeric Only envía segundos Unix; las demás codificaciones envían ISO 8601 ("2018-12-05T18:14:52.000Z")
if isinstance(value, (int, float)) and not isinstance(value, bool):
return int(value * 1000)
if isinstance(value, str):
try:
return int(datetime.fromisoformat(value.replace("Z", "+00:00")).timestamp() * 1000)
except ValueError:
return None
return None
def flatten(tags, prefix=""):
# Carpetas, tag sets con etiqueta y arreglos llegan como objetos anidados; sus nombres se unen con "-".
for name, value in tags.items():
if name in SKIP:
continue
full = f"{prefix}-{name}" if prefix else str(name)
if isinstance(value, dict) and "Value" in value: # Send Properties: el dato está en "Value"
yield full, value["Value"], value.get("Units") or ""
elif isinstance(value, dict):
yield from flatten(value, full)
else:
yield full, value, ""
def main(args):
payload = args.get("payload") or {}
if isinstance(payload, str):
payload = json.loads(payload)
# Tópico: /prv/<username>/<function-label>/<device-label>; el Topic Suffix de un tag set puede aportar el último nivel.
# Los niveles vacíos se omiten, así que un sufijo con o sin "/" propio da el mismo dispositivo.
parts = [part for part in args["topic"].split("/") if part]
device_label = label(parts[3]) if len(parts) > 3 else DEFAULT_DEVICE
ts = timestamp_ms(payload.get("timestamp"))
dots = {}
def add(name, value, units=""):
key = label(name)
if not key:
return
number = to_number(value)
if number is not None:
dot = {"value": number}
if units:
dot["context"] = {"units": units}
elif isinstance(value, str):
dot = {"value": 1, "context": {"text": value}} # tag de texto: el texto va en el contexto del punto
else:
return
if ts:
dot["timestamp"] = ts
dots[key] = dot
tags = payload.get("tags")
if isinstance(tags, dict):
for name, value, units in flatten(tags):
add(name, value, units)
else:
# Force Into Root: los tags quedan en el nivel superior junto a connected y timestamp
for name, value in payload.items():
if name not in SKIP | {"tags", "timestamp", "connected", "historic", "adhoc"} and not isinstance(value, dict):
add(name, value)
if "connected" in payload: # true en cada envío, false en el mensaje de última voluntad
add("connected", payload["connected"])
if not dots:
return {"status": "ignored"}
response = requests.post(
f"{BASE_URL}/api/v1.6/devices/{device_label}/",
headers={"X-Auth-Token": TOKEN, "Content-Type": "application/json"},
json=dots,
timeout=10,
)
return {"status": response.status_code, "text": response.text}
Apunta el conector a la función
Campo | Valor |
Host Name 1 | functions.ubidots.com |
Client ID | Cualquier nombre único para este dispositivo |
Publication Topic | /prv/<your-username>/<function-label>/<device-label>, por ejemplo /prv/acme/crimson-decoder/line-1 |
Subscription Topic | Déjalo vacío |
Force into Root | Disabled |
Data Encoding | Standard |
User Name | Tu nombre de usuario de Ubidots |
Password | Tu token de Ubidots |
Nota: el endpoint de funciones recibe tu nombre de usuario como usuario MQTT y tu token como contraseña. Es al revés que en el broker de Ubidots de la ruta A, donde el token es el nombre de usuario.
En la pestaña Network, pon Transport Protocol en TLS y Connect via Port en 8883. Para enviar los tag sets a dispositivos distintos, termina el Publication Topic en la etiqueta de la función y dale a cada tag set un Topic Suffix con la etiqueta de su dispositivo, como /line-1 y /line-2. La función lee la etiqueta del dispositivo del último nivel del tópico.
3. Revisa los mensajes y los datos
El servidor web de Crimson, en los dispositivos con software Group 3 o superior, tiene una Debug Console que muestra cada mensaje MQTT que envía el conector, con su tópico y su JSON. Actívala en Web Server → Features → System Pages con Debug Console en Enabled with Commands, y pon Debug Output en Enabled en la pestaña Network del conector. Después de descargar la base de datos, abre el servidor web del dispositivo y elige System → Debug Console.
La captura de arriba es un mensaje de la ruta A desde Crimson 3.1: {"changeValue":0,"connected":1,"connectionInteger":4,"officeTemp":0,"testValue":0,"timestamp":1573231789,"upDown":0}. En Ubidots, ve a Devices → Devices: el dispositivo tiene una variable por clave, en minúsculas.
Solución de problemas
¿Por qué mis tags de Crimson no aparecen en Ubidots?
Ruta A, no llega nada. El broker no puede leer el mensaje anidado de Crimson ni los valores de texto. Revisa que Force into Root esté en Enabled y Data Encoding en Numeric Only, y que el Publication Topic sea /v1.6/devices/ seguido de una etiqueta de dispositivo en minúsculas.
El conector nunca se conecta. En la ruta A, el usuario es tu token y la contraseña va vacía; en la ruta B, el usuario es tu nombre de usuario y la contraseña es tu token. El puerto debe coincidir con el transporte: 8883 con TLS, 1883 con TCP.
Ruta B, conectado pero sin dispositivo. Abre los logs de la función. El tópico debe empezar por /prv/<your-username>/<function-label>/, con la etiqueta que aparece en la URL del endpoint, y el método de la función debe ser POST. Un 401 o 403 en los logs significa que el token del código está mal.
El tag Status se queda por debajo de 4. Los valores significan lo mismo que en el conector de Ubidots; consulta la tabla de Status en la guía de configuración del FlexEdge.
¿Por qué el conector se reconecta una y otra vez a functions.ubidots.com?
Según el manual Crimson 3.2 Software Guide, el conector Generic MQTT se suscribe a su Subscription Topic, o a crimson/generic/<client-id>/sub cuando ese campo está vacío ($crimson/… cuando Use Dollar Sign está en Yes). El endpoint de funciones acepta publicaciones bajo /prv/<your-username>/ y rechaza las suscripciones. Si el endpoint cierra la conexión por esa suscripción, el tag Status vuelve una y otra vez a 0 o 1. Usa la ruta A para tags numéricos, o pon un puente adelante: un broker Mosquitto local o un flujo de Node-RED que reciba los mensajes de Crimson y los reenvíe a functions.ubidots.com. Para una flota, el equipo de ventas de Ubidots puede asignar un broker dedicado a tu función.
Preguntas frecuentes
¿Qué JSON publica el conector Generic MQTT de Crimson?
El conector Generic MQTT publica un objeto device, un objeto tags con una clave por tag, connected y timestamp. Con Force into Root, cada valor sube al nivel superior. Con Numeric Only, true y false pasan a 1 y 0, y el timestamp a segundos Unix. Label Set envuelve cada tag set en su propio objeto, como set1.
¿Cómo aparecen los tags de texto en Ubidots?
En la ruta B, el decodificador escribe cada tag de texto como variable con valor 1, con el texto en el contexto del dot, bajo text, porque Ubidots no guarda texto como valor. Un widget de tabla o la lista de dots lo muestran. La ruta A descarta los tags de texto: Numeric Only no puede codificarlos.
¿La ruta A conserva las marcas de tiempo de Crimson?
No. En la ruta A, cada valor toma su hora de llegada a Ubidots, y la hora de Crimson llega como una variable timestamp aparte, en segundos Unix. Después de un corte, los datos del buffer quedan con la hora en que se reenvían. La ruta B usa la marca de tiempo de Crimson como hora de cada valor.
¿Ubidots puede escribir valores de vuelta en los tags de Crimson por Generic MQTT?
Esta guía no lo cubre. El conector Generic MQTT espera las escrituras en el JSON de Crimson, como {"tags":{"Tag1":100}}, y Ubidots envía valores simples en sus tópicos /lv. Usa en su lugar Tag Writes del conector Ubidots MQTT, que se explica en la guía de configuración del FlexEdge.
¿Qué versiones de Crimson incluyen el conector Generic MQTT?
Lo incluyen tanto Crimson 3.1 como Crimson 3.2. El conector Generic MQTT es anterior al conector Ubidots MQTT, que llegó en los builds 3.1.3119.001 y 3.2.0014.0 a finales de 2020, así que Generic MQTT también funciona en dispositivos que todavía usan un build anterior de Crimson.
Otras guías de Red Lion
