Skip to content

feat(test-bench): 接入真全双工音频与整机 SDK 测试台 - #40

Merged
Mr-KID-github merged 3 commits into
mainfrom
codex/sdk-media-lab-full-duplex-audio
Aug 12, 2026
Merged

feat(test-bench): 接入真全双工音频与整机 SDK 测试台#40
Mr-KID-github merged 3 commits into
mainfrom
codex/sdk-media-lab-full-duplex-audio

Conversation

@Mr-KID-github

@Mr-KID-github Mr-KID-github commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

目标

将原 SDK Media Lab 扩展为面向真实硬件的 SDK 测试台,并修复全双工音频只验证电脑本机回环、无法证明 Watcher 麦克风上行的问题。

主要改动

  • 复用 Python Application RTC Device channel,实现电脑麦克风到 Watcher 扬声器、Watcher 麦克风到浏览器播放器的双向 WebRTC。
  • 健康判断同时要求浏览器发送/接收、设备麦克风采集、设备 RTP 发送四段证据,避免把 transport connected 误报为真全双工。
  • 将页面升级为 SDK 测试台,新增 robot.motionrobot.lights 公共 SDK 域的运动、灯光控制及基础整机全检。
  • 服务端增加在线、capability、参数与稳定错误合同;停止运动/扬声器作为显式中断,即使普通操作忙也可达。
  • 保留 example.sdk_media_lab Application id 和目录以兼容既有脚本。

架构边界

  • 不在 Daemon 增加业务消息类型分支或直达设备旁路。
  • RTC 信令及运动/灯光控制均经当前 Application 的 Device channel。
  • 浏览器媒体与 Watcher 走局域网 WebRTC,Application 仅管理信令。

验证

  • Python 全量回归:674 passed、2 skipped。
  • SDK 测试台定向回归:45 passed。
  • RTC 音频健康判断:4 passed。
  • app.js 语法检查与 git diff --check 通过。
  • 配套 ESP32 PR #143 提供 PTL 拍照修复、麦克风采集/RTP 真值统计及生命周期加固。

待完成的人工验收

  • 使用 COM20 对机器人麦克风说话,确认电脑耳机可听,并核对浏览器接收、设备采集、设备 RTP 发送四段指标。

- 复用 Python Application RTC 通道实现电脑麦克风到 Watcher 扬声器及 Watcher 麦克风到浏览器播放器的双向 WebRTC 会话。
- 将实时视频与全双工音频统一纳入 RTC 生命周期和媒体互斥管理,不在 Daemon 增加任何业务消息旁路。
- 增加电脑发送、电脑接收、机器人麦克风采集和机器人成功发送四组指标,只有四段链路均成立才显示真全双工成功。
- 对机器人未采集、未成功发送、浏览器未收到以及发送错误提供明确故障提示,并补充前端纯函数测试和 HTTP 契约测试。

验证:
- python -m pytest tests/test_sdk_media_lab.py tests/application/test_rtc.py -q:41 passed。
- node --test tests/js/test_rtc_audio_health.mjs:4 passed。
- node --check examples/sdk_media_lab/web/app.js:通过。
- mypy 的新增代码检查通过;全目标仅受既有 pyserial 缺少类型声明阻塞。

配套关系:ESP32 固件的麦克风采集与 RTP 发送真值统计位于 codex/fix-sdk-camera-ptl-capture 分支。
将 SDK Media Lab 的用户界面升级为 SDK 测试台,并保持 example.sdk_media_lab 应用标识和目录兼容。

新增运动云台和机身灯光控制区,所有操作只调用 robot.motion 与 robot.lights 公共 SDK 域;服务端增加参数、设备能力与稳定 409 错误门禁,避免绕过页面时向不支持固件下发命令。

修复设备忙时运动/扬声器停止按钮不可达的问题,将停止动作作为显式中断请求处理,同时保留在线和 capability 校验。统一页面中文文案、序号、响应式布局与基础全检流程。

测试覆盖运动和灯光成功合同、能力缺失、停止中断静态合同、RTC 双向健康判断及既有媒体能力。配套 ESP32 PR #143 提供 PTL 拍照与 RTC 麦克风真值统计。
@Mr-KID-github Mr-KID-github changed the title feat(media-lab): 接入可验证的 RTC 全双工音频测试 feat(test-bench): 接入真全双工音频与整机 SDK 测试台 Aug 12, 2026
将全量示例测试中的旧版‘SDK 媒体实验室’断言更新为‘SDK 测试台’,使页面产品命名与自动化契约保持一致。\n\n验证:python -m pytest,674 passed、2 skipped。
@Mr-KID-github
Mr-KID-github marked this pull request as ready for review August 12, 2026 15:14
@Mr-KID-github
Mr-KID-github merged commit a8d7f72 into main Aug 12, 2026
12 checks passed
@github-actions

Copy link
Copy Markdown

🤖 Luxiao PR 审查报告

🤖 PR 审查报告

PR: ESP32:修复 SD 资源安装、SDSC 兼容与启动恢复
变更: 27 个文件, +1113 / -154


维度一:代码质量

🏗️ 架构视角 — ✅

SDSC 兼容读写层拆分合理。sdspi_read_compat.csdspi_write_compat.c 作为独立编译单元,通过函数指针注入单扇区读写原语,与 sensecap-watcher.c 中 FATFS diskio 层形成清晰的分层:

  • 底层:sdmmc_read_sectors / sdmmc_write_sectors(ESP-IDF 原生)
  • 兼容层:watcher_sdspi_read/write_single_sector_chunks(扇区级循环)
  • diskio 适配层:watcher_sdcard_diskio_read/write(按 OCR 中的 SDHC 位分流)

