ESP32 MQTT Client Communication using ESP-IDF

In this tutorial, We are going to learn how to use MQTT protocol for communication between devices. We will use MQTT client library from ESP-IDF and will connect to free MQTT broker and subscribe and publish messages.

What is MQTT?

MQTT (Message Queuing Telemetry Transport) is a lightweight, publish-subscribe based messaging protocol designed for resource-constrained devices and low-bandwidth, high-latency, or unreliable networks. It is widely used in Internet of Things (IoT) applications, providing efficient communication between sensors, actuators, and other devices.

Key Features of MQTT

  • Lightweight
    Requires fewer resources and has small overhead.
  • Reliable
    Has low latency and supports QOS levels which ensures reliable message delivery.
  • Secure Communications
    Supports TLS, SSL encryption and ensures data confidentiality during transmission.
  • Bi-directionality
    Allows bi-directional communication between devices. Client devices can publish and subscribe to receive messages based on topics.
  • Large-scale IoT device support
    Lightweight nature, low bandwidth consumption and efficient resource use.
  • Language support
    Has broad language support which enables easy integration with multiple platforms.

Prerequisite

Before proceeding further make sure you have installed VS Code with ESP-IDF extension. You can follow steps mentioned at this link to install and configure ESP-IDF in VS Code.


Hardware Used

In this tutorial we are using ESP32-C6 Dev Kit. You can use any ESP32 based board with this code.

ESP32-C3-DevKitC-02 is an entry-level development board based on ESP32-C3-WROOM-02 or ESP32-C3-WROOM-02U, general-purpose modules with 4 MB SPI flash. This board integrates complete Wi-Fi and Bluetooth® Low Energy functions.


Create Example Project ESP-IDF

Open VS Code and Press CTRL+SHIFT+P or Click on View > Command Palette to Open Command Palette option. Select ESP-IDF: Show Example Projects Option to view all available examples from ESP-IDF.



Select hello_world under get-started section, then Select location at which you want to create example project.



After project is created you will see project folder open in VS Code.



ESP-IDF ESP32 MQTT Code

Code for 2 files are provided below,

Rename "hello_world_main.c" to "mqtt_example.c" and replace code inside that with below code,
/*
  ESP32 MQTT Client Communication using ESP-IDF Example

  A Example to Communicate using MQTT Protocol on ESP32 Board with ESP-IDF.

  created 29 Nov 2025
  by Himanshu Gajjar
  based on examples code given in ESP-IDF.

  Find the full documentation here:
  www.embetronics.com
 */

/* Include Required Header files */
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include <netdb.h>
#include "nvs_flash.h"
#include "mqtt_client.h"

/* Wifi Credentials and Retry Counts */
// #define EXAMPLE_WIFI_SSID             "WRITE_YOUR_WIFI_SSID_HERE"
// #define EXAMPLE_WIFI_PASS             "WRITE_YOUR_WIFI_PASSWORD_HERE"
#define EXAMPLE_WIFI_SSID               "SPiDiGO2"
#define EXAMPLE_WIFI_PASS               "41Shukan"
#define EXAMPLE_MAXIMUM_RETRY           5

/* The event group allows multiple bits for each event, but we only care about two events:
 * - we are connected to the AP with an IP
 * - we failed to connect after the maximum amount of retries
*/
#define CONNECTED_BIT                   BIT0
#define WIFI_FAIL_BIT                   BIT1

/* MQTT Broker URL and Topics */
#define MQTT_BROKER_URL                 "mqtt://test.mosquitto.org"
#define MQTT_PUB_TOPIC                  "/embetronics/pub"
#define MQTT_SUB_TOPIC                  "/embetronics/sub"

/* Event group for WiFi Connect Disconnect Tracking */
static EventGroupHandle_t s_network_event_group;

/* MQTT Client Handle */
static esp_mqtt_client_handle_t mqtt_client = NULL;

/* TAG for ESP Log Print */
static const char *TAG = "esp32_mqtt";

