Skip to main content

Crimson Generic MQTT Setup Guide: Red Lion Tags to the Cloud

Send Red Lion Crimson 3.1 or 3.2 tags to Ubidots with the Generic MQTT connector: your own topics, string tags, several devices and a UbiFunction decoder.

Written by Sergio M

Crimson's Generic MQTT connector publishes Red Lion tags as JSON to any MQTT topic you choose, in Crimson 3.1 and 3.2. With Ubidots, point it at the Ubidots broker, or at a UbiFunction that reshapes each message first. Use the Generic MQTT connector instead of Crimson's built-in Ubidots MQTT connector when you need your own topics, string tags or several devices per connector.

A Ubidots device named Line 1 with variables published by Crimson's Generic MQTT connector: officetemp, linespeed, partcount, running and connected

When to use Generic MQTT instead of the Ubidots connector

Crimson's Ubidots MQTT connector needs three settings: a host, a device name and a token. The Generic MQTT connector exposes the MQTT topic, the login and the message format instead, so it fits setups the Ubidots connector can't express. The Crimson 3.2 Software Guide (LP1153, chapter 24) lists both connectors' settings. For numeric tags going to one device, the Ubidots MQTT connector guide is shorter.

Need

Ubidots MQTT connector

Generic MQTT connector

MQTT topic

Built from the Device Name

Any Publication Topic, plus a Topic Suffix per tag set in Crimson 3.2

Login

Access Token

User Name and Password, which UbiFunctions need

String tags

Not sent

Sent as JSON text; a UbiFunction stores them in the dot's context

Message format

Fixed

Force Into Root, Data Encoding, Label Set, Tag Structure, Site Name

Crimson builds

3.2.0014.0 and 3.1.3119.001 or later

Earlier builds too

Writes from Ubidots to tags

Tag Writes on the tag set

Not covered here: the subscription expects Crimson's own JSON format

Two routes to Ubidots

Route A publishes straight to the Ubidots broker at industrial.api.ubidots.com. Route B publishes to a UbiFunction at functions.ubidots.com, which converts each Crimson message and writes it to Ubidots. Route A has fewer moving parts; Route B keeps more of the data.

Route A: Ubidots broker

Route B: UbiFunction

Variables

One per numeric tag, plus connected and a timestamp variable holding Crimson's time in Unix seconds

One per tag, plus connected

String tags

Dropped

Stored as text in the dot's context

Time of each value

Arrival time in Ubidots

Crimson's timestamp, so buffered data keeps its original time

Several devices

One connector per device (Crimson 3.2)

One connector, a Topic Suffix per tag set

Tested on hardware

Yes, Crimson 3.1 on a CR3000

No, see Troubleshooting

Requirements

  • A Red Lion device programmed with Crimson 3.1 or 3.2 and software Group 2 or higher, for example a FlexEdge, a Graphite or CR3000 HMI, or a DA30D. Download Crimson from HMS Networks' Crimson page.

  • An Ubidots account, your Ubidots token and, for Route B, your Ubidots username.

  • A network that lets the device reach industrial.api.ubidots.com (Route A) or functions.ubidots.com (Route B) on port 8883 with TLS, or 1883 without it, with a default gateway and DNS servers.

1. Create the tags and enable the Generic MQTT connector

The Generic MQTT connector publishes the data tags you place in its tag sets. Create your tags under Data Tags; this guide's example uses four numeric tags from a CR3000 HMI. Then open Communications, select Generic MQTT under Connectors, and set Enable Agent to Yes on the Service tab.

Crimson Data Tags list with the example tags officeTemp, upDown, changeValue and testValue
  1. Under Diagnostics, type a new tag name such as connectionStatus in Status. Crimson offers to create the tag; click Yes. The connector writes its state to this tag, from 0 to 4.

  2. On the Device Data tab, set Transfer Mode to Disabled. The device block holds placeholders, not data.

  3. On the Tag Set 1 tab, keep Transfer Mode on Periodic, set the Update Rate and drag your tags into Contents. Use more tag sets for tags that need a different rate.

Crimson Generic MQTT Tag Set 1 tab: Periodic transfer every 1.0 seconds, Label Set, Tag Structure and four tags in Contents

2A. Route A: publish to the Ubidots broker

On Route A, the Generic MQTT connector publishes to a Ubidots device topic, and the broker turns each numeric key into a variable. Crimson's default message nests the tags and sends some values as text, which the broker can't read, so Force into Root and Numeric Only must both be on. Set the Service tab as follows.

Field

Value

Host Name 1

industrial.api.ubidots.com

Client ID

Any name unique to this device, for example line-1-cr3000

Publication Topic

/v1.6/devices/<device-label>, for example /v1.6/devices/line-1, in lowercase

Subscription Topic

Leave empty

Use Dollar Sign

No

Force into Root

Enabled

Data Encoding

Numeric Only

User Name

Your Ubidots token

Password

Leave empty

Crimson Generic MQTT Service tab for Route A: Host Name 1 industrial.api.ubidots.com, Publication Topic /v1.6/devices/helloedge, Force into Root Enabled, Data Encoding Numeric Only

On the Network tab, set Transport Protocol to TLS and Connect via Port to 8883, then download the database to the device. To feed several Ubidots devices in Crimson 3.2, add one Generic MQTT connector per device under Connectors, each with its own Publication Topic.

2B. Route B: publish to a UbiFunction

On Route B, the Generic MQTT connector publishes Crimson's full JSON to a UbiFunction, and the function writes the values to Ubidots. The function keeps string tags as text, uses Crimson's timestamp as each value's time and reads the device label from the topic. Route B has not been tested on Red Lion hardware; read the reconnect note under Troubleshooting first.

