Control device MQTT flow

MQTT is an optional transport for control devices that should keep a broker connection open. Your firmware still starts with the HTTPS API: authenticate, read the MQTT catalog, request a short-lived MQTT credential, then connect with the values returned by Realer.

The public MQTT URL is currently mqtts://mqtt.therealer.com:8883. Firmware should still use the catalog broker_url instead of hard-coding a host name or IP address.
If the catalog has no credential_endpoint, MQTT credentials are not available for that device yet. Continue using the HTTPS catalog and feed-data endpoints.
Realer IoT V1 MQTT device flow diagram

Firmware loop

  1. Get an OAuth access token
    Call POST /oauth/token with grant_type=client_credentials. Request iot:catalog:read and the MQTT scopes your firmware needs.
  2. Read the MQTT catalog
    Call GET /iot/v1/devices/{device_id}/mqtt with Authorization: Bearer <access_token>. This response tells the device which broker URL, client ID, topics, limits, and credential request to use.
  3. Request the MQTT CONNECT tuple
    Call the catalog credential_endpoint. The response returns mqtt_client_id, mqtt_username, mqtt_credential, expires_in, and renew_after.
  4. Connect over MQTT/TLS
    Connect to broker_url with the exact client ID, username, and password returned by Realer. The OAuth Bearer token is not used as the MQTT password.
  5. Use only catalog topics
    Subscribe to feed_data_ack_topic. Subscribe to command desired_topic values when your catalog contains command routes. Publish measurements and command acknowledgements to route feed_data_topic values.
  6. Renew before expiry
    Use renew_after to request the next MQTT credential, reconnect with the new tuple, and resubscribe.

OAuth scopes

MQTT uses OAuth only for HTTPS authorization. Request only the scopes your firmware needs.

Scope Firmware use
iot:catalog:read Read the MQTT catalog.
iot:mqtt:connect Request a short-lived MQTT credential.
iot:mqtt:ack:read Subscribe to application acknowledgement messages.
iot:mqtt:feed-data:write Publish sensor values and command acknowledgements.
iot:mqtt:desired:read Subscribe to command desired-state messages. Sensor-only devices can omit this scope.

Read the MQTT catalog

The OAuth response does not include the MQTT broker host, topics, username, or password. Read the catalog after authentication.

cURL

          curl "https://api.therealer.com/iot/v1/devices/12345/mqtt" \
            -H 'Authorization: Bearer b11db7f6c816568eb3b156df3aeaa5'
        
GET /iot/v1/devices/{device_id}/mqtt

Save the returned broker_url, client_id, acknowledgement topic, route topics, and credential request body.

Response example

          {
            "code": 2000,
            "mqtt": {
              "broker_url": "mqtts://mqtt.therealer.com:8883",
              "protocol": "mqtt-5.0",
              "client_id": "cdv_1234567890abcdef",
              "feed_data_ack_topic": "realer/iot/v1/devices/cdv_1234567890abcdef/feed-data/acks",
              "credential_endpoint": {
                "endpoint": "/iot/v1/mqtt-credentials",
                "http_method": "POST",
                "body": {
                  "device_id": 12345,
                  "scopes": [
                    "iot:mqtt:connect",
                    "iot:mqtt:ack:read",
                    "iot:mqtt:feed-data:write"
                  ]
                }
              }
            },
            "mqtt_routes": []
          }
        

Sensor routes and command routes

Sensor routes and command routes use the same feed-data publish shape. Command routes add an optional desired-state subscription.

Publishing command feed data reports the physical command state observed by the device. It does not directly update the desired command value stored by Realer.

Route type Firmware publishes Firmware subscribes
sensor feed_data_topic with sensor value payloads feed_data_ack_topic
command feed_data_topic with command acknowledgement payloads feed_data_ack_topic and desired_topic
Route examples

          {
            "source_type": "sensor",
            "mqtt": {
              "feed_data_topic": "realer/iot/v1/devices/cdv_123/routes/rte_aaaaaaaaaaaaaaaaaaaaaaaaaa/feed-data",
              "feed_data_publish_scope": "iot:mqtt:feed-data:write"
            }
          },
          {
            "source_type": "command",
            "mqtt": {
              "feed_data_topic": "realer/iot/v1/devices/cdv_123/routes/rte_bbbbbbbbbbbbbbbbbbbbbbbbbb/feed-data",
              "feed_data_publish_scope": "iot:mqtt:feed-data:write",
              "desired_topic": "realer/iot/v1/devices/cdv_123/routes/rte_bbbbbbbbbbbbbbbbbbbbbbbbbb/desired",
              "desired_subscribe_scope": "iot:mqtt:desired:read"
            }
          }
        

Request the CONNECT tuple

Use the credential request from the catalog. The password is returned once, so keep it only in short-lived runtime memory.

cURL

          curl "https://api.therealer.com/iot/v1/mqtt-credentials" \
            -H 'Authorization: Bearer b11db7f6c816568eb3b156df3aeaa5' \
            -H 'Content-Type: application/json' \
            -d '{"device_id":12345,"scopes":["iot:mqtt:connect","iot:mqtt:ack:read","iot:mqtt:feed-data:write"]}'
        
POST /iot/v1/mqtt-credentials

          {
            "mqtt": {
              "mqtt_client_id": "cdv_1234567890abcdef",
              "mqtt_username": "realer-cdv-1234567890abcdef-cred-v12",
              "mqtt_credential": "plaintext-returned-once",
              "expires_in": 3600,
              "renew_after": 2700,
              "session_hard_expires_in": 3600
            }
          }
        
Do not log MQTT credentials. Do not store plaintext MQTT credentials in long-lived storage. Reconnect with a new tuple before expiry.

Publish and acknowledgements

Publish feed data with QoS 1 and retain disabled. MQTT PUBACK means broker acceptance only; the application result arrives later on feed_data_ack_topic.

  • message_id is required for retry and idempotency.
  • value is required.
  • value_received_at is required.
  • Command acknowledgements should include desired_id when responding to a desired-state message. Use report_status only when the outcome is not the default applied.
  • Command publishes without desired_id report local physical changes, such as a switch toggled at the device.
  • After reconnecting, publish the latest physical command state with a new message_id if the device changed while offline.
  • Acknowledgement statuses can be accepted, replayed, conflict, rejected, or error.