/* WiFi Event Handler Function */
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    /* WiFi Connect Retry Count */
    static int s_retry_num = 0;

    /* If WiFi Station Mode Start Event Received */
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    }
    /* If WiFi Disconnect Event Received */
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        /* If WiFi Cconnect Retry Count not Completed,Try Connecting */
        if (s_retry_num < EXAMPLE_MAXIMUM_RETRY) {
            esp_wifi_connect();
            s_retry_num++;
            ESP_LOGI(TAG, "retry to connect to the AP");
        } else {
            xEventGroupSetBits(s_network_event_group, WIFI_FAIL_BIT);
        }
        ESP_LOGI(TAG,"connect to the AP fail");
    }
    /* If IP Got Event Received */
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "static ip:" IPSTR, IP2STR(&event->ip_info.ip));
        s_retry_num = 0;
        xEventGroupSetBits(s_network_event_group, CONNECTED_BIT);
    }
}

/* Init WiFi with Station Mode */
static void wifi_init_sta(void)
{
    //Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");

    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &wifi_event_handler,
                                                        sta_netif,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &wifi_event_handler,
                                                        sta_netif,
                                                        &instance_got_ip));

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_WIFI_SSID,
            .password = EXAMPLE_WIFI_PASS,
            /* Setting a password implies station will connect to all security modes including WEP/WPA.
             * However these modes are deprecated and not advisable to be used. In case your Access point
             * doesn't support WPA2, these mode can be enabled by commenting below line */
	     .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start() );

    ESP_LOGI(TAG, "wifi_init_sta finished.");

    /* Waiting until either the connection is established (CONNECTED_BIT) or connection failed for the maximum
     * number of re-tries (WIFI_FAIL_BIT). The bits are set by wifi_event_handler() (see above) */
    EventBits_t bits = xEventGroupWaitBits(s_network_event_group,
            CONNECTED_BIT | WIFI_FAIL_BIT,
            pdFALSE,
            pdFALSE,
            portMAX_DELAY);

    /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
     * happened. */
    if (bits & CONNECTED_BIT) {
        ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
                 EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS);
    } else if (bits & WIFI_FAIL_BIT) {
        ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
                 EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS);
    } else {
        ESP_LOGE(TAG, "UNEXPECTED EVENT");
    }

    /* The event will not be processed after unregister */
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
    vEventGroupDelete(s_network_event_group);
}

/* MQTT Event Handler Callback Function */
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
            /* Subscribe to Topic */
            if (esp_mqtt_client_subscribe(mqtt_client, MQTT_SUB_TOPIC, 0) < 0) {
                // Disconnect to retry the subscribe after auto-reconnect timeout
                esp_mqtt_client_disconnect(mqtt_client);
            }
            break;
        case MQTT_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
            break;

        case MQTT_EVENT_SUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_UNSUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_PUBLISHED:
            ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_DATA:
            ESP_LOGI(TAG, "MQTT_EVENT_DATA");
            ESP_LOGI(TAG, "TOPIC=%.*s", event->topic_len, event->topic);
            ESP_LOGI(TAG, "DATA=%.*s", event->data_len, event->data);
            break;
        case MQTT_EVENT_ERROR:
            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
            break;
        default:
            ESP_LOGI(TAG, "Other event id:%d", event->event_id);
            break;
    }
    return ESP_OK;
}

/* MQTT Event Handler Function */
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRId32 "", base, event_id);
    mqtt_event_handler_cb(event_data);
}

/* Init and Start MQTT Client */
void mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
            .broker.address.uri = MQTT_BROKER_URL,
    };

    mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, mqtt_client);
    esp_mqtt_client_start(mqtt_client);
}

/* Publish Message on MQTT */
void mqtt_app_publish(char* topic, char *publish_string)
{
    if (mqtt_client)
    {
        int msg_id = esp_mqtt_client_publish(mqtt_client, topic, publish_string, 0, 1, 0);
        ESP_LOGI(TAG, "sent publish returned msg_id=%d", msg_id);
    }
}

