Thời gian Mở cửa: Các ngày trong tuần: 7:30 - 20:00

0 sản phẩm

  • Giỏ hàng của bạn trống!

ESP32 hướng dẫn lập trình kết nối MQTT - IoT

04/12/2021   |   994

MQTT (Message Queuing Telemetry Transport) là giao thức truyền thông điệp (message) theo mô hình publish/subscribe (cung cấp / thuê bao), được sử dụng cho các thiết bị IoT với băng thông thấp, độ tin cậy cao và khả năng được sử dụng trong mạng lưới không ổn định. Nó dựa trên một Broker (tạm dịch là “Máy chủ môi giới”) “nhẹ” (khá ít xử lý) và được thiết kế có tính mở (tức là không đặc trưng cho ứng dụng cụ thể nào), đơn giản và dễ cài đặt.

1. Tài liệu

ESP32 Get Started

ESP32 Windows Setup

2. Kit phát triển các bạn có thể mua tại link sau: 

KIT PHÁT TRIỂN WIFI BLUETOOTH ESP32-C3U

KIT PHÁT TRIỂN WIFI BLUETOOTH ESP32-C3S

KIT PHÁT TRIỂN WIFI BLUETOOTH ESP32-S3-DEVKITC-1

KIT PHÁT TRIỂN WIFI BLUETOOTH ESP32 S NODEMCU

KIT PHÁT TRIỂN 3G 4G SIM7600CE ESP32

3. Giới thiệu về MQTT

MQTT (Message Queuing Telemetry Transport) là giao thức truyền thông điệp (message) theo mô hình publish/subscribe (cung cấp / thuê bao), được sử dụng cho các thiết bị IoT với băng thông thấp, độ tin cậy cao và khả năng được sử dụng trong mạng lưới không ổn định. Nó dựa trên một Broker (tạm dịch là “Máy chủ môi giới”) “nhẹ” (khá ít xử lý) và được thiết kế có tính mở (tức là không đặc trưng cho ứng dụng cụ thể nào), đơn giản và dễ cài đặt.

MQTT là lựa chọn lý tưởng trong các môi trường như:

  • Những nơi mà giá mạng viễn thông đắt đỏ hoặc băng thông thấp hay thiếu tin cậy.
  • Khi chạy trên thiết bị nhúng bị giới hạn về tài nguyên tốc độ và bộ nhớ.
  • Bởi vì giao thức này sử dụng băng thông thấp trong môi trường có độ trễ cao nên nó là một giao thức lý tưởng cho các ứng dụng M2M (Machine to Machine).
  • MQTT cũng là giao thức được sử dụng trong Facebook Messenger

4. Ví dụ Kết nối MQTT sử dụng Kit ESP32

               ESP_IDF\examples\protocols\mqtt\tcp

  • Copy project và đổi tên:

ESP_IDF\examples\protocols\mqtt\tcp   --> D:\mqtt_tcp

nếu ESP_IDF Cài đặt tại D:\esp-idf_master thì:

D:\esp-idf_master\examples\protocols\mqtt\tcp -> D:\mqtt_tcp

  • Note:
    • Trong ví dụ này kết nối MQTT là TCP (không bảo mật), nếu các bạn muốn sử dụng MQTTS vui lòng xem tại:
      • ESP_IDF\examples\mqtt\ssl
      • ESP_IDF\examples\mqtt\ssl_mutual_auth
    • Kết nối SSL sẽ bảo mật hơn trong các ứng dụng IoT

idf_cmd_init.bat

  • Vào menuconfig:

idf.py menuconfig

  • Ở menu Example Configuration:

Đổi lại broker thành: mqtt://mqtt.eclipseprojects.io (mặc định)

  • Ở menu Example Connection Example:

        -> Đổi wifi SSID

        -> Đổi wifi Password

  • Thoát ra menuconfig (Ấn phím Q để thoát và ấn Y để lưu lại)

  • Từ command, build project:

idf.py build

  • Nạp và kiểm tra:

idf.py -p COM6 flash monitor

  • Sau khi nạp xong màn hình sẽ show kết quả như hình

Trong đó có log kết quả kết nối Wi-Fi, MQTT và MQTT Message

Trong ví dụ này, MQTT sẽ tự động kết nối và reconnect khi kết nối Wi-Fi bị ngắt hoặc bị ngắt kết nối từ server

