707 lines
25 KiB
Markdown
707 lines
25 KiB
Markdown
---
|
|
title: "paho-mqtt: Eclipse Paho MQTT Python Client"
|
|
library_name: paho-mqtt
|
|
pypi_package: paho-mqtt
|
|
category: networking
|
|
python_compatibility: "3.7+"
|
|
last_updated: "2025-11-02"
|
|
official_docs: "https://eclipse.dev/paho/files/paho.mqtt.python/html"
|
|
official_repository: "https://github.com/eclipse-paho/paho.mqtt.python"
|
|
maintenance_status: "active"
|
|
---
|
|
|
|
# paho-mqtt: Eclipse Paho MQTT Python Client
|
|
|
|
## Core Purpose
|
|
|
|
The model must state that paho-mqtt is the official Eclipse Foundation implementation of the MQTT protocol client for Python.
|
|
|
|
MQTT (Message Queuing Telemetry Transport) is a lightweight publish-subscribe messaging protocol designed for machine-to-machine (M2M) and Internet of Things (IoT) communication. The model must explain that paho-mqtt solves the problem of reliable, lightweight messaging in bandwidth-constrained or unreliable network environments.
|
|
|
|
### What Problem Does It Solve?
|
|
|
|
The model must identify these key use cases:
|
|
|
|
1. **IoT Device Communication**: Enables lightweight messaging between sensors, actuators, and control systems
|
|
2. **Publish-Subscribe Patterns**: Provides decoupled communication where publishers and subscribers do not need to know about each other
|
|
3. **Bandwidth-Constrained Networks**: Minimizes network overhead compared to HTTP/REST
|
|
4. **Unreliable Network Handling**: Built-in Quality of Service (QoS) levels ensure message delivery guarantees
|
|
5. **Bi-directional Communication**: Supports both sending commands to devices and receiving telemetry data
|
|
|
|
### Reinventing the Wheel Without It
|
|
|
|
The model must verify that without paho-mqtt, developers would need to:
|
|
|
|
- Implement the complex MQTT protocol specification from scratch @ <https://mqtt.org/mqtt-specification/>
|
|
- Handle connection management, keep-alive pings, and automatic reconnection logic
|
|
- Implement three QoS levels (0, 1, 2) with appropriate acknowledgment mechanisms
|
|
- Manage topic subscriptions and wildcard matching
|
|
- Handle TLS/SSL encryption and WebSocket transport layers
|
|
|
|
## Official Information
|
|
|
|
The model must cite these verified sources:
|
|
|
|
- **Official Repository**: <https://github.com/eclipse-paho/paho.mqtt.python> @ verified 2025-10-21
|
|
- **PyPI Package**: `paho-mqtt` @ <https://pypi.org/project/paho-mqtt/>
|
|
- **Official Documentation**: <https://eclipse.dev/paho/files/paho.mqtt.python/html/>
|
|
- **License**: EPL-2.0 OR BSD-3-Clause (Eclipse Distribution License v1.0 and Eclipse Public License 2.0)
|
|
- **Maintainer**: Eclipse Foundation @ <https://www.eclipse.org/paho/>
|
|
- **Latest Version**: 2.1.0 (as of 2025-10-21)
|
|
- **Status**: Active development, production-ready (Beta classification indicates mature but evolving API)
|
|
|
|
## Python Version Compatibility
|
|
|
|
The model must verify from pyproject.toml @ <https://github.com/eclipse-paho/paho.mqtt.python/blob/master/pyproject.toml>:
|
|
|
|
- **Minimum Python Version**: 3.7
|
|
- **Tested Versions**: 3.7, 3.8, 3.9, 3.10
|
|
- **Python 3.11-3.14 Status**: The model must state that Python 3.11+ compatibility is likely based on package maturity, but official classifiers only list up to 3.10. Users should test thoroughly.
|
|
- **Python 2.x**: NOT supported (users must stay on paho-mqtt 1.x for Python 2)
|
|
|
|
### Breaking Changes
|
|
|
|
The model must warn that version 2.0 introduced breaking changes:
|
|
|
|
- Callback API signatures changed (VERSION1 vs VERSION2)
|
|
- `CallbackAPIVersion` must now be explicitly specified
|
|
- Migration guide available @ <https://eclipse.dev/paho/files/paho.mqtt.python/html/migrations.html>
|
|
|
|
## Core Features
|
|
|
|
### 1. Quality of Service (QoS) Levels
|
|
|
|
The model must explain that MQTT provides three QoS levels @ <https://mqtt.org/mqtt-specification/>:
|
|
|
|
- **QoS 0 (At most once)**: Fire-and-forget, no acknowledgment, possible message loss
|
|
- **QoS 1 (At least once)**: Guaranteed delivery, possible duplicates, uses PUBACK
|
|
- **QoS 2 (Exactly once)**: Guaranteed single delivery, uses PUBREC/PUBREL/PUBCOMP handshake
|
|
|
|
Example from official docs @ <https://github.com/eclipse-paho/paho.mqtt.python/blob/master/README.rst>:
|
|
|
|
```python
|
|
import paho.mqtt.client as mqtt
|
|
|
|
# QoS 0: Fire and forget
|
|
client.publish("topic/sensor", "temperature:22", qos=0)
|
|
|
|
# QoS 1: At least once delivery
|
|
msg_info = client.publish("topic/critical", "alert", qos=1)
|
|
msg_info.wait_for_publish() # Wait for PUBACK
|
|
|
|
# QoS 2: Exactly once delivery
|
|
client.publish("topic/transaction", "payment:100", qos=2)
|
|
```
|
|
|
|
### 2. Connection Management
|
|
|
|
The model must verify that paho-mqtt handles:
|
|
|
|
- **Keep-Alive Mechanism**: Automatic ping/pong to maintain connection
|
|
- **Automatic Reconnection**: Built-in retry logic with exponential backoff
|
|
- **Clean Session vs Persistent Session**: Control message persistence across disconnections
|
|
- **Last Will and Testament (LWT)**: Automatic message sent on unexpected disconnection
|
|
|
|
Example @ <https://eclipse.dev/paho/files/paho.mqtt.python/html/client.html>:
|
|
|
|
```python
|
|
import paho.mqtt.client as mqtt
|
|
|
|
def on_connect(client, userdata, flags, reason_code, properties):
|
|
if reason_code.is_failure:
|
|
print(f"Failed to connect: {reason_code}")
|
|
else:
|
|
print("Connected successfully")
|
|
# Subscribe in on_connect ensures subscriptions persist across reconnections
|
|
client.subscribe("sensors/#")
|
|
|
|
def on_disconnect(client, userdata, flags, reason_code, properties):
|
|
if reason_code != 0:
|
|
print(f"Unexpected disconnect: {reason_code}")
|
|
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
|
client.on_connect = on_connect
|
|
client.on_disconnect = on_disconnect
|
|
|
|
# Configure reconnection with exponential backoff
|
|
client.reconnect_delay_set(min_delay=1, max_delay=120)
|
|
|
|
client.connect("mqtt.eclipseprojects.io", 1883, keepalive=60)
|
|
client.loop_forever() # Handles automatic reconnection
|
|
```
|
|
|
|
### 3. Topic Wildcards
|
|
|
|
The model must explain MQTT topic wildcards @ <http://www.steves-internet-guide.com/understanding-mqtt-topics/>:
|
|
|
|
- **`+` (single-level wildcard)**: Matches one topic level, e.g., `home/+/temperature` matches `home/bedroom/temperature`
|
|
- **`#` (multi-level wildcard)**: Matches multiple levels, e.g., `sensors/#` matches `sensors/temp`, `sensors/humidity/outside`
|
|
|
|
```python
|
|
# Subscribe to all system topics
|
|
client.subscribe("$SYS/#")
|
|
|
|
# Subscribe to all rooms' temperature
|
|
client.subscribe("home/+/temperature")
|
|
|
|
# Helper function to check topic matches
|
|
from paho.mqtt.client import topic_matches_sub
|
|
|
|
assert topic_matches_sub("foo/#", "foo/bar")
|
|
assert topic_matches_sub("+/bar", "foo/bar")
|
|
assert not topic_matches_sub("non/+/+", "non/matching")
|
|
```
|
|
|
|
## Real-World Examples
|
|
|
|
The model must cite these verified examples from GitHub search @ 2025-10-21:
|
|
|
|
### 1. Home Assistant Integration
|
|
|
|
**Repository**: <https://github.com/home-assistant/core> (82,088 stars) **Use Case**: Open-source home automation platform using MQTT for device integration **Pattern**: Bidirectional communication with IoT devices (lights, sensors, thermostats)
|
|
|
|
```python
|
|
# Pattern extracted from Home Assistant ecosystem
|
|
import paho.mqtt.client as mqtt
|
|
|
|
def on_message(client, userdata, message):
|
|
topic = message.topic # e.g., "homeassistant/switch/living_room/state"
|
|
payload = message.payload.decode() # e.g., "ON" or "OFF"
|
|
# Process device state changes
|
|
handle_device_update(topic, payload)
|
|
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
|
client.on_message = on_message
|
|
client.connect("homeassistant.local", 1883)
|
|
client.subscribe("homeassistant/#")
|
|
client.loop_forever()
|
|
```
|
|
|
|
### 2. AWS IoT Integration
|
|
|
|
**Repository**: <https://github.com/mariocannistra/python-paho-mqtt-for-aws-iot> (82 stars) **Use Case**: Connect Python applications to AWS IoT Core using MQTT over TLS **Pattern**: Secure cloud IoT communication with certificate-based authentication
|
|
|
|
```python
|
|
# Pattern from AWS IoT example @ https://github.com/mariocannistra/python-paho-mqtt-for-aws-iot
|
|
import paho.mqtt.client as mqtt
|
|
import ssl
|
|
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
|
|
|
# AWS IoT requires TLS with client certificates
|
|
client.tls_set(
|
|
ca_certs="root-CA.crt",
|
|
certfile="device-cert.pem",
|
|
keyfile="device-private.key",
|
|
tls_version=ssl.PROTOCOL_TLSv1_2
|
|
)
|
|
|
|
# AWS IoT endpoint
|
|
client.connect("a1b2c3d4e5f6g7.iot.us-west-2.amazonaws.com", 8883)
|
|
|
|
# Publish sensor data
|
|
client.publish("device/telemetry", '{"temp": 22.5, "humidity": 65}', qos=1)
|
|
```
|
|
|
|
### 3. Async Wrapper Pattern
|
|
|
|
**Repository**: <https://github.com/mossblaser/aiomqtt> (53 stars) **Use Case**: AsyncIO wrapper around paho-mqtt for non-blocking event loops **Pattern**: Integration with modern Python async/await patterns
|
|
|
|
Note: The model must verify that paho-mqtt itself does NOT have native async support. Third-party wrappers exist:
|
|
|
|
- `aiomqtt` @ <https://github.com/empicano/aiomqtt> (recommended, actively maintained)
|
|
- `asyncio-mqtt` @ <https://github.com/sbtinstruments/asyncio-mqtt> (deprecated)
|
|
|
|
## Integration Patterns
|
|
|
|
### 1. MQTT Broker Compatibility
|
|
|
|
The model must verify that paho-mqtt works with these brokers @ <https://mqtt.org/software/>:
|
|
|
|
- **Eclipse Mosquitto**: Open-source, lightweight broker @ <https://mosquitto.org/>
|
|
- **HiveMQ**: Enterprise MQTT platform @ <https://www.hivemq.com/>
|
|
- **EMQX**: Scalable, distributed broker @ <https://www.emqx.io/>
|
|
- **AWS IoT Core**: Cloud-based managed service
|
|
- **Azure IoT Hub**: Microsoft cloud IoT platform
|
|
- **Google Cloud IoT Core**: Google cloud service
|
|
|
|
Example with Mosquitto @ <http://www.steves-internet-guide.com/into-mqtt-python-client/>:
|
|
|
|
```python
|
|
import paho.mqtt.client as mqtt
|
|
|
|
def on_message(client, userdata, message):
|
|
print(f"Received: {message.payload.decode()} on {message.topic}")
|
|
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="python_client")
|
|
client.on_message = on_message
|
|
|
|
# Local Mosquitto broker
|
|
client.connect("localhost", 1883, 60)
|
|
client.subscribe("test/topic")
|
|
client.loop_forever()
|
|
```
|
|
|
|
### 2. WebSocket Transport
|
|
|
|
The model must verify WebSocket support @ <https://github.com/eclipse-paho/paho.mqtt.python/blob/master/ChangeLog.txt>:
|
|
|
|
```python
|
|
import paho.mqtt.client as mqtt
|
|
|
|
# Connect via WebSocket (useful for browser-based or proxy environments)
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, transport="websockets")
|
|
|
|
# Configure WebSocket path and headers
|
|
client.ws_set_options(path="/mqtt", headers={'User-Agent': 'Paho-Python'})
|
|
|
|
# Connect to broker's WebSocket port
|
|
client.connect("mqtt.example.com", 8080, 60)
|
|
```
|
|
|
|
### 3. TLS/SSL Encryption
|
|
|
|
The model must verify TLS support @ <https://eclipse.dev/paho/files/paho.mqtt.python/html/client.html>:
|
|
|
|
```python
|
|
import paho.mqtt.client as mqtt
|
|
import ssl
|
|
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
|
|
|
# Server certificate validation
|
|
client.tls_set(
|
|
ca_certs="ca.crt",
|
|
certfile="client.crt",
|
|
keyfile="client.key",
|
|
tls_version=ssl.PROTOCOL_TLSv1_2
|
|
)
|
|
|
|
# For testing only: disable certificate verification (insecure!)
|
|
# client.tls_insecure_set(True)
|
|
|
|
client.connect("secure.mqtt.broker", 8883)
|
|
```
|
|
|
|
## Usage Examples
|
|
|
|
### Basic Publish
|
|
|
|
Example from official docs @ <https://github.com/eclipse-paho/paho.mqtt.python/blob/master/README.rst>:
|
|
|
|
```python
|
|
import paho.mqtt.publish as publish
|
|
|
|
# One-shot publish (connect, publish, disconnect)
|
|
publish.single(
|
|
"home/temperature",
|
|
payload="22.5",
|
|
hostname="mqtt.eclipseprojects.io",
|
|
port=1883
|
|
)
|
|
|
|
# Multiple messages at once
|
|
msgs = [
|
|
{'topic': "sensor/temp", 'payload': "22.5"},
|
|
{'topic': "sensor/humidity", 'payload': "65"},
|
|
('sensor/pressure', '1013', 0, False) # Alternative tuple format
|
|
]
|
|
publish.multiple(msgs, hostname="mqtt.eclipseprojects.io")
|
|
```
|
|
|
|
### Basic Subscribe
|
|
|
|
Example from official docs @ <https://github.com/eclipse-paho/paho.mqtt.python/blob/master/README.rst>:
|
|
|
|
```python
|
|
import paho.mqtt.subscribe as subscribe
|
|
|
|
# Simple blocking subscribe (receives one message)
|
|
msg = subscribe.simple("home/temperature", hostname="mqtt.eclipseprojects.io")
|
|
print(f"{msg.topic}: {msg.payload.decode()}")
|
|
|
|
# Callback-based subscription
|
|
def on_message_handler(client, userdata, message):
|
|
print(f"{message.topic}: {message.payload.decode()}")
|
|
userdata["count"] += 1
|
|
if userdata["count"] >= 10:
|
|
client.disconnect() # Stop after 10 messages
|
|
|
|
subscribe.callback(
|
|
on_message_handler,
|
|
"sensors/#",
|
|
hostname="mqtt.eclipseprojects.io",
|
|
userdata={"count": 0}
|
|
)
|
|
```
|
|
|
|
### Production-Grade Client
|
|
|
|
Example combining best practices @ <https://cedalo.com/blog/configuring-paho-mqtt-python-client-with-examples/>:
|
|
|
|
```python
|
|
import paho.mqtt.client as mqtt
|
|
import time
|
|
|
|
def on_connect(client, userdata, flags, reason_code, properties):
|
|
if reason_code.is_failure:
|
|
print(f"Connection failed: {reason_code}")
|
|
return
|
|
|
|
print(f"Connected with result code {reason_code}")
|
|
# Subscribe in on_connect ensures subscriptions persist after reconnection
|
|
client.subscribe("sensors/#", qos=1)
|
|
|
|
def on_disconnect(client, userdata, flags, reason_code, properties):
|
|
if reason_code != 0:
|
|
print(f"Unexpected disconnect. Reconnecting... (code: {reason_code})")
|
|
|
|
def on_message(client, userdata, message):
|
|
print(f"Topic: {message.topic}")
|
|
print(f"Payload: {message.payload.decode()}")
|
|
print(f"QoS: {message.qos}")
|
|
print(f"Retain: {message.retain}")
|
|
|
|
def on_publish(client, userdata, mid, reason_code, properties):
|
|
print(f"Message {mid} published")
|
|
|
|
# Create client with VERSION2 callbacks (recommended)
|
|
client = mqtt.Client(
|
|
mqtt.CallbackAPIVersion.VERSION2,
|
|
client_id="sensor_monitor",
|
|
clean_session=False # Persistent session
|
|
)
|
|
|
|
# Set callbacks
|
|
client.on_connect = on_connect
|
|
client.on_disconnect = on_disconnect
|
|
client.on_message = on_message
|
|
client.on_publish = on_publish
|
|
|
|
# Authentication
|
|
client.username_pw_set("username", "password")
|
|
|
|
# TLS (if required)
|
|
# client.tls_set(ca_certs="ca.crt")
|
|
|
|
# Reconnection settings
|
|
client.reconnect_delay_set(min_delay=1, max_delay=120)
|
|
|
|
# Connect
|
|
client.connect("mqtt.example.com", 1883, keepalive=60)
|
|
|
|
# Start network loop in background thread
|
|
client.loop_start()
|
|
|
|
# Application logic
|
|
try:
|
|
while True:
|
|
# Publish sensor data
|
|
result = client.publish("sensors/temperature", "22.5", qos=1)
|
|
result.wait_for_publish() # Block until published
|
|
time.sleep(5)
|
|
except KeyboardInterrupt:
|
|
print("Shutting down...")
|
|
finally:
|
|
client.loop_stop()
|
|
client.disconnect()
|
|
```
|
|
|
|
### Loop Management Patterns
|
|
|
|
The model must explain three loop options @ <https://eclipse.dev/paho/files/paho.mqtt.python/html/client.html>:
|
|
|
|
```python
|
|
import paho.mqtt.client as mqtt
|
|
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
|
client.connect("mqtt.eclipseprojects.io", 1883)
|
|
|
|
# OPTION 1: Blocking loop (simplest)
|
|
# Runs forever, handles reconnection automatically
|
|
client.loop_forever()
|
|
|
|
# OPTION 2: Threaded loop (recommended for most cases)
|
|
# Runs in background thread, main thread free for other work
|
|
client.loop_start()
|
|
# ... do other work ...
|
|
client.loop_stop()
|
|
|
|
# OPTION 3: Manual loop (advanced, full control)
|
|
# Must be called regularly, manual reconnection handling
|
|
while True:
|
|
rc = client.loop(timeout=1.0)
|
|
if rc != 0:
|
|
# Handle connection error
|
|
break
|
|
```
|
|
|
|
## When NOT to Use paho-mqtt
|
|
|
|
The model must provide clear decision guidance based on verified constraints:
|
|
|
|
### Use HTTP/REST Instead When
|
|
|
|
1. **Request-Response Pattern**: Simple one-off queries without persistent connection
|
|
- Example: Weather API calls, database queries
|
|
- Reason: HTTP is simpler for synchronous request-response
|
|
|
|
2. **Large Payload Transfer**: Transferring files, images, or large datasets
|
|
- Example: Uploading videos, downloading reports
|
|
- Reason: HTTP has better tooling for chunked transfer, range requests
|
|
|
|
3. **Browser-Based Only**: Pure web applications without IoT integration
|
|
- Example: Standard web app, SPA without real-time requirements
|
|
- Reason: REST APIs are natively supported by browsers
|
|
|
|
4. **Strong Consistency Required**: Immediate consistency across all clients
|
|
- Example: Financial transactions, inventory management
|
|
- Reason: MQTT is eventually consistent, REST can enforce immediate consistency
|
|
|
|
### Use WebSockets Instead When
|
|
|
|
1. **Full-Duplex, Low-Latency Communication**: Real-time chat, gaming, collaborative editing
|
|
- Example: Slack-like messaging, Google Docs collaboration
|
|
- Reason: WebSockets provide bidirectional streams without MQTT protocol overhead
|
|
|
|
2. **Custom Protocol**: Need full control over message format and semantics
|
|
- Example: Proprietary binary protocols, custom RPC
|
|
- Reason: WebSockets are a transport layer, MQTT adds specific semantics
|
|
|
|
### Use Message Queues (RabbitMQ, Kafka) Instead When
|
|
|
|
1. **Complex Routing Logic**: Advanced routing rules, message transformation
|
|
- Example: Enterprise service bus, workflow orchestration
|
|
- Reason: RabbitMQ exchanges provide richer routing than MQTT topics
|
|
|
|
2. **High-Throughput Log Streaming**: Million+ messages per second, log aggregation
|
|
- Example: Centralized logging, event sourcing at scale
|
|
- Reason: Kafka optimized for high-throughput sequential writes
|
|
|
|
3. **Message Persistence and Replay**: Need to replay message history
|
|
- Example: Event sourcing, audit trails
|
|
- Reason: Kafka provides durable log storage, MQTT has limited persistence
|
|
|
|
## Decision Matrix: MQTT vs Alternatives
|
|
|
|
The model must provide this decision matrix based on verified use cases:
|
|
|
|
| **Use Case** | **MQTT (paho-mqtt)** | **HTTP/REST** | **WebSocket** | **Message Queue** |
|
|
| --- | --- | --- | --- | --- |
|
|
| **IoT Sensor Data** | ✅ Optimal | ❌ Too heavy | ⚠️ Possible | ❌ Overkill |
|
|
| **Home Automation** | ✅ Optimal | ❌ Polling inefficient | ⚠️ Possible | ❌ Too complex |
|
|
| **Mobile Notifications** | ✅ Good (battery efficient) | ⚠️ Polling wastes battery | ✅ Good | ❌ Overkill |
|
|
| **Real-time Chat** | ⚠️ Possible | ❌ No real-time | ✅ Optimal | ⚠️ Possible |
|
|
| **File Transfer** | ❌ Not designed for this | ✅ Better tools | ⚠️ Possible | ❌ Wrong tool |
|
|
| **Microservices RPC** | ⚠️ Possible | ✅ Standard approach | ❌ Overkill | ✅ Enterprise scale |
|
|
| **Telemetry Collection** | ✅ Optimal | ❌ Too chatty | ❌ Overkill | ✅ At massive scale |
|
|
|
|
### Use MQTT When
|
|
|
|
The model must verify these conditions favor MQTT:
|
|
|
|
1. ✅ **Bandwidth is constrained** (cellular, satellite links)
|
|
2. ✅ **Network is unreliable** (intermittent connectivity)
|
|
3. ✅ **Many-to-many communication** (pub-sub pattern)
|
|
4. ✅ **Low latency required** (< 100ms message delivery)
|
|
5. ✅ **Battery-powered devices** (minimal protocol overhead)
|
|
6. ✅ **IoT/M2M communication** (devices, sensors, actuators)
|
|
7. ✅ **Topic-based routing** (hierarchical topic namespaces)
|
|
|
|
### Use HTTP/REST When
|
|
|
|
The model must verify these conditions favor HTTP:
|
|
|
|
1. ✅ **Request-response pattern** (client initiates, server responds)
|
|
2. ✅ **Stateless interactions** (no persistent connection needed)
|
|
3. ✅ **Large payloads** (files, documents, media)
|
|
4. ✅ **Caching required** (HTTP caching semantics)
|
|
5. ✅ **Browser-based clients** (native browser support)
|
|
6. ✅ **Standard CRUD operations** (REST conventions)
|
|
|
|
### Use WebSocket When
|
|
|
|
The model must verify these conditions favor WebSocket:
|
|
|
|
1. ✅ **Full-duplex communication** (simultaneous send/receive)
|
|
2. ✅ **Custom protocol** (need full control over wire format)
|
|
3. ✅ **Browser-based real-time** (chat, collaboration, gaming)
|
|
4. ✅ **Lower latency than MQTT** (no protocol overhead)
|
|
5. ✅ **Simple point-to-point** (no pub-sub routing needed)
|
|
|
|
## Known Limitations
|
|
|
|
The model must cite these verified limitations @ <https://github.com/eclipse-paho/paho.mqtt.python/blob/master/README.rst>:
|
|
|
|
### Session Persistence
|
|
|
|
1. **Memory-Only Sessions**: When `clean_session=False`, session state is NOT persisted to disk
|
|
- Impact: Session lost if Python process restarts
|
|
- Lost data: QoS 2 messages in-flight, pending QoS 1/2 publishes
|
|
- Mitigation: Use `wait_for_publish()` to ensure message delivery before shutdown
|
|
|
|
```python
|
|
# Session is only in memory!
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, clean_session=False)
|
|
|
|
# Ensure message is fully acknowledged before shutdown
|
|
msg_info = client.publish("critical/data", "important", qos=2)
|
|
msg_info.wait_for_publish() # Blocks until PUBCOMP received
|
|
```
|
|
|
|
2. **QoS 2 Duplicate Risk**: With `clean_session=True`, QoS > 0 messages are republished after reconnection
|
|
- Impact: QoS 2 messages may be received twice (non-compliant with MQTT spec)
|
|
- Standard requires: Discard unacknowledged messages on reconnection
|
|
- Recommendation: Use `clean_session=False` for exactly-once guarantees
|
|
|
|
### Native Async Support
|
|
|
|
The model must verify that paho-mqtt does NOT have native asyncio support:
|
|
|
|
- **Workaround**: Use third-party wrappers like `aiomqtt` @ <https://github.com/empicano/aiomqtt>
|
|
- **Alternative**: Use threaded loops (`loop_start()`) or external event loop support
|
|
|
|
```python
|
|
# NOT native async - need wrapper
|
|
import asyncio
|
|
from aiomqtt import Client # Third-party wrapper
|
|
|
|
async def main():
|
|
async with Client("mqtt.eclipseprojects.io") as client:
|
|
async with client.messages() as messages:
|
|
await client.subscribe("sensors/#")
|
|
async for message in messages:
|
|
print(message.payload.decode())
|
|
|
|
asyncio.run(main())
|
|
```
|
|
|
|
## Installation
|
|
|
|
The model must verify installation from official sources @ <https://pypi.org/project/paho-mqtt/>:
|
|
|
|
```bash
|
|
# Standard installation
|
|
pip install paho-mqtt
|
|
|
|
# With SOCKS proxy support
|
|
pip install paho-mqtt[proxy]
|
|
|
|
# Development installation from source
|
|
git clone https://github.com/eclipse-paho/paho.mqtt.python
|
|
cd paho.mqtt.python
|
|
pip install -e .
|
|
```
|
|
|
|
## Common Patterns and Best Practices
|
|
|
|
### 1. Reconnection Handling
|
|
|
|
The model must recommend this pattern @ <https://eclipse.dev/paho/files/paho.mqtt.python/html/client.html>:
|
|
|
|
```python
|
|
import paho.mqtt.client as mqtt
|
|
|
|
def on_connect(client, userdata, flags, reason_code, properties):
|
|
# ALWAYS subscribe in on_connect callback
|
|
# This ensures subscriptions are renewed after reconnection
|
|
client.subscribe("sensors/#", qos=1)
|
|
|
|
def on_disconnect(client, userdata, flags, reason_code, properties):
|
|
if reason_code != 0:
|
|
print(f"Unexpected disconnect: {reason_code}")
|
|
# loop_forever() and loop_start() will automatically reconnect
|
|
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
|
client.on_connect = on_connect
|
|
client.on_disconnect = on_disconnect
|
|
|
|
# Configure reconnection delay
|
|
client.reconnect_delay_set(min_delay=1, max_delay=120)
|
|
|
|
client.connect("mqtt.example.com", 1883)
|
|
client.loop_forever() # Handles reconnection automatically
|
|
```
|
|
|
|
### 2. Logging for Debugging
|
|
|
|
The model must recommend enabling logging @ <https://eclipse.dev/paho/files/paho.mqtt.python/html/client.html>:
|
|
|
|
```python
|
|
import logging
|
|
import paho.mqtt.client as mqtt
|
|
|
|
# Enable standard Python logging
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
|
client.enable_logger() # Uses standard logging module
|
|
|
|
# Or use custom on_log callback
|
|
def on_log(client, userdata, level, buf):
|
|
if level == mqtt.MQTT_LOG_ERR:
|
|
print(f"ERROR: {buf}")
|
|
|
|
client.on_log = on_log
|
|
```
|
|
|
|
### 3. Graceful Shutdown
|
|
|
|
The model must recommend this pattern for clean disconnection:
|
|
|
|
```python
|
|
import paho.mqtt.client as mqtt
|
|
import signal
|
|
import sys
|
|
|
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
|
|
|
def signal_handler(sig, frame):
|
|
print("Shutting down gracefully...")
|
|
client.disconnect() # Triggers clean disconnect
|
|
client.loop_stop()
|
|
sys.exit(0)
|
|
|
|
signal.signal(signal.SIGINT, signal_handler)
|
|
|
|
client.connect("mqtt.example.com", 1883)
|
|
client.loop_start()
|
|
|
|
# Application runs...
|
|
signal.pause() # Wait for SIGINT
|
|
```
|
|
|
|
## References and Sources
|
|
|
|
The model must cite these verified sources used in this research:
|
|
|
|
1. Official Eclipse Paho repository @ <https://github.com/eclipse-paho/paho.mqtt.python>
|
|
2. Official documentation @ <https://eclipse.dev/paho/files/paho.mqtt.python/html/>
|
|
3. MQTT specification @ <https://mqtt.org/mqtt-specification/>
|
|
4. Steve's Internet Guide (MQTT tutorials) @ <http://www.steves-internet-guide.com/>
|
|
5. HiveMQ MQTT client guide @ <https://www.hivemq.com/blog/mqtt-client-library-paho-python/>
|
|
6. Cedalo MQTT configuration guide @ <https://cedalo.com/blog/configuring-paho-mqtt-python-client-with-examples/>
|
|
7. EMQX Python MQTT guide @ <https://www.emqx.com/en/blog/how-to-use-mqtt-in-python>
|
|
8. Home Assistant core repository @ <https://github.com/home-assistant/core>
|
|
9. AWS IoT Python example @ <https://github.com/mariocannistra/python-paho-mqtt-for-aws-iot>
|
|
10. aiomqtt async wrapper @ <https://github.com/empicano/aiomqtt>
|
|
|
|
## Summary
|
|
|
|
The model must conclude that paho-mqtt is the recommended solution when:
|
|
|
|
1. Building IoT applications with resource-constrained devices
|
|
2. Implementing pub-sub messaging patterns with topic-based routing
|
|
3. Operating in unreliable or bandwidth-limited network environments
|
|
4. Requiring specific QoS guarantees for message delivery
|
|
5. Integrating with standard MQTT brokers (Mosquitto, HiveMQ, EMQX, AWS IoT)
|
|
|
|
The model must avoid paho-mqtt when:
|
|
|
|
1. Simple request-response patterns suffice (use HTTP/REST)
|
|
2. Real-time, low-latency browser communication needed (use WebSocket)
|
|
3. Complex message routing or high-throughput streaming required (use RabbitMQ/Kafka)
|
|
4. Large file transfers or binary data streaming needed (use HTTP)
|
|
|
|
The model must verify that paho-mqtt is production-ready, actively maintained by the Eclipse Foundation, and the de facto standard MQTT client library for Python.
|