# wifi_ps + MQTT 示例 ## 功能说明 在 [basic 子工程](../basic/README.md) 的 WiFi 自动轻睡眠基础上挂一个 coreMQTT 客户端,演示在 AUTO_LIGHT_SLEEP 下如何安全地跑 socket 收发: - 连上 broker(默认匿名,端口 1883),订阅 `arcs/test/sub`,启动时往 `arcs/test/pub` 发一条 `hello` - 收到下行消息时打印 - 主循环里 `MQTT_ProcessLoop` 前后用 `lisa_pm_wifi_lock_acquire/release` 包裹,避免在 socket 收发中途进 light sleep 导致丢包 ## 与 basic 的差异 | 项 | basic | mqtt | |----|-------|------| | WiFi + AUTO_LIGHT_SLEEP | ✓ | ✓ | | MQTT 客户端 | ✗ | ✓ | | 额外 Kconfig | —— | `CONFIG_SDK_MODULE_COREMQTT=y` | | `lisa_pm_wifi_lock_*` | ✗ | 主循环包裹 `MQTT_ProcessLoop` | ## 使用前修改 `src/main.c` 顶部: ```c #define TARGET_WIFI_SSID "YOUR_WIFI_SSID" #define TARGET_WIFI_PWD "YOUR_WIFI_PASSWORD" #define MQTT_BROKER_HOST "192.168.1.100" #define MQTT_BROKER_PORT 1883 ``` ## 配套主机脚本 `mqtt_test.sh` 在 Linux 主机上一键配置 Mosquitto broker、订阅设备消息、向设备发命令: ```bash ./mqtt_test.sh setup # 首次配置 + 启动 broker(需要 sudo) ./mqtt_test.sh sub # 终端 A:订阅设备上行 ./mqtt_test.sh pub ping # 终端 B:向设备发命令 ``` ## 编译 ```{eval-rst} .. include:: /sample_build.rst ``` ## 烧录 两份固件必须**同时**烧到 flash: | 固件 | 路径 | 烧录地址 | |------|------|----------| | AP 固件 | `build/remote/ap.bin` | `0x0` | | CP 固件 | `build/arcs.bin` | `0x100000` | ```bash ./tools/burn/cskburn -s /dev/ttyUSB0 -b 3000000 \ 0x0 build/remote/ap.bin \ 0x100000 build/arcs.bin \ -C arcs ``` ## 预期输出 ``` === lisa_pm wifi_ps + MQTT === Waiting for WiFi + IP... WiFi connected DHCP success: 192.168.x.x Connected to MQTT broker 192.168.1.100:1883 MQTT connected Published: hello from arcs SUBACK AUTO_LIGHT_SLEEP enabled RX: topic=arcs/test/sub, payload=ping ← 主机端 ./mqtt_test.sh pub ping ``` ## 关键 API ```c /* socket / MQTT 临界段必须持锁,否则可能在收发中途被 light sleep 切断 */ lisa_pm_wifi_lock_acquire(); MQTTStatus_t st = MQTT_ProcessLoop(&g_mqtt); lisa_pm_wifi_lock_release(); ``` | API | 说明 | |-----|------| | `lisa_pm_wifi_lock_acquire()` / `release()` | WiFi 省电锁,临界段引用计数;持锁期间 WiFi 不进 PS | | `MQTT_Init` / `MQTT_Connect` / `MQTT_Subscribe` / `MQTT_Publish` / `MQTT_ProcessLoop` | coreMQTT 标准 API | ## 注意事项 1. **临界段必须持锁**:在 MQTT 收发期间不持锁,可能引发包丢失或连接异常。任何应用层的 socket / TCP 业务都应该用同样模式包裹。 2. **WiFi 是 AUTO_LIGHT_SLEEP 的硬依赖**:与 basic 一样,必须先连上 AP 才能切到 AUTO_LIGHT_SLEEP。 3. **回调上下文**:`mqtt_event_callback` 在 `MQTT_ProcessLoop` 调用栈中运行;如果要在回调里 publish 响应,必须用独立任务 + 队列,**不能在回调里直接调 MQTT_Publish**(会形成嵌套)。本示例只打印,不响应,避免该复杂度。