ESP8266 và giao thức MQTT cơ bản

Thảo luận trong 'IOT' bắt đầu bởi VuPhat.MCA, 3/6/19.

  1. VuPhat.MCA

    VuPhat.MCA New Member

    MQTT là gì? Trong bài viết này chúng ta sẽ đi tìm hiểu một trong những phương thức truyền nhận dữ liệu được sử dụng phổ biến nhất trong các ứng dụng IOT là MQTT, bên cạnh đó chúng ta sẽ học cách sử dụng chúng với ESP8266!

    TỔNG QUAN MQTT
    MQTT là một giao thức gởi dạng publish/subscribe sử dụng cho các thiết bị Internet of Things 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.
    [​IMG]
    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. MQTT cũng là giao thức sử dụng trong Facebook Messager.
    Và MQTT là gì? Để có một cái nhìn toàn diện hoặc định nghĩa chi tiết, chỉ cần google "what is mqtt", "mqtt slides"... Ở đây chúng ta chỉ nói ngắn gọn thôi, đủ để hiểu giao thức MQTT, bao gồm các định nghĩa "subscribe", "publish", "qos", "retain", " lwt".

    Publish/subscribe
    Trong một hệ thống sử dụng giao thức MQTT, nhiều node trạm (gọi là mqtt client – gọi tắt là client) kết nối tới một MQTT server (gọi là broker). Mỗi client sẽ đăng ký một vài kênh (topic), ví dụ như "/client1/channel1", "/client1/channel2". Quá trình đăng ký này gọi là "subscribe", giống như chúng ta đăng ký nhận tin trên một kênh Youtube vậy. Mỗi client sẽ nhận được dữ liệu khi bất kỳ trạm nào khác gởi dữ liệu và kênh đã đăng ký. Khi một client gởi dữ liệu tới kênh đó, gọi là "publish".

    QOS
    Ở đây có 3 tuỳ chọn QoS khi "publish" và "subscribe":
    • QoS0 broker/client sẽ gởi dữ liệu đúng 1 lần, quá trình gởi được xác nhận bởi chỉ giao thức TCP/IP, giống kiểu đem con bỏ chợ
    • QoS1 broker/client sẽ gởi dữ liệu với ít nhất 1 lần xác nhận từ đầu kia, nghĩa là có thể có nhiều hơn 1 lần xác nhận đã nhận được dữ liệu
    • QoS2 broker/client đảm bảm khi gởi dữ liệu thì phía nhận chỉ nhận được đúng 1 lần, quá trình này phải trải qua 4 bước bắt tay
    [​IMG]
    Một gói tin có thể được gởi ở bất kỳ QoS nào, và các client cũng có thể subscribe với bất kỳ yêu cầu QoS nào. Có nghĩa là client sẽ lựa chọn QoS tối đa mà nó có để nhận tin. Ví dụ, nếu 1 gói dữ liệu được publish với QoS2, và client subscribe với QoS0, thì gói dữ liệu được nhận về client này sẽ được broker gởi với QoS0, và 1 client khác đăng ký cùng kênh này với QoS 2, thì nó sẽ được broker gởi dữ liệu với QoS2. Một ví dụ khác, nếu 1 client subscribe với QoS2 và gói dữ liệu gởi vào kênh đó publish với QoS0 thì client đó sẽ được broker gởi dữ liệu với QoS0. QoS càng cao thì càng đáng tin cậy, đồng thời độ trễ và băng thông đòi hỏi cũng cao hơn.

    Retain
    Nếu retain được set bằng 1, khi gói tin được publish từ client, broker phải lưu trữ lại gói tin với QoS, và nó sẽ được gởi đến bất kỳ client nào subscribe cùng kênh trong tương lai. Khi một client kết nối tới broker và subscribe, nó sẽ nhận được gói tin cuối cùng có retain = 1 với bất kỳ topic nào mà nó đăng ký trùng. Tuy nhiên, nếu broker nhận được gói tin mà có QoS = 0 và retain = 1, nó sẽ huỷ tất cả các gói tin có retain = 1 trước đó. Và phải lưu gói tin này lại, nhưng hoàn toàn có thể huỷ bất kỳ lúc nào.
    Khi publish một gói dữ liệu đến client, broker phải se retain = 1 nếu gói được gởi như là kết quả của việc subscribe mới của client (giống như tin nhắn ack báo subscribe thành công). retain phải bằng 0 nếu không quan tâm tới kết quả của viẹc subscribe.
    Ngoài ra còn rất nhiều các thông số khác, các bạn có thể tìm hiểu thêm.

    CHỐT HẠ
    Nếu các bạn mới học, có thể sẽ không hiểu hết được nội dung trên, nhưng xin hãy nhớ một cách đơn giản dễ hiểu là... Nếu coi đây là một hệ thống Youtube thì broker chính là server của youtube, mỗi người dùng là một client, mỗi một topic giống như là một kênh nào đó, khi client nhà xuất bản muốn gửi dữ liệu tới server, chúng ta phải publish nó lên, khi client muốn nhận được thông báo từ một kênh nào đó, chúng ta cần subscribe kênh đó. Chất lượng QOS càng cao thì độ tin cậy truyền càng cao.

    ESP8266 VÀ MQTT CƠ BẢN
    Chuẩn bị

    Bài này chúng ta sẽ chỉ điều khiển bật tắt LED có trên KIT đơn giản thông qua một Client MQTT đó là MQTT Box.

    Lập trình ESP8266
    Trước khi lập trình, các bạn cần đảm bảo rằng đã cài Core ESP8266 Arduino, và đã thêm thư viện PubSubClient.
    Đầu tiên là khai báo thư viện, chúng ta sẽ sử dụng 2 thư viện để kết nối Wifi và MQTT:
    Mã:
    #include <ESP8266WiFi.h>
    #include <PubSubClient.h>
    
    Tiếp tục định nghĩa các kết nối:
    Mã:
    const char* ssid = "Ten_Wifi_Ket_Noi";
    const char* password = "Mat_Khau_Wifi_Ket_Noi";
    const char* mqtt_server = "broker.hivemq.com";
    
    ssidpassword là tên và mật khẩu Wifi để ESP8266 kết nối, nhớ rằng chúng ta sử dụng broker public thì Wifi cần phải có mạng để sử dụng.
    mqtt_server chính là broker mà chúng ta cần kết nối đến, ở đây mình muốn điều khiển thông qua mạng internet nên mình sẽ sử dụng một broker public miễn phí đó là broker.hivemq.com với giao thức kết nối tcp/ip, cổng là 1883.
    Tiếp theo chúng ta đi khai báo hai thể hiện của 2 class WifiClient và PubSubClient đó là espClient và client:
    Mã:
    WiFiClient espClient;
    PubSubClient client(espClient);
    
    Bước đầu chúng ta đã khai báo thành công, tiếp theo chúng ta sẽ viết một hàm để kết nối Wifi:
    Mã:
    void setup_wifi() {
      delay(10);
      Serial.println();
      Serial.print("Connecting to ");
      Serial.println(ssid);
    
      WiFi.begin(ssid, password);
    
      while (WiFi.status() != WL_CONNECTED) {
       delay(500);
       Serial.print(".");
      }
    
      Serial.println("");
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
    }
    
    Tiếp theo là hàm callback, hàm này sẽ được gọi khi có dữ liệu tới broker và gửi về client MQTT ESP8266:
    Mã:
    void callback(char* topic, byte* payload, unsigned int length) {
      Serial.print("Message arrived [");
      Serial.print(topic);
      Serial.print("] ");
      for (int i = 0; i < length; i++) {
       Serial.print((char)payload[i]);
      }
      Serial.println();
    
      if ((char)payload[0] == '1') {
       digitalWrite(BUILTIN_LED, LOW);
      } else {
       digitalWrite(BUILTIN_LED, HIGH);
      }
    }
    
    Khi có tin nhắn "1" nhận được, đèn LED trên ESP8266 sẽ phát sáng và khi nhận được khác "1" đèn LED sẽ tắt.
    Tiếp tục, hàm reconnect() cho phép kết nối MQTT khi khởi tạo hoặc kết nối lại nếu bị lỗi đường truyền.
    Mã:
    void reconnect() {
      while (!client.connected()) {
       Serial.print("Attempting MQTT connection...");
    
       String clientId = "ESP8266Client-";
       clientId += String(random(0xffff), HEX);
    
       if (client.connect(clientId.c_str())) {
         Serial.println("connected");
    
         client.publish("phatvu1294/outTopic", "hello world");
         client.subscribe("phatvu1294/inTopic");
       } else {
         Serial.print("failed, rc=");
         Serial.print(client.state());
         Serial.println(" try again in 5 seconds");
         delay(5000);
       }
      }
    }
    
    Client ESP8266 sẽ kết nối tới broker với một tên ngẫu nhiên. Khi client ESP8266 kết nối thành công tới broker, client này sẽ publish một tin nhắn tới topic "phatvu1294/outTopic" đó là "hello world", đồng thời subscribe topic "phatvu1294/inTopic", topic này chờ khi nào có dữ liệu từ broker đến, thông qua callback để chúng ta lấy dữ liệu.
    OK, gần như đã xong, cuối cùng là hai hàm khởi tạo và lặp:
    Mã:
    void setup() {
      digitalWrite(LED_BUILTIN, HIGH);
      pinMode(BUILTIN_LED, OUTPUT);
      Serial.begin(115200);
      setup_wifi();
      client.setServer(mqtt_server, 1883);
      client.setCallback(callback);
    }
    
    void loop() {
      if (!client.connected()) {
       reconnect();
      }
      client.loop();
    }
    
    Hàm setup sẽ cấu hình đầu ra trên LED, khởi tạo Serial tốc độ baud 115200, kết nối Wifi, đặt Server, cổng kết nối và đặt thuộc tính callback.
    Hàm loop sẽ kiểm tra nếu mất kết nối tới broker thì kết nối lại và lặp client liên tục.

    Chuẩn bị trên PC
    Các bạn tải và cài đặt MQTTBox, sau khi cài đặt xong, thì tạo mới một Client, cấu hình với các thông số như sau:
    [​IMG]

    • (1) Tên hiển thị client, các bạn có thể cài đặt bất kỳ
    • (2) Chọn giao thức kết nối, ở đây chọn mqtt/tcp với cổng là 1883, nếu bạn muốn chạy với thư viện Paho Javascript thì chọn là websocket với cổng do nhà cung cấp broker đưa ra.
    • (3) Broker và port MQTT, phải giống với broker trong khi lập trình trên ESP8266
    • (4) Sau khi hoàn thiện các thông số, bấm Save để lưu client
    Sau khi tạo xong client, tiếp theo chúng ta đi truyền nhận dữ liệu, như trong phần lập trình, ngay sau khi client ESP8266 kết nối thành công, lập tức chúng sẽ publish tin nhắn "hello world" tới topic "phatvu1294/outTopic", để nhận được dữ liệu này trên client PC chúng ta sẽ subscribe topic này với chất lượng QOS tùy chọn.
    [​IMG]
    Do trên client đã subcribe topic "phatvu1294/inTopic", để gửi dữ liệu chúng ta sẽ publish từ client PC vào topic này. Khung payload chứa tin nhắn mà chúng ta gửi đến client ESP8266.
    [​IMG]
    Khi vừa kết nối MQTT sẽ có một tin nhắn gửi từ client ESP8266 đến client PC là "hello world". Khi Publish tin nhắn "1" từ client PC thì client ESP8266 sẽ bật đèn LED tích hợp. và ngược lại khi gửi tin nhắn khác "1" đèn LED sẽ hoạt động.
    Như vậy chúng ta đã tìm hiểu thành công về giao thức MQTT thông qua một ví dụ đơn giản... TRong loạt bài tiếp theo chúng ta sẽ đi so sánh hai giao thức RESTful với MQTT, và đi xây dựng ứng dụng điều khiển bằng giọng nói với google Asisstant bằng cả hai giao thức này.

    Video Demo
     

    File đính kèm :

    Last edited: 3/6/19

trang này