Hiểu rõ về mô hình Pub/Sub trong giao thức MQTT thông qua các ví dụ thực hành

Tiếp nối hai bài viết “Giao thức MQTT: Ưu điểm và ứng dụng” và “Tìm hiểu về định dạng của một số gói tin MQTT”, ở bài viết này mình sẽ hướng dẫn các bạn thực hiện kết nối đến một MQTT Broker, publish một gói tin đến topic và subscribe topic từ một TCP Client bất kỳ.

Mình sử dụng Eclipse Mosquitto làm MQTT Broker, đây là một MQTT Broker mã nguồn mở cho phép thiết bị truyền nhận dữ liệu theo giao thức MQTT version 3.1, 3.1.1 và 5.0. Các bạn có thể tham khảo cách cài đặt Eclipse Mosquitto trên Windows tại đây hoặc nếu các bạn đang sử dụng một MQTT Broker khác thì các bạn có thể bỏ qua bước này.

Để có thể biểu diễn rõ về cơ chế truyền nhận gói tin qua giao thức MQTT giữa các Client, và định dạng của một số gói tin MQTT, mình sẽ sử dụng phần mềm Hercules SETUP utility để đóng vai trò là một TCP Client kết nối đến MQTT Broker và thực hiện publish một gói tin hoặc subscribe một topic cụ thể. Các bạn tải phần mềm tại đây.

Sau khi các bạn đã hoàn thành xong các bước cài đặt MQTT Broker và phần mềm Hercules SETUP utility, chúng ta cùng bắt tay thực hành:

1. Thực hiện kết nối TCP đến máy chủ chứa MQTT Broker 

– Mở phần mềm Hercules SETUP utility, sau đó chọn tab TCP Client

– Tại ô Module IP các bạn điền địa chỉ của máy chủ chứa MQTT Broker. Ở đây mình đã cài đặt Eclipse Mosquitto trên máy tính nên mình sẽ điền địa chỉ mặc định: 127.0.0.1 hoặc điền localhost

– Tại ô Port các bạn điền 1883

– Click vào nút Connect

* Lưu ý: Tất cả dữ liệu trong các gói tin MQTT đều được biểu diễn dưới dạng mã hexa. Để có thể xem dữ liệu dưới dạng mã hexa trên phần mềm Hercules SETUP utility, các bạn thực hiện các bước sau:

– Kích chuột phải vào giao diện hiển thị và chọn Special Chars -> Hexadecimal

– Tiếp tục kích chuột phải và chọn HEX Enable

2. Thiết lập kết nối đến Broker bằng cách gửi gói tin CONNECT

Gói tin CONNECT gồm các trường Fixed Header, Variable Header và Payload:

– Fixed Header: 10 16

* Lưu ý: Để hiểu rõ về ý nghĩa các bit trong từng byte của mỗi gói tin MQTT Control, các bạn tham khảo tại đây.

– Variable Header:

  • Protocol name: 00 04 4D 51 54 54. Với MQTT Version 3.1.1 thì protocol name là “MQTT”

  • Protocol level: 04
  • Connect Flags: 02

  • Keep-alive: 01 2C. Thời gian giữ kết nối: 300s

– Payload:

  • Cliend ID: 00 0A 54 43 50 43 6C 69 65 6E 74 31. Ở đây mình sẽ đặt tên là “TCPClient1”, các bạn có thể đặt tên khác tùy thích

–> Nội dung gói tin CONNECT: 10 16 00 04 4D 51 54 54 04 02 01 2C 00 0A 54 43 50 43 6C 69 65 6E 74 31

Client đợi gói tin CONNACK phản hồi từ Broker để kiểm tra kết nối được thiết lập thành công hay thất bại. Gói tin CONNACK gồm các trường Fixed Header và Variable Header:

– Fixed header: 20 02

– Variable header: 00 00

–> Nội dung gói tin CONNACK: 20 02 00 00

3. Client gửi gói tin PUBLISH hoặc SUBSCRIBE đến Broker

