4. Create a subscriber
This entry shows how you can create a subscriber with an ESP32 in wokwi that can subscribe to topics.
Client and Topic names
You're going to use a public broker that is used by many people simultaneously. Hence, you must choose the clients and topics name with this in mind. I.e., avoid using generic names as a test
or example
. Also, emember that the client name is unique.
-
Open a new project in wokwi and load the following diagram.json.
Show diagram.json
diagram.json{ "version": 1, "author": "Juan M. Gandarias", "editor": "wokwi", "parts": [ { "type": "board-esp32-devkit-c-v4", "id": "esp", "top": 0, "left": 0, "attrs": {} } ], "connections": [ [ "esp:TX", "$serialMonitor:RX", "", [] ], [ "esp:RX", "$serialMonitor:TX", "", [] ] ], "dependencies": {} }
-
Run the following code
client_subscriber.ino#include <WiFi.h> #include <WiFiClient.h> #include <PubSubClient.h> #define WIFI_SSID "Wokwi-GUEST" #define WIFI_PASSWORD "" #define WIFI_CHANNEL 6 const char *MQTT_BROKER_ADRESS = "mqtt.eclipseprojects.io"; const uint16_t MQTT_PORT = 1883; const char *MQTT_CLIENT_NAME = "ESP32_test_sub"; WiFiClient espClient; PubSubClient mqttClient(espClient); String payload; String content = ""; // (1)! void ConnectWiFi() { WiFi.begin(WIFI_SSID, WIFI_PASSWORD, WIFI_CHANNEL); Serial.print("Connecting to WiFi "); Serial.print(WIFI_SSID); while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print("."); } Serial.println(" Connected!"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } void InitMqtt() { mqttClient.setServer(MQTT_BROKER_ADRESS, MQTT_PORT); SuscribeMqtt(); // (2)! mqttClient.setCallback(OnMqttReceived); // (3)! } void ConnectMqtt() { while (!mqttClient.connected()) { Serial.print("Starting MQTT connection..."); if (mqttClient.connect(MQTT_CLIENT_NAME)) { Serial.println("Client connected!"); SuscribeMqtt(); // (4)! } else { Serial.print("Failed MQTT connection, rc="); Serial.print(mqttClient.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } } void HandleMqtt() { if (!mqttClient.connected()) { ConnectMqtt(); } mqttClient.loop(); } void SuscribeMqtt() // (5)! { mqttClient.subscribe("/testing_topic"); } void OnMqttReceived(char *topic, byte *payload, unsigned int length) // (6)! { Serial.print("Received on "); Serial.print(topic); Serial.print(": "); content = ""; for (size_t i = 0; i < length; i++) // (7)! { content.concat((char)payload[i]); } Serial.print(content); Serial.println(); } void setup(void) { Serial.begin(115200); ConnectWiFi(); InitMqtt(); } void loop() // (8)! { HandleMqtt(); delay(10); }
- As the message received in the topic will be a
char
, you'll use this variable to convert it toString
for easier manipulation. - Now, after setting the server, we need to call the function
SubscribeMqtt()
. This functions establishes the topics to which the client will be subscribed. This operation is a function for two reasons:- If the client is disconnected, it needs to subscribe to the topics again. So the function can be called multiple times in the code.
- If there is (or could be in the future) more than one topics to subscribe to, it can be easily addressed by simply modifying the code inside this function.
- We need to set the function (callback) that will be called everytime a message is received. This function has been named
OnMqttReceived
. SubscribeMqtt()
is called again if the connection to the broker is lost.SubscribeMqtt()
defines the topics to which the client will subscribe. In this case, it will only subscribe to the topic/testing_topic
, but there could be more than one inside the function. The client is subscribed to a topic using the methodsubscribe()
from thePubSubClient.h
library.- This function is a callback that will be called everytime a message is published in any of the topics that the client is subscribed to (similar to an interruption). Inside the callback, you get access to the
topic
where the message was published, the content of the message throught the variablepayload
, and thelength
of that message. - The content of
payload
will be casted intoString
. In this case,payload
is an array of bytes. Thesebytes
need to be first casted into characters and then concatenated to form the finalString
. To do this, we first need to go through all the positions of the array (i.e., we use afor
loop). This loop will go from the first element (i=0
) to the last one (i=length
). In every step of the loop, we first cast the elementi
of the arraypayload
tochar
:(char)payload[i]
. The data of this element should be concatenated to the string ofcontent
to form the final message. To do that we can use the methodconcat()
. When the loop finishes, thecontent
of the message is displayed through the serial port. - This client works as a subscriber only. It means it won't do anything until a message is received. Hence, there's nothing inside the
loop()
(apart from theHandleMqtt()
funcion that was explained in a previous entry).
- As the message received in the topic will be a
-
If you have done it correctly, you should see that the ESP32 prints the content of the messages received in the topic
/testing_topic
. You can test it from the MQTT Explorer or the terminal.
CONGRATULATIONS!
Now you're able to subscribe to a MQTT topic with an ESP32.