发帖
0 0 0

MQTT 入门与实战:从协议原理到两块 WB2 对联

XEMOWO
中级会员

4

主题

2

回帖

262

积分

中级会员

积分
262
小安AI 33 0 昨天 16:09

📡 MQTT 入门与实战:从协议原理到两块 WB2 对联

两块 Ai-WB2 开发板 · 一个 MQTT Broker · 板 A 发、板 B 收、收到就闪灯

Ai-WB2 MQTT 3.1.1 RISC-V FreeRTOS


📖 一、什么是 MQTT

一句话定义

MQTT(Message Queuing Telemetry Transport)是一种基于发布/订阅模型的极轻量级消息协议,专为低带宽、高延迟、不可靠网络下的物联网设备而设计。

1999 年诞生 IBM 发明 最初用于石油管道监控 如今是 IoT 事实标准

它解决什么问题

假如你有 1000 个温度传感器分布在一个城市里。如果用 HTTP:

每个传感器每 5 秒问一次服务器:"有指令吗?"
服务器 99% 的时间回答:"没有。"
浪费带宽、浪费电量、响应还慢。

这叫 轮询(Pull)。MQTT 反过来——推送(Push)

传感器连上 Broker,安静等着。
控制台发出"全部上报" → Broker 瞬间推给 1000 个传感器。
省电、省带宽、实时。

HTTP vs MQTT

维度 HTTP MQTT
通信模型 请求/响应(客户端拉) 发布/订阅(服务器推)
连接方式 短连接,每次握手 TCP 长连接,一次复用
最小报文 几百字节 仅 2 字节
消息方向 单向 双向
功耗 每次完整 TCP 握手 维持心跳即可
适用场景 Web、REST API IoT、智能家居、车联网

🧱 二、MQTT 架构:三个角色

MQTT 的世界只有三种角色。理解它们就理解了 MQTT:

graph LR A[📢 Publisher · 发布者] -->|"PUBLISH /home/temp"| B[🏢 Broker · 消息代理] B -->|FORWARD| C[📥 Subscriber A · 手机App] B -->|FORWARD| D[📥 Subscriber B · 监控大屏]
角色 英文 职责 打个比方
🏢代理 Broker 接收所有消息、按主题路由、转发给订阅者 快递中转站
📢发布者 Publisher 往指定 Topic 发消息,不知道谁在收 寄件人
📥订阅者 Subscriber 订阅感兴趣的 Topic,有新消息就收到 收件人

🎯 核心设计哲学

Publisher 和 Subscriber 完全解耦。双方只和 Broker 对话。
你可以随时增删设备,系统不受任何影响。


🏷️ 三、Topic:消息的门牌号

Topic 是一个 UTF-8 字符串,用 / 分层,和文件路径一样。每条消息必须带一个 Topic,Broker 据此决定转发给谁。

✅ 推荐 vs ❌ 不推荐

✅ 好的 Topic ❌ 差的 Topic 原因
home/bedroom/temp /temp 不要 / 开头
WB2 temp001 层级化便于扩展
building/3F/light builDing_3F_light_Data 简短清晰

🌟 通配符:一次订阅一类消息

符号 作用 匹配范围 举例
+ 通配一层 只替代一个层级 home/+/temphome/bedroom/temp
# 通配所有后续层 从当前位置往后全部 home/#home 下一切

⚠️ # 必须是最后一个字符。home/#/temp 非法。


🛡️ 四、QoS:消息可靠性三档

不是越高越好,是越合适越好

0️⃣ QoS 0 · 最多一次

发完就忘。不等确认。丢了就丢了。
温湿度定时上报,丢几条不影响大局。

1️⃣ QoS 1 · 至少一次 ⭐ 最常用

发出 → 等对方回 PUBACK 确认。没收到确认就重发。
保证不丢,但可能重复。开关灯、开门锁。

2️⃣ QoS 2 · 仅一次

PUBLISH → PUBREC → PUBREL → PUBCOMP。四步握手。
不丢不重。支付扣款,多扣一次就破产了。

QoS 保证 开销 典型场景
0 不保证 最低 传感器定时上报
1 不丢,可能重复 中等 指令下发、开关控制
2 不丢不重 最高 支付、计费

🎯 实战铁律:99% 场景 QoS 0 或 1。你的项目,QoS 1 够用。


📚 五、其他重要概念

概念 一句话解释 典型用法
❤️Keep Alive 定期心跳。超时没心跳,Broker 判你离线 每 60 秒自动 PINGREQ/PINGRESP
💀Last Will 设备非正常断线时,Broker 代发的一条消息 连上后发 online,遗嘱设 offline
🧹Clean Session true=断线全忘,false=记住订阅和未收消息 电池设备用 true,可靠设备用 false
📌Retained Broker 保留指定 Topic 的最后一条消息 新订阅者一上来就能收到当前温度

🔬 六、实战:两块 WB2 对联

理论知识讲完。下面用两块 Ai-WB2 开发板验证一切。

硬件准备

  • 🔵 Ai-WB2 开发板 (BL602 RISC-V) × 2
  • 🔌 USB Type-C 数据线× 2
  • 📶 可上网的 Wi-Fi

两块 WB2 模组合照

目标架构

graph TD B[🏢 Broker · mqtt.xemowo.top] A[🔵 板 A · Publisher] -->|"PUBLISH /WB2 每5秒一条"| B B -->|"FORWARD /WB2"| C[🟢 板 B · Subscriber] C -->|收到消息| D[💡 RGB 闪绿 100ms]