void app_main(void)
{
    /* Init Network group to track Wifi Connect and Disconnect */
    s_network_event_group = xEventGroupCreate();

    ESP_ERROR_CHECK(esp_netif_init());

    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /* Start WiFi in Station Mode */
    wifi_init_sta();

    /* Start MQTT and Subscrice to Topic */
    mqtt_app_start();

    /* Publish message on MQTT Every 5 Secs */
    int Count = 0;
    char PublishBuffer[64] = "";
    while(1)
    {
        sprintf(PublishBuffer,"EmbeTronics Publish Msg Count : %d",Count++);
        mqtt_app_publish(MQTT_PUB_TOPIC,PublishBuffer);
        vTaskDelay(5000 / portTICK_PERIOD_MS);
    }
}

Modify CMakeLists.txt below code,
idf_component_register(SRCS "mqtt_example.c" 

PRIV_REQUIRES nvs_flash esp_event esp_wifi mqtt
INCLUDE_DIRS "")


Working Of Code

Now we will see Working of Code. ESP32 Board will publish message on MQTT broker every 5 seconds and will print received MQTT messages on Serial Console.
  1. First build and flash code on ES32 Board.
  2. Open "https://testclient-cloud.mqtt.cool/" mqtt client on browser and connect with "test.mosquitto.org".
    Select "test.mosquitto.org" from Select a Broaker drop down and Click on Connect Button.
  3. Subcribe to "/embetronics/pub" topic to receive ESP32 Published messages.


  4. You can publish message to ESP32 Board using topic "/embetronics/sub"

See below logs from ESP32 Console,

ESP-ROM:esp32c3-api1-20210207
Build:Feb 7 2021
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5820,len:0x1574
load:0x403cc710,len:0xc30
load:0x403ce710,len:0x2f64
entry 0x403cc71a
I (30) boot: ESP-IDF v5.4.1-dirty 2nd stage bootloader
I (30) boot: compile time Nov 29 2025 13:25:20
I (30) boot: chip revision: v0.3
I (31) boot: efuse block revision: v1.2
I (34) boot.esp32c3: SPI Speed : 80MHz
I (38) boot.esp32c3: SPI Mode : DIO
I (42) boot.esp32c3: SPI Flash Size : 2MB
I (46) boot: Enabling RNG early entropy source...
I (50) boot: Partition Table:
I (53) boot: ## Label Usage Type ST Offset Length
I (59) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (66) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (72) boot: 2 factory factory app 00 00 00010000 00100000
I (79) boot: End of partition table
I (82) esp_image: segment 0: paddr=00010020 vaddr=3c0c0020 size=1db6ch (121708) map
I (109) esp_image: segment 1: paddr=0002db94 vaddr=3fc93a00 size=02484h ( 9348) load
I (111) esp_image: segment 2: paddr=00030020 vaddr=42000020 size=b00b8h (721080) map
I (228) esp_image: segment 3: paddr=000e00e0 vaddr=3fc95e84 size=00934h ( 2356) load
I (228) esp_image: segment 4: paddr=000e0a1c vaddr=40380000 size=139e4h ( 80356) load
I (246) esp_image: segment 5: paddr=000f4408 vaddr=50000200 size=0001ch ( 28) load
I (253) boot: Loaded app from partition at offset 0x10000
I (253) boot: Disabling RNG early entropy source...
I (264) cpu_start: Unicore app
I (272) cpu_start: Pro cpu start user code
I (272) cpu_start: cpu freq: 160000000 Hz
I (272) app_init: Application information:
I (272) app_init: Project name: hello_world
I (276) app_init: App version: 1
I (280) app_init: Compile time: Nov 29 2025 13:24:08
I (285) app_init: ELF file SHA256: e2f9eac48...
I (289) app_init: ESP-IDF: v5.4.1-dirty
I (294) efuse_init: Min chip rev: v0.3
I (297) efuse_init: Max chip rev: v1.99
I (301) efuse_init: Chip rev: v0.3
I (305) heap_init: Initializing. RAM available for dynamic allocation:
I (311) heap_init: At 3FC9B070 len 00024F90 (147 KiB): RAM
I (317) heap_init: At 3FCC0000 len 0001C710 (113 KiB): Retention RAM
I (323) heap_init: At 3FCDC710 len 00002950 (10 KiB): Retention RAM
I (329) heap_init: At 5000021C len 00001DCC (7 KiB): RTCRAM
I (335) spi_flash: detected chip: generic
I (338) spi_flash: flash io: dio
W (341) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (353) sleep_gpio: Configure to isolate all GPIO pins in sleep state
I (359) sleep_gpio: Enable automatic switching of GPIO sleep configuration
I (366) main_task: Started on CPU0
I (376) main_task: Calling app_main()
I (386) esp32_mqtt: ESP_WIFI_MODE_STA
I (386) pp: pp rom version: 9387209
I (396) net80211: net80211 rom version: 9387209
I (406) wifi:wifi driver task: 3fca3b90, prio:23, stack:6656, core=0
I (406) wifi:wifi firmware version: 79fa3f41ba
I (406) wifi:wifi certification version: v7.0
I (406) wifi:config NVS flash: enabled
I (406) wifi:config nano formatting: disabled
I (416) wifi:Init data frame dynamic rx buffer num: 32
I (416) wifi:Init static rx mgmt buffer num: 5
I (426) wifi:Init management short buffer num: 32
I (426) wifi:Init dynamic tx buffer num: 32
I (436) wifi:Init static tx FG buffer num: 2
I (436) wifi:Init static rx buffer size: 1600
I (436) wifi:Init static rx buffer num: 10
I (446) wifi:Init dynamic rx buffer num: 32
I (446) wifi_init: rx ba win: 6
I (446) wifi_init: accept mbox: 6
I (456) wifi_init: tcpip mbox: 32
I (456) wifi_init: udp mbox: 6
I (456) wifi_init: tcp mbox: 6
I (466) wifi_init: tcp tx win: 5760
I (466) wifi_init: tcp rx win: 5760
I (466) wifi_init: tcp mss: 1440
I (466) wifi_init: WiFi IRAM OP enabled
I (476) wifi_init: WiFi RX IRAM OP enabled
I (476) phy_init: phy_version 1200,2b7123f9,Feb 18 2025,15:22:21
I (516) wifi:mode : sta (68:67:25:4e:9a:4c)
I (516) wifi:enable tsf
I (526) esp32_mqtt: wifi_init_sta finished.
I (526) wifi:new:<5,2>, old:<1,0>, ap:<255,255>, sta:<5,2>, prof:1, snd_ch_cfg:0x0
I (526) wifi:state: init -> auth (0xb0)
I (536) wifi:state: auth -> assoc (0x0)
I (536) wifi:state: assoc -> run (0x10)
I (546) wifi:connected with SPiDiGO2, aid = 1, channel 5, 40D, bssid = 60:31:92:03:70:83
I (546) wifi:security: WPA2-PSK, phy: bgn, rssi: -49
I (546) wifi:pm start, type: 1
I (556) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us
I (556) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 25000, mt_pti: 0, mt_time: 10000
I (566) wifi:AP's beacon interval = 102400 us, DTIM period = 1
I (976) wifi:<ba-add>idx:0 (ifx:0, 60:31:92:03:70:83), tid:0, ssn:2, winSize:64
I (1776) esp_netif_handlers: sta ip: 192.168.2.10, mask: 255.255.255.0, gw: 192.168.2.1
I (1776) esp32_mqtt: static ip:192.168.2.10
I (1776) esp32_mqtt: connected to ap SSID:SPiDiGO2 password:41Shukan
I (1776) esp32_mqtt: Other event id:7
I (3236) esp32_mqtt: MQTT_EVENT_CONNECTED
I (3236) esp32_mqtt: sent publish returned msg_id=37891
I (7426) esp32_mqtt: MQTT_EVENT_SUBSCRIBED, msg_id=63926
I (7426) esp32_mqtt: MQTT_EVENT_DATA
I (7426) esp32_mqtt: TOPIC=/embetronics/sub
I (7426) esp32_mqtt: DATA=***** Message from EmbeTronics *****
I (7436) esp32_mqtt: MQTT_EVENT_PUBLISHED, msg_id=37891
I (8236) esp32_mqtt: sent publish returned msg_id=10198
I (8866) esp32_mqtt: MQTT_EVENT_DATA
I (8866) esp32_mqtt: TOPIC=/embetronics/sub
I (8866) esp32_mqtt: DATA=***** Message from EmbeTronics *****
I (8866) esp32_mqtt: MQTT_EVENT_PUBLISHED, msg_id=10198


Explanation of Code

Let us understand blocks of code and see how it works.

First we will include all requied header files. Header files for FreeRTOS, WiFi, MQTT and Logging are included.
/* Include Required Header files */
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include <netdb.h>
#include "nvs_flash.h"
#include "mqtt_client.h"

Modify Wi-Fi Credentials with You Wi-Fi Credentials, .
/* Wifi Credentials and Retry Counts */
#define EXAMPLE_WIFI_SSID             "WRITE_YOUR_WIFI_SSID_HERE"
#define EXAMPLE_WIFI_PASS             "WRITE_YOUR_WIFI_PASSWORD_HERE"

To track Wi-Fi connection status Event Groups from FreeRTOS is used. You can read more about Event Groups at https://freertos.org/Documentation/02-Kernel/02-Kernel-features/06-Event-groups.
/* The event group allows multiple bits for each event, but we only care about two events:
 * - we are connected to the AP with an IP
 * - we failed to connect after the maximum amount of retries
*/
#define CONNECTED_BIT                   BIT0
#define WIFI_FAIL_BIT                   BIT1

/* Event group for WiFi Connect Disconnect Tracking */
static EventGroupHandle_t s_network_event_group;

MQTT Broker URL and Topics are defined using Macros. You can change them if you want to connect with different MQTT broker or another topics are to be used.
/* MQTT Broker URL and Topics */
#define MQTT_BROKER_URL                 "mqtt://test.mosquitto.org"
#define MQTT_PUB_TOPIC                  "/embetronics/pub"
#define MQTT_SUB_TOPIC                  "/embetronics/sub"

MQTT Client library handle is defined which will be used through out this project.
/* MQTT Client Handle */
static esp_mqtt_client_handle_t mqtt_client = NULL;

TAG to be used when ESP Log print is defined. You can modify as per your requirement.
/* TAG for ESP Log Print */
static const char *TAG = "esp32_mqtt";

Handler function to handle all WiFi related events is defined. It handles WiFi Connect, Disconnect and IP Got events. It will try to connect with provided WiFi network with defined number of retries.
/* WiFi Event Handler Function */
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    /* WiFi Connect Retry Count */
    static int s_retry_num = 0;

    /* If WiFi Station Mode Start Event Received */
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    }
    /* If WiFi Disconnect Event Received */
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
        /* If WiFi Cconnect Retry Count not Completed,Try Connecting */
        if (s_retry_num < EXAMPLE_MAXIMUM_RETRY) {
            esp_wifi_connect();
            s_retry_num++;
            ESP_LOGI(TAG, "retry to connect to the AP");
        } else {
            xEventGroupSetBits(s_network_event_group, WIFI_FAIL_BIT);
        }
        ESP_LOGI(TAG,"connect to the AP fail");
    }
    /* If IP Got Event Received */
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "static ip:" IPSTR, IP2STR(&event->ip_info.ip));
        s_retry_num = 0;
        xEventGroupSetBits(s_network_event_group, CONNECTED_BIT);
    }
}

