Litmus DeviceHub / DataHub Message Format Reference
You are at https://api.litmus.io/reference/devicehub-message-format.md Parent: https://api.litmus.io/agents.md This is a reference, not a router. For routing start at /agents.md.
This is the JSON shape of a single tag value as it flows through Litmus Edge: published by DeviceHub to NATS, read by a DataHub Subscribe, and consumed by Analytics processors, Integration (CC) connectors, and Digital Twins transformations. When you wire any of those to a tag, assume this envelope.
It is a flat object -- there is no payload wrapper. A JSONata/Expression schema reads the top-level fields directly (e.g. value, tagName), and emits an object, not a bare scalar.
Envelope (placeholders, not literal values)
{
"datatype": "<value type as string: int64 | float64 | uint64 | string | bool | ...>",
"description": "<string, tag description, may be empty>",
"deviceID": "<UUID>",
"deviceName": "<string>",
"metadata": {},
"registerId": "<UUID>",
"success": <bool>,
"tagName": "<string>",
"timestamp": <int64, epoch milliseconds>,
"value": <the reading; JSON type per `datatype`>
}
Fields
| Field | Type | Notes |
|---|---|---|
datatype |
string | The value's data type as a string (int64, float64, uint64, string, bool, ...). Describes value. |
description |
string | Tag description. May be empty. |
deviceID |
UUID | The device the tag belongs to. |
deviceName |
string | Device display name. |
metadata |
object | Extra key/values. Usually {}. |
registerId |
UUID | The register/tag identifier. |
success |
bool | Whether the read succeeded. false means the value is stale or invalid. |
tagName |
string | The tag name. |
timestamp |
int64 | Reading time, epoch milliseconds. |
value |
per datatype |
The actual reading. JSON number for numeric types, string for string, boolean for bool. |
NATS / topic format
DeviceHub publishes each tag on a dotted NATS subject. DeviceHub tag topics look like:
devicehub.alias.<deviceName-or-alias>.<tagName>
NATS subjects use . as the separator, not /. When you set a topic on a DataHub Subscribe or DataHub Publish processor, use dotted form (e.g. ABC.temperature).
Worked example
A real message (for illustration only -- do not hard-code these IDs):
{"datatype":"int64","description":"PackML constant value 17","deviceID":"22763B35-14A1-4A4E-8D3D-F1472753353D","deviceName":"parth","metadata":{},"registerId":"00A8396E-534F-4A22-AAED-DD5B384FF88C","success":true,"tagName":"State_Complete","timestamp":1779926165055,"value":17}
JSONata on this message (cheatsheet)
The fields above are top-level, so a JSONata schema references them by bare name. A processor schema should emit an object, not a bare scalar.
| Goal | JSONata schema |
|---|---|
| Keep just the reading | {"value": value} |
| Rename the reading | {"temperature": value} |
| Reading + which tag it came from | {"tag": tagName, "value": value} |
| Convert (e.g. C -> F) | {"value": value * 1.8 + 32} |
| Keep reading + original time | {"value": value, "ts": timestamp} |
| Drop bad reads (guard) | success ? {"value": value} : undefined |
Pitfalls: there is no payload wrapper, so payload.value is wrong -- use value. A bare value (scalar) is not a usable downstream message; wrap it in an object. metadata is usually {}.