Zenoh-MQTT Bridge¶
The Zenoh-MQTT Bridge provides bidirectional protocol translation between MQTT and Zenoh, enabling IoT devices and applications using MQTT to seamlessly communicate with Zenoh-based systems.
Overview¶
This bridge connects the MQTT and Zenoh worlds, translating messages in both directions while maintaining topic structure and message semantics.
graph LR
subgraph "MQTT Domain"
MP[MQTT Publisher] -->|MQTT| MB[MQTT Broker<br/>:1883]
MB -->|MQTT| MS[MQTT Subscriber]
end
subgraph "Bridge"
Bridge[Zenoh-MQTT Bridge<br/>:1884, :8001]
end
subgraph "Zenoh Domain"
ZR[Zenoh Router<br/>:7447]
ZS[Zenoh Subscriber]
end
MP -->|MQTT :1884| Bridge
Bridge <-->|MQTT| MB
Bridge <-->|Zenoh| ZR
ZR -->|Zenoh| ZS
classDef bridge fill:#fff3e0
class Bridge bridge
Key Features¶
1. Bidirectional Translation¶
- MQTT → Zenoh: MQTT messages are published to Zenoh with scoped keys
- Zenoh → MQTT: Zenoh messages are published to MQTT topics
2. Topic Mapping¶
- Configurable scope prefix (
mqtt/demo) - Topic filtering with allow/deny patterns
- Generalised subscriptions for wildcard topics
3. MQTT Server¶
Acts as an MQTT broker on port 1884: - Clients can connect directly to the bridge - Messages automatically forwarded to Zenoh
4. REST API¶
Provides monitoring and management via HTTP (port 8001)
Configuration¶
Current Configuration¶
Located at zenoh-mqtt-bridge/config.json5:
{
mode: "client",
connect: {
endpoints: ["tcp/zenoh-router:7447"],
},
plugins: {
rest: {
http_port: 8000,
},
mqtt: {
port: "0.0.0.0:1884",
scope: "mqtt/demo",
allow: ".*",
deny: "^\\$SYS/.*|^private/.*",
generalise_subs: [
"sensor/*",
"device/*",
"data/*"
],
generalise_pubs: [
"sensor/**",
"device/**",
"data/**"
],
tx_channel_size: 65536,
}
},
plugins_loading: {
enabled: true
}
}
Configuration Parameters¶
Mode¶
Bridge connects as a client to the Zenoh router.Zenoh Connection¶
Specifies the Zenoh router endpoint.MQTT Plugin Settings¶
Port
The bridge listens for MQTT connections on port 1884.Scope
All MQTT topics are prefixed with this scope in Zenoh. For example: - MQTT topic:sensor/temperature
- Zenoh key: mqtt/demo/sensor/temperature
Allow/Deny Filters
-allow: Accept all topics by default
- deny: Reject system topics ($SYS/*) and private topics
Generalised Subscriptions
generalise_subs: ["sensor/*", "device/*", "data/*"]
generalise_pubs: ["sensor/**", "device/**", "data/**"]
Buffer Size
Transmission buffer size for high-throughput scenarios.Usage Examples¶
Publishing MQTT Messages¶
Direct to Bridge¶
# Publish to bridge (port 1884)
mosquitto_pub -h localhost -p 1884 \
-t 'sensor/temperature' \
-m '{"temp":25.5,"humidity":60}'
This message will appear in Zenoh as: mqtt/demo/sensor/temperature
Via MQTT Broker¶
# Publish to Mosquitto (port 1883)
mosquitto_pub -h localhost -p 1883 \
-t 'sensor/temperature' \
-m '{"temp":25.5,"humidity":60}'
The bridge subscribes to the broker and forwards to Zenoh.
Subscribing to MQTT Messages¶
# Subscribe via bridge
mosquitto_sub -h localhost -p 1884 -t 'sensor/#' -v
# Subscribe via broker
mosquitto_sub -h localhost -p 1883 -t 'sensor/#' -v
Zenoh to MQTT Flow¶
Messages published to Zenoh keys matching the scope appear in MQTT:
# Python Zenoh publisher
import zenoh
session = zenoh.open()
session.put("mqtt/demo/sensor/status", "online")
MQTT subscribers see this on topic: sensor/status
Docker Configuration¶
zenoh-mqtt-bridge:
container_name: zenoh-mqtt-bridge
image: eclipse/zenoh-bridge-mqtt:latest
restart: unless-stopped
depends_on:
- mosquitto
- zenoh-router
ports:
- "8001:8000" # REST API
- "1884:1884" # MQTT port
volumes:
- ./zenoh-mqtt-bridge/config.json5:/etc/zenoh/config.json5
environment:
- RUST_LOG=debug
networks:
- zenoh-mqtt-net
command: "-c /etc/zenoh/config.json5"
Port Mappings¶
| Container Port | Host Port | Protocol | Purpose |
|---|---|---|---|
| 8000 | 8001 | HTTP | REST API |
| 1884 | 1884 | MQTT | MQTT server |
Monitoring¶
View Logs¶
# Real-time logs
docker-compose logs -f zenoh-mqtt-bridge
# Filter for errors
docker-compose logs zenoh-mqtt-bridge | grep -i error
REST API¶
Check bridge status:
# Bridge information
curl http://localhost:8001/@/local/status
# List active subscriptions
curl http://localhost:8001/@/local/subscriptions
Test Connectivity¶
# Test MQTT connection
mosquitto_pub -h localhost -p 1884 -t 'test' -m 'hello' -d
# Test from Zenoh side
python3 sub.py
Topic Mapping Examples¶
Example 1: Simple Topic¶
| MQTT Topic | Zenoh Key |
|---|---|
sensor/temperature |
mqtt/demo/sensor/temperature |
device/status |
mqtt/demo/device/status |
data/metrics |
mqtt/demo/data/metrics |
Example 2: Hierarchical Topics¶
| MQTT Topic | Zenoh Key |
|---|---|
home/living/temp |
mqtt/demo/home/living/temp |
factory/line1/sensor3 |
mqtt/demo/factory/line1/sensor3 |
Example 3: Wildcards¶
MQTT subscriptions with wildcards work seamlessly:
Receives all Zenoh messages under mqtt/demo/sensor/*
Performance¶
Throughput¶
- 10,000+ messages/second typical
- 100,000+ messages/second with tuning
Latency¶
- < 1ms local bridge latency
- < 5ms end-to-end (MQTT → Zenoh)
Resource Usage¶
- Memory: ~50 MB base
- CPU: < 2% idle, scales with message rate
Troubleshooting¶
Bridge Not Starting¶
# Check logs for errors
docker-compose logs zenoh-mqtt-bridge
# Verify Zenoh router is accessible
docker exec zenoh-mqtt-bridge ping -c 2 zenoh-router
# Test Zenoh connection
docker exec zenoh-mqtt-bridge nc -zv zenoh-router 7447
Messages Not Forwarding¶
# Check if bridge receives MQTT messages
docker-compose logs zenoh-mqtt-bridge | grep -i "received\|publish"
# Verify topic matches allow/deny filters
# Check configuration: cat zenoh-mqtt-bridge/config.json5
# Test direct connection
mosquitto_pub -h localhost -p 1884 -t 'test' -m 'hello' -d
High Latency¶
# Check buffer sizes in configuration
# Verify network connectivity
docker exec zenoh-mqtt-bridge ping -c 5 zenoh-router
# Monitor resource usage
docker stats zenoh-mqtt-bridge
Advanced Configuration¶
Custom Topic Mapping¶
Modify the scope for different key namespaces:
{
plugins: {
mqtt: {
scope: "iot/sensors", // Custom scope
// MQTT 'temp' becomes 'iot/sensors/temp' in Zenoh
}
}
}
Multiple Bridges¶
Run multiple bridge instances with different scopes:
zenoh-mqtt-bridge-1:
volumes:
- ./bridge1-config.json5:/etc/zenoh/config.json5
ports:
- "1884:1884"
zenoh-mqtt-bridge-2:
volumes:
- ./bridge2-config.json5:/etc/zenoh/config.json5
ports:
- "1885:1884"
QoS Mapping¶
MQTT QoS levels are handled: - QoS 0: Fire and forget (Zenoh default) - QoS 1: At least once (Zenoh with reliability) - QoS 2: Exactly once (Not fully supported)
Best Practices¶
- Use Meaningful Scopes: Choose scopes that reflect your data organization
- Filter Topics: Use allow/deny to reduce unnecessary traffic
- Monitor Logs: Check for dropped messages or errors
- Test Bidirectionally: Verify both MQTT→Zenoh and Zenoh→MQTT
- Tune Buffer Sizes: Adjust
tx_channel_sizefor your throughput needs
Security Considerations¶
- Bridge has no authentication by default
- Consider using MQTT authentication on broker
- Use network isolation (Docker networks)
- For production, implement TLS/SSL