Create the decoder function

  1. In Ubidots, go to Dev Center → Functions and click +.

  2. Set the Name to crimson-decoder, the Method to POST and the Runtime to Python 3.14 Lite.

  3. Replace the sample code with the code below, put your Ubidots token in TOKEN and save the function.

  4. Copy the function's label from the end of its HTTPS endpoint URL, /prv/<your-username>/<function-label>. The label can differ from the name, for example with underscores.

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 adds these to every message; they are not tags.
SKIP = {"device", "cid"}


def label(name):
# Ubidots labels: lowercase letters, numbers, - and _. "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 encoding sends Unix seconds; the other encodings send 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=""):
# Folders, labelled tag sets and arrays arrive as nested objects; join their names with "-".
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: the data is in "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)

# Topic: /prv/<username>/<function-label>/<device-label>; a tag set's Topic Suffix can supply the last level.
# Empty levels are skipped, so a suffix written with or without its own "/" gives the same device.
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}} # string tag: the text goes in the dot's context
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: tags sit at the top level next to connected and 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 in every update, false in the last-will message
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}

Point the connector at the function

Field

Value

Host Name 1

functions.ubidots.com

Client ID

Any name unique to this device

Publication Topic

/prv/<your-username>/<function-label>/<device-label>, for example /prv/acme/crimson-decoder/line-1

Subscription Topic

Leave empty

Force into Root

Disabled

Data Encoding

Standard

User Name

Your Ubidots username

Password

Your Ubidots token


Note: the function endpoint takes your username as the MQTT user and your token as the password. That's the reverse of the Ubidots broker in Route A, where the token is the user name.


Set Transport Protocol to TLS and Connect via Port to 8883 on the Network tab. To send tag sets to different devices, end the Publication Topic at the function label and give each tag set a Topic Suffix with its device label, such as /line-1 and /line-2. The function reads the device label from the last topic level.

3. Check the messages and the data

Crimson's web server, on devices with software Group 3 or higher, has a Debug Console that shows every MQTT message the connector sends, with its topic and JSON. Enable it under Web Server → Features → System Pages with Debug Console set to Enabled with Commands, and set Debug Output to Enabled on the connector's Network tab. After downloading the database, open the device's web server and choose System → Debug Console.

Crimson Web Server Features tab with Debug Console set to Enabled with Commands
Crimson Debug Console showing an MQTT publish to /v1.6/devices/helloedge with changeValue, connected, officeTemp, timestamp and upDown

The capture above is a Route A message from Crimson 3.1: {"changeValue":0,"connected":1,"connectionInteger":4,"officeTemp":0,"testValue":0,"timestamp":1573231789,"upDown":0}. In Ubidots, go to Devices → Devices: the device has one variable per key, in lowercase.

Troubleshooting

Why don't my Crimson tags show up in Ubidots?

  • Route A, nothing arrives. The broker can't read Crimson's nested message or text values. Check that Force into Root is Enabled and Data Encoding is Numeric Only, and that the Publication Topic is /v1.6/devices/ followed by a lowercase device label.

  • The connector never connects. On Route A the user name is your token and the password is empty; on Route B the user name is your username and the password is your token. The port must match the transport: 8883 with TLS, 1883 with TCP.

  • Route B, connected but no device. Open the function's logs. The topic must start with /prv/<your-username>/<function-label>/, using the label from the endpoint URL, and the function's method must be POST. A 401 or 403 in the logs means the token in the code is wrong.

  • The Status tag stays below 4. The values mean the same as on the Ubidots connector; see the Status table in the FlexEdge setup guide.

Why does the connector keep reconnecting to functions.ubidots.com?

The Crimson 3.2 Software Guide describes the Generic MQTT connector as subscribing to its Subscription Topic, or to crimson/generic/<client-id>/sub when that field is empty ($crimson/… when Use Dollar Sign is Yes). The function endpoint accepts publishes under /prv/<your-username>/ and rejects subscriptions. If the endpoint closes the connection over that subscription, the Status tag keeps dropping back to 0 or 1. Use Route A for numeric tags, or put a bridge in front: a local Mosquitto broker or Node-RED flow that receives Crimson's messages and forwards them to functions.ubidots.com. For a fleet, Ubidots sales can map a dedicated broker to your function.

FAQ

What JSON does the Crimson Generic MQTT connector publish?

The Generic MQTT connector publishes a device object, a tags object with one key per tag, connected and timestamp. With Force into Root, every value moves to the top level. With Numeric Only, true and false become 1 and 0 and the timestamp becomes Unix seconds. Label Set wraps each tag set in its own object, such as set1.

How do string tags appear in Ubidots?

On Route B, the decoder writes each string tag as a variable with value 1 and the text in the dot's context, under text. Ubidots stores strings in context, not as values. A table widget or the variable's dot list shows the text. Route A drops string tags, because Numeric Only can't encode them.

Does Route A keep Crimson's timestamps?

No. On Route A, each value gets the time it reaches Ubidots, and Crimson's time arrives as a separate timestamp variable in Unix seconds. After an outage, buffered data lands at the replay time. Route B uses Crimson's timestamp as each value's time.

Can Ubidots write values back to Crimson tags through Generic MQTT?

This guide doesn't cover it. The Generic MQTT connector expects writes as Crimson JSON, such as {"tags":{"Tag1":100}}, and Ubidots sends plain values on its /lv topics. Use the Ubidots MQTT connector's Tag Writes instead, described in the FlexEdge setup guide.

Which Crimson versions include the Generic MQTT connector?

Crimson 3.1 and Crimson 3.2 both include it. The Generic MQTT connector predates the Ubidots MQTT connector, which arrived in builds 3.1.3119.001 and 3.2.0014.0 in late 2020, so Generic MQTT also works on devices still running an earlier Crimson build.

Other Red Lion guides

Did this answer your question?