Skip to content

MQTT

This page shows how to control AWTRIX through an MQTT broker. For example, show a doorbell alert, a build status or a power reading on the display. MQTT is a messaging system: your automation publishes a message to the broker, and the broker passes it on to AWTRIX. Your automation never has to reach AWTRIX directly.

How it behaves

AWTRIX connects to one broker and listens on <prefix>/cmd/.... The message you publish there is the same JSON you would send over HTTP, so anything you can curl you can publish. AWTRIX answers every command it knows on the same topic with /result added. A topic it does not know gets no answer at all. AWTRIX also publishes its state by itself, on retained topics under <prefix>/state/, so a new subscriber gets the current values at once.

Point AWTRIX at your broker

MQTT is off until you switch it on. You can do this in the web UI (System tab, MQTT section), or with one API call:

curl -X PUT http://<awtrix-ip>/api/v1/system \
  -H 'Content-Type: application/json' \
  -d '{"mqttEnabled":true,"mqttHost":"192.168.1.10","mqttPort":1883,"mqttPrefix":"awtrixNG"}'

Then restart AWTRIX, because the MQTT settings are read once, at start-up:

curl -X POST http://<awtrix-ip>/api/v1/device/reboot

If your broker needs a login, add mqttUser and mqttPass. With both empty, AWTRIX connects without a login. Every key, its default and its type is in System configuration → MQTT and Home Assistant.

To see whether it worked, read GET /api/v1/device: the mqtt object says whether AWTRIX is connected and, if not, why. The web UI shows the same thing as Connection in the MQTT section of the System tab.

To turn MQTT off again, send {"mqttEnabled":false} and restart. AWTRIX stays connected to the broker until the restart. The host and login are kept.

Publish your first command

mosquitto_pub -h 192.168.1.10 -t 'awtrixNG/cmd/notify' \
  -m '{"text":"Doorbell","textColor":"#FF0000","durationMs":10000}'

The display interrupts what it was showing and shows DOORBELL in red for ten seconds. This is the same object you would send to POST /api/v1/notifications: same keys, same defaults, same result.

Watch the answer come back on a second terminal:

mosquitto_sub -h 192.168.1.10 -t 'awtrixNG/cmd/#' -v
awtrixNG/cmd/notify {"text":"Doorbell","textColor":"#FF0000","durationMs":10000}
awtrixNG/cmd/notify/result {"ok":true}

MQTT messages have no Content-Type header, so there is nothing to forget. The curl calls on this page always send Content-Type: application/json. Without it, curl -d marks the body as a form, and AWTRIX refuses a PUT or PATCH with that (Content-Type).

The prefix

<prefix> is the value of mqttPrefix. If you leave it empty, AWTRIX uses its own uid (the twelve-character MAC address) so topics look like a4cf12ab34cd/cmd/notify. That works, but a readable prefix such as awtrixNG is easier to use.

AWTRIX ignores every topic outside <prefix>/, and only topics under <prefix>/cmd/ are commands. State topics only go out from AWTRIX: publishing to one does nothing.

Give every AWTRIX on your broker its own prefix. If two share one, both act on every command.

Anything you can curl, you can publish

To turn an HTTP request into an MQTT command, take the path after /api/v1/, put cmd/ in front of it, and publish the body you would have sent. A few topics have shorter names: notifications go to cmd/notify, and switching to an app is cmd/apps/switch. Both commands below show the same notification:

# HTTP
curl -X POST http://<awtrix-ip>/api/v1/notifications \
  -H 'Content-Type: application/json' \
  -d '{"text":"Build failed","textColor":"#FF0000"}'

# MQTT - same body, byte for byte
mosquitto_pub -h 192.168.1.10 -t 'awtrixNG/cmd/notify' \
  -m '{"text":"Build failed","textColor":"#FF0000"}'

What the notification shows on the display

More examples:

# a pushed app that stays in the rotation
mosquitto_pub -h 192.168.1.10 -t 'awtrixNG/cmd/apps/pushed/power' \
  -m '{"text":"432W","icon":"1234","textColor":"#FFAA00"}'

# an empty payload deletes it again
mosquitto_pub -h 192.168.1.10 -t 'awtrixNG/cmd/apps/pushed/power' -m ''

# settings, validated exactly as PATCH /api/v1/settings validates them
mosquitto_pub -h 192.168.1.10 -t 'awtrixNG/cmd/settings' \
  -m '{"brightness":120,"autoBrightness":false}'

# jump to an app - a bare name works, no JSON needed
mosquitto_pub -h 192.168.1.10 -t 'awtrixNG/cmd/apps/switch' -m 'Time'

