MQTT Protocol Overview
:::info Status
Implemented. Source: docs/user-device-mqtt-contract.md (stream player, v1.0), docs/transmitter-mqtt-contract.md (transmitter, v1.0).
:::
Azan360's two physical device types — the transmitter and the
stream player — both speak MQTT against the same
self-hosted EMQX broker, using the same JSON envelope shape. They are
not the same contract: each is independently versioned v1.0, and the
differences below (topic scheme, credential model, entitlement) are
permanent design differences between the two device roles, not a version
gap waiting to close.
The mobile app holds no MQTT connection at all — it is not a device; see App install / mobile app below.
Two contracts, one broker
| Transmitter | Stream player | |
|---|---|---|
| Source contract | docs/transmitter-mqtt-contract.md | docs/user-device-mqtt-contract.md |
| Topic base | masjidconnect/{mosqueId}/device/{deviceId}/ (mosque and device in the path) | masjidconnect/rx/{deviceId}/ (device-scoped only, no mosque in the path) |
| Credential | Shared, fleet-wide MQTT username/password (MQTT_DEVICE_USER/MQTT_DEVICE_PASS) — every transmitter authenticates as the same identity | Per-device credential, broker-enforced subtree ACL |
| Broker-side isolation | None — topic-path convention + HTTP-side authorization only | Yes — broker refuses a wildcard or wrong-subtree subscribe outright |
| Keepalive | 30 s | 60 s |
| Heartbeat default | 60 s | 300 s |
| Bound to | One mosque, for the unit's life | One member (owner); mosque binding is mutable, can rebind repeatedly |
| Client ID | azan360-tx-{device_id} | azan360-rx-{device_id} |
See Topic Structure for the full topic tables and the broker ACL model, and Device Authorization for how a unit earns the right to receive azaan at all — this page and its siblings describe the wire protocol, not the authorization decision behind it.
Envelope conventions (both contracts)
- Encoding: UTF-8 JSON on every topic.
- Timestamps: Unix epoch seconds (integer), UTC.
- Every device-published payload carries
"v": "1.0"— the contract version the device implements. A breaking change bumps the major version. - Commands (
cmdtopic) carry areq_id; devices ack with the samereq_idon theacktopic. See Commands and Error Handling — idempotency.
QoS and retained-message conventions
| Topic | QoS | Retained | Why |
|---|---|---|---|
status | 1 | yes | Lifecycle state must survive a reconnect and a fresh subscriber |
heartbeat | 0 | no | High-frequency telemetry; loss is acceptable |
config | 1 | yes | Desired state must be delivered even to a unit that was offline for a month |
cmd | 1 | no | A command is a moment, not durable state — see Error Handling for why it is never retained or queued |
ack | 1 | no | Response correlated by req_id, not meant to persist |
log | 0 | no | Optional diagnostics, throttled |
Session semantics differ deliberately
- Transmitter:
clean_session = true— subscriptions re-established every connect, matching a mosque-bolted asset that's expected to stay connected. - Stream player:
clean_start = true,Session-Expiry-Interval = 0— explicitly non-persistent. A stream player's contract is explicit that the broker must never queue aplayfor later delivery: a missed azaan delivered late is worse than one never delivered. See Error Handling for the full reasoning and the comparison table between persistent and clean sessions.
Broker deployment and operations
How the EMQX broker itself is deployed, secured (TLS, Postgres-backed authn/authz views), rate-limited, monitored, upgraded, and how a device is revoked at the broker level is covered in Device Deployment and Monitoring — not repeated here. This section and its siblings describe what a device sends and receives on the wire.
The mobile app is not on this broker
The Android/iOS app holds no MQTT connection, background or foreground —
iOS terminates background sockets and Android Doze does the same within
minutes, so an app that tried would drain battery, get killed, and still
miss azaan. Its azaan wakeup path is push (APNs VoIP / FCM) plus an HTTP
stream-token exchange; see Azaan Broadcast and
API Reference (stream-auth, app-installs tags).
Next
- Topic Structure — full topic tables and the ACL model
- Commands — the
cmdtopic, including azaanplay - Events — status, heartbeat, ack, log
- Device Registration — how a unit gets its credentials
- Transmitter Audio Uplink — the transmitter's second, non-MQTT connection
- Error Handling — reconnection, close codes, idempotency