MQTT Hello World

This is a simple example of using the MQTT protocol to send data to a remote broker on the Internet.

We set everything up, wait for the GOT_IP event, and then start MQTT and send the string “Hello World” followed by the MAC address of the respective node every 5 seconds.

  1#include <esp_err.h>
  2#include <esp_event.h>
  3#include <esp_log.h>
  4#include <esp_mac.h>
  5#include <esp_wifi.h>
  6#include <freertos/FreeRTOS.h>
  7#include <freertos/task.h>
  8#include <meshnow.h>
  9#include <mqtt_client.h>
 10#include <nvs_flash.h>
 11
 12// The Wi-Fi credentials are configured via sdkconfig
 13#define ROUTER_SSID CONFIG_EXAMPLE_ROUTER_SSID
 14#define ROUTER_PASS CONFIG_EXAMPLE_ROUTER_PASSWORD
 15
 16// MQTT broker URI is configured via sdkconfig
 17#define MQTT_BROKER_URI CONFIG_EXAMPLE_MQTT_BROKER_URI
 18
 19// Waitbits
 20#define GOT_IP_BIT BIT0
 21#define MQTT_CONNECTED_BIT BIT1
 22
 23static const char *TAG = "hello-world";
 24
 25// Fixed MAC address of the root node
 26static const uint8_t root_mac[MESHNOW_ADDRESS_LENGTH] = {0x24, 0x6f, 0x28, 0x4a, 0x63, 0x3c};
 27
 28// MAC address of the current node
 29static uint8_t node_mac[MESHNOW_ADDRESS_LENGTH];
 30
 31// Whether this node is the root
 32static bool is_root = false;
 33
 34// Event group for various waiting processes
 35static EventGroupHandle_t my_event_group;
 36
 37// Event handler for IP_EVENT
 38static void ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
 39    assert(event_base == IP_EVENT);
 40    assert(event_id == IP_EVENT_STA_GOT_IP);
 41
 42    // set the bit for getting IP
 43    xEventGroupSetBits(my_event_group, GOT_IP_BIT);
 44}
 45
 46// Event handler for MQTT_EVENT
 47static void mqtt_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
 48    assert(event_id == MQTT_EVENT_CONNECTED);
 49
 50    xEventGroupSetBits(my_event_group, MQTT_CONNECTED_BIT);
 51}
 52
 53// Sends messages via MQTT
 54static void perform_mqtt() {
 55    // initialize
 56    esp_mqtt_client_config_t config = {
 57        .broker.address.uri = MQTT_BROKER_URI,
 58    };
 59    esp_mqtt_client_handle_t client = esp_mqtt_client_init();
 60
 61    // register event handler
 62    ESP_ERROR_CHECK(esp_mqtt_client_register_event(client, MQTT_EVENT_CONNECTED, &mqtt_event_handler, NULL));
 63
 64    char *msg;
 65    asprintf(&msg, "Hello World from " MACSTR "(%s)", MAC2STR(node_mac), is_root ? "root" : "node");
 66    size_t len = strlen(msg);
 67
 68    // start
 69    ESP_ERROR_CHECK(esp_mqtt_client_start(client, &config));
 70
 71    // wait for connection
 72    EventBits_t bits = xEventGroupWaitBits(my_event_group, MQTT_CONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
 73    assert((bits & MQTT_CONNECTED_BIT) != 0);
 74
 75    while (true) {
 76        ESP_ERROR_CHECK(esp_mqtt_client_publish(client, "/helloworld", msg, len, 0, 0));
 77        vTaskDelay(pMS_TO_TICKS(5000));
 78    }
 79}
 80
 81// Initializes NVS, Event Loop, Wi-Fi, and Netif
 82static void pre_init(void) {
 83    // nvs
 84    esp_err_t ret = nvs_flash_init();
 85    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
 86        ESP_ERROR_CHECK(nvs_flash_erase());
 87        ret = nvs_flash_init();
 88    }
 89    ESP_ERROR_CHECK(ret);
 90
 91    // event loop
 92    ESP_ERROR_CHECK(esp_event_loop_create_default());
 93
 94    // wifi
 95    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
 96    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
 97
 98    // netif
 99    ESP_ERROR_CHECK(esp_netif_init());
100}
101
102void app_main(void) {
103    pre_init();
104
105    // get MAC address
106    ESP_ERROR_CHECK(esp_read_mac(node_mac, ESP_MAC_WIFI_STA));
107
108    // check if root
109    is_root = memcmp(node_mac, root_mac, MESHNOW_ADDRESS_LENGTH) == 0;
110
111    // create event group
112    my_event_group = xEventGroupCreate();
113    assert(my_event_group != NULL);
114
115    // initialize meshnow
116    wifi_sta_config_t sta_config = {
117        .ssid = ROUTER_SSID,
118        .password = ROUTER_PASS,
119    };
120    meshnow_config_t config = {
121        .root = is_root,
122        .router_config =
123            {
124                .should_connect = true,  // MQTT requires internet access
125                .sta_config = sta_config,
126            },
127    };
128    ESP_ERROR_CHECK(meshnow_init(&config));
129
130    // register event handler for IP_EVENT
131    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL, NULL));
132
133    // start meshnow
134    ESP_ERROR_CHECK(meshnow_start());
135
136    // wait for IP
137    // when we get an IP address, the node has to have connected to a parent/router
138    // in a real application, you would want to handle disconnects/lost IP as well and restart MQTT
139    EventBits_t bits = xEventGroupWaitBits(my_event_group, GOT_IP_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
140    assert((bits & GOT_IP_BIT) != 0);
141
142    perform_mqtt();
143}