Ở bài trước chúng ta đã biết cách điều khiển đèn LED thông qua WebSocket thông qua việc truyền các tin nhắn “on” hoặc “off“. Trong bài này chúng ta sẽ làm điều tương tự nhưng sử dụng MQTT.
Trước tiên chúng ta cần cài đặt thư viện PubSubClient cho Arduino IDE. Bạn vào menu Sketch > Include Library > Manage Libraries. Tìm và cài đặt thư viện PubSubClient:
Khai báo các thư viện cần thiết:
#include <ESP8266WiFi.h> // Thư viện dùng để kết nối WiFi của ESP8266 #include <PubSubClient.h> // Thư viện dùng để connect, publish/subscribe MQTT
Để sử dụng thư viện PubSubClient ta cần khởi tạo một đối tượng tên là là client.
WiFiClient espClient; PubSubClient client(espClient);
Khai báo hàm dùng để kết nối đến broker. Ta sẽ dùng broker miễn phí của HiveMQ có thông tin như sau:
const char* mqttServer = "broker.hivemq.com"; const int mqttPort = 8000; const char* mqttUser = ""; const char* mqttPassword = "";
void connectBroker() { client.setServer(mqttServer, mqttPort); client.setCallback(callback); // Hàm callback sẽ được gọi khi nhận được tin nhắn từ broker while (!client.connected()) { Serial.println("Connecting to MQTT..."); if (client.connect("BlockyNodeClient", mqttUser, mqttPassword )) { // Kêt nối đến broker thành công Serial.println("connected"); } else { Serial.print("failed with state "); Serial.print(client.state()); delay(2000); } } }
Để đăng ký nhận tin từ một kênh cụ thể ta dùng lệnh sau:
client.subscribe("blockynode/led"); // Đăng ký nhận tin từ topic = "blockynode/led"
Để gởi tin nhắn đến một kênh cụ thể ta dùng lệnh sau:
client.publish("blockynode/led", "Hello from Blocky Node"); // Gởi message = "Hello from Blocky Node" đến topic = "blockynode/led"
Khi nhận được tin nhắn từ broker, hàm callback sẽ được gọi và ta sẽ dựa vào nội dung tín nhắn nhận được để điều khiển đèn LED.
void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); int i; for (i = 0; i < length; i++) { messageBuff[i] = (char)payload[i]; } messageBuff[i] = '\0'; String message = String(messageBuff); Serial.println(message); if (message == "on") { digitalWrite(led, LOW); // Bật đèn LED khi nhận được tin nhắn "on" client.publish("blockynode/led", "LED is turned ON"); // Thông báo trạng thái bật LED cho tất cả client đăng ký topic = "blockynode/led" } else if (message == "off") { // Tắt đèn LED khi nhận được tin nhắn "off" digitalWrite(led, HIGH); client.publish("blockynode/led", "LED is turned OFF"); // Thông báo trạng thái tắt LED cho tất cả client đăng ký topic = "blockynode/led" } }
Cuối cùng chúng ta cần gọi phương thức client.loop() trong vòng lặp chính để lắng nghe các sự kiện từ broker.
void loop() { client.loop(); }
Bạn dùng Arduino IDE để nạp chương trình sau:
#include <ESP8266WiFi.h> // Thư viện dùng để kết nối WiFi của ESP8266 #include <PubSubClient.h> // Thư viện dùng để connect, publish/subscribe MQTT const char* ssid = "Blocky AP"; // Tên của mạng WiFi mà bạn muốn kết nối đến const char* password = "password_ap"; // Mật khẩu của mạng WiFi const char* mqttServer = "broker.hivemq.com"; const int mqttPort = 1883; const char* mqttUser = ""; const char* mqttPassword = ""; const int led = 15; // Đèn led ở chân GPIO2 char messageBuff[100]; // Biến dùng để lưu nội dung tin nhắn WiFiClient espClient; PubSubClient client(espClient); void setup() { Serial.begin(115200); // Khởi tạo kết nối Serial để truyền dữ liệu đến máy tính pinMode(led, OUTPUT); startWiFi(); connectBroker(); client.subscribe("blockynode/led"); // Đăng ký nhận tin từ topic = "blockynode/led" client.publish("blockynode/led", "Hello from Blocky Node"); // Gởi message = "Hello from Blocky Node" đến topic = "blockynode/led" } void loop() { if (!client.connected()) { connectBroker(); } client.loop(); } void startWiFi() { WiFi.begin(ssid, password); // Kết nối vào mạng WiFi Serial.print("Connecting to "); Serial.print(ssid); // Chờ kết nối WiFi được thiết lập while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println("\n"); Serial.println("Connection established!"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); // Gởi địa chỉ IP đến máy tinh } void connectBroker() { client.setServer(mqttServer, mqttPort); client.setCallback(callback); while (!client.connected()) { Serial.print("Connecting to MQTT..."); if (client.connect("BlockyNodeClientID")) { // Kêt nối đến broker thành công Serial.println("\n"); Serial.println("MQTT connected"); } else { Serial.println("\n"); Serial.print("MQTT failed with state "); Serial.println(client.state()); delay(2000); } } } void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); int i; for (i = 0; i < length; i++) { messageBuff[i] = (char)payload[i]; } messageBuff[i] = '\0'; String message = String(messageBuff); Serial.println(message); if (message == "on") { digitalWrite(led, LOW); // Bật đèn LED khi nhận được tin nhắn "on" client.publish("blockynode/led", "LED is turned ON"); // Thông báo trạng thái bật LED cho tất cả client đăng ký topic = "blockynode/led" } else if (message == "off") { // Tắt đèn LED khi nhận được tin nhắn "off" digitalWrite(led, HIGH); client.publish("blockynode/led", "LED is turned OFF"); // Thông báo trạng thái tắt LED cho tất cả client đăng ký topic = "blockynode/led" } }
Sau khi nạp code thành công, ta dùng một MQTT Client để kiểm tra. Ta có thể dùng HiveMQ online tại đây:
Bạn kết nối chương trình đến brorker broker.hivemq.com (Port 8000).
Sau đó subscribe/publish topic = “blockynode/led” và thử gởi các tin nhắn như “on“, “off” để kiểm tra sự thay đổi trạng thái của đèn LED ở chân GPIO2 (có sẵn trên ESP8266).