4.1 KiB
4.1 KiB
💓 MQTT Heartbeat Feature
Overview
Implemented a retained MQTT heartbeat system that sends periodic status updates every 30 seconds when the controller is connected to MQTT.
What It Does
Heartbeat Message
Every 30 seconds, the controller publishes a retained message to:
vesper/{deviceID}/status/heartbeat
Message Format
{
"status": "INFO",
"type": "heartbeat",
"payload": {
"device_id": "VESPER-ABC123",
"firmware_version": "130",
"timestamp": "Uptime: 5h 23m 45s",
"ip_address": "192.168.1.100",
"gateway": "192.168.1.1",
"uptime_ms": 19425000
}
}
Key Features
✅ Retained Message - Only the LAST heartbeat stays on the broker
✅ Auto-Start - Begins when MQTT connects
✅ Auto-Stop - Stops when MQTT disconnects
✅ 30-Second Interval - Periodic updates
✅ First Beat Immediate - Sends first heartbeat right after connecting
✅ QoS 1 - Reliable delivery
Why This is Awesome
For Your Flutter App
- Immediate Status - Any new connection gets the last known status instantly
- Stale Detection - Can detect if controller went offline (timestamp too old)
- Device Discovery - Apps can subscribe to
vesper/+/status/heartbeatto find all controllers - No Polling - Just subscribe once and get automatic updates
Example App Logic
// Subscribe to heartbeat
mqtt.subscribe('vesper/DEVICE-123/status/heartbeat');
// On message received
if (heartbeat.uptime_ms > lastSeen.uptime_ms + 120000) {
// No heartbeat for 2+ minutes = controller offline
showOfflineWarning();
}
Implementation Details
Files Modified
- MQTTAsyncClient.hpp - Added heartbeat timer and methods
- MQTTAsyncClient.cpp - Implemented heartbeat logic
- Networking.hpp - Added
getGateway()method - Networking.cpp - Implemented
getGateway()method
New Methods Added
void startHeartbeat(); // Start 30s periodic timer
void stopHeartbeat(); // Stop timer
void publishHeartbeat(); // Build and publish message
void heartbeatTimerCallback(); // Timer callback handler
Timer Configuration
- Type: FreeRTOS Software Timer
- Mode: Auto-reload (repeating)
- Period: 30,000 ms (30 seconds)
- Core: Runs on Core 0 (MQTT task core)
Testing
How to Test
- Flash the firmware
- Subscribe to the heartbeat topic:
mosquitto_sub -h YOUR_BROKER -t "vesper/+/status/heartbeat" -v - You should see heartbeats every 30 seconds
- Disconnect the controller - the last message stays retained
- Reconnect - you'll immediately see the last retained message, then new ones every 30s
Expected Serial Output
💓 Starting MQTT heartbeat (every 30 seconds)
💓 Published heartbeat (retained) - IP: 192.168.1.100, Uptime: 45000ms
💓 Published heartbeat (retained) - IP: 192.168.1.100, Uptime: 75000ms
❤️ Stopped MQTT heartbeat (when MQTT disconnects)
Future Enhancements (Optional)
Possible Additions:
- Add actual RTC timestamp (instead of just uptime)
- Add WiFi signal strength (RSSI) for WiFi connections
- Add free heap memory
- Add current playback status
- Add bell configuration version/hash
Implementation Example:
// In publishHeartbeat()
payload["rssi"] = WiFi.RSSI(); // WiFi signal strength
payload["free_heap"] = ESP.getFreeHeap();
payload["playback_active"] = player.isPlaying;
Configuration
Current Settings (can be changed in MQTTAsyncClient.hpp):
static const unsigned long HEARTBEAT_INTERVAL = 30000; // 30 seconds
To change interval to 60 seconds:
static const unsigned long HEARTBEAT_INTERVAL = 60000; // 60 seconds
Notes
- Message is published with QoS 1 (at least once delivery)
- Message is retained (broker keeps last message)
- Timer starts automatically when MQTT connects
- Timer stops automatically when MQTT disconnects
- First heartbeat is sent immediately upon connection (no 30s wait)
Feature Implemented: January 2025
Version: Firmware v130+
Status: ✅ Production Ready