Skip to main content
PAI’s MQTT interface publishes all panel state and live events to an MQTT broker and subscribes to control topics so you can arm, disarm, and trigger outputs from any MQTT client.

Enabling MQTT

Set MQTT_ENABLE = True in your pai.conf and point PAI at your broker:
pai.conf
MQTT_ENABLE = True
MQTT_HOST = '192.168.1.10'
MQTT_PORT = 1883
MQTT_USERNAME = 'pai'
MQTT_PASSWORD = 'secret'
The MQTT interface is disabled by default. You must set MQTT_ENABLE = True for any of the MQTT settings to take effect.

Connection settings

SettingDefaultDescription
MQTT_USERNAMENoneMQTT username for broker authentication
MQTT_PASSWORDNoneMQTT password for broker authentication
MQTT_KEEPALIVE60Keep-alive interval in seconds (1–3600)
Set MQTT_TLS_CERT_PATH to the path of your CA certificate to enable TLS. When TLS is active, MQTT_PORT becomes the TLS port.
pai.conf
MQTT_TLS_CERT_PATH = '/etc/pai/certs/ca.pem'
MQTT_PORT = 8883
PAI uses ssl.PROTOCOL_TLSv1_2 with ssl.CERT_REQUIRED and does not allow insecure connections.
SettingDefaultAllowed values
MQTT_PROTOCOL'3.1.1''3.1', '3.1.1', '5'
MQTT_TRANSPORT'tcp''tcp', 'websockets'
MQTT_BIND_ADDRESS''Client bind address (empty = auto)
MQTT_BIND_PORT0Client bind port (0 = auto)
SettingDefaultDescription
MQTT_QOS0QoS level: 0 = fire-and-forget, 1 = at least once, 2 = exactly once
MQTT_RETAINTruePublish messages with the retain flag
MQTT_USE_NUMERIC_STATESFalsePublish 0/1 instead of False/True

Topic structure

All topics are rooted under MQTT_BASE_TOPIC (default: paradox). State topics follow the pattern:
{base}/states/{element-type}/{name}/{property}
The states segment comes from MQTT_STATES_TOPIC (default: states) and appears before the element type, not after the element name.
In the source code (basic.py), state topics are built as {MQTT_BASE_TOPIC}/{MQTT_STATES_TOPIC}/{element_topic}/{sanitized_name}/{attribute}. Element names are slugified before use as topic segments.

Element topics

ElementTopic segment config keyDefault segmentFull example
ZonesMQTT_ZONE_TOPICzonesparadox/states/zones/front_door/open
PartitionsMQTT_PARTITION_TOPICpartitionsparadox/states/partitions/home/arm
Outputs / PGMsMQTT_OUTPUT_TOPICoutputsparadox/states/outputs/siren/on
BusesMQTT_BUS_TOPICbusesparadox/states/buses/bus_1/tamper
Bus modulesMQTT_MODULE_TOPICbus-moduleparadox/states/bus-module/module_1/tamper
DoorsMQTT_DOOR_TOPICdoorsparadox/states/doors/main_entry/open
KeypadsMQTT_KEYPAD_TOPICkeypadsparadox/states/keypads/keypad_1/trouble
RepeatersMQTT_REPEATER_TOPICrepeatersparadox/states/repeaters/repeater_1/trouble
SystemMQTT_SYSTEM_TOPICsystemparadox/states/system/power/dc
UsersMQTT_USER_TOPICusersparadox/states/users/user_1/login

Special topics

PurposeTopic (default values)Notes
Raw JSON eventsparadox/events/rawPublished when MQTT_PUBLISH_RAW_EVENTS = True (default)
PAI run statusparadox/interface/pai_statusValues: initializing, connected, online, paused, stopped, error
Availability (LWT)paradox/interface/availabilityValues: online / offline
Challenge (HMAC auth)paradox/states/challengePublished when MQTT_CHALLENGE_SECRET is set
Command statusparadox/interface/command_statusPublished when MQTT_PUBLISH_COMMAND_STATUS = True (QoS 2, retained)
The pai_status topic carries one of: initializing, connected, online, paused, stopped, error, or offline.

Topic config reference

Config keyDefault
MQTT_BASE_TOPIC'paradox'
MQTT_STATES_TOPIC'states'
MQTT_EVENTS_TOPIC'events'
MQTT_RAW_TOPIC'raw'
MQTT_CONTROL_TOPIC'control'
MQTT_DEFINITION_TOPIC'definitions'
MQTT_NOTIFICATIONS_TOPIC'notifications'
MQTT_SEND_PANIC_TOPIC'panic'
MQTT_INTERFACE_TOPIC'interface'
MQTT_CHALLENGE_TOPIC'challenge'
MQTT_COMMAND_STATUS_TOPIC'command_status'

