MQTT Topic Schema

Canonical topic reference for jettyd devices. Source of truth: apps/platform/src/mqtt.rs and apps/platform/src/routes/mqtt_auth.rs.

Connection Reference

Broker
mqtt.jettyd.com
Port
8883 (TLS required)
client_id
device UUID
password
device_key (from provisioning)
TLS is required. The broker does not accept plaintext connections on port 8883. Your MQTT client must enable TLS. The standard plaintext port (1883) is not exposed publicly.

The device_key is returned during provisioning (see QuickStart) as dk_…. It is also visible in the dashboard under Device → Credentials.

Topic Routing Table

All device topics are scoped to jettyd/{tenant_id}/{device_id}/… where tenant_id and device_id are UUIDs returned at provisioning time.

Topic Direction QoS Payload
jettyd/{tenant_id}/{device_id}/telemetry device → broker 1 {"readings": {"<metric>": <number|string>}} confirmed
jettyd/{tenant_id}/{device_id}/command broker → device 1 payload format not yet confirmed in codebase TBD
jettyd/{tenant_id}/{device_id}/config broker → device 1 payload format not yet confirmed in codebase TBD
jettyd/{tenant_id}/{device_id}/config/ack device → broker 1 ack payload not yet confirmed in codebase TBD
jettyd/{tenant_id}/{device_id}/command/response device → broker 1 {"id": "<command_uuid>", "status": "<string>"} confirmed
Three payload formats are TBD. command, config, and config/ack payloads are not yet confirmed in the platform source. These topics are authenticated and ACL-enforced but the payload contracts are still being finalised. Do not rely on these for production firmware until they are marked confirmed.

Payload Details

Telemetry — …/telemetry

Devices publish readings as a map under the readings key. Metric names are arbitrary strings; values are either numbers (stored in value_numeric) or strings (stored in value_text).

{
  "readings": {
    "temperature": 23.4,
    "humidity": 61,
    "door_state": "open"
  }
}

Each key-value pair is inserted as a row in the telemetry time-series table and merged into the device's shadow.reported field.

Command Response — …/command/response

After executing a command the device publishes a response with the command's UUID and a status string. The platform matches this to the commands table by id and marks it acknowledged.

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "ok"
}

Common status values: ok, error, acked (default when omitted).

Additional Topics

These topics are used internally by the platform but are not part of the standard device ACL.

Topic Direction Notes
jettyd/{tenant_id}/{device_id}/status device → broker Online/offline heartbeat. Payload: {"status": "online"} or {"status": "offline"}
jettyd/provision/request device → broker Initial provisioning. Uses fleet token as MQTT password. Payload: {"fleet_token": "…", "device_type": "…", "firmware_version": "…", "mac_address": "…"}
jettyd/provision/response/{device_id} broker → device Returns device_id, device_key, tenant_id, and mqtt_uri for subsequent connections.

CLI Examples

Publish telemetry

mosquitto_pub \
  --host mqtt.jettyd.com \
  --port 8883 \
  --tls-version tlsv1.2 \
  --capath /etc/ssl/certs \
  --username "$DEVICE_ID" \
  --pw "$DEVICE_KEY" \
  --topic "jettyd/$TENANT_ID/$DEVICE_ID/telemetry" \
  --message '{"readings":{"temperature":23.4,"humidity":61}}' \
  --qos 1

Subscribe to commands

mosquitto_sub \
  --host mqtt.jettyd.com \
  --port 8883 \
  --tls-version tlsv1.2 \
  --capath /etc/ssl/certs \
  --username "$DEVICE_ID" \
  --pw "$DEVICE_KEY" \
  --topic "jettyd/$TENANT_ID/$DEVICE_ID/command" \
  --qos 1
Environment variables. Set DEVICE_ID, DEVICE_KEY, and TENANT_ID from the values returned at provisioning time (or from the dashboard under Device → Credentials).

Testing Against Staging

The validation script at apps/docs/scripts/validate-mqtt-topics.sh checks that this page exists and contains all canonical topic patterns. Run it locally:

bash apps/docs/scripts/validate-mqtt-topics.sh

To perform a live broker smoke-test against staging, set the following environment variables and run the mosquitto_pub example above: