Kết nối thiết bị giao thức Mqtt

Tổng quan trang
Lối vào kết nối và quy trình tối thiểu
- Tạo và phát hành sản phẩm MQTT trong quản lý sản phẩm, xác nhận Product ID, mã thiết bị, tài khoản MQTT, mật khẩu và mã ủy quyền thiết bị.
- Thiết bị hoặc MQTTX dùng
clientId,userName,passwordtheo quy ước để kết nối dịch vụ MQTT. - Sau khi kết nối thành công, publish
/info/posttrước, rồi publish/property/posthoặc/event/post. - Phía nền tảng xác nhận đường truyền khép kín qua trạng thái chạy, nhật ký sự kiện, nhật ký lệnh và quy tắc kịch bản trong chi tiết thiết bị.
1. Các bước kết nối
提示
- Mã nguồn SDK phần cứng ESP8266 tham khảo FastBee Arduino SDK
- Nếu định dạng tin nhắn Mqtt của thiết bị là cố định, có thể chuyển tiếp qua Rule Engine để thích ứng với nền tảng
- netty-mqtt hệ thống tự có: hỗ trợ chuyển tiếp topic và nội dung
- Dùng middleware emqx: hỗ trợ chuyển tiếp nội dung, topic có thể chuyển tiếp qua rule engine tự có của emqx
1. Xác thực thiết bị
- Xác thực mã hóa (khuyến nghị)
- Xác thực đơn giản
2. Tương tác thiết bị
- Publish các topic Mqtt liên quan Thing Model, thông tin thiết bị, đồng bộ đồng hồ
- Subscribe các topic Mqtt liên quan Thing Model, nâng cấp thiết bị, đồng bộ đồng hồ
3. Cấu hình mạng AP cho thiết bị (tùy chọn, chỉ thiết bị loại Wifi)
- API phát hiện thiết bị
- API cấu hình thiết bị
2. Xác thực thiết bị
提示
- Kiểu xác thực: S=xác thực đơn giản, E=xác thực mã hóa
- Sau khi sản phẩm bật mã ủy quyền thiết bị, mã ủy quyền không được để trống
- User ID chính là ID của người dùng đăng nhập, dùng User ID khác nhau thì thiết bị thuộc về người dùng khác nhau. Có thể thống nhất dùng tài khoản admin ID 1, sau đó qua cấu hình mạng hoặc quét mã gắn kết để phân bổ thiết bị cho người dùng khác nhau.
- Mã thiết bị có hai cách lấy: 1. Dùng mã thiết bị được sinh khi tạo thiết bị trong hệ thống; 2. Hệ thống chưa tạo thiết bị, phía phần cứng sinh một mã duy nhất làm mã thiết bị, sau khi xác thực hệ thống sẽ tự động đăng ký một thực thể thiết bị (khi thiết bị nhiều, khuyến nghị cách này)
1. Xác thực mã hóa
Lấy mã sản phẩm, tài khoản Mqtt, mật khẩu Mqtt và khóa bí mật sản phẩm trong chi tiết sản phẩm, mật khẩu được mã hóa AES bằng khóa bí mật sản phẩm rồi truyền tới backend; backend dùng khóa bí mật sản phẩm giải mã để xác thực; kết nối máy chủ tin nhắn Mqtt cần cung cấp client ID, tên đăng nhập và mật khẩu duy nhất, định dạng cụ thể như sau:
# Client ID bằng kiểu xác thực + mã thiết bị + mã sản phẩm + User ID
clientId = E & deviceNumber & productId & userId
# Tên đăng nhập
userName = fastbee
# Mật khẩu
password = mật khẩu mqtt & thời gian hết hạn
password = mật khẩu mqtt & thời gian hết hạn & mã ủy quyền thiết bị (định dạng khi sản phẩm bật ủy quyền thiết bị)- Client ID bằng kiểu xác thực + mã thiết bị + mã sản phẩm + User ID, nối bằng ký hiệu
&, giữa không có dấu cách; - Tên đăng nhập nhập trực tiếp tài khoản Mqtt
- Mật khẩu bằng mật khẩu Mqtt + thời gian hết hạn mật khẩu + mã ủy quyền thiết bị (tùy chọn), rồi tiến hành mã hóa AES. Để an toàn, thời gian hết hạn mật khẩu nên trong vòng 24 giờ, dùng định dạng timestamp, chính xác đến mili giây.
Ví dụ thông tin cấu hình tài khoản:
clientId = "E&D68329VL588&2&1"
userName = "fastbee"
password = "/W2A/4MK+9cEGBhyBDgr2K5c62DAjAK4m0b5pvwxX6FFMzI3h1pUmaDY3BH1P2mI"2. Xác thực đơn giản
Lấy tài khoản Mqtt và mật khẩu Mqtt trong chi tiết sản phẩm, khuyến nghị dùng trong môi trường kiểm thử. Định dạng client ID Mqtt giống xác thực mã hóa, trong đó E đổi thành S.
# Client ID bằng kiểu xác thực + mã thiết bị + mã sản phẩm + User ID
clientId = S & deviceNumber & productId & userId
# Tên đăng nhập
userName = fastbee
# Mật khẩu
password = mật khẩu mqtt
password = mật khẩu mqtt & mã ủy quyền thiết bị (định dạng khi sản phẩm bật ủy quyền thiết bị)Ví dụ thông tin cấu hình tài khoản:
# Client ID bằng kiểu xác thực + mã thiết bị + mã sản phẩm + User ID
clientId = "S&D68329VL588&2&1"
userName = "fastbee"
password = "PHYFED93WSFF1DAS"
password = "PHYFED93WSFF1DAS&ADBFCC8934864B26B55658C66F562AC5" (định dạng khi sản phẩm bật ủy quyền thiết bị)3. Thiết bị lấy thời gian hiện tại
Để lấy thời gian hiện tại, có thể gọi API thời gian NTP của hệ thống, khi request API gửi số mili giây chạy hiện tại của thiết bị, trả về thời gian gửi của thiết bị, thời gian nhận của server, thời gian gửi của server. Sau đó lấy số mili giây chạy hiện tại của thiết bị làm thời gian nhận của thiết bị. Cuối cùng dùng công thức tính ra thời gian hiện tại của thiết bị, thời gian phải lấy mili giây làm đơn vị. Công cụ timestamp trực tuyến
# deviceSendTime là số mili giây chạy hiện tại của thiết bị
http://localhost:8080/iot/tool/ntp?deviceSendTime=35768
# Tính thời gian
thời gian hiện tại của thiết bị = (thời gian nhận server + thời gian gửi server + thời gian nhận thiết bị - thời gian gửi thiết bị) / 24. Giải thích mã hóa AES
Áp dụng chế độ mã hóa CBC của AES, offset cố định là wumei-smart-open 16 ký tự, đầu ra là Base64, mật khẩu dùng để mã hóa là khóa bí mật sản phẩm. Kiểm thử có thể dùng: công cụ mã hóa/giải mã trực tuyến
Chế độ mã hóa: CBC
Padding: pkcs5padding
Khối dữ liệu: 128 bit
Offset: wumei-smart-open
Đầu ra: base64
Mật khẩu: khóa bí mật sản phẩm tương ứng trong hệ thống
Nội dung mã hóa: mật khẩu mqtt & expireTime & mã ủy quyền(tùy chọn)3. Tương tác thiết bị
{productId} đại diện Product ID, {deviceNum} đại diện mã thiết bị. Lấy Product ID và mã thiết bị qua web, nếu dùng thêm thiết bị tự động, mã thiết bị có thể dùng mã duy nhất hoặc dùng địa chỉ MAC của thiết bị, sau khi thiết bị xác thực thành công sẽ tự động thêm một thực thể thiết bị tương ứng ở backend.
1. Topic subscribe
| Topic | Mô tả |
|---|---|
| /{productId}/{deviceNum}/function/get | Subscribe lệnh nền tảng |
| /{productId}/{deviceNum}/info/get | Subscribe thông tin thiết bị (subscribe tới topic này thì publish thông tin thiết bị) |
| /{productId}/{deviceNum}/monitor/get | Subscribe tín hiệu giám sát thời gian thực (theo số lần và khoảng cách giám sát, rồi publish dữ liệu giám sát) |
| /{productId}/{deviceNum}/ntp/get | Subscribe đồng bộ đồng hồ (tùy chọn, dùng để đồng bộ thời gian hiện tại của thiết bị) |
| /{deviceNum}/http/upgrade/set | Subscribe nâng cấp OTA theo cách HTTPS (mới) |
| /{deviceNum}/fetch/upgrade/set | Subscribe nâng cấp OTA theo cách gói nhị phân (mới) |
| /{productId}/{deviceNum}/ota/get | Subscribe nâng cấp thiết bị (cũ) |
| /{productId}/{deviceNum}/property/get | 2.x ngừng dùng Subscribe thuộc tính (server publish, thiết bị subscribe) |
| /{productId}/{deviceNum}/property-online/get | 2.x ngừng dùng Subscribe thuộc tính (chế độ online, phía người dùng publish, thiết bị subscribe) |
| /{productId}/{deviceNum}/function-online/get | 2.x ngừng dùng Subscribe chức năng (chế độ online, phía người dùng publish, thiết bị subscribe) |
2. Topic publish
| Topic | Mô tả |
|---|---|
| /{productId}/{deviceNum}/property/post | Publish dữ liệu (hiển thị thời gian thực, dữ liệu thuộc tính/chức năng và giám sát, có thể hẹn giờ báo dữ liệu giám sát) |
| /{productId}/{deviceNum}/info/post | Publish thông tin thiết bị |
| /{productId}/{deviceNum}/event/post | Publish sự kiện |
| /{productId}/{deviceNum}/monitor/post | Publish dữ liệu giám sát thời gian thực (chỉ dùng cho hiển thị biểu đồ giám sát thời gian thực, không lưu trữ) |
| /{productId}/{deviceNum}/ntp/post | Publish đồng bộ đồng hồ (tùy chọn) |
| /{deviceNum}/http/upgrade/reply | Phản hồi nâng cấp OTA theo cách HTTPS (mới) |
| /{deviceNum}/fetch/upgrade/reply | Phản hồi nâng cấp OTA theo cách gói nhị phân (mới) |
| /{productId}/{deviceNum}/upgrade/reply | Phản hồi nâng cấp OTA (cũ) |
| /{productId}/{deviceNum}/function/post | 2.x ngừng dùng Publish chức năng (hiển thị thời gian thực) |
3. Định dạng dữ liệu
Thiết bị và hệ thống tương tác bằng định dạng JSON
- Subscribe thông tin thiết bị, topic tương ứng:
/info/get
# Mô tả: sau khi subscribe được thông tin thiết bị, publish thông tin thiết bị, giải quyết vấn đề đồng bộ trạng thái thiết bị
# Nội dung tin nhắn thiết bị rỗng- Publish thông tin thiết bị, topic tương ứng:
/info/post
# Mô tả: 1. Sau khi thiết bị cấp nguồn thì publish thông tin thiết bị; 2. Sau khi thiết bị nhận được lệnh thông tin thiết bị thì publish thông tin thiết bị
# rssi Tín hiệu thiết bị (tín hiệu rất tốt[-55— 0], tín hiệu tốt[-70— -55], tín hiệu trung bình[-85— -70], tín hiệu kém[-100— -85])
# status Trạng thái thiết bị, cố định là 3, nghĩa là online
# firmwareVersion Phiên bản firmware
# userId ID người dùng, có thể đặt User ID là 1 (quản trị viên), khi cấu hình mạng sẽ phân bổ thiết bị cho người dùng cụ thể.
# longitude Tùy chọn, kinh độ, cần tải lên khi dùng định vị thiết bị
# latitude Tùy chọn, vĩ độ, cần tải lên khi dùng định vị thiết bị
# iccid Tùy chọn, số ICCID của thẻ SIM IoT, tải lên khi thiết bị dùng thẻ SIM IoT
# cardPlatformId Tùy chọn, tương ứng mã nền tảng thẻ trong quản lý thẻ SIM IoT, tải lên khi thiết bị tải số ICCID lên, nếu không tải thì mặc định duyệt tất cả nền tảng thẻ để truy vấn
# summary Tùy chọn, tóm tắt, thông tin cấu hình của thiết bị..., định dạng json, đối tượng có thể tùy biến
{
"rssi": -43,
"firmwareVersion": 1.2,
"status": 3,
"userId": 2,
"longitude": 0,
"latitude": 0,
"iccid": 898604293620C0000970,
"cardPlatformId": 0,
"summary": {
"name": "FastBee",
"chip": "ESP8266",
"author": "fastbee",
"deliveryTime": "2023-06-06",
"activeTime": "2022-10-01"
}
}- Subscribe giám sát thời gian thực, topic tương ứng:
/monitor/get
# Mô tả: subscribe được tin nhắn giám sát thời gian thực, theo số lượng và khoảng cách publish dữ liệu giám sát thời gian thực
# count Số lượng
# interval Khoảng cách, đơn vị mili giây
{
"count": 60,
"interval": 1000
}- Publish giám sát thời gian thực, topic tương ứng:
/monitor/post
# Mô tả: theo tin nhắn giám sát thời gian thực subscribe được, publish dữ liệu giám sát với số lượng và khoảng cách chỉ định
# id Định danh, giám sát thời gian thực là thuộc tính trong Thing Model, xem định danh trong chi tiết sản phẩm, tương ứng giá trị id
# value Giá trị thiết bị thu thập, chỉ có thể là số nguyên hoặc số thập phân, truyền dạng chuỗi
# remark Có thể để trống hoặc dùng thời gian hiện tại của thiết bị
[{
"id": "temperature",
"value": "27.43",
"remark": ""
}, {
"id": "humidity",
"value": "32.18",
"remark": ""
}]- Subscribe lệnh nền tảng, topic tương ứng:
/function/get
# Mô tả: thuộc tính, chức năng, sự kiện đều thuộc Thing Model, định nghĩa Json giống nhau. Ví dụ đều subscribe được tin nhắn mở công tắc, xử lý của thiết bị đều là mở công tắc.
# id Định danh, xem Thing Model trong chi tiết sản phẩm, tương ứng định danh Thing Model
# value Giá trị, tương ứng định nghĩa trong Thing Model, truyền dạng chuỗi
# remark Lệnh gửi xuống từ cảnh báo, Scene Linkage và hẹn giờ trên nền tảng có thông tin ghi chú
[{
"id": "gear",
"value": "1",
"remark": "hẹn giờ thiết bị"
},{
"id": "switch",
"value": "0",
"remark": "Scene Linkage kích hoạt"
}]- Publish dữ liệu và sự kiện, topic tương ứng:
/property/post,/event/post
# Mô tả: thuộc tính, chức năng, sự kiện đều thuộc Thing Model, định nghĩa Json giống nhau. Nếu giá trị của `value` là kiểu boolean, giá trị là "0" hoặc "1", đại diện bật/tắt; kiểu enum tương ứng giá trị khóa của mục enum (ví dụ "1", đại diện tốc độ trung); kiểu mảng là chuỗi phân tách bằng dấu phẩy tiếng Anh.
# id Định danh, xem Thing Model trong chi tiết sản phẩm, tương ứng định danh Thing Model
# value Giá trị, tương ứng định nghĩa trong Thing Model, truyền dạng chuỗi
# remark Có thể dùng trực tiếp thông tin ghi chú subscribe được, xem ghi chú đó trong thông tin nhật ký thiết bị
[{
"id": "gear",
"value": "1",
"remark": "đặt tốc độ thành công"
}, {
"id": "switch",
"value": "0",
"remark": "công tắc đã tắt"
}]Giải thích Thing Model liên quan
- ID (định danh) của tất cả Thing Model đều duy nhất, cố gắng không dùng ký tự đặc biệt, chủ yếu dùng chữ cái và số.
- Định dạng ID (định danh) mô hình con dưới Thing Model kiểu đối tượng: parentId_childId, kiểu mảng đối tượng cũng vậy, ID mô hình con thêm ID cấp cha phân tách bằng gạch dưới, ví dụ:
# ID Thing Model cấp cha: power
# ID Thing Model cấp con: power_light- Thing Model kiểu mảng (bao gồm kiểu mảng đối tượng) chỉ có một ID (định danh), giá trị Thing Model là mảng (lưu dạng chuỗi phân tách bằng dấu phẩy tiếng Anh), ví dụ chuỗi
98,100,50. Vì vậy báo thuộc tính/chức năng/sự kiện kiểu mảng tương đối đặc biệt, ID (định danh) phải bắt đầu bằngarray_chỉ số, chỉ số là hai chữ số, ví dụ:shell# Định dạng mảng thường `array_00_RGB` # Định dạng mảng đối tượng `array_00_power_switch` # Chỉ số 00 đại diện phần tử thứ nhất trong mảng, 02 / 03 ... 98 / 99 và cứ thế, độ dài mảng không quá 100 [{ "id": "array_01_power_switch", // array_01 làm tiền tố, biểu thị phần tử thứ hai trong mảng "value": "1", "remark": "" }]
- Publish đồng bộ đồng hồ, topic tương ứng:
/ntp/post
# Mô tả: tùy chọn, publish tin nhắn đồng bộ đồng hồ, sau khi server subscribe được sẽ gửi tin nhắn đồng bộ đồng hồ xuống
# deviceSendTime Thời gian gửi của thiết bị
{
"deviceSendTime": "1592361428000"
}- Subscribe đồng bộ đồng hồ, topic tương ứng:
/ntp/get
# Mô tả: tùy chọn, subscribe được tin nhắn đồng bộ đồng hồ, tính thời gian hiện tại = (thời gian nhận server + thời gian gửi server + thời gian nhận thiết bị - thời gian gửi thiết bị) / 2
# deviceSendTime Thời gian gửi của thiết bị
# serverRecvTime Thời gian nhận của server
# serverSendTime Thời gian gửi của server
{
"deviceSendTime": "1592361428000",
"serverSendTime": "1592366463548",
"serverRecvTime": "1592366463548"
}- Subscribe nâng cấp OTA, topic tương ứng:
/http/upgrade/sethoặc/fetch/upgrade/set
# Mô tả: sau khi subscribe được tin nhắn nâng cấp thiết bị, theo địa chỉ tải firmware, request Http tải firmware và nâng cấp
# version Số phiên bản, có thể dùng khớp phiên bản firmware
# downloadUrl Địa chỉ tải firmware
{
"taskId": 26,
"url": "/profile/iot/1/2024-0824-001954.bin",
"version": 1.2,
"status": 1
}4. Cấu hình mạng thiết bị (tùy chọn, chỉ thiết bị loại Wifi)
提示
- Thiết bị dùng cấu hình mạng AP, khi cấu hình mạng, thiết bị bật hotspot và cung cấp dịch vụ web. Đầu di động truyền thông tin cấu hình qua dịch vụ web mà thiết bị cung cấp.
- Địa chỉ hotspot phía thiết bị đặt là: 192.168.4.1
- Có thể tham khảo SDK dự án
1. API phát hiện thiết bị
Phía thiết bị cung cấp API phát hiện, đầu di động qua API này hiện thực chức năng phát hiện thiết bị, áp dụng cấu hình mạng một thiết bị.
# Phương thức request: Get
# Địa chỉ API: http://192.168.4.1/status
# Tham số: không có
# Thông tin trả về: mã trạng thái HTTP 200 nghĩa là phát hiện được thiết bị2. API cấu hình
Phía thiết bị cung cấp API cấu hình để lấy thông tin, đầu di động gửi thông tin cấu hình, tham số truyền theo cách Url, trong đó SSID, password, userId là tham số bắt buộc.
# Phương thức request: Post
# Địa chỉ API: http://192.168.4.1/config
# Tham số như sau:
SSID # Tên Wifi
password # Mật khẩu Wifi
userId # Mã/ID người dùng
deviceNum # Tùy chọn, mã thiết bị
authCode # Tùy chọn, mã ủy quyền
extra # Tùy chọn, thông tin bổ sung
# Thông tin trả về: mã trạng thái HTTP 200 nghĩa là cấu hình mạng thành công; mã trạng thái HTTP 500 nghĩa là cấu hình mạng thất bại;
# Ví dụ URL request, thiết bị lấy tham số qua Url này, lưu vào thiết bị
http://192.168.4.1/config?SSID=mywifi&password=mywifipassword&userId=1
http://192.168.4.1/config?SSID=mywifi&password=mywifipassword&userId=1&deviceNum=D68329VL588&authCode=6688&extra=open5. Checklist nghiệm thu liên hợp
Khuyến nghị nghiệm thu kết nối thiết bị MQTT theo thứ tự sau, tránh chỉ thấy kết nối thành công nhưng dữ liệu nghiệp vụ không vào nền tảng.
| Bước | Nội dung nghiệm thu | Biểu hiện thành công |
|---|---|---|
| 1 | Sản phẩm đã phát hành | Trạng thái sản phẩm là đã phát hành |
| 2 | MQTTX hoặc thiết bị kết nối | Bảng điều khiển EMQX xuất hiện kết nối client |
| 3 | Trạng thái thiết bị | Chi tiết thiết bị hiển thị online hoặc thời gian online gần nhất được làm mới |
| 4 | /info/post | Các trường thông tin thiết bị, tín hiệu, phiên bản... được cập nhật |
| 5 | /property/post | Trạng thái chạy hiển thị giá trị thuộc tính Thing Model |
| 6 | /event/post | Nhật ký sự kiện xuất hiện sự kiện báo lên |
| 7 | /function/get | Thiết bị nhận được lệnh sau khi nền tảng gửi xuống |
| 8 | Trả kết quả về | Thiết bị trả về theo kết quả gửi xuống, trạng thái nền tảng được làm mới |
| 9 | Quy tắc/kịch bản | Các quy tắc, kịch bản, cảnh báo liên quan có thể được kích hoạt |
6. Lỗi thường gặp
Kết nối bị từ chối
Ưu tiên kiểm tra:
- Cổng
1883của máy chủ đã mở chưa. - EMQX hoặc dịch vụ MQTT tích hợp sẵn đã khởi động chưa.
clientIdcó khớp định dạngS&mã thiết bị&Product ID&User IDhoặc định dạng xác thực mã hóa không.- Sản phẩm có bật ủy quyền thiết bị không, sau khi bật mật khẩu có chứa mã ủy quyền không.
- Thiết bị có bị vô hiệu hóa không.
Thiết bị online nhưng thuộc tính không làm mới
Ưu tiên kiểm tra:
- Topic publish có phải
/{productId}/{deviceNum}/property/postkhông. productIdcó dùng Product ID, chứ không phải mã sản phẩm không.deviceNumcó hoàn toàn khớp với mã thiết bị không.- Message body có phải mảng không.
idcó hoàn toàn khớp với định danh Thing Model không.valuecó phù hợp kiểu dữ liệu không.
Nền tảng gửi xuống nhưng thiết bị không nhận được
Ưu tiên kiểm tra:
- Thiết bị đã subscribe
/{productId}/{deviceNum}/function/getchưa. - MQTTX hoặc kết nối thiết bị còn online không.
- Thing Model có phải chức năng ghi được hoặc thuộc tính gửi xuống được không.
- Người dùng có quyền xem chi tiết thiết bị và gửi lệnh không.
- Device shadow có ảnh hưởng phán đoán hiện tại không.
Quy tắc hoặc cảnh báo không kích hoạt
Ưu tiên kiểm tra:
- Dữ liệu thiết bị có vào trạng thái chạy của nền tảng không.
- Sản phẩm, thiết bị, biến mà kịch bản hoặc quy tắc gắn với có đúng không.
- Biểu thức điều kiện có nhất quán với kiểu giá trị báo lên không.
- Cấu hình cảnh báo đã bật chưa.
7. Lối vào phát triển thứ cấp
| Loại | Đường dẫn hoặc API | Mô tả |
|---|---|---|
| Xác thực MQTT | /iot/tool/mqtt/auth, /iot/tool/mqtt/webhook | Lối vào xác thực EMQX và Webhook |
| API thiết bị | /iot/device | Thiết bị online, trạng thái, chi tiết |
| API Thing Model | /iot/model | Định nghĩa và ánh xạ mô hình |
| Mô-đun giao thức | springboot/fastbee-protocol | Phân tích và chuyển đổi tin nhắn MQTT |
| Mô-đun dữ liệu | springboot/fastbee-iot-data | Xử lý dữ liệu thuộc tính, sự kiện, giám sát |
| Trang frontend | vue3/src/views/iot/device | Chi tiết thiết bị, trạng thái chạy, debug dữ liệu |
| API frontend | vue3/src/api/iot | Đóng gói request thiết bị và Thing Model |


