3. Create a publisher

Let's give some action to our MQTT application. This entry shows how you can create a publisher with an ESP32 in wokwi that can send messages to your PC.

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.

  1. 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": {}
    }
    

  2. Run the following code

    client_publisher.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_pub";
    
    WiFiClient espClient;
    PubSubClient mqttClient(espClient);
    
    String payload; // (1)!
    
    void ConnectWiFi()
    {
      WiFi.begin(WIFI_SSID, WIFI_PASSWORD, WIFI_CHANNEL);
      Serial.print("Connecting to WiFi ");
      Serial.print(WIFI_SSID);
      // Wait for connection
      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);
    }
    
    void ConnectMqtt()
    {
      while (!mqttClient.connected())
      {
        Serial.print("Starting MQTT connection...");
        if (mqttClient.connect(MQTT_CLIENT_NAME))
        {
          Serial.print("Client connected");
        }
        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 PublishMqtt(unsigned long data) // (2)!
    {
      payload = "";
      payload = String(data);
      mqttClient.publish("/running_time", (char *)payload.c_str());
    }
    
    void setup(void)
    {
      Serial.begin(115200);
      ConnectWiFi();
      InitMqtt();
    }
    
    void loop()
    {
      HandleMqtt();
    
      PublishMqtt(millis()); // (3)!
      Serial.println(millis()); 
    
      delay(1000);
    }
    
    1. The client will publish messages to a topic using the method publish() from the PubSubClient.h library. Checking the code of that method you will see it publishes char data. Remember the difference between char and String: In C++, the sequence of characters can be stored in two ways: either as a std::string (String in Arduino) object or char array. The latter is an array that contains single characters terminated by a null character, while the former creates an object that is used to represent strings in C++ and contain many methods to help in string manipulation. Since it's easier to manipulate Stringdata than char data, we will use the String object payload to store the message that will be publish. This message, however, will need to be casted to a charbefore being published with publish() (explained later in the code).
    2. This function is used to publish data in a specific topic. It receives the data as a parameter (in this case data is an unsigned long variable, but it could have been something else, e.g., a boolean, or a float). The content of data need to be casted into String: here's when you use the payload variable. Then, the content of payload need to be casted into char according to the specifications of the method publish(). This is done with (char *)payload.c_str().
    3. The function PublishMqtt() is called in the loop every 1s. The running time in milliseconds is given as a parameter to that function, meaning that will be the message to be published.
  3. If you have done it correctly, you should see the following

    Info

    By checking the topic in MQTT Explorer you can see the time in milliseconds it takes for the ESP32 to publish the message and print over the serial port: 4 ms (it has to run the code inside PublishMqtt(), which also runs the method publish()).

  4. Subscribe to the topic in your terminal

    Run the following command in the terminal and you'll see that the ESP32 is communicating with your PC via MQTT as shwon in the image below

    mosquitto_sub -h mqtt.eclipseprojects.io -t /running_time
    

CONGRATULATIONS!

Now you're able to publish messages to a MQTT topic with an ESP32.