> For the complete documentation index, see [llms.txt](https://adatrack.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://adatrack.gitbook.io/docs/documentation/iot-ingestion/mqtt.md).

# MQTT Protocol

AdaTrack includes a built-in MQTT broker as a standard plugin. IoT devices can send telemetry and receive commands over MQTT — no external broker, no cloud dependency, and no changes to your existing decoders or alert rules.

***

## When to Use MQTT vs UDP

|                              | UDP                                 | MQTT                                                                  |
| ---------------------------- | ----------------------------------- | --------------------------------------------------------------------- |
| **Protocol overhead**        | Minimal — single packet per reading | Small — TCP + MQTT framing                                            |
| **Connection model**         | Stateless, fire-and-forget          | Persistent TCP session                                                |
| **Guaranteed delivery**      | No (best-effort UDP)                | Yes (QoS 1/2 available)                                               |
| **Bi-directional commands**  | No                                  | Yes — subscribe to `commands/{device_id}`                             |
| **Firewall / NAT traversal** | Can be blocked                      | TCP on port 1883 / 8883 passes most firewalls                         |
| **TLS support**              | No (HMAC auth only)                 | Yes — optional TLS on port 8883                                       |
| **Best for**                 | High-frequency, low-latency sensors | Devices that need reliable delivery, two-way comms, or are behind NAT |

Both transports feed the same decoder, database, geofencing, alerting, and real-time dashboard pipeline. Switching a device between UDP and MQTT does not require any changes to its device profile or decoder script.

***

## Prerequisites

* AdaTrack **Standard tier** license or above
* The **MQTT Broker** plugin enabled in **Admin > Plugins**

***

## Enabling the Plugin

1. Navigate to **Admin > Plugins**.
2. Find **MQTT Broker** and click **Enable**.
3. Optionally open **Configure** to set a custom listen address (default `0.0.0.0:1883`), maximum concurrent clients, or TLS certificate paths.
4. The broker starts immediately — no server restart required.

***

## Setting a Device to MQTT Transport

1. Open the device in **Devices > Edit** (or create a new device).
2. Under **Transport Type**, select **MQTT**.
3. Save the device.

On a newly created device, a **Connection Guide** appears showing the broker address, credentials, topic names, and code snippets. Copy these before leaving the page — the device secret is only shown once.

***

## Connecting a Device

### Credentials

| Field        | Value                                                     |
| ------------ | --------------------------------------------------------- |
| **Host**     | Your AdaTrack server hostname or IP                       |
| **Port**     | `1883` (plain TCP) · `8883` (TLS)                         |
| **ClientID** | Device UUID (e.g. `550e8400-e29b-41d4-a716-446655440000`) |
| **Username** | Device UUID (same as ClientID)                            |
| **Password** | Device Secret (shown on device creation)                  |

Authentication is connection-scoped. Once a device connects successfully, all messages on that session are trusted — no per-message signatures required.

### Topics

| Topic                  | Direction         | Description                                            |
| ---------------------- | ----------------- | ------------------------------------------------------ |
| `data/{device_id}`     | Device → Platform | Uplink — publish raw telemetry payload here            |
| `commands/{device_id}` | Platform → Device | Downlink — subscribe here to receive operator commands |

Replace `{device_id}` with the device's UUID. The broker enforces strict per-device topic isolation: a device can only publish to its own `data/` topic and subscribe to its own `commands/` topic.

### Payload Format

The payload published to `data/{device_id}` is passed directly to the device's JavaScript decoder — identical to the binary payload received over UDP. Use the same decoder logic and the same payload format you would use for UDP.

***

## Code Examples

### Python (paho-mqtt)

```python
import paho.mqtt.client as mqtt

DEVICE_ID = "550e8400-e29b-41d4-a716-446655440000"
DEVICE_SECRET = "your-device-secret"
BROKER_HOST = "adatrack.example.com"

def on_connect(client, userdata, flags, rc):
    if rc == 0:
        client.subscribe(f"commands/{DEVICE_ID}")

def on_message(client, userdata, msg):
    print(f"Command received: {msg.payload}")

client = mqtt.Client(client_id=DEVICE_ID)
client.username_pw_set(DEVICE_ID, DEVICE_SECRET)
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER_HOST, 1883)

# Publish a telemetry reading
payload = bytes([0x01, 0x02, 0x03])  # your binary payload
client.publish(f"data/{DEVICE_ID}", payload)

client.loop_forever()
```

### Arduino (PubSubClient)

```cpp
#include <PubSubClient.h>
#include <WiFi.h>

const char* DEVICE_ID     = "550e8400-e29b-41d4-a716-446655440000";
const char* DEVICE_SECRET = "your-device-secret";
const char* BROKER_HOST   = "adatrack.example.com";

WiFiClient   wifiClient;
PubSubClient mqtt(wifiClient);

void setup() {
    WiFi.begin("ssid", "password");
    mqtt.setServer(BROKER_HOST, 1883);
    mqtt.connect(DEVICE_ID, DEVICE_ID, DEVICE_SECRET);

    char commandTopic[128];
    snprintf(commandTopic, sizeof(commandTopic), "commands/%s", DEVICE_ID);
    mqtt.subscribe(commandTopic);
}

void loop() {
    mqtt.loop();

    // Publish a reading
    char topic[128];
    snprintf(topic, sizeof(topic), "data/%s", DEVICE_ID);
    uint8_t payload[] = {0x01, 0x02, 0x03};
    mqtt.publish(topic, payload, sizeof(payload));
    delay(5000);
}
```

***

## Downlink Commands

Operators can push arbitrary command payloads to any connected MQTT device from the AdaTrack UI or API.

**From the device details panel:**

1. Open the device page.
2. Click **Send Command**.
3. Enter the command payload and confirm.

The platform publishes the payload to `commands/{device_id}` via the internal broker client. The command is logged with a timestamp and delivery status in the device details panel.

**Via API:**

```http
POST /api/v1/plugins/mqtt_broker/downlink/{device_id}
Authorization: Bearer <token>
Content-Type: application/json

{"payload": "base64-encoded-bytes"}
```

***

## TLS Configuration

To enable TLS (port 8883), configure the plugin with paths to your certificate and private key:

1. Go to **Admin > Plugins > MQTT Broker > Configure**.
2. Toggle **Enable TLS** on.
3. Enter the absolute path to your PEM certificate file and private key file on the server.
4. Save. The broker will accept connections on both port 1883 (plain) and port 8883 (TLS) simultaneously.

For production deployments, TLS is strongly recommended. Use a certificate signed by a trusted CA so devices can verify the server identity without distributing a custom CA bundle.

***

## Monitoring

The **MQTT Broker** plugin page (**Admin > Plugins > MQTT Broker**) shows:

* **Connected clients** — live count updated over WebSocket
* **Messages in / out** — throughput per minute
* **Active sessions table** — device UUID, remote IP, connection time

The device details panel for MQTT devices shows the current connection status (connected / disconnected), last seen time, and remote IP address.

***

## Broker Stats API

```http
GET /api/v1/plugins/mqtt_broker/stats
Authorization: Bearer <token>
```

Returns connected client count, total messages received and sent, and broker uptime in seconds.

```http
GET /api/v1/plugins/mqtt_broker/sessions
GET /api/v1/plugins/mqtt_broker/sessions/{device_id}
Authorization: Bearer <token>
```

Lists current and recent device sessions with connection timestamps and remote addresses.

***

## License Requirement

The MQTT Broker plugin requires a **Standard** or **Enterprise** license. It is not available on the Community Edition. See [Licensing](/docs/documentation/administration/licensing.md) for upgrade information.
