【物联网】MQTT / Broker / Topic 是什么?

发布于:2025-08-31 ⋅ 阅读:(20) ⋅ 点赞:(0)

1) MQTT / Broker / Topic 是什么?在你项目里怎么用

  • MQTT 是轻量级发布/订阅消息协议:设备把消息“发布(publish)”到某个主题(topic);任何“订阅(subscribe)”了该主题的客户端都会收到消息;中间的Broker(代理服务器)只负责接收并转发消息。课件明确了这是 IoT 中常用的架构,并给了 Publish/Subscribe 的示意。

  • 本课使用 AWS EC2 自建 Mosquitto 作为 Broker:在 EC2 上安装 mosquitto/mosquitto-clients,启用并启动服务(systemctl enable/start mosquitto),就能作为 MQTT Broker 收发消息。

  • 要让外网可以访问,需要两处设置:

    1. Security Group 放通 TCP 1883(明文 MQTT;若走 TLS 是 8883)到 0.0.0.0/0;课件截图特别强调 SG 里“Allows MQTT traffic from anywhere (1883; 8883)”。

    2. /etc/mosquitto/mosquitto.conf 加:

      listener 1883 0.0.0.0
      allow_anonymous true
      

      然后 systemctl restart mosquitto;并可用 ss -ltnp | grep 1883 检查端口监听。

  • 快速自测命令(课件也给了):

    • 订阅:mosquitto_sub -h <EC2_public_IP> -t test
    • 发布:mosquitto_pub -h <EC2_public_IP> -t test -m "hello"

你的截图里 EC2 的 Public IPv41xxxx。把它放进 Python 里当 MQTT_HOST,外网(校园网、家庭网等)都能连到你的 Broker,只要 SG 和 mosquitto.conf 按上面配置好了。


2) 你的完整数据管道:如何映射到代码

课件在 Practical #5 里把 A1 的上下行两条链路讲得很清楚:

  • 上行(Uplink):Arduino(BLE Peripheral)→ BLE Notify → Raspberry Pi(Python/bleak)→ MQTT PublishBroker(EC2)
  • 下行(Downlink):云端或手机 → MQTT Publish 命令 → Pi 订阅到命令 → Pi 用 BLE Write 写回 Arduino → Arduino 控制执行器(LED)。

在你的两份代码里,正好是一一对应的:

Arduino(Nano 33 IoT,BLE 外设)

  • GATT 设计

    • Service UUIDf75cfb20-...e2f5
    • Sensor Characteristicf75cfb21-...e2f5Read | Notify)——上行数据口
    • Command Characteristicf75cfb22-...e2f5Write)——下行命令口
      这就是课件建议的“多特征、分工明确”的做法,利于拿满分。
  • 上行实现

    • 周期性(每 6s)读取 DHT11,用 ArduinoJson 组装 JSON:{temperature, humidity, timestamp, device_id}
    • 把 JSON 写入 Notify 特征sensorCharacteristic.writeValue(json),Central 若订阅了就会收到通知。
  • 下行实现

    • 只要 Central 对 Write 特征 写入(commandCharacteristic.written() 为真),就解析 JSON({"led":"on/off/toggle"})或纯文本(LED_ON/LED_OFF),并控制板载 LED

这部分正是 A1「Send the data to RPi via BLE」「Receive commands from RPi」「Operate actuators (LED)」的评分点。

Raspberry Pi(Python,bleak + paho-mqtt)

  • BLE(bleak)部分

    • 扫描并连接BleakScanner.find_device_by_filter(lambda d: d.name and DEVICE_NAME in d.name)
    • 订阅上行数据client.start_notify(SENSOR_CHAR_UUID, on_ble_notify)
    • 收到 Notify 后,回调 on_ble_notify 把 payload publish 到 MQTT
  • MQTT(paho-mqtt)部分

    • mqtt.Client(...).connect(MQTT_HOST, MQTT_PORT) 与 Broker 建连;
    • 订阅命令主题iot/commands/arduino):回调 on_mqtt_message 把命令 JSON 原样 BLE writeCOMMAND_CHAR_UUID
  • 这正是课件“把 BLE 与 MQTT 拼到一起”的桥接方式(上行 bleread_mqttpub;下行 mqttsub_blewrite)。你已经把它们合成到一个脚本里了,结构更清晰。