SDHC 走快速多扇区路径、SDSC 走单扇区回退的判断逻辑放在 diskio 层而非调用方,调用方无需感知卡类型,封装合理。sdcard_diskio_cards[FF_VOLUMES] 数组和 sdcard_disk_status_check_enabled 标志位是向多卷支持的预留扩展点,方向正确。

🎨 产品视角 — ✅

从用户角度看,这次改动直接解决三个可感知的问题:

  1. SDSC 小容量卡插入后无法读写 — 之前直接不可用,现在可用
  2. 启动阶段误报 SD 未挂载或循环重启 — 之前必须拔卡重试,现在自动恢复
  3. 串口安装资源时可能损坏唯一可用副本 — 之前用户可能变砖,现在先校验后替换

这三个问题都是实打实的用户痛点,改动方向正确。SDSC 写入速度降低在 PR 描述中已明确声明,属于可接受的取舍。

📏 规范视角 — ⚠️

做得好的:

  • 头文件守卫规范(WATCHER_SDSPI_READ_COMPAT_H
  • extern "C" 包裹
  • 错误码使用有意义的宏(WATCHER_SDSPI_READ_INVALID_ARGUMENT
  • 整数溢出检查到位(sector_count > SIZE_MAX / sector_size
  • 无符号字面量使用 U 后缀
  • 参数校验完整(NULL 指针、零值、溢出)

需要关注:

  • sdspi_read_compat.csdspi_write_compat.c 的实现几乎完全对称,但缺少对 read_sector / write_sector 回调返回值的文档说明(期望什么返回值算成功?0?ESP_OK?)。当前代码中 read_sector 返回值与 ESP_OK 比较(在 watcher_sdcard_read_one_sector 中转换),但兼容层本身只检查 != 0。虽然实际一致,但没有显式约定。
  • 兼容层函数缺少注释说明设计意图(为什么需要单扇区回退、SDSC 卡的多扇区问题是什么)。
  • watcher_sdcard_diskio_read 中的 ESP_LOGE 日志格式字符串正确使用了 %lu / %u 配合显式转换,这点值得肯定。

⚠️ 损伤视角 — ⚠️

已确认安全:

  • SDHC 路径完全保留:(target_card->ocr & SD_OCR_SDHC_CAP) != 0U 分支直接走原生 sdmmc_read_sectors,对现有 SDHC 用户零影响。
  • 单扇区回退是纯增量路径,不会改变 SDHC 的行为。
  • 状态检查可通过 sdcard_disk_status_check_enabled 按卷关闭,不影响不需要状态检查的场景。

需要关注:

  • 由于本次只展示了部分 diff,以下关键路径无法在本次审查中确认:
    • sdmmc_write_sectors 的 SDSC 单扇区写入路径是否与读取路径对称实现
    • SHA-256 校验实现是否正确(独立实现有引入哈希 bug 的风险)
    • 启动恢复逻辑中 RTC 防循环标记的清除时机是否覆盖所有异常路径(看门狗复位、掉电等)
    • 资源替换的原子性:旧资源先被移除还是先被新资源覆盖?中间状态是否安全?
  • PR 描述明确写了"本轮最终提交尚未重新执行真实硬件插卡启动验证",这是一个实际风险点。

维度二:意图分析

🎯 意图提炼

在 ESP-IDF 6 架构升级后,修复 SD 卡挂载、SDSC 小容量卡读写、串口资源安装校验和启动恢复四个链路上的兼容性问题,恢复固件在真实硬件上的可靠运行能力。

🔀 偏离检测

无偏离。 这是一个纯粹的兼容性修复 + 鲁棒性增强 PR,所有改动都围绕 IDF6 升级带来的回归问题展开。没有引入新功能,没有功能蔓延。SDSC 兼容层虽然新增了约 45 行 C 代码,但这是解决实际硬件兼容问题的必要抽象,而非过度设计。

与配套 PR(桌面端 #106、SDK #33)的联动说明这个改动的边界清晰,固件侧只做自己该做的事。


Merge 建议

⚠️ 有条件合并

条件:

  1. 确认 SDSC 写入路径完整 — 本次 diff 只展示了 watcher_sdcard_diskio_read,需要确认 watcher_sdcard_diskio_write 已按相同模式实现 SDSC 单扇区写入分流。
  2. 补充兼容层注释 — 在 sdspi_read_compat.c / sdspi_write_compat.c 头部添加简要注释,说明为什么需要单扇区回退(SDSC 卡多扇区访问在某些条件下超时/失败),以及回调函数的返回值约定。
  3. 真实硬件验证 — PR 描述已声明"尚未重新执行真实硬件插卡启动验证",建议在合并前至少完成一次插卡启动 + SDSC 卡读写 + 热插拔的硬件验证。如果时间不允许,至少明确记录为已知风险并在合并后立即安排验证。

不阻止合并的因素:

  • 测试覆盖充分(52 项 SD 契约测试 + 43 项主机测试全部通过)
  • 架构设计合理,SDHC 路径零影响
  • 已有 1 项既有失败与本次改动无关,未引入新回归

总结: 这是一个架构清晰、方向正确的兼容性修复 PR,SDSC 读写分层和启动恢复逻辑设计合理,但缺少部分关键路径的 diff 可见性和硬件验证,建议在确认写入路径完整并补充注释后合并。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant