A complete MQTT-based communication system for managing a fleet of Raspberry Pi devices with a central server.
- https://claude.ai/chat/cda74945-7244-4719-944c-0c4acf683741
- https://m365.cloud.microsoft/chat/?auth=1&origindomain=microsoft365&client-request-id=1016845e-9396-4907-9a5e-e23d633122ad
- MQTT Broker: Eclipse Mosquitto (runs in Docker)
- Raspberry Pi Client: Rust application sending heartbeats (500ms) and state reports
- Server: Rust application monitoring clients and sending segment commands
- Heartbeat (every 500ms):
{timestamp: u64}- one per client - State Report (configurable rate):
{entity_id: u32, pose: {x, y, angle}, velocity: {vx, vy}}- All coordinates are 32-bit integers
- Each Raspberry Pi can manage multiple entities (vehicles)
- Segment:
{entity_id: u32, start: (i32, i32), end: (i32, i32), velocity_start: i32, velocity_end: i32, segment_type: u8}- Targeted to specific entity on the client
# Create necessary directories
mkdir -p mosquitto/config mosquitto/data mosquitto/log
# Copy mosquitto.conf to mosquitto/config/
cp mosquitto.conf mosquitto/config/
# Start the broker
docker-compose up -d
# Check broker status
docker-compose logs -f mosquittocd mqtt-server
cargo build --release
cargo run --releaseThe server will:
- Subscribe to all RPI heartbeats and state reports
- Monitor connected clients and their entities
- Send segment commands to specific entities every 3 seconds
cd rpi-mqtt-client
cargo build --release
cargo run --releaseFor multiple Raspberry Pi devices, change the CLIENT_ID constant in main.rs:
const CLIENT_ID: &str = "rpi_client_002"; // Unique ID per deviceFor multiple entities per client, modify the entity_ids vector:
let entity_ids = vec![1u32, 2u32, 3u32]; // Add more entity IDs as neededYou can run the client on your development machine to test:
# Terminal 1: Start broker
docker-compose up
# Terminal 2: Start server
cd mqtt-server && cargo run
# Terminal 3: Start client 1
cd rpi-mqtt-client && cargo run
# Terminal 4: Start client 2 (modify CLIENT_ID first)
cd rpi-mqtt-client && cargo runrpi/{client_id}/heartbeat- Client heartbeat messagesrpi/{client_id}/state- Client state reportsserver/{client_id}/segment- Server segment commands
Both client and server connect to localhost:1883 by default. For production:
Client (rpi-mqtt-client/src/main.rs):
const BROKER_HOST: &str = "your-server-ip";Server (mqtt-server/src/main.rs):
const BROKER_HOST: &str = "localhost"; // Usually stays localhostClient heartbeat rate:
let mut interval = time::interval(Duration::from_millis(500));Client state report rate:
let mut interval = time::interval(Duration::from_millis(100)); // 10 HzServer segment sending rate:
let mut interval = time::interval(Duration::from_secs(3));- Enable Authentication in
mosquitto.conf:
allow_anonymous false
password_file /mosquitto/config/passwd
Generate password file:
docker exec -it mqtt-broker mosquitto_passwd -c /mosquitto/config/passwd username- Enable TLS/SSL:
listener 8883
cafile /mosquitto/config/ca.crt
certfile /mosquitto/config/server.crt
keyfile /mosquitto/config/server.key
- Use QoS 1 or 2 for critical messages (already configured in code)
For large fleets (100+ devices):
- Increase
max_connectionsin mosquitto.conf - Adjust
max_queued_messagesbased on message rates - Consider running broker on dedicated hardware
- Monitor broker metrics
Check broker statistics:
# Subscribe to system topics
mosquitto_sub -h localhost -t '$SYS/#' -vMonitor specific metrics:
$SYS/broker/clients/connected- Connected clients$SYS/broker/messages/received- Message throughput$SYS/broker/load/messages/sent/1min- Send rate
- Heartbeat: ~16 bytes (timestamp + overhead)
- State Report: ~28 bytes (entity_id + 6 × i32 + overhead)
- Segment: ~25 bytes (entity_id + 6 × i32 + 1 × u8 + overhead)
All well within your 16-64 byte requirement!
Each Raspberry Pi client can manage multiple entities (vehicles, robots, etc.):
Client Side:
- One heartbeat per client (500ms)
- State reports for each entity (configurable rate)
- Receives segments tagged with
entity_id - Routes segments to appropriate entity handler
Server Side:
- Tracks all clients and their entities
- Sends segments targeted to specific entities
- Monitors entity states independently
Example output:
=== Active Clients: 1 ===
rpi_client_001: last_hb=127ms ago, entities=3
Entity 1: pos=(123, 456), angle=45000
Entity 2: pos=(789, 012), angle=90000
Entity 3: pos=(345, 678), angle=135000
Connection refused:
- Check broker is running:
docker-compose ps - Verify port 1883 is accessible:
netstat -an | grep 1883
Messages not received:
- Check topic subscriptions match publish topics
- Verify client IDs are unique
- Check QoS levels
High latency:
- Check network connectivity
- Reduce message rates
- Increase broker resources