877,
As I was thinking about this, yours is an example that could cost real money if the end point goes rogue since it is common that local police charge a nuisance fine for alarms that result in a police visit or neighbor complaint.
I will share with you that I struggled when I deployed my irrigation controller last month because the NodeMCU-ESP32s would not stay connected. Turns out it takes a wifi-connected esp32 to illuminate what is really going on with the wifi network.
For those who want to do esp32/MQTT/wifi, I highly recommend the EspMQTTClient library, which wraps knolleary's PubSubClient for the specific purpose of adding reconnect (both wifi and mqtt) capability. Without reconnect logic, the endpoint is on its own.
Indeed, as I sat down to write this, I received a reconnect notice from the irrigation controller.
2019.6.28 5:43:35: {"mode":"diagnostic","event":"reconnect","sys":"esp32-irr","topic":"irrigation/monitor","action":"notify","version":"2.0.1","ssid":"Hairy Feet","mac":"pending","mclient":"esp32-irr","free":272936,"invalid":0,"connect":2}
Because of that darn MQTT/Wifi connector, I have found it very useful to implement a ping pub/sub pair to be able to validate that the NodeMCU is connected. When the NodeMCU responds, it also reports free heap as a way to monitor for memory leaks.
I have a local fork of the EspMQTTClient that has an minor tweak (added mqttClient.mqttConnectionCount()) to be able to report startup vs reconnect.
// onConnectionEstablished() is called just once after both
// the WiFi client and the MQTT are successfully connected
//
// it is in this function that the subscriber is initialized
//
// when the subscriber is initialized, it is possible to
// assign a function to process the topic payload
//
// NOTE : If this function is not implemented, then no subscriber
// will be initialized, which means that this sketch will NOT
// process incoming MQTT messages
void onConnectionEstablished()
{
char msgBuffer[256];
String mqttResponse;
// Subscribe to topic and provide the function that will
// process the payload
mqttClient.subscribe(TOPIC_EVENT, [](const String & payload)
{
topicPayloadProcess(payload);
});
// if connection count is > 1, then the call here is
// a reconnect
if(mqttClient.mqttConnectionCount() > 1)
{
sprintf(msgBuffer,
"{\"mode\":\"diagnostic\",\"event\":\"reconnect\",\"sys\":\"%s\",\"topic\":\"%s\",\"action\":\"notify\",\"version\":\"%s\",\"ssid\":\"%s\",\"mac\":\"%s\",\"mclient\":\"%s\",\"free\":%d,\"invalid\":%d,\"connect\":%d}",
NODE_MCU_NAME,
TOPIC_MONITOR,
VERSION,
WIFI_AP_SSID,
"pending",
NODE_MCU_NAME,
ESP.getFreeHeap(),
heap_caps_get_free_size(MALLOC_CAP_INVALID),
mqttClient.mqttConnectionCount());
}
else
{
sprintf(msgBuffer,
"{\"mode\":\"diagnostic\",\"event\":\"startup\",\"sys\":\"%s\",\"topic\":\"%s\",\"action\":\"notify\",\"version\":\"%s\",\"ssid\":\"%s\",\"mac\":\"%s\",\"mclient\":\"%s\",\"free\":%d,\"invalid\":%d}",
NODE_MCU_NAME,
TOPIC_MONITOR,
VERSION,
WIFI_AP_SSID,
"pending",
NODE_MCU_NAME,
ESP.getFreeHeap(),
heap_caps_get_free_size(MALLOC_CAP_INVALID));
}
// Publish the message
mqttResponse = msgBuffer;
mqttClient.publish(TOPIC_MONITOR,
mqttResponse);
}
The ping response also reports the reconnect count.
if(strcmp(eventStr,EVENT_PING) == 0)
{
sprintf(msgBuffer,
"{\"mode\":\"diagnostic\",\"event\":\"%s\",\"sys\":\"%s\",\"topic\":\"%s\",\"action\":\"notify\",\"msgID\":\"%s\",\"version\":\"%s\",\"ssid\":\"%s\",\"mac\":\"%s\",\"mclient\":\"%s\",\"free\":%d,\"invalid\":%d,\"connect\":%d}",
EVENT_PING,
NODE_MCU_NAME,
TOPIC_MONITOR,
msgIdStr,
VERSION,
WIFI_AP_SSID,
"pending",
NODE_MCU_NAME,
ESP.getFreeHeap(),
heap_caps_get_free_size(MALLOC_CAP_INVALID),
mqttClient.mqttConnectionCount());
mqttResponse = msgBuffer;
mqttClient.publish(TOPIC_MONITOR,
mqttResponse);