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 收发消息。要让外网可以访问,需要两处设置:
Security Group 放通 TCP 1883(明文 MQTT;若走 TLS 是 8883)到 0.0.0.0/0;课件截图特别强调 SG 里“Allows MQTT traffic from anywhere (1883; 8883)”。
在 /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 IPv4 是 1xxxx。把它放进 Python 里当
MQTT_HOST
,外网(校园网、家庭网等)都能连到你的 Broker,只要 SG 和mosquitto.conf
按上面配置好了。
2) 你的完整数据管道:如何映射到代码
课件在 Practical #5 里把 A1 的上下行两条链路讲得很清楚:
- 上行(Uplink):Arduino(BLE Peripheral)→ BLE Notify → Raspberry Pi(Python/bleak)→ MQTT Publish → Broker(EC2)。
- 下行(Downlink):云端或手机 → MQTT Publish 命令 → Pi 订阅到命令 → Pi 用 BLE Write 写回 Arduino → Arduino 控制执行器(LED)。
在你的两份代码里,正好是一一对应的:
Arduino(Nano 33 IoT,BLE 外设)
GATT 设计
- Service UUID:
f75cfb20-...e2f5
- Sensor Characteristic:
f75cfb21-...e2f5
(Read | Notify)——上行数据口 - Command Characteristic:
f75cfb22-...e2f5
(Write)——下行命令口
这就是课件建议的“多特征、分工明确”的做法,利于拿满分。
- Service UUID:
上行实现
- 周期性(每 6s)读取 DHT11,用 ArduinoJson 组装 JSON:
{temperature, humidity, timestamp, device_id}
; - 把 JSON 写入 Notify 特征:
sensorCharacteristic.writeValue(json)
,Central 若订阅了就会收到通知。
- 周期性(每 6s)读取 DHT11,用 ArduinoJson 组装 JSON:
下行实现
- 只要 Central 对 Write 特征 写入(
commandCharacteristic.written()
为真),就解析 JSON({"led":"on/off/toggle"}
)或纯文本(LED_ON/LED_OFF
),并控制板载 LED。
- 只要 Central 对 Write 特征 写入(
这部分正是 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 write 到COMMAND_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 端的最小可用配置(对照你的截图)
创建/启动实例后,确认 Security Group 里:
- Inbound 允许
TCP 22
(SSH,校网段已预设); - 允许
TCP 1883
(0.0.0.0/0),若做 TLS 再开放 8883。
- Inbound 允许
首次 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
打开外部监听与匿名访问(课堂环境):
sudo nano /etc/mosquitto/mosquitto.conf # 添加: listener 1883 0.0.0.0 allow_anonymous true sudo systemctl restart mosquitto sudo ss -ltnp | grep 1883
本地或手机自测:
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-11:
dht.readHumidity()/readTemperature()
;失败打印“DHT sensor read failed!”。 - Send the data to RPi via BLE:
sensorCharacteristic
(Notify)+ 周期 6s 上报 JSON。 - Receive commands from RPi:
commandCharacteristic.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 要求。
小结 / 你现在要做的事
- 确保 EC2:Security Group 放通 1883;
mosquitto
已安装并监听 0.0.0.0:1883。 - 把 Python 的
MQTT_HOST
设为1xxx.137
(你的截图里公有 IP)。 - 先开一个订阅窗口观察:
mosquitto_sub -h 13.236.187.137 -t iot/sensors/data
。 - 烧录 Arduino(你贴的最新 ino 没问题);再运行 Python 桥接脚本。
- 手机/MyMQTT 或命令行向
iot/commands/arduino
发{"led":"on"}
/{"led":"off"}
,观察板载 LED 响应。