Bây giờ mình sẽ mở thêm một giao diện phần mềm Hercules nữa để đóng vai trò là TCP Client thứ 2, có Client ID là “TCPClient2”.  TCPClient1 thực hiện subscribe topic “sensor/value” và TCPClient2 thực hiện publish nội dung “value = 123” đến topic “sensor/value”. Quá trình publish/subscribe được biểu diễn như hình sau:

B1. Sau khi thiết lập kết nối TCP đến máy chủ chứa Broker, TCPClient2 thực hiện kết nối đến Broker bằng cách gửi gói tin CONNECT và đợi Broker phản hồi gói tin CONNACK

B2. Bước này đã được thực hiện ở mục 1 và mục 2 ở trên, tuy nhiên nếu vượt quá thời gian giữ kết nối (300s) mà không có bất kỳ hoạt động nào diễn ra giữa TCPClient1 và Broker thì kết nối này sẽ bị ngắt. Lúc này bạn hãy thực hiện lại các thao tác ở 2 mục trên để mở một kết nối mới.

B3. TCPClient1 thực hiện gửi gói tin SUBSCRIBE đến Broker để đăng ký theo dõi topic “sensor/value” và đợi Broker phản hồi về gói tin SUBACK

Gói tin SUBSCRIBE gồm các trường Fixed Header, Variable Header và Payload. Tương tự cách phân tích như gói tin CONNECT và CONNACK ở trên ta có gói tin SUBSCRIBE như sau:

– Fixed Header: 82 11

– Variable Header:

  • Packet Identifier: 00 0A

– Payload:

  • Topic Filter: 00 0C 73 65 6E 73 6F 72 2F 76 61 6C 75 65 (“sensor/value”)
  • QoS: 00

–> Nội dung gói tin SUBSCRIBE: 82 11 00 0A 00 0C 73 65 6E 73 6F 72 2F 76 61 6C 75 65 00

Sau khi Client gửi gói tin SUBSCRIBE, Broker sẽ phản hồi về gói tin SUBACK. Gói tin SUBACK gồm các trường Fixed Header, Variable Header và Payload:

– Fixed Header: 90 03

– Variable Header:

  • Packet Identifier: 00 0A

– Payload:

  • Return code: 00

B4. TCPClient2 gửi gói tin PUBLISH với nội dung “value = 123” đến topic “sensor/value” 

Gói tin PUBLISH gồm các trường Fixed Header, Variable Header và Payload. Với tên topic là “sensor/value”, nội dung bảng tin là “value=123”, DUP flag = 0, QoS level = 0, Retain = 0, ta có gói tin PUBLISH như sau:

– Fixed Header: 30 17

– Variable Header:

  • Topic name: 00 0C 73 65 6E 73 6F 72 2F 76 61 6C 75 65

– Payload:

  • Message: 76 61 6C 75 65 3D 31 32 33

–> Nội dung gói tin PUBLISH: 30 17 00 0C 73 65 6E 73 6F 72 2F 76 61 6C 75 65 76 61 6C 75 65 3D 31 32 33

B5. Vì TCPClient1 đã subscribe topic “sensor/value” nên sau khi TCPClient2 thực hiện publish gói tin có nội dung trường Payload là “value=123” thì TCPClient1 cũng sẽ nhận được nội dung trên

 

Trên đây mình đã hướng dẫn các bạn cách thực hiện truyền nhận gói tin qua giao thức MQTT giữa các Client. Hy vọng qua các ví dụ đơn giản trong bài viết sẽ giúp các bạn có thể hiểu và tự mình tạo ra các ứng dụng sử dụng giao thức MQTT thật tuyệt vời nhé.

Chúc các bạn thành công!

TAPIT ARM R&D

[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]

  • Xem thêm Tổng hợp các bài hướng dẫn Lập trình vi điều khiển STM32 tại đây.
  • Xem thêm Tổng hợp hướng dẫn Internet of Things với NodeMCU ESP8266 và ESP32 tại đây.