Last will and testament

TTGO 800L
Android
Blynk server

Going through the site i see a hand full of people have experimented with the LWT of the pubSubClient but couldn’t find full implementation. My sketch seeks to determine the exact moment the esp32 powers off so the last will and testament feature would really do it for me. code compiles fine, node-red shows that the client connects to the broker, but no LWT is published when client abruptly disconnects.

// TTGO T-Call pin definitions
#define MODEM_RST            5
#define MODEM_PWKEY          4
#define MODEM_POWER_ON       23
#define MODEM_TX             27
#define MODEM_RX             26
#define I2C_SDA              21
#define I2C_SCL              22

#define BLYNK_PRINT Serial    
#define BLYNK_HEARTBEAT 30
#define TINY_GSM_MODEM_SIM800

#include <PubSubClient.h> 
#include <TinyGsmClient.h>
#include <BlynkSimpleSIM800.h>

#include <Wire.h>
// #include <TinyGsmClient.h>
#include "utilities.h"

// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial

// Hardware Serial on Mega, Leonardo, Micro
#define SerialAT Serial1


const char apn[]  = "gloflat";
const char user[] = "flat";
const char pass[] = "flat";

//Blynk Authentication
const char auth[] = "YKVZxVmxfW6mnNAnW3yHK4X7kX1tP0x-";


// MQTT
byte willQos = 0;
const char* mqtt_server = "192.168.43.220";
const char* mqtt_topic = "fujo/power";
const char* clientID = "powerMonitor";
const char* willTopic = "fujo/power/will";
const char* willMessage = "Power Off";
const char* mqttUser = "admin";
const char* mqttPass = "switchfoot";

TinyGsm modem(SerialAT);
//PubSubClient client(mqtt_server, 1883);

void setup()
{
  // Set console baud rate
  SerialMon.begin(115200);
  delay(10);

  // Keep power when running from battery
  Wire.begin(I2C_SDA, I2C_SCL);
  bool   isOk = setPowerBoostKeepOn(1);
  SerialMon.println(String("IP5306 KeepOn ") + (isOk ? "OK" : "FAIL"));

  // Set-up modem reset, enable, power pins
  pinMode(MODEM_PWKEY, OUTPUT);
  pinMode(MODEM_RST, OUTPUT);
  pinMode(MODEM_POWER_ON, OUTPUT);

  digitalWrite(MODEM_PWKEY, LOW);
  digitalWrite(MODEM_RST, HIGH);
  digitalWrite(MODEM_POWER_ON, HIGH);

  // Set GSM module baud rate and UART pins
  SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
  delay(3000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println("Initializing modem...");
  modem.restart();

  String modemInfo = modem.getModemInfo();
  SerialMon.print("Modem: ");
  SerialMon.println(modemInfo);

  // Unlock your SIM card with a PIN
  //modem.simUnlock("1234");

   SerialMon.print("Waiting for network...");
  if (!modem.waitForNetwork(240000L)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" OK");

  if (modem.isNetworkConnected()) {
    SerialMon.println("Network connected");
  }

  SerialMon.print(F("Connecting to APN: "));
  SerialMon.print(apn);
  if (!modem.gprsConnect(apn, user, pass)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" OK");

  Blynk.begin(auth, modem, apn, user, pass);
  boolean rc = client.connect("clientID", willTopic, willQoS, willRetain, willMessage); 


//    client.connect(clientID, (char*)mqttUser, (char*)mqttPass, willTopic, 0, true, (char*)willMessage);
//  if (client.connect(clientID)) {
    Serial.println("Connected to MQTT Broker!");
    client.publish(mqtt_topic, "Power On");
}

void loop()
{
  Blynk.run();
}

I think you should be publishing this to willTopic rather than mqtt_topic

Basically, LWT will publish your willMessage when the client disconnects. To be able to look at one topic and see if your client is connected or disconnected, it makes sense to publish an 'alive message ("Power On") which will be replaced with your 'dead message of “Power Off”.

For me, it takes around 35 seconds after the client goes AWOL before the LWT message is generated. It takes a similar amount of time for client.connected() to return false.

Without seeing what’s in your utilities.h file it’s impossible to say any more, as it appears that this is where your client definition lives.

Pete.

I thought i implemented the LWT with this line:
boolean rc = client.connect("clientID", willTopic, willQoS, willRetain, willMessage); and i used the ("Power On") mess as the ‘alive message’ so maybe my problem is somewhere else in the code?

It’s difficult to tell without seeing your full code. As the line of code above doesn’t contain any MQTT username and password, I suspect that you’re actually establishing the connection elsewhere and that this line of code is being ignored.
My MQTT connection process looks like this:

  if(MQTTclient.connect(mqtt_client_id.c_str(), mqtt_username, mqtt_password, (base_mqtt_topic + "/Status").c_str(),0, 1, "Dead"))
  {
    // We get here if the connection was successful... 
    Serial.println(F("MQTT Connected"));
    mqtt_connect_count++;
    MQTTclient.publish((base_mqtt_topic + "/Status").c_str(),"Alive",true);

If LWT is working correctly then there shouldn’t be a need for an “Alive” message, but the point I was making is that unless you reset your LWT topic to something other than your ‘dead’ message then it will always show as ‘dead’ because you’ll be seeing the old message. To a degree this depends on your retain settings, but most MQTT explorer type of utilities will show the last message that was received anyway.

In my example above I use the /Status topic to show the dead/alive status of the device.

Pete.