3) 代码里“Broker/MQTT/Topic”的具体体现

以你的 Python 为例(省略无关行,只看 MQTT 相关):

MQTT_HOST   = "13.236.187.137"   # 你的 EC2 公网 IP
MQTT_PORT   = 1883               # mosquitto 默认端口(明文)

TOPIC_SENSOR = "iot/sensors/data"     # 上行主题:Pi 发布
TOPIC_CMD    = "iot/commands/arduino" # 下行主题:Pi 订阅

mqtt_client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
mqtt_client.on_message = on_mqtt_message
mqtt_client.connect(MQTT_HOST, MQTT_PORT, 60)
mqtt_client.subscribe(TOPIC_CMD)      # 订阅命令
mqtt_client.loop_start()

# 上行发布:在 BLE 回调里
mqtt_client.publish(TOPIC_SENSOR, payload)
  • MQTT_HOST/MQTT_PORT 指向Broker(EC2 上的 mosquitto);课件中也使用相同端口并强调先放通安全组与 broker 配置。
  • TOPIC_SENSOR / TOPIC_CMD 是你定义的主题(可以自取层级结构);课件也建议用分层命名和通配符做调试,例如 ifn649/#
  • 你的 上行是“BLE Notify → 回调 → publish”;下行是“订阅 → 回调 → write_gatt_char”。这与课件的 E2E Pipeline 完全一致。

4) AWS EC2 端的最小可用配置(对照你的截图)

  1. 创建/启动实例后,确认 Security Group 里:

    • Inbound 允许 TCP 22(SSH,校网段已预设);
    • 允许 TCP 1883(0.0.0.0/0),若做 TLS 再开放 8883。
  2. 首次 SSH(确保 .pem 权限是 400),连接到公网 IP(如 13.236.187.137),执行:

    sudo apt update && sudo apt upgrade -y
    sudo apt install -y mosquitto mosquitto-clients
    sudo systemctl enable mosquitto
    sudo systemctl start mosquitto
    
  3. 打开外部监听与匿名访问(课堂环境):

    sudo nano /etc/mosquitto/mosquitto.conf
    # 添加:
    listener 1883 0.0.0.0
    allow_anonymous true
    sudo systemctl restart mosquitto
    sudo ss -ltnp | grep 1883
    
  4. 本地或手机自测

    • mosquitto_sub -h 13.236.187.137 -t iot/sensors/data(先开订阅窗口)
    • 运行你的 Python,看到订阅窗口里出现 Arduino 上来的 JSON;
    • 用手机 MyMQTT 连接 13.236.187.137:1883,往 iot/commands/arduino{"led":"on"},观察板载 LED 亮起。

若你把 Python 里 MQTT_HOST 误写成 私网 IP(172.31.x.x),则校园网/家庭网无法直连(除非你的 Pi 也在同一 VPC),因此要用Public IPv4。这也是课件“外部访问需要开放 1883 并配置 broker 外部监听”的原因。


5) 与评分点的对齐(快速核对)

  • Collect data from DHT-11dht.readHumidity()/readTemperature();失败打印“DHT sensor read failed!”。
  • Send the data to RPi via BLEsensorCharacteristic(Notify)+ 周期 6s 上报 JSON。
  • Receive commands from RPicommandCharacteristic.written() + JSON/文本命令解析。
  • Operate actuators (LED)digitalWrite(LED_PIN, HIGH/LOW) 对应 {"led":"on/off/toggle"}
  • RPi 端:bleak 读写 + paho-mqtt 发布/订阅,完成“Read data via BLE / Publish to MQTT / Receive subscribed topics / Send commands to Arduino”。这些正是 Practical #5 的 E2E 要求。

小结 / 你现在要做的事

  1. 确保 EC2:Security Group 放通 1883;mosquitto 已安装并监听 0.0.0.0:1883。
  2. 把 Python 的 MQTT_HOST 设为 1xxx.137(你的截图里公有 IP)。
  3. 先开一个订阅窗口观察:mosquitto_sub -h 13.236.187.137 -t iot/sensors/data
  4. 烧录 Arduino(你贴的最新 ino 没问题);再运行 Python 桥接脚本。
  5. 手机/MyMQTT 或命令行iot/commands/arduino{"led":"on"}/{"led":"off"},观察板载 LED 响应。