Every command topic, with its HTTP route and accepted payload, is listed in MQTT topics → Command topics. The payload keys (text, icons, colors, effects) are described in App & notification payload.

Four differences from HTTP:

  • Reading is HTTP-only. There is no cmd/device/get. Instead, AWTRIX publishes its state to retained topics. See Subscribe to state below. The one exception is cmd/screen/get, which asks for a single state/screen message.
  • Factory reset is HTTP-only. Publishing to cmd/device/factory-reset does nothing and answers nothing. The route is POST /api/v1/device/factory-reset.
  • MQTT reaches pushed apps only. cmd/apps/pushed/<name> creates, replaces and deletes a pushed app. Scripts have no topic at all, and removing one is DELETE /api/v1/apps/{name} over HTTP.
  • An empty message deletes. An empty payload (or {}) deletes a pushed app, turns the mood light off or turns an indicator off, like the HTTP DELETE. Never publish an empty message just to test a topic.

Read the answer

Every command AWTRIX recognizes is answered on the same topic with /result added (not retained):

awtrixNG/cmd/settings       ->  awtrixNG/cmd/settings/result
awtrixNG/cmd/apps/pushed/x  ->  awtrixNG/cmd/apps/pushed/x/result

Success is exactly:

{"ok":true}

Failure is the HTTP error body wrapped in ok:false:

{"ok":false,"error":{"code":"validationFailed","message":"out of range","field":"brightness"}}

The codes are the same ones HTTP returns for the same mistake, listed with the messages they carry over MQTT in Errors → Errors over MQTT.

A topic AWTRIX does not recognize gets no answer at all: no error, nothing. A typo such as awtrixNG/cmd/notfiy is simply ignored, and so is awtrixNG/cmd/indicators/9, where HTTP would answer 404. If a command seems to do nothing, check the topic spelling first.

Commands that restart AWTRIX (cmd/device/reboot, cmd/settings/reset) may restart before the answer goes out. Do not wait for it.

Subscribe to state

AWTRIX publishes its state by itself. These topics are retained: the broker keeps the last value, so a new subscriber gets it the moment it connects.

Topic What
<prefix>/state/device the GET /api/v1/device object
<prefix>/state/settings the GET /api/v1/settings object
<prefix>/state/apps/active the current app name, as a plain string
<prefix>/state/capabilities available effects, transitions, overlays, palettes
mosquitto_sub -h 192.168.1.10 -t 'awtrixNG/state/#' -v

state/device is the one most automations want: uptime, free memory, Wi-Fi signal, light level, battery and the current app. Its fields are documented at Device state. The full topic list, including the radio and screen topics and every retain flag, is MQTT topics → State topics.

state/settings and state/apps/active are published as soon as the value changes, so a change made over HTTP or in the web UI shows up on MQTT at once. state/device goes out every statsInterval milliseconds (10 000 by default) and sooner when the display power or an indicator changes.

Base your automations on these state topics, not on the command you published. A lost message is lost without a warning. The state topics show what AWTRIX is really doing.

Button presses

Each button publishes "1" when pressed and "0" when released. The messages are not retained, so only a client that is subscribed at that moment sees a press:

mosquitto_sub -h 192.168.1.10 -t 'awtrixNG/state/buttons/+' -v
awtrixNG/state/buttons/select 1
awtrixNG/state/buttons/select 0

The three buttons are left, select and right. Use these topics to trigger automations. In Home Assistant the button binary_sensor entities follow them too. See Home Assistant.

Is it alive?

AWTRIX publishes online to <prefix>/availability (retained) when it connects. If AWTRIX drops off, the broker publishes offline there for it (MQTT "last will"):

mosquitto_sub -h 192.168.1.10 -t 'awtrixNG/availability' -v

Home Assistant discovery uses the same <prefix>/availability topic, so an automation that watches it keeps working when you switch discovery on. See Availability and LWT.

Good to know

  • Nothing arrives, and a yellow dot pulses in the bottom-left corner of the display. AWTRIX cannot reach the broker. See MQTT never connects.
  • A command does nothing and no /result comes back. The topic is misspelled or does not exist.
  • A large command does nothing and gets no answer. A command over 8192 bytes is dropped, most often a notification that carries a big icon. See Limits.
  • The /result says ok:false. The error names the problem and usually the field. See Errors over MQTT.
  • You are not sure which command failed. Subscribe to awtrixNG/event/error. Every rejected command appears there, also the ones sent over HTTP. See event/error.