消息流程序列

sequenceDiagram participant A as 🔵 板 A (发布者) participant B as 📡 Broker participant C as 🟢 板 B (订阅者) A->>B: CONNECT A->>B: SUBSCRIBE /WB2 C->>B: CONNECT C->>B: SUBSCRIBE /WB2 Note over A,C: 两边就绪 loop 每 5 秒 A->>B: PUBLISH /WB2 "TEST1" B-->>A: PUBACK B->>C: FORWARD "TEST1" Note over C: 💡 闪绿 100ms → 熄 end

🔵 板 A · 定时发布者

static int g_count = 0;

/* FreeRTOS 定时器:每 5 秒触发 */
static void pub_cb(TimerHandle_t x)
{
    char msg[32];
    snprintf(msg, sizeof(msg), "TEST%d", ++g_count);

    axk_mqtt_client_publish(g_client, "WB2", msg, 0, 1, 0);
    printf("📤 [A] → %s\r\n", msg);
}

/* Broker 连上 → 订阅 → 启动定时器 */
static axk_err_t on_mqtt(axk_mqtt_event_handle_t e)
{
    if (e->event_id == MQTT_EVENT_CONNECTED)
        axk_mqtt_client_subscribe(e->client, "WB2", 0);

    if (e->event_id == MQTT_EVENT_SUBSCRIBED) {
        TimerHandle_t t = xTimerCreate("pub",
            pdMS_TO_TICKS(5000), pdTRUE, NULL, pub_cb);
        xTimerStart(t, 0);
        printf("✅ [A] 开始定时发布\r\n");
    }
    return AXK_OK;
}

上电 → WiFi → Broker → 订阅 WB2 → 每 5 秒发 TEST1 TEST2 TEST3


🟢 板 B · 订阅者 + RGB 反馈

static TimerHandle_t g_led_timer;   /* 100ms 后自动关灯 */

static void led_off(TimerHandle_t x) {
    ws2812_set_pixel_color(0, 0, 0, 0);
    ws2812_show_leds();
}

static axk_err_t on_mqtt(axk_mqtt_event_handle_t e)
{
    if (e->event_id == MQTT_EVENT_CONNECTED)
        axk_mqtt_client_subscribe(e->client, "WB2", 0);

    if (e->event_id == MQTT_EVENT_DATA) {
        printf("📥 [B] ← %.*s\r\n", e->data_len, e->data);

        ws2812_set_pixel_color(0, 0x00, 0xFF, 0x00);  /* 绿 */
        ws2812_show_leds();
        xTimerStart(g_led_timer, 0);                   /* 100ms 熄 */
    }
    return AXK_OK;
}

上电 → WiFi → Broker → 订阅 WB2 → 安静等 → 收到 → 💡 闪 → 继续等


烧录 & 运行

cd applications/xemowo/XEMOWO_TEST1
export BL60X_SDK_PATH=~/Ai-Thinker-WB2

make -j8                                  # 编译

make flash p=/dev/ttyUSB0 b=921600        # 烧板 A
make flash p=/dev/ttyUSB1 b=921600        # 烧板 B

运行效果

两块板各自的串口输出(115200 波特率):

时间 🔵 板 A 串口 🟢 板 B 串口 板 B LED
+5s 📤 → TEST1 📥 ← TEST1 💡
+10s 📤 → TEST2 📥 ← TEST2 💡
+15s 📤 → TEST3 📥 ← TEST3 💡
+20s 📤 → TEST4 📥 ← TEST4 💡

两块板串口同时输出

🎉 一条 publish 调用,穿越房间,变成另一块板上的物理绿光。

PC 端验证

也可以用电脑上的 MQTT 客户端和板子互动:

方向 截图
💻 电脑发消息到 /WB2 电脑发送MQTT消息
📡 板子收到电脑发来的消息 板子收到MQTT消息

✅ 七、知识清单

  • MQTT = Push(服务器推),不是 HTTP 的 Pull(客户端拉)
  • Broker 只管中转 — Publisher 和 Subscriber 完全解耦
  • Topic 层级命名,+ 通配一层,# 通配所有
  • QoS 0(不管)/ 1(确认)/ 2(四步握手)
  • Keep Alive 心跳 / Last Will 遗嘱 / Retained 保留消息
  • FreeRTOS 定时器驱动周期发布
  • 一条 MQTT 消息 = RGB 闪绿 — 协议变成了可见的光

🚀 八、下一步

方向 怎么做 效果
🔒 TLS 加密 mqtt://mqtts:// 数据不再明文
📊 JSON 载荷 Payload 改 {"temp":25.5} 结构化数据
🔄 双向通信 B 收到后回一条给 A 形成闭环
💀 遗嘱消息 断线时 Broker 自动通知 全网感知设备状态
📱 手机接入 MQTTX App 连同一 Broker 手机和板子聊天
☁️ 云平台 对接阿里云 IoT / AWS IoT Core 数据实时可视化

"A single protocol, from the sensor on the wall to the dashboard in the cloud."

Andy Stanford-Clark, MQTT 发明人


Ai-WB2 (BL602 RISC-V) · Broker: mqtt.xemowo.top · 代码: applications/xemowo/XEMOWO_TEST1/

──── 0人觉得很赞 ────

使用道具 举报

您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 31193 个
  • 话题数: 42275 篇