开发者调试页:在没有真实配 WiFi 的 CM4 的情况下直连 EMQX broker,订阅一个写死的设备 topic(CM4_A322),手动发 4 个测试命令(SET_RD / SET_F / SET_C / VER),实时查看 MQTT log 流。
lib/features/thermometer/presentation/pages/mqtt_test_page.dart(315 行)regionServiceProvider(MqttService 为页面内直接实例化,无全局 Provider)MqttService.connect / disconnect / sendCommand / logStream / connectionStateStream/mqtt-test(MqttTestPage.routeName)lib/app.dart 静态 routes map「终端调试器」风格:黑色背景,AppBar 标题左边一个连接状态色圆点(绿/橙/红)+ "MQTT Debug" 文字(Courier 字体绿色)。下方两个 banner:broker 地址(host:port,引自 region service)+ 设备 ID 与状态。再下方一行 5 个胶囊按钮(Connect/Disconnect / SET_RD / SET_F / SET_C / VER),未连接时除 Connect 外都置灰。下方占满剩余空间的 log ListView:每条带颜色编码(红=错误、绿=连接成功、青=接收、橙=发布、浅绿=订阅、白=其他)。AppBar 右上有 🗑 清空 log 按钮。
Navigator.pop(context)IconButton.onPressed: _clearLog_logs 列表 + 清空 MqttService.logHistory_ActionButton.onPressed,isConnecting 时禁用onPressed → _connect()
→ final region = ref.read(regionServiceProvider)
→ _mqtt.connect(_testDeviceId='CM4_A322', serverConfig: region.config)
→ 触发 mqtt 客户端 TLS 握手 → 订阅 device topic → emit 状态流
onPressed → _disconnect() → _mqtt.disconnect()
MqttService()(不走 CloudConnectionRegistry):本页 dev tool 调试盒 CM4_A322 单独取一个 MqttService 实例 + 独立 clientId,不影响正常 App 流(每个绑定 CM4 各自一份 MqttService 与 broker session);先前共享单例时同 clientId 三个并发 connect 会被 broker 按 MQTT 3.1.4 互踢出独占(field log 单 session 2181 次 autoReconnect 暴风)现已根除_ActionButton,分别 onPressed: () => _publishTest('SET_RD' / 'SET_F' / 'SET_C' / 'VER')onPressed → _publishTest(command)
→ _mqtt.sendCommand(_testDeviceId, command)
→ MQTT publish → broker → 设备
→ 设备回应 → telemetryStream → log 中显示 "Received ..."
initState 拉一次 _mqtt.logHistory 当快照填入 _logs;订阅 _mqtt.logStream + _mqtt.connectionStateStream 持续更新本地 state,每来新 entry 调 _scrollToBottom 自动滚到底部。
不直接 ref.watch —— 因为 MqttService 的 stream 不是 Riverpod Provider 形态,本页用原生 StreamSubscription。regionServiceProvider 通过 ref.read 取实例(MqttService 为页面内直接实例化)。
无显著差异。EMQX TLS 8883 端口在两端行为一致。
_testDeviceId 硬编码 'CM4_A322':仅当真有这个设备 ID 时测试才有意义;其他情况 publish 命令会发到无人订阅的 topic,看不到回应。改设备测试时必须改源码。MqttService()(不走 per-device CloudConnectionRegistry),从而获得独立 MqttService + 独立 clientId,不再串扰正常流。_logColor 启发式:根据 message 里的关键词判定颜色("Connected" / "Received" / "Published")。文案变化会让颜色失效。