Controlling the panel via MQTT

Publish to the control topic to send commands:
{base}/control/{element-type}/{name}  payload: <command>
Retained messages are ignored — PAI logs a warning and discards them.

Partition commands

Publish to paradox/control/partitions/{name}/{command}:
CommandAction
armArm away
disarmDisarm
arm_stayArm stay (home)
arm_sleepArm sleep (night)

Output / PGM commands

Publish to paradox/control/outputs/{name}/{command}:
CommandAction
onActivate output
offDeactivate output
pulsePulse output (duration set by OUTPUT_PULSE_DURATION, default 1 s)

Panic command

Publish to paradox/panic/{type}/{partition}/{userid} to trigger a panic. {type} is the panic type code accepted by the panel, {partition} is the partition name, and {userid} is the user ID number. Customise the topic prefix with MQTT_SEND_PANIC_TOPIC (default: 'panic').

Command aliases

MQTT_COMMAND_ALIAS maps incoming payloads to internal commands before execution. The default mapping provides homebridge compatibility:
pai.conf
MQTT_COMMAND_ALIAS = {
    'armed_home': 'arm_stay',
    'armed_night': 'arm_sleep',
    'armed_away': 'arm',
    'disarmed': 'disarm',
}

Code-protected toggle commands

MQTT_TOGGLE_CODES maps code strings to user labels. When a code_toggle-{code} command is received, PAI checks the current arm state and toggles between arm and disarm:
pai.conf
MQTT_TOGGLE_CODES = {
    '1234': 'John',
    '5678': 'Jane',
}
Send the payload code_toggle-1234 to a partition control topic to use it.

HMAC command authorisation

Set MQTT_CHALLENGE_SECRET to require HMAC-SHA1 challenge–response authentication for all commands. PAI publishes a fresh random challenge to paradox/states/challenge after every command attempt.
pai.conf
MQTT_CHALLENGE_SECRET = 'my-shared-secret'
MQTT_CHALLENGE_ROUNDS = 1000  # PBKDF iteration count, default 1000
Command payload format when challenge auth is active:
{command} {response}
Or, when MQTT_CHALLENGE_SECRET is a dict keyed by username:
{command} {username} {response}
Do not set MQTT_CHALLENGE_SECRET if you do not have a client that implements the HMAC-SHA1 challenge protocol — all commands will be rejected.

Publishing command status

Enable MQTT_PUBLISH_COMMAND_STATUS = True to have PAI publish accepted/refused messages for each command to paradox/interface/command_status (topic: {base}/{MQTT_INTERFACE_TOPIC}/{MQTT_COMMAND_STATUS_TOPIC}, QoS 2, retained).

Republishing state

PAI republishes all cached state to MQTT periodically so that new subscribers receive full state without waiting for a panel change.
Config keyDefaultMin
MQTT_REPUBLISH_INTERVAL43200 (12 hours)60
Value is in seconds. Any topic that has not been published within the interval is re-sent.

Publishing raw events

When MQTT_PUBLISH_RAW_EVENTS = True (default), every live panel event is serialised to JSON and published to paradox/events/raw at QoS 0. Set MQTT_PUBLISH_DEFINITIONS = False (default) to suppress publishing zone/partition/user definitions to paradox/definitions/.... Enable it only if a downstream consumer needs static entity metadata.

MQTT Dash integration

PAI can publish a dashboard configuration for the MQTT Dash Android app.
Config keyDefaultDescription
MQTT_DASH_PUBLISHFalseEnable publishing of the Dash config
MQTT_DASH_TOPIC'metrics/exchange/pai'Topic to publish the Dash config to
MQTT_DASH_TEMPLATE'/etc/pai/mqtt_dash.txt'Path to the Dash template file
The template file may contain __PARTITION{N}__ placeholders that are replaced with partition labels at publish time. Publishing only occurs when at least two partitions are detected.

Minimal configuration example

pai.conf
# Connection
CONNECTION_TYPE = 'IP'
IP_CONNECTION_HOST = '192.168.1.100'
IP_CONNECTION_PORT = 10000
IP_CONNECTION_PASSWORD = 'paradox'

# MQTT
MQTT_ENABLE = True
MQTT_HOST = '192.168.1.10'
MQTT_PORT = 1883
MQTT_USERNAME = 'pai'
MQTT_PASSWORD = 'secret'
MQTT_RETAIN = True
MQTT_QOS = 0

Build docs developers (and LLMs) love