Skip to main content
PAI searches for a configuration file in the following order:
  1. Path passed via the --config CLI argument
  2. Path in the PAI_CONFIG_FILE environment variable
  3. The following locations, in order, for each of pai.conf, pai.json, and pai.yaml:
    • Current working directory
    • ~/.local/etc/
    • /etc/pai/
    • /usr/local/etc/pai/
If none of those exist, PAI prints:
ERROR: Could not find configuration file. Tried: [...]
Fix: Create /etc/pai/pai.conf (copy from config/pai.conf.example), or set the PAI_CONFIG_FILE environment variable to your config file’s absolute path.When running in Docker, mount your config directory:
docker run ... -v /etc/pai:/etc/pai paradoxalarminterface/pai
The Docker image sets PAI_CONFIG_FILE=/etc/pai/pai.conf by default.
Check the port pathThe default in pai.conf is /dev/ttyS1. USB serial adapters (CP2102, PL2303, CH340) typically appear as /dev/ttyUSB0. Verify the device exists:
ls -la /dev/ttyUSB* /dev/ttyS*
Update your config to match:
pai.conf
SERIAL_PORT = '/dev/ttyUSB0'
Check permissionsThe user running PAI must be in the dialout group to access serial ports:
sudo usermod -aG dialout $USER
Log out and back in for the group change to take effect. When running Docker, pass the device through:
docker run --device=/dev/ttyUSB0 ...
Verify the baud rateThe baud rate must match your panel type:
PanelBaud rate
SP / MG (Spectra, Magellan)9600
EVO (default)38400
EVO (alternate)57600
pai.conf
SERIAL_BAUD = 9600   # SP/MG panels
# SERIAL_BAUD = 38400  # EVO panels
Raspberry Pi GPIO serial portParadox panels use TTL 5V logic. Connecting a 3.3 V GPIO pin directly to the panel will damage the Raspberry Pi or cause unreliable communication. Use a level shifter between the panel’s serial port and the Pi’s GPIO.
Check host and port
pai.conf
CONNECTION_TYPE = 'IP'
IP_CONNECTION_HOST = '192.168.1.100'  # IP150 address on your network
IP_CONNECTION_PORT = 10000            # Default port
Verify the IP150 is reachable from the PAI host:
ping 192.168.1.100
Check the module passwordThe default IP module password is paradox. If you changed it in the IP150 configuration, update:
pai.conf
IP_CONNECTION_PASSWORD = 'paradox'
Firmware version mattersPAI supports direct connection to IP150 when the module firmware is below 4.0 or at 4.40.004 and above. Firmware versions between 4.0 and 4.40.004 require connecting through the Paradox SWAN cloud service via IP_CONNECTION_SITEID and IP_CONNECTION_EMAIL.
Paradox SWAN connections go through the cloud. The PAI maintainers do not recommend this method. See the security advisory linked in the README.
Verify MQTT is enabledMQTT is disabled by default. Check your config:
pai.conf
MQTT_ENABLE = True
Check host and port
pai.conf
MQTT_HOST = '127.0.0.1'  # Hostname or IP of your broker
MQTT_PORT = 1883          # Default MQTT port
Verify the broker is running
# For Mosquitto
systemctl status mosquitto

# Test connectivity with mosquitto_sub
mosquitto_sub -h 127.0.0.1 -t 'paradox/#' -v
AuthenticationIf your broker requires credentials, set them in the config:
pai.conf
MQTT_USERNAME = 'myuser'
MQTT_PASSWORD = 'mypassword'
Both default to None (no authentication).Verify the base topicPAI publishes to paradox/# by default (MQTT_BASE_TOPIC = 'paradox'). Subscribe to the wildcard to see all messages:
mosquitto_sub -h 127.0.0.1 -t 'paradox/#' -v
Check the interface is enabledEach interface is disabled by default:
pai.conf
PUSHBULLET_ENABLE = True
PUSHOVER_ENABLE = True
SIGNAL_ENABLE = True
GSM_ENABLE = True
HOMEASSISTANT_NOTIFICATIONS_ENABLE = True
Review event filter settingsThe default tag filters for most interfaces are:
pai.conf
PUSHBULLET_EVENT_FILTERS = [
    'live,alarm,-restore',
    'trouble,-clock',
    'live,tamper',
]
If the event you expect does not carry all the tags in at least one filter entry, it will be silently dropped. Enable LOGGING_DUMP_EVENTS = True to log every event and its tags, then cross-check against your filter.Check MIN_EVENT_LEVELEvents below the configured level are dropped before the filters run:
pai.conf
PUSHBULLET_MIN_EVENT_LEVEL = 'INFO'
GSM_MIN_EVENT_LEVEL = 'CRITICAL'  # GSM default is CRITICAL
Lower the level temporarily to DEBUG to confirm events are reaching the interface.
Set the console log level to DEBUG in your config:
pai.conf
import logging
LOGGING_LEVEL_CONSOLE = logging.DEBUG
For deeper diagnostics, enable one or more dump flags:
pai.conf
LOGGING_DUMP_PACKETS  = True  # Raw bytes sent/received on the wire
LOGGING_DUMP_MESSAGES = True  # Decoded protocol messages
LOGGING_DUMP_STATUS   = True  # Panel status updates
LOGGING_DUMP_EVENTS   = True  # Full event details including tags
Enabling all dump flags produces a large volume of log output and will slow PAI down. Use them only during active debugging and disable them once the issue is resolved.
To write logs to a file, set:
pai.conf
LOGGING_FILE = '/var/log/pai/paradox.log'
LOGGING_LEVEL_FILE = logging.DEBUG
LOGGING_FILE_MAX_SIZE  = 10  # MB
LOGGING_FILE_MAX_FILES = 2   # Rotated copies to keep
EVO firmware version 7.50.000 and above introduced serial communication encryption. PAI cannot decrypt this communication, so the serial connection stops working after upgrading to an affected firmware.
This firmware upgrade is irreversible. Do not upgrade EVO panels to firmware 7.50.000 or later if you rely on a serial connection with PAI.
Options if you have already upgraded:
  • Purchase a Paradox unlock code. Paradox sells a code that re-enables the unencrypted serial port. Contact your Paradox dealer.
  • Use an IP150 module. The IP150 connection is not affected by serial encryption. Switch CONNECTION_TYPE to IP and configure the module.
pai.conf
CONNECTION_TYPE = 'IP'
IP_CONNECTION_HOST = '192.168.1.100'
IP_CONNECTION_PORT = 10000
IP_CONNECTION_PASSWORD = 'paradox'

Build docs developers (and LLMs) love