Hello guys,
following your tutorial “ESP32 / module7 /unit3”, I have successfully connected the esp32 to my mqtt broker, being able to receive and send messages on the topics indicated in the code. I then modified the code to subscribe to the topic “esp32/led/switch” instead of “esp32/led”. Trying to send messages to the new topic, they are received correctly:
21:53:41.783 -> Publish received.
21:53:41.783 -> message: ciao
21:53:41.783 -> topic: esp32/led/switch
21:53:41.783 -> qos: 0
21:53:41.783 -> dup: 0
21:53:41.783 -> retain: 0
21:53:41.783 -> len: 4
21:53:41.783 -> index: 0
21:53:41.783 -> total: 4
Without changing the subscription to the topic, I sent again a message on the old topic “esp32/led”, thinking it would not have been intercepted by esp32, and instead it is received as if at startup it had also subscribed to the topic “esp32/led”:
21:54:26.836 -> Publish received.
21:54:26.836 -> message: ciao2
21:54:26.836 -> topic: esp32/led
21:54:26.836 -> qos: 0
21:54:26.836 -> dup: 0
21:54:26.836 -> retain: 0
21:54:26.836 -> len: 5
21:54:26.836 -> index: 0
21:54:26.836 -> total: 5
After various tests I realized that the problem lies with the broker, for which all the various subscriptions made in the various tests remain active.
At this point it would be good to cancel all the topics previously subscribed on the broker, before subscribing to the desired topics.
How could this be done? Is there a command that removes from the broker the subscription made to any topic in previous executions of the code?
Best regards,
Mose
Hello Mose, can you post your full code that you that keeps the MQTT subscribed to “esp32/led” topic?
Unfortunately I can’t replicate that behavior on my end. The ESP32 only subscribes to the topics in the newly uploaded code (all previous MQTT topics are automatically unsubscribed).
Thank you!
Hello Rui, many thanks for your answer. Below you can find the code. I’m using a MQTT broker inside Openhab, installed on a Beaglebone black, whith UBUNTU. I solved unsubscribing manually from the old topic…my Broker is like the Godfather: It doesn’t forget 😀
Sorry, I don’t know why but, the formatting doesn’t work on many rows
/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
#include <WiFi.h>
extern “C” {
#include “freertos/FreeRTOS.h”
#include “freertos/timers.h”
}
#include <AsyncMqttClient.h>
// Change the credentials below, so your ESP32 connects to your router
#define WIFI_SSID “service2”
#define WIFI_PASSWORD “xxx”
// Change the MQTT_HOST variable to your Raspberry Pi IP address,
// so it connects to your Mosquitto MQTT broker
#define MQTT_HOST IPAddress(192, 168, 1, 20)
#define MQTT_PORT 1883
#define MQTT_USERNAME “xxx”
#define MQTT_PASSWD “xxx”
// Create objects to handle MQTT client
AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;
boolean MQTTConnectionStatus = false;
unsigned long previousMillis = 0; // Stores last time temperature was published
const long interval = 30000; // interval at which to publish sensor readings
uint16_t packetIdPub2;
String TopicTarget; // TOPIC where to publish
String MQTTmessageString; // message to send in the TOPIC
int QOSLevel; // QOS requested
// —————————————————————–
// **************************************************
// * Start User declarations and functions section *
// **************************************************
#include <DHT.h>
#define DHTPIN 27 // Digital pin connected to the DHT sensor
// Uncomment the type of sensor in use:
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);
String temperatureString = “”; // Variable to hold the temperature reading
String humidityString = “”; // Variable to hold the temperature reading
const int ledPin = 25; // GPIO where the LED is connected to
int ledState = LOW; // the current state of the output pin
const int RxTxLED = 2; // GPIO where the LED RX/TX is connected to
int RxTxLEDState = LOW; // the current state of the output pin
String readDHTTemperature() {
// Sensor readings may also be up to 2 seconds ‘old’ (its a very slow sensor)
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
//float t = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(t)) {
Serial.println(“Failed to read from DHT sensor!”);
return “–“;
}
else {
//Serial.println(t);
return String(t);
}
}
String readDHTHumidity() {
// Sensor readings may also be up to 2 seconds ‘old’ (its a very slow sensor)
float h = dht.readHumidity();
if (isnan(h)) {
Serial.println(“Failed to read from DHT sensor!”);
return “–“;
}
else {
//Serial.println(h);
return String(h);
}
}
void connectToWifi() {
Serial.println(“Connecting to Wi-Fi…”);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}
void connectToMqtt() {
Serial.println(“Connecting to MQTT…”);
mqttClient.connect();
}
void WiFiEvent(WiFiEvent_t event) {
Serial.printf(“[WiFi-event] event: %d\n”, event);
switch(event) {
case SYSTEM_EVENT_STA_GOT_IP:
Serial.println(“WiFi connected”);
Serial.println(“IP address: “);
Serial.println(WiFi.localIP());
connectToMqtt();
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
Serial.println(“WiFi lost connection”);
xTimerStop(mqttReconnectTimer, 0); // ensure we don’t reconnect to MQTT while reconnecting to Wi-Fi
xTimerStart(wifiReconnectTimer, 0);
break;
}
}
// Add more topics that want your ESP32 to be subscribed to
void onMqttConnect(bool sessionPresent) {
uint16_t packetIdSub;
String TopicString;
int QosLevel;
Serial.println(“Connected to MQTT.”);
Serial.print(“Session present: “);
Serial.println(sessionPresent);
// TOPIC: “esp32/led/switch”
// —————————————————————–
TopicString = “esp32/led/switch”;
QosLevel = 1;
packetIdSub = mqttClient.subscribe(TopicString.c_str(), QosLevel);
Serial.print(“Subscribing on topic: \””+TopicString+”\”, at QoS “+QosLevel+”, packetId: “);
Serial.println(packetIdSub);
// ###
// Subscription TEMPLATE
// TOPIC: “topic/subject”
// —————————————————————–
// TopicString = “topic/subject”;
// QosLevel = 0;
// packetIdSub = mqttClient.subscribe(TopicString.c_str(), QosLevel);
// Serial.print(“Subscribing on topic: \””+TopicString+”\”, at QoS “+QosLevel+”, packetId: “);
// Serial.println(packetIdSub);
// ###
MQTTConnectionStatus = true;
if (MQTTConnectionStatus){
Serial.println(“MQTTConnectionStatus = true”);
}
else {
Serial.println(“MQTTConnectionStatus = false”);
}
}
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
Serial.println(“Disconnected from MQTT.”);
if (WiFi.isConnected()) {
xTimerStart(mqttReconnectTimer, 0);
}
}
void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
Serial.println(“Subscribe acknowledged.”);
Serial.print(” packetId: “);
Serial.println(packetId);
Serial.print(” qos: “);
Serial.println(qos);
}
void onMqttUnsubscribe(uint16_t packetId) {
Serial.println(“Unsubscribe acknowledged.”);
Serial.print(” packetId: “);
Serial.println(packetId);
}
void onMqttPublish(uint16_t packetId) { //executed only on messages whith QOS>=1
Serial.println(“Publish acknowledged.”);
Serial.print(” packetId: “);
Serial.println(packetId);
}
// You can modify this function to handle what happens when you receive a certain message in a specific topic
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
digitalWrite(RxTxLED,HIGH);
String messageTemp;
for (int i = 0; i < len; i++) {
messageTemp += (char)payload[i];
}
Serial.println(“Publish received.”);
Serial.print(” message: “);
Serial.println(messageTemp);
Serial.print(” topic: “);
Serial.println(topic);
Serial.print(” qos: “);
Serial.println(properties.qos);
Serial.print(” dup: “);
Serial.println(properties.dup);
Serial.print(” retain: “);
Serial.println(properties.retain);
Serial.print(” len: “);
Serial.println(len);
Serial.print(” index: “);
Serial.println(index);
Serial.print(” total: “);
Serial.println(total);
// *** TOPIC action for: “esp32/led/switch”
//———————————–
if (strcmp(topic, “esp32/led/switch”) == 0) {
if (messageTemp == “1”){
ledState = HIGH;
Serial.println(“Led ON”);
} else {
ledState = LOW;
Serial.println(“Led OFF”);
}
digitalWrite(ledPin, ledState);
// Publication messagge on TOPIC “esp32/led/status”
// —————————————————————–
TopicTarget = “esp32/led/status”; // Variable to hold the TOPIC
MQTTmessageString = ledState; // Variable to hold the message to send
QOSLevel =1; // Variable to hold the QOS to be used
PublishMessage(TopicTarget, MQTTmessageString, QOSLevel);
TopicTarget = “”;
MQTTmessageString = “”;
QOSLevel = 0;
}
// ###
// TEMPLATE
// *** TOPIC action: “topic/subject”
//———————————–
//if (strcmp(topic, “topic/subject”) == 0) {
// *** Start section actions to do
//}
// ###
digitalWrite(RxTxLED,LOW);
}
void PublishMessage (String topic, String message, int qos){
digitalWrite(RxTxLED,HIGH);
packetIdPub2 = mqttClient.publish(topic.c_str(), qos, true, message.c_str());
Serial.println(“Publishing on topic “+topic+” at QoS “+qos+”, packetId: “+packetIdPub2);
Serial.println();
// delay(100);
digitalWrite(RxTxLED,LOW);
}
void setup() {
// Define LED as an OUTPUT and set it LOW
pinMode(ledPin, OUTPUT);
pinMode(RxTxLED, OUTPUT);
digitalWrite(ledPin, LOW);
dht.begin();
Serial.begin(115200);
mqttReconnectTimer = xTimerCreate(“mqttTimer”, pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
wifiReconnectTimer = xTimerCreate(“wifiTimer”, pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));
WiFi.onEvent(WiFiEvent);
mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect);
mqttClient.onSubscribe(onMqttSubscribe);
mqttClient.onUnsubscribe(onMqttUnsubscribe);
mqttClient.onMessage(onMqttMessage);
mqttClient.onPublish(onMqttPublish);
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
mqttClient.setCredentials( MQTT_USERNAME, MQTT_PASSWD);
connectToWifi();
delay (5000);
Serial.println(“first reading sensor”);
// temperature readings
temperatureString = (readDHTTemperature().c_str());
Serial.println(“# Temperature: “+ temperatureString + “*C”);
PublishMessage(“esp32/temperature”, temperatureString, 0);
// Humidity readings
humidityString = (readDHTHumidity().c_str());
Serial.println(“# Humidity: “+ humidityString + “%”);
PublishMessage(“esp32/humidity”, humidityString, 0);
Serial.println(“*** END SETUP, START LOOPING ***”);
}
void loop() {
unsigned long currentMillis = millis();
// Every X number of seconds (interval defined on top page)
// it publishes a new MQTT message on topic esp32/temperature
if ((currentMillis – previousMillis >= interval)) {
// Save the last time a new reading was published
previousMillis = currentMillis;
// —————————————————————–
// ***********************
// * Start User section *
// ***********************
// New temperature readings
temperatureString = (readDHTTemperature().c_str());
Serial.println(“# Temperature: “+ temperatureString + “*C”);
// Publication messagge on TOPIC “esp32/temperature”
// —————————————————————–
TopicTarget = “esp32/temperature”; // Variable to hold the TOPIC
MQTTmessageString = temperatureString; // Variable to hold the message to send
QOSLevel =0; // Variable to hold the QOS to be used
PublishMessage(TopicTarget, MQTTmessageString, QOSLevel);
TopicTarget = “”;
MQTTmessageString = “”;
QOSLevel = 0;
// New humidity readings
humidityString = (readDHTHumidity().c_str());
Serial.println(“# Humidity: “+ humidityString + “%”);
// Publication messagge on TOPIC: “esp32/humidity”
// —————————————————————–
TopicTarget = “esp32/humidity”; // TOPIC where to publish
MQTTmessageString = humidityString; // message to send in the TOPIC
QOSLevel = 0; // QOS requested
PublishMessage(TopicTarget, MQTTmessageString, QOSLevel);
TopicTarget = “”;
MQTTmessageString = “”;
QOSLevel = 0;
} //end of if
// TEMPLATE
// Publication messagge on TOPIC
// —————————————————————–
//TopicTarget = “”; // Variable to hold the TOPIC
//MQTTmessageString = “”; // Variable to hold the message to send
//QOSLevel =””; // Variable to hold the QOS to be used
//packetIdPub2 = mqttClient.publish(TopicTarget.c_str(), QOSLevel, true, MQTTmessageString.c_str());
//Serial.println(“Publishing on topic “+TopicTarget+” at QoS “+QOSLevel+”, packetId: “+packetIdPub2);
//Serial.println();
//TopicTarget = “”;
//MQTTmessageString = “”;
//QOSLevel = 0;
}