MQTT nhập môn - đưa robot và cảm biến ESP32 lên Internet đúng chuẩn

MQTT là giao thức nhắn tin pub/sub chuẩn của IoT. Hiểu broker, topic, QoS qua ví dụ đời thường và code ESP32 publish cảm biến, subscribe lệnh hoàn chỉnh. Trong bài viết này, chúng ta sẽ cùng tìm hiểu chi tiết và ứng dụng thực tế trong robot.
MQTT giải bài toán gì?
Robot phát WiFi điều khiển trong phòng thì web server là đủ. Nhưng kịch bản IoT thật khác hẳn: trạm cảm biến ở nhà kính gửi số liệu về điện thoại đang ở bất kỳ đâu; một dashboard theo dõi 30 thiết bị; bật máy bơm từ xa qua 4G. Các thiết bị không nhìn thấy nhau trực tiếp, mạng chập chờn, thiết bị yếu — HTTP không sinh ra cho việc này.
MQTT (Message Queuing Telemetry Transport) là giao thức nhắn tin siêu nhẹ chuẩn công nghiệp của IoT, thiết kế từ thời đường truyền vệ tinh đắt đỏ: gói tin tối giản, chịu mạng kém, chip yếu chạy tốt. Từ cảm biến hồ cá đến xe Tesla đều có bóng dáng MQTT.
Ba khái niệm cốt lõi qua ví dụ bảng tin lớp học
Broker - bảng tin trung tâm
Mọi tin nhắn đều đi qua broker (máy chủ trung gian) — như bảng tin ở sảnh trường: người viết dán tin lên bảng, người đọc tự đến xem, hai bên không cần gặp nhau, không cần biết mặt nhau, không cần có mặt cùng lúc. Thiết bị chỉ cần biết địa chỉ broker — đây là điều kỳ diệu giải bài toán "hai thiết bị sau hai cái router khác nhau nói chuyện với nhau".
Topic - chuyên mục của bảng tin
Tin nhắn dán vào topic — chuỗi phân cấp bằng dấu gạch chéo:
nhakinh/khu-a/nhiet-do
nhakinh/khu-a/do-am
robot/xe01/lenh
robot/xe01/trang-thai/pinNgười đọc subscribe (đăng ký) topic quan tâm; người viết publish (đăng) lên topic. Ký tự đại diện khi subscribe: + thay một cấp (nhakinh/+/nhiet-do — nhiệt độ mọi khu), # thay mọi cấp còn lại (robot/xe01/# — tất cả về xe 01).
QoS - mức cam kết chuyển phát
- QoS 0: gửi rồi quên — nhanh nhất, chấp nhận rơi gói (số liệu cảm biến gửi mỗi 5 giây, rơi một gói không sao)
- QoS 1: đảm bảo đến, có thể trùng lặp (lệnh bật bơm)
- QoS 2: đến đúng một lần — nặng nhất, hiếm khi cần ở mức học tập
Thực hành: trạm cảm biến + nhận lệnh trên ESP32
Thư viện: PubSubClient (Library Manager). Broker thử nghiệm: test.mosquitto.org hoặc broker.hivemq.com (công cộng, miễn phí, KHÔNG riêng tư — chỉ để học).
#include <WiFi.h>
#include <PubSubClient.h>
const char* WIFI_SSID = "TenWifiNha";
const char* WIFI_PASS = "matkhau";
const char* BROKER = "test.mosquitto.org";
WiFiClient espClient;
PubSubClient mqtt(espClient);
// nhận lệnh: broker đẩy xuống qua callback
void onMessage(char* topic, byte* payload, unsigned int len) {
String msg;
for (unsigned int i = 0; i < len; i++) msg += (char)payload[i];
Serial.printf("[%s] %s\n", topic, msg.c_str());
if (String(topic) == "lop9a/robot/lenh") {
if (msg == "den_bat") digitalWrite(2, HIGH);
if (msg == "den_tat") digitalWrite(2, LOW);
}
}
void connectMqtt() {
while (!mqtt.connected()) {
// clientId phải KHÁC NHAU giữa các thiết bị
if (mqtt.connect("esp32-xe01-ngau-nhien-4721")) {
mqtt.subscribe("lop9a/robot/lenh");
Serial.println("MQTT da ket noi");
} else {
delay(2000);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(2, OUTPUT);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(300);
mqtt.setServer(BROKER, 1883);
mqtt.setCallback(onMessage);
}
unsigned long lastPublish = 0;
void loop() {
if (!mqtt.connected()) connectMqtt(); // tự nối lại khi rớt
mqtt.loop(); // BẮT BUỘC gọi dày - tim của MQTT
if (millis() - lastPublish > 5000) {
float tempC = readTemperature(); // DHT22 như bài cảm biến
char buf[16];
dtostrf(tempC, 4, 1, buf);
mqtt.publish("lop9a/nhakinh/nhiet-do", buf);
lastPublish = millis();
}
}Kiểm chứng không cần viết thêm gì: điện thoại cài app MQTT Dashboard / IoT MQTT Panel, trỏ cùng broker, subscribe lop9a/# — số nhiệt độ hiện lên mỗi 5 giây; tạo nút publish "den_bat" lên lop9a/robot/lenh — LED trên bo sáng. Hai thiết bị cách nhau nghìn km vẫn vậy.
Thiết kế topic tử tế ngay từ đầu
Thói quen đặt topic phân biệt dự án nghiêm túc với demo:
- Cấu trúc
khu-vực/thiết-bị/loại-dữ-liệu:nha/phong-khach/nhiet-do— dashboard tự gom nhóm được - Tách kênh lệnh và kênh trạng thái:
robot/xe01/lenh(app ghi) vớirobot/xe01/trang-thai(robot ghi) — không bao giờ chung một topic hai chiều - Tiền tố riêng độc nhất khi dùng broker công cộng (
lop9a-thcs-xyz/...) — tránh đụng topic người lạ - Payload có cấu trúc khi dữ liệu nhiều trường: JSON
{"t":28.5,"h":72}với thư viện ArduinoJson
Broker nào cho dự án của bạn?
| Lựa chọn | Chi phí | Hợp với |
|---|---|---|
| test.mosquitto.org / broker.hivemq.com | Miễn phí, công cộng | Buổi học, thử nghiệm — dữ liệu ai cũng đọc được |
| HiveMQ Cloud / EMQX Cloud free tier | Miễn phí có tài khoản + mật khẩu + TLS | Dự án cá nhân, KHKT — khuyến nghị chính |
| Mosquitto tự cài (Raspberry Pi/laptop) | Miễn phí, tự quản | Phòng lab trường — chạy LAN không cần Internet |
| Home Assistant tích hợp | Miễn phí | Hệ nhà thông minh hoàn chỉnh |
Lớp học lý tưởng: Mosquitto trên một Raspberry Pi của phòng lab — cả lớp chung broker LAN, không phụ thuộc Internet trường, giáo viên thấy mọi luồng tin bằng lệnh mosquitto_sub -t '#' -v.
Câu hỏi thường gặp
MQTT có điều khiển robot thời gian thực được không?
Lái xe kiểu tay cầm — không nên: đường đi qua broker (thường trên Internet) trễ 100-500 ms và thất thường. MQTT hợp lệnh rời rạc ("tuần tra đi", "về trạm sạc") và telemetry. Lái thời gian thực dùng ESP-NOW hoặc WebSocket cục bộ — xem bài Điều khiển robot từ xa ở mục Kiến thức.
Vì sao thiết bị của tôi cứ tự rớt kết nối MQTT liên tục?
Nghi phạm số một: hai thiết bị trùng clientId — broker đá con này để nhận con kia, hai bên đá nhau vòng lặp. Mỗi thiết bị một clientId duy nhất (thêm số ngẫu nhiên/MAC vào tên). Nghi phạm hai: quên gọi mqtt.loop() thường xuyên khiến broker coi là chết (quá keepalive).
Dữ liệu MQTT có riêng tư không?
Trên broker công cộng: hoàn toàn không — ai subscribe # đọc được tất cả. Mức tối thiểu cho dữ liệu thật: broker có tài khoản/mật khẩu + TLS (cổng 8883, WiFiClientSecure). Không bao giờ đẩy vị trí nhà, mật khẩu, ảnh lên broker công cộng.
Retained message và Last Will là gì, có cần không?
Hai tính năng nhỏ mà chuyên nghiệp: retained — broker giữ tin cuối của topic, dashboard mở sau vẫn thấy trạng thái hiện tại thay vì màn hình trống; Last Will — broker tự đăng "thiết bị offline" khi thiết bị rớt đột ngột. Dùng cả hai cho topic trạng thái là dấu hiệu của người thiết kế IoT có nghề.
Tài nguyên tải về
Tải bản PDF của bài viết để in giáo án hoặc gửi trước cho học viên.



