Skip to content

SenML Message Format

Py ToloMEO uses a SenML-inspired JSON format (RFC 8428) for all messages exchanged over NATS and HTTP.

Record Structure

A message is a JSON array containing one SenML record:

[
  {
    "bn": "urn:cpt:device:sn:abc123:",
    "n": "CommandName",
    "vs": "{\"id\": \"swupdate\", \"fw_version\": \"1.2.3\"}",
    "t": 1700000010.5
  }
]

Fields

Field Type Required Description
bn string NATS only Base name — device URN prefix (urn:cpt:device:sn:<serial>:)
n string Yes Name — command name or metric identifier
vs string For commands JSON-encoded string payload. Contains the command parameters dict.
v number For readings Numeric sensor value
u string No Unit of measure (e.g. "°C")
t number No Unix timestamp in seconds (float)

Command Messages

Commands use n for the command class name and vs for the JSON-encoded payload:

[{"bn":"", "t":1700000010.5, "n":"StartOTADownload", "vs":"{\"id\":\"swupdate\"}"}]

Note

vs is a JSON-encoded string, not a direct JSON object. The inner dict must be serialised to a string before being placed in vs.

Sensor Data Messages

Sensor readings use n for the metric name, v for the value, and u for the unit:

[{"bn":"urn:cpt:device:sn:abc123:", "n":"temperature_sensor:temperature", "u":"°C", "v":23.5, "t":1700000010.0}]

Command Response Messages

Responses are published to events.params with vs containing the JSON-encoded result dict:

[{"bn":"urn:cpt:device:sn:abc123:", "n":"GetOTAStatus",
  "vs":"{\"id\": \"swupdate\", \"result\": \"success\", \"status\": \"update_ready\"}"}]

NATS Subject Conventions

Subject Direction Purpose
commands.{service}.req Inbound Command messages sent to the service
events.data Outbound Sensor metric readings
events.params Outbound Command responses and parameter updates
events.infos Outbound OTA status events and service info
heartbeat.{service}.service Outbound Liveness heartbeat (every 10 s)