Pendahuluan
Message Queue Telemetry Transport (MQTT) adalah many-to-many communication protocol dimana message broker sebagai mediator. Terdapat publishers yang berfungsi mengirim messages ke topic pada broker, dan ada subscribers, yang menerima messages dari topics yang mereka subscribe. Sebuah node dapat berfungsi sebagai publisher dan subscriber secara bersamaan.
MQTT menggunakan TCP sebagai transport protocol dan menggunakan TLS untuk communication security.
Topics adalah cara kita mengorganisasi information dalam MQTT. Berikut beberapa aturan dan best practice mengenai topics:
- / (slash) adalah level separator. Kita tidak mulai dengan / untuk memberi nama sebuah topic (karena akan menambahkan level yang tidak diperlukan).
- + (plus) adalah single-level wildcard. Agar jelasnya kita langsung gunakan contoh, ketika kita subscribe home/+/light, kita akan menerima semua topic yang sesuai dengan pattern, misalnya home/kitchen/light atau home/bedroom/light.
- # (sharp) adalah multi-level wildcard dan hanya dapat digunakan diakhir. Akan matches semua topic pada level tersebut dan dibawahnya.
- Topic names tidak bolah mengandung space atau non-printable characters.
- Penamaan dan levels tergantung dari context.
- IoT protocols with ESP32 30
Persiapan Project
Pada aplikiasi kali ini kita akan menggunakan sensor DHT11. Aplikasi akan publish data temperature dan humidity sebagai topics terpisah pada MQTT broker.
Untuk keperluan modul ini, diperlukan Eclipse Mosquitto, yaitu MQTT message broker. Silakan download di https://mosquitto.org/download
Untuk sensor DHT11 hubungkan ke GPIO17 pin pada ESP32 Devkit.
Buat project baru, lalu ubah platformio.ini seperti berikut: (gunakan path tempat anda menyimpan library.
[env:az-delivery-devkit-v4] platform = espressif32 board = az-delivery-devkit-v4 framework = espidf monitor_speed = 115200 lib_extra_dirs = ../esp-idf-lib/components ../common build_flags = -DWIFI_SSID=${sysenv.WIFI_SSID} -DWIFI_PASS=${sysenv.WIFI_PASS} -DMQTT_BROKER_URL=${sysenv.MQTT_BROKER_URL}
Kemudian download library https://drive.google.com/file/d/1_zAaUaJJY22HuVUk6Ora1vhLfPdjkOI-/view?usp=sharing, extract dan simpan didirectory common (sesuai dengan directory yang ditulias pada platformio.ini).
Library diatas akan beris file header untuk sensor DHT11 dan WiFi Connect.
Buka platformio CLI, kemudian definsikan environment variable: (ganti export dengan set untuk windows platform).
(penv)$ export WIFI_SSID='\"<your_ssid>\"'
(penv)$ export WIFI_PASS='\"<your_pass>\"'
Code
Setelah persiapan diatas selesai, kita lakukan coding dengan membuka file main.c, lalu gunakan code dibawah:
//import library dan variable init #include <string.h> #include <stdbool.h> #include <stdlib.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "mqtt_client.h" #include "app_temp.h" #include "app_wifi.h" #define TAG "app" //#ifndef MQTT_BROKER_URL #define MQTT_BROKER_URL "mqtt://localhost" //#endif #define SENSOR_NO "1" #define ENABLE_TOPIC "home/" SENSOR_NO "/enable" #define TEMP_TOPIC "home/temperature/" SENSOR_NO #define HUM_TOPIC "home/humidity/" SENSOR_NO static esp_mqtt_client_handle_t client = NULL; static bool enabled = false; // fungsi publish reading static void publish_reading(int temp, int hum) { char buffer[5]; if (client != NULL && enabled) { esp_mqtt_client_publish(client, TEMP_TOPIC, itoa(temp, buffer, 10), 0, 1, 0); esp_mqtt_client_publish(client, HUM_TOPIC, itoa(hum, buffer, 10), 0, 1, 0); } } //fungsi handle mqtt events static void handle_mqtt_events(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { esp_mqtt_event_handle_t event = event_data; switch ((esp_mqtt_event_id_t)event_id) { case MQTT_EVENT_CONNECTED: ESP_LOGI(TAG, "mqtt broker connected"); esp_mqtt_client_subscribe(client, ENABLE_TOPIC, 0); break; case MQTT_EVENT_DATA: if (!strncmp(event->topic, ENABLE_TOPIC, event->topic_len)) { enabled = event->data[0] - '0'; } break; case MQTT_EVENT_ERROR: ESP_LOGE(TAG, "errtype: %d", event->error_handle->error_type); break; default: ESP_LOGI(TAG, "event: %d", event_id); break; } } //fungsi handle wifi connect static void handle_wifi_connect(void) { esp_mqtt_client_config_t mqtt_cfg = { .uri = MQTT_BROKER_URL }; client = esp_mqtt_client_init(&mqtt_cfg); esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, handle_mqtt_events, NULL); esp_mqtt_client_start(client); apptemp_init(publish_reading); } //fungsi handle wifi failed static void handle_wifi_failed(void) { ESP_LOGE(TAG, "wifi failed"); } //main function void app_main() { esp_event_loop_create_default(); connect_wifi_params_t cbs = { .on_connected = handle_wifi_connect, .on_failed = handle_wifi_failed}; appwifi_connect(cbs); }
Penjelasan Code
Bagian Import Library dan variable init
KIta include header files yang diperlukan. Header file untuk MQTT library adalah mqtt_client.h.
Kemudian kita definisikan global variable.
Kita cadangkan MQTT topic untuk enable atau disable sensor device. Sensor akan melakuka subscribe topic.
ENABLE_TOPIC, untuk set/reset enabled global variable. Ketika enabled, sensor device akan publish ke TEMP_TOPIC dan HUM_TOPIC, dan client lainnya didalam network dapat subscribe topik ini untuk mendapatkan informasi.
Bagian Main Function
Oertama kita buat default event loop untuk menerima MQTT events. Kemudian kita panggil appwifi_connect untuk connect ke local Wi-Fi.
Bagian Wifi Connect
Ketika WiFi terhubung, kita init MQTT client dan register MQTT event handler function, handle_mqtt_events.
Kita jalankan MQTT client untuk connect ke broker dengan memanggil esp_mqtt_client_start.
Terakhir, kita init DHT11 readings dengan publish_reading sebagai callback function.
Bagian handle MQTT event
Event pertama adalah MQTT_EVENT_CONNECTED, dimana kita akan subscribe ENABLE_TOPIC untuk mendengarkan messages untuk enable/disable sensor commands.
Ketika MQTT_EVENT_DATA terjadi, berarti kita menerima message dari topic. Pada kasus kita hanya memiliki satu topic.
Event terakhir adalah MQTT_EVENT_ERROR. Disini kita akan print error type ke serial console.
Bagian publish reading
Untuk publish message, kita panggil esp_mqtt_client_publish. Diperlukan parameter MQTT client, topic name, dan data untuk dipublish.
Untuk parameter quality of service (QoS) terdapat tiga pilihan:
- QoS level-0: no delivery guarantee to subscribers. subscribers tidak harus melakukan acknowledge receipt message.
- QoS level-1: Guarantees delivery, namun subscribers dapat menerima beberapa copy message.
- QoS level-2: Subscribers hanya menerima persis satu copy dari message.
Untuk menggunakan QoS, sesuaikan dengan kebutuhan aplikasi. Contoh, jika tidak masalah ada pembacaaan yang terlewat, kita dapat gunakan QoS-0.
QoS-1 dan QoS-2 memerlukan extra message yaitu ACK, dimana akan menambah overhead pada jalur komuniskasi.
Compile, Upload dan Test
Sampai disini kita sudah selesai membuat code.
Berikutnya kita akan mempersiapkan Mosquitto.
Untuk testing, Mosquito sebagai broker, publisher dan subcriber client (link download adal pada awal modul ini).
Buka command prompt, lalu jalankan mosquito.
Kemudian buka command prompt, lalu jalankan mosquitto untuk listening:
$ mosquitto_sub -h localhost -t home/test
Buka command promp baru, lalu jalankan untuk publishing:
$ mosquitto_pub -h localhost -t home/test -m "test message"
Jika Anda melihat message pada window command prompt subcriber, maka mosquito sudah berjalan dengan baik. Berikutnya kita test dengan aplikasi ESP32.
Anda bisa tutup 2 window command prompt untuk publish dan subcribe, tapi window yang menjalankan mosquitto service harus tetap berjalan.
Lalu buka command promt baru, lalu jalankan perintah berikut
$ mosquitto_sub -h localhost -t "home/+/1" -d
Kembali ke visual studio code, lalu pada platformIO CLI, jalankan perintah
(penv)$ pio run -t upload && pio device monitor
Kemudian pada command prompt baru, jalankan perintah mosquitto untuk enable sensor.
mosquitto_pub -h localhost -t home/1/enable -m "1"
Sampai disini kita sudah selesai membahas penggunaan MQTT communication protocol.
Pada modul selanjutnya kita akan bahas CoAP comm protocol.