A Python application to bridge MQTT messages from a local LoRaWAN gateway broker to multiple remote MQTT brokers with powerful filtering capabilities.
- Multi-Broker Support: Forward messages to multiple remote MQTT brokers simultaneously
- Flexible Topic Forwarding: Each remote broker can receive LoRa topics, SCADA topics, or both
- Message Filtering: Filter messages based on DevEUI, JoinEUI, or AppEUI using whitelists and blacklists
- Field Filtering: Include or exclude specific fields from forwarded messages
- Dynamic Topic Patterns: Use variables like
%(gwuuid)s,%(deveui)s,%(appeui)sin remote topics - Gateway UUID: Automatically retrieve gateway UUID for topic patterns
- TLS Support: Secure connections to remote brokers with full TLS/SSL support
- Message Queuing: Queue messages when remote brokers are temporarily unavailable
- Status Reporting: Write status.json for mLinux app-manager integration
- Syslog Logging: Native syslog support for gateway deployments
| Platform | Python Version | Status |
|---|---|---|
| Ubuntu/Debian | 3.10+ | ✅ Supported |
| MultiTech mLinux 7 | 3.10 | ✅ Supported |
| MultiTech mLinux 6 | 3.8 | ✅ Supported |
Download the appropriate tarball from the releases page:
lora_mqtt_bridge-1.0.0-mlinux7.tar.gzfor mLinux 7.xlora_mqtt_bridge-1.0.0-mlinux6.tar.gzfor mLinux 6.x
Install via the mPower web UI:
- Navigate to Administration > Custom Applications
- Click Upload and select the tarball
- Click Install
- Configure via the app's config file at
/var/config/app/lora_mqtt_bridge/config/config.json - Start the application
# Clone the repository
git clone https://github.com/MultiTechSystems/lora-mqtt-bridge.git
cd lora-mqtt-bridge
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -e ".[dev]"Create config.json:
{
"local_broker": {
"host": "127.0.0.1",
"port": 1883
},
"remote_brokers": [
{
"name": "cloud",
"host": "mqtt.example.com",
"port": 8883,
"username": "your-username",
"password": "your-password",
"tls": {
"enabled": true
},
"source_topic_format": ["lora", "scada"],
"topics": {
"uplink_pattern": "lorawan/%(gwuuid)s/%(appeui)s/%(deveui)s/up"
}
}
]
}# Using configuration file
lora-mqtt-bridge -c config.json
# Or using environment variables
export LORA_MQTT_BRIDGE_LOCAL_HOST=127.0.0.1
export LORA_MQTT_BRIDGE_REMOTE_HOST=mqtt.example.com
lora-mqtt-bridge --envEach remote broker can specify which local topics to forward:
{
"remote_brokers": [
{
"name": "lora-only",
"host": "lora.example.com",
"source_topic_format": ["lora"]
},
{
"name": "scada-only",
"host": "scada.example.com",
"source_topic_format": ["scada"]
},
{
"name": "all-data",
"host": "cloud.example.com",
"source_topic_format": ["lora", "scada"]
}
]
}Use these variables in remote broker uplink_pattern:
| Variable | Description | Example |
|---|---|---|
%(gwuuid)s |
Gateway UUID (auto-detected) | 244ab1fb-b08d-1dcc-d02d-bee6f5236ced |
%(deveui)s |
Device EUI | 00-80-00-00-0a-00-11-ba |
%(appeui)s |
Application EUI | 16-ea-76-f6-ab-66-3d-80 |
%(joineui)s |
Join EUI | 16-ea-76-f6-ab-66-3d-80 |
%(gweui)s |
Gateway EUI | 00-80-00-00-d0-00-42-6e |
Example:
{
"topics": {
"uplink_pattern": "lorawan/%(gwuuid)s/%(appeui)s/%(deveui)s/up"
}
}Filter which devices' messages are forwarded:
{
"message_filter": {
"deveui_whitelist": ["00-11-22-33-44-55-66-77"],
"appeui_blacklist": ["ff-ff-ff-ff-ff-ff-ff-ff"]
}
}Control which fields are included in forwarded messages:
{
"field_filter": {
"exclude_fields": ["rssi", "snr", "freq"],
"always_include": ["deveui", "appeui", "time"]
}
}See docs/configuration.md for complete configuration options.
Local subscriptions:
lora/+/+/up- Device uplinkslora/+/joined- Join eventslora/+/+/moved- Device moved events
Local subscriptions:
scada/+/+/up- Device uplinks (e.g.,scada/lorawan/{deveui}/up)
SCADA topics contain JSON-decoded payload data instead of base64-encoded data.
On mLinux gateways, the application writes status to /var/config/app/lora_mqtt_bridge/status.json:
{"pid": 12345, "AppInfo": "Local:OK | Remote:1/1 | Msgs:42 @ 14:30:00"}Status format: Local:{OK|DISC} | Remote:{connected}/{total} [| Msgs:{count}] @ {time}
Local:OK- Connected to local broker,Local:DISC- DisconnectedRemote:1/2- 1 of 2 remote brokers connectedMsgs:42- Messages forwarded (only shown when > 0)
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run linter
ruff check src tests
# Run formatter
ruff format src tests
# Run type checker
mypy src --ignore-missing-importslora-mqtt-bridge/
├── src/lora_mqtt_bridge/ # Main source (Python 3.10+)
├── mlinux-6/ # mLinux 6 version (Python 3.8)
├── mlinux-7/ # mLinux 7 version (Python 3.10)
├── ubuntu/ # Ubuntu/server version
├── tests/ # Test suite
├── docs/ # Documentation
├── config/ # Example configurations
└── dist/ # Built tarballs
- Getting Started
- Configuration Guide
- Filtering Guide
- Topic Formats
- API Reference
- Deployment Guide
- Cursor Agent Development Guide
┌──────────────────┐ ┌─────────────────┐ ┌──────────────────┐
│ LoRa Gateway │────▶│ MQTT Bridge │────▶│ Remote Broker 1 │
│ (Local Broker) │ │ │────▶│ Remote Broker 2 │
│ │◀────│ │────▶│ Remote Broker N │
└──────────────────┘ └─────────────────┘ └──────────────────┘
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Based on the MultiTech LoRaWAN App Connect specification
- Uses paho-mqtt for MQTT connectivity