MQTT Last Will and Testament

User avatar
PaulVdBergh
Posts: 58
Joined: Fri Feb 23, 2018 4:45 pm
Location: Brasschaat, Belgium

MQTT Last Will and Testament

Postby PaulVdBergh » Tue Mar 20, 2018 12:29 pm

Hi All,

In my project I have several ESP32 devices participating in an IoT solution based on MQTT. I have a Mosquitto instance running on an RPi 3. I will have info about the status of all the ESP devices broad-casted : when a device becomes active, it will publish a message telling it is "Online", when the device becomes inactive, there must be a message send telling the device is "Offline". I try to accomplish this by setting an LWT in the connection data of the device. However, there are some troubles with this:
- If I set the keepAliveInterval of the connectData to 0, the LWT message will never be published...
- if I set the keepAliveInterval to 60 seconds (the default in MQTTPacket_connectData_initializer), then when there is no activity on the ESP device fore more than 60 seconds the device logs off and the LWT is published....

How can I make this work, having the LWT send only if the ESP device is effectively disconnected (or powered off) ?

my code (still a Work in Progress) :

Code: Select all

#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <stdio.h>

#include <inttypes.h>

#include "MQTTClient.h"
#include "sdkconfig.h"

static char tag[] = "mqtt_paho";
static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];
Network network;

MQTTClient client;

#include "IoTMQTTMessageQueueItem.h"


void task_paho(void *ignore) {
	ESP_LOGI(tag, "Starting ...");
	int rc;
	NetworkInit(&network);
	ESP_LOGI(tag, "::NetworkConnect  ...");
	NetworkConnect(&network, "192.168.1.105", 1883);
	ESP_LOGI(tag, "::MQTTClientInit  ...");
	MQTTClientInit(&client, &network,
		1000,            // command_timeout_ms
		sendBuf,         //sendbuf,
		sizeof(sendBuf), //sendbuf_size,
		readBuf,         //readbuf,
		sizeof(readBuf)  //readbuf_size
	);

	union
	{
		uint64_t	llmac;
		uint8_t		mac[6];
	} mac_t;

	ESP_ERROR_CHECK(esp_efuse_mac_get_default(mac_t.mac));
	char szMac[21];
	snprintf(szMac, sizeof(szMac), "%" PRIu64, mac_t.llmac);

	MQTTString clientId = MQTTString_initializer;
	clientId.cstring = szMac;

	char szStatusTopic[256];
	snprintf(szStatusTopic, sizeof(szStatusTopic), "TBTIoT/Devices/%s/Status", szMac);

	MQTTString willTopic = MQTTString_initializer;
	willTopic.cstring = szStatusTopic;

	MQTTString willMessage = MQTTString_initializer;
	willMessage.cstring = "Offline";

	MQTTPacket_willOptions willOptions = MQTTPacket_willOptions_initializer;
	willOptions.topicName = willTopic;
	willOptions.message = willMessage;
	willOptions.retained = true;
	willOptions.qos = QOS0;

	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
	data.clientID          = clientId;
	data.willFlag          = 1;
	data.MQTTVersion       = 4;
	data.keepAliveInterval = 0;
	data.cleansession      = 1;
	data.will			   = willOptions;

	ESP_LOGI(tag, "::MQTTConnect  ...");
	rc = MQTTConnect(&client, &data);
	if (rc != SUCCESS)
	{
		ESP_LOGE(tag, "MQTTConnect: %d", rc);
	}

	MQTTMessage statusMessage;
	statusMessage.qos = QOS0;
	statusMessage.retained = true;
	statusMessage.dup = 0;
	statusMessage.id = 0;
	statusMessage.payload = "Online";
	statusMessage.payloadlen = strlen("Online");

	ESP_LOGI(tag, "::MQTTPublish ...");
	rc = MQTTPublish(&client, szStatusTopic, &statusMessage);
	if (rc != SUCCESS)
	{
		ESP_LOGE(tag, "::MQTTPublish: %d", rc);
	}

	ESP_LOGI(tag, "::MQTTSubscribe  ...");
	rc = MQTTSubscribe(&client, "#", QOS0, IoTMQTTMessageHandler_func);
	if (rc != SUCCESS)
	{
		ESP_LOGE(tag, "::MQTTSubscribe: %d", rc);
	}

	while(1)
	{
		MQTTYield(&client, 1000);
	}
	vTaskDelete(NULL);
}
Thanks in advance for your input !

Paul.

Who is online

Users browsing this forum: No registered users and 51 guests