# 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)

```json
{
  "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):

```json
{"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 `{}`.