Following function will initialize WiFi into Station mode and Connect with provided WiFi Credentials. It will do necessary initialization for WiFi and assign handler functions to it. It will also initialize Event groups for tracking WiFi connect and disconnect events.
/* Init WiFi with Station Mode */
static void wifi_init_sta(void)
{
    //Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");

    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &wifi_event_handler,
                                                        sta_netif,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &wifi_event_handler,
                                                        sta_netif,
                                                        &instance_got_ip));

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_WIFI_SSID,
            .password = EXAMPLE_WIFI_PASS,
            /* Setting a password implies station will connect to all security modes including WEP/WPA.
             * However these modes are deprecated and not advisable to be used. In case your Access point
             * doesn't support WPA2, these mode can be enabled by commenting below line */
	     .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start() );

    ESP_LOGI(TAG, "wifi_init_sta finished.");

    /* Waiting until either the connection is established (CONNECTED_BIT) or connection failed for the maximum
     * number of re-tries (WIFI_FAIL_BIT). The bits are set by wifi_event_handler() (see above) */
    EventBits_t bits = xEventGroupWaitBits(s_network_event_group,
            CONNECTED_BIT | WIFI_FAIL_BIT,
            pdFALSE,
            pdFALSE,
            portMAX_DELAY);

    /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
     * happened. */
    if (bits & CONNECTED_BIT) {
        ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
                 EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS);
    } else if (bits & WIFI_FAIL_BIT) {
        ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
                 EXAMPLE_WIFI_SSID, EXAMPLE_WIFI_PASS);
    } else {
        ESP_LOGE(TAG, "UNEXPECTED EVENT");
    }

    /* The event will not be processed after unregister */
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
    vEventGroupDelete(s_network_event_group);
}  

Below functions handle all MQTT client related events like MQTT Connect, Disconnect, Topic Subscribe, Unsubscribe, Message Publish and Received.  
/* MQTT Event Handler Callback Function */
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
            /* Subscribe to Topic */
            if (esp_mqtt_client_subscribe(mqtt_client, MQTT_SUB_TOPIC, 0) < 0) {
                // Disconnect to retry the subscribe after auto-reconnect timeout
                esp_mqtt_client_disconnect(mqtt_client);
            }
            break;
        case MQTT_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
            break;

        case MQTT_EVENT_SUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_UNSUBSCRIBED:
            ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_PUBLISHED:
            ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
            break;
        case MQTT_EVENT_DATA:
            ESP_LOGI(TAG, "MQTT_EVENT_DATA");
            ESP_LOGI(TAG, "TOPIC=%.*s", event->topic_len, event->topic);
            ESP_LOGI(TAG, "DATA=%.*s", event->data_len, event->data);
            break;
        case MQTT_EVENT_ERROR:
            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
            break;
        default:
            ESP_LOGI(TAG, "Other event id:%d", event->event_id);
            break;
    }
    return ESP_OK;
}
/* MQTT Event Handler Function */
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRId32 "", base, event_id);
    mqtt_event_handler_cb(event_data);
}

MQTT initialization is done by below function. It initializes MQTT client config structure and client handle. After initialization it registers MQTT evet handler function and start MQTT connection.
/* Init and Start MQTT Client */
void mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
            .broker.address.uri = MQTT_BROKER_URL,
    };

    mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, mqtt_client);
    esp_mqtt_client_start(mqtt_client);
}

We have defined following function to publish message on MQTT broker. It wll publish given string data to defined MQTT topic.
/* Publish Message on MQTT */
void mqtt_app_publish(char* topic, char *publish_string)
{
    if (mqtt_client)
    {
        int msg_id = esp_mqtt_client_publish(mqtt_client, topic, publish_string, 0, 1, 0);
        ESP_LOGI(TAG, "sent publish returned msg_id=%d", msg_id);
    }
}

At last main function of our code is defined which will call all initialization functions and continuously publish message on MQTT evert 5 seconds.
void app_main(void)
{
    /* Init Network group to track Wifi Connect and Disconnect */
    s_network_event_group = xEventGroupCreate();

    ESP_ERROR_CHECK(esp_netif_init());

    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /* Start WiFi in Station Mode */
    wifi_init_sta();

    /* Start MQTT and Subscrice to Topic */
    mqtt_app_start();

    /* Publish message on MQTT Every 5 Secs */
    int Count = 0;
    char PublishBuffer[64] = "";
    while(1)
    {
        sprintf(PublishBuffer,"EmbeTronics Publish Msg Count : %d",Count++);
        mqtt_app_publish(MQTT_PUB_TOPIC,PublishBuffer);
        vTaskDelay(5000 / portTICK_PERIOD_MS);
    }
}


Wrapping Up

In todays tutorial you have learned how to communicate using MQTT protocol on ESP32 C3 Board with ESP-IDF.

Please leave a comment if you have a question or you found this helpful.

Post a Comment

0 Comments