4. Ví dụ thực tế

  • Trong ví dụ này mình sẽ làm một ứng dụng nho nhỏ đọc nhiệt độ theo thời gian và gửi lên server, đồng thời điều khiển relay hoặc LED
  • Topic nhận trạng thái: test/status
    • Data sẽ có dạng json: {"temp": <temperature>}
    • Ví dụ {"temp": 33.3}
  • Topic điều khiển: test/control
    • Data là: on --> LED Sáng
    • Data là: off --> LED Tắt
    • Data là: toggle --> LED đổi trạng thái


#include "stdio.h"
#include "stdint.h"
#include "stddef.h"
#include "string.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"

#include "esp_log.h"
#include "mqtt_client.h"

#include "driver/gpio.h"

#define GPIO_OUTPUT_IO_0        18
#define GPIO_OUTPUT_IO_1        19
#define GPIO_OUTPUT_PIN_SEL     ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))

static const char *TAG = "MQTT_EXAMPLE";

static const char* topicControl = "test/control";
static const char* topicStatus = "test/status";

static esp_mqtt_client_handle_t client;
static bool mqttConnected;
static float temperature = 30.0F;
static char mqtt_tx_buf[64];
static uint32_t mqtt_tx_buf_len;

void mqtt_on_message(char *msg, uint32_t len);

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    esp_mqtt_event_handle_t event = event_data;
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    switch ((esp_mqtt_event_id_t)event_id) {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");

        /*  Set MQTT Connected  */
        mqttConnected = true;

        /*  Subcribe topic test/control */
        msg_id = esp_mqtt_client_subscribe(client, topicControl, 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_DISCONNECTED:
        /*  Set MQTT Disconnected  */
        mqttConnected = false;

        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:
        mqtt_on_message(event->data, event->data_len);
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        printf("\t\tTOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("\t\tDATA=%.*s\r\n", 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;
    }
}

static void mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = { .uri = CONFIG_BROKER_URL};
    client = esp_mqtt_client_init(&mqtt_cfg);
    /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    esp_mqtt_client_start(client);
}

static void app_gpio_init(void)
{
    gpio_config_t io_conf;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_INPUT_OUTPUT ;
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    gpio_config(&io_conf);
    gpio_set_level(GPIO_OUTPUT_IO_0, 1);
    gpio_set_level(GPIO_OUTPUT_IO_1, 1);
}

/*
*   Receive message MQTT
*/
void mqtt_on_message(char *msg, uint32_t len){
    if(strstr(msg, "on") != NULL){   
        ESP_LOGI(TAG, "ON LED");
        gpio_set_level(GPIO_OUTPUT_IO_0, 0);
    }
    else if(strstr(msg, "off")  != NULL){
        ESP_LOGI(TAG, "OFF LED");
        gpio_set_level(GPIO_OUTPUT_IO_0, 1);
    }
    else if(strstr(msg, "toggle") != NULL){
        ESP_LOGI(TAG, "TOGGLE LED");
        gpio_set_level(GPIO_OUTPUT_IO_0, gpio_get_level(GPIO_OUTPUT_IO_0) ^ 1);
    }
}

/*
*   Publish message to broker
*   QoS:    1
*   Retain: True
*/
bool mqtt_publish(char *msg, uint32_t len){
    if(!mqttConnected) return false;
    int msg_id = esp_mqtt_client_publish(client, topicStatus, msg, len, 1, 1);
    ESP_LOGI(TAG, "Send status data");
    return true;
}

void app_main(void)
{
    ESP_LOGI(TAG, "[APP] Startup..");
    ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
    ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
    esp_log_level_set("*", ESP_LOG_INFO);

    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /*  Init GPIO   */
    app_gpio_init();

    /*  Connect Wi-Fi   */
    ESP_ERROR_CHECK(example_connect());

    /*  MQTT Init & Connect  */
    mqtt_app_start();

    while(true)
    {
        temperature += 0.1F;
        if(temperature > 50.0F) temperature = 30.0F;

        mqtt_tx_buf_len = sprintf(mqtt_tx_buf, "{\"temp\": %f}", temperature);

        /*  Publish message to MQTT broker  */
        mqtt_publish(mqtt_tx_buf, mqtt_tx_buf_len);

        /*  Toggle Pin out  */
        // gpio_set_level(GPIO_OUTPUT_IO_0, gpio_get_level(GPIO_OUTPUT_IO_0) ^ 1);

        /*  Sleep 5000ms to let task to Suspended Mode  */
        /*  Refer: https://www.freertos.org/RTOS-task-states.html   */
        vTaskDelay(1000 / portTICK_RATE_MS);
    }
}

 

Kết quả