Heartbeat & Keep-Alive
VWire tracks device health using a combination of MQTT keep-alive (automatic) and optional application-level heartbeats (recommended for long-idle devices).
MQTT keep-alive (automatic)
When the VWire library connects, it negotiates a 60-second keep-alive with the broker:
| Event | What happens |
|---|---|
| Device publishes data | Keep-alive timer resets |
| No activity for 30 s | Library sends MQTT PINGREQ |
| Broker doesn't respond | Library considers connection lost |
| PING acknowledged | Timer resets, connection healthy |
| Connection truly dropped | Broker publishes LWT (status: offline) |
This is all handled automatically — you don't need to write any PING code.
Reconnect behavior
The VWire library reconnects automatically after a disconnect:
Disconnect → Wait 5 s → Reconnect attempt
→ Failed → Wait 10 s → Retry
→ Failed → Wait 30 s → Retry
→ ...exponential backoff, cap 120 s
After reconnecting, the library calls Vwire.syncVirtual() for all pins that were registered for sync.
Application-level heartbeat (recommended)
For devices that sleep or have long idle periods, supplement MQTT keep-alive with a periodic data push:
unsigned long lastHeartbeat = 0;
const unsigned long HEARTBEAT_INTERVAL = 30000; // 30 s
void loop() {
Vwire.run();
// Normal sensor data (infrequent)
if (someCondition) {
Vwire.virtualSend(V0, sensorValue);
}
// Heartbeat — just push uptime so the server sees activity
if (millis() - lastHeartbeat >= HEARTBEAT_INTERVAL) {
lastHeartbeat = millis();
Vwire.virtualSend(V9, millis() / 1000); // uptime in seconds
}
}
Bind V9 to a Value Display widget labeled "Uptime (s)" to confirm the device is alive.
Detecting device health in the dashboard
| Indicator | Meaning |
|---|---|
| Green dot (Online) | MQTT connection active |
| Red dot (Offline) | MQTT LWT received or connection timed out |
| "Last Seen" timestamp | When the device last published any data |
Watchdog timer (ESP32 / ESP8266)
Enable the hardware watchdog as a safety net against firmware hangs:
#include <esp_task_wdt.h>
void setup() {
esp_task_wdt_init(30, true); // 30 s timeout, panic on hang
esp_task_wdt_add(NULL); // watch current task (loop)
// ...
}
void loop() {
Vwire.run();
esp_task_wdt_reset(); // reset watchdog every loop
// ...
}
If loop() ever stops running (stuck, blocked I/O), the watchdog resets the device and VWire reconnects automatically.