feat(cli): 完善机器人配网引导与 Wi-Fi 状态闭环 - #67
Conversation
robot setup 在开始扫描前明确提示打开电脑蓝牙,并针对蓝牙关闭或缺少适配器、系统权限拒绝、未发现机器人、连接超时、固件拒绝或响应异常、配对阶段失败和用户取消分别输出可执行的恢复步骤,不再向普通用户返回单行 JSON 异常。 旧固件缺少 Device ID 时明确说明可能需要升级固件,同时保留 Bluetooth ID 兼容能力。补充各异常分支与敏感信息不泄露测试,并在中英文 CLI 参考、蓝牙配网文档和排障表中增加完整交互状态矩阵。 文档同时明确 app init 已按项目目录自动生成稳定的 local.<项目名> ID;若仍出现 Application ID 逐项提问,应检查是否误用了旧版 CLI。用户名、时间戳和随机值不用于默认 ID,以保持安装升级身份稳定。
使用 Bleak 原生 POWERED_OFF、NO_BLUETOOTH 和 NO_BLE_CENTRAL_ROLE 原因验证扫描后端统一映射为 BluetoothUnavailableError,并确保平台底层错误细节不会直接暴露给用户。
|
补充提交覆盖 Bleak 原生 POWERED_OFF、NO_BLUETOOTH 和 NO_BLE_CENTRAL_ROLE 三类状态,确认电脑蓝牙关闭、无适配器或不支持 BLE Central 时都会进入明确的 Bluetooth unavailable 恢复引导。 |
🤖 Luxiao PR 审查报告🤖 PR 审查报告 PR: fix(cli): 补齐配网异常恢复与自动 ID 说明 维度一:代码质量🏗️ 架构视角 — ✅整体改动遵循现有结构:
没有新增不合理依赖、循环依赖或过度抽象。 需要注意的是,当前 CLI 恢复策略依赖较多具体异常类型。后续如果异常类型继续增加,建议将“异常分类—用户提示—退出码”集中为结构化映射,避免 🎨 产品视角 —
|
🤖 Luxiao PR 审查报告🤖 PR 审查报告 PR: fix(cli): 补齐配网异常恢复与自动 ID 说明 维度一:代码质量🏗️ 架构视角 —
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8f3f5541fa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| else: | ||
| lines = ( | ||
| "Robot setup could not be completed.", | ||
| " 1. Keep the robot on Settings > Wi-Fi and nearby.", | ||
| " 2. Run watcherobot robot setup again.", | ||
| ) |
There was a problem hiding this comment.
Preserve recovery guidance for oversized provisioning payloads
When the SSID and password are each within their individual limits but their combined JSON request exceeds the 180-byte protocol limit, build_request() raises PayloadTooLargeError. Because that exception falls into this generic branch, setup now hides the actionable size error and only tells the user to retry, which will fail indefinitely with the same credentials. Handle this exception separately by explaining that the SSID or password must be shortened, or otherwise preserve its sanitized limit details.
Useful? React with 👍 / 👎.
| elif isinstance(exc, DeviceNotFoundError): | ||
| lines = ( | ||
| "No WatcheRobot was found.", |
There was a problem hiding this comment.
Distinguish a missing requested ID from an empty scan
When scanning finds robots but none matches an explicit --device value, _select_setup_device() raises DeviceNotFoundError with the requested identifier. This handler discards that distinction and reports No WatcheRobot was found, misleading the user into troubleshooting advertising or proximity instead of correcting the ID or selecting one of the discovered devices. Preserve a separate message for the requested-ID mismatch rather than treating every DeviceNotFoundError as an empty scan.
Useful? React with 👍 / 👎.
| If an explicit directory is followed by `Application ID:` or other metadata | ||
| prompts, the terminal is running an older CLI. Activate the intended virtual | ||
| environment and check the command source with `where.exe watcherobot`. An |
There was a problem hiding this comment.
Include the POSIX command-source check
In the supported macOS environment, where.exe is unavailable, so users following this newly added recovery instruction receive another command-not-found error and still cannot determine which CLI installation is being invoked. The installation guide already uses which watcherobot for macOS/Linux; include that alternative here and in the Chinese reference rather than providing only the Windows command.
Useful? React with 👍 / 👎.
将 Wi-Fi 配置拒绝、固件响应超时、协议不兼容和 Runtime 配对失败拆分为独立用户提示,避免把通信或版本问题误导为密码错误。引入 RobotSetupError 与 RobotPairingError 收窄预期交互异常边界,并修复 ValueError 仍回落为 JSON 的遗漏路径。 明确 robot setup 是面向人的引导命令;需要结构化输出的自动化继续使用 watcherobot bluetooth 命令,其 JSON 合同不变。补充所有异常分支、未知配网异常、ValueError 与配对恢复测试,并增强中英文状态矩阵及 Windows、macOS/Linux 命令来源排查说明。
|
已在 d28611f 处理审查条件:\n\n- 修复 ValueError 回落到 JSON 的遗漏路径\n- 分开 Wi-Fi 配置拒绝、响应超时、协议不兼容和 Runtime 配对失败提示\n- 使用 RobotSetupError / RobotPairingError 收窄预期交互异常边界\n- 补齐上述分支、未知 provisioning 异常与 ValueError 回归测试\n- 明确 |
🤖 Luxiao PR 审查报告🤖 PR 审查报告 PR: fix(cli): 补齐配网异常恢复与自动 ID 说明 维度一:代码质量🏗️ 架构视角 —
|
根据配网向导审查继续完善交互状态:仅在 TTY 终端展示面向用户的恢复步骤,非交互调用继续沿用结构化 JSON 错误合同;将 EOF 与 Ctrl+C 统一为取消并返回 130,避免自动化调用和人工流程出现不一致。 新增不支持 BLE Central 的独立异常和恢复建议,补齐设备身份冲突、配对返回非零、缺失输入、未知程序性 ValueError 不被吞掉等边界。同步中英文 CLI 参考和排障文档,并用 hello_robot_test 固化 local.hello_robot_test 的自动稳定 ID 行为。 验证:pytest -q tests/test_robot_onboarding.py tests/provisioning tests/test_documentation.py tests/test_app_cli_usability.py;python -m mypy src;git diff --check。
|
已在 d5f096e 继续处理最新审查意见: |
🤖 Luxiao PR 审查报告🤖 PR 审查报告 PR: fix(cli): 补齐配网异常恢复与自动 ID 说明 维度一:代码质量🏗️ 架构视角 — ✅整体分层合理,改动基本保持在既有职责边界内:
新增
交互终端输出恢复指导、非交互终端保留 JSON 合同的处理方式兼顾了人机交互与自动化兼容性,没有直接破坏底层命令的结构化输出。 需要关注的长期问题是:恢复文案目前同时存在于 CLI、英文文档、中文文档和排障文档中。当前规模尚可,但后续新增错误类型时容易发生行为与文档漂移。现阶段不构成合并阻塞。 🎨 产品视角 — ✅这是本次改动最明显的提升。 原先单行 JSON 对普通用户几乎没有恢复价值;现在针对以下状态提供了明确、可执行的下一步:
错误提示没有直接展示 Bleak 的平台内部信息,也没有输出 Wi-Fi 密码。错误恢复步骤围绕用户能够执行的动作展开,而不是暴露底层异常堆栈,符合面向消费级硬件的 CLI 定位。 Device ID 的说明也比较准确:
稳定 ID 对应用升级和覆盖安装是必要的;避免用户名也减少了本机信息泄露。 一个轻微的产品风险是 📏 规范视角 —
|
保留 pair_robot 返回 130 时的取消语义,避免被统一折叠为普通 setup 失败;在配对异常进入交互文本或非交互 JSON 前统一遮蔽六位配对码。 新增非交互配对失败 JSON、配对码脱敏与配对取消退出码测试。验证配网和文档相关 123 项测试、mypy 与 diff check 通过。
|
补充确认并在 d0f0f96 加固两项非阻塞风险:pair_robot 当前实现只会成功返回 0、失败抛 CliError,但 setup 仍显式保留未来返回 130 的取消语义;配对异常进入人工文本或非交互 JSON 前会遮蔽六位配对码。新增非交互配对失败、脱敏与 130 回归测试。当前最低依赖为 bleak>=3,<4,本机 bleak 3.0.2 已包含 NO_BLE_CENTRAL_ROLE,映射测试通过。 |
🤖 Luxiao PR 审查报告🤖 PR 审查报告 PR: fix(cli): 补齐配网异常恢复与自动 ID 说明 维度一:代码质量🏗️ 架构视角 — ✅整体分层合理,改动基本遵循现有架构:
异常到文案的映射目前集中在 🎨 产品视角 — ✅这是一次有明确用户价值的修复:
交互与自动化边界也处理得较好:交互终端使用可读文本,非交互调用继续得到 JSON,避免为了改善人工体验而破坏脚本。 📏 规范视角 —
|
robot setup 在最长约十秒的蓝牙扫描期间持续输出进度点,并在扫描结束后显示发现的机器人数量,避免用户误判命令卡死。 Wi-Fi 写入阶段不再把凭据保存描述成联网成功,明确提示当前 BLE ACK 只证明 SSID 和密码已存储、尚未验证;交互式流程要求机器人设置页显示 Connected 后才继续配对,Offline 或 Wi-Fi failed 时给出断开、忘记网络和重新配网步骤。配对失败提示同步前移检查 Wi-Fi 状态。 同步中英文 CLI 参考与排障文档,新增慢扫描进度、Wi-Fi 确认取消和错误密码恢复文案测试。验证相关 125 项测试、mypy 与 diff check 通过。
|
新增 5b7d20f:蓝牙扫描期间按秒输出进度点并在结束后报告发现数量;Wi-Fi 阶段不再把 credentials_saved 误报成联网成功,明确说明密码尚未验证,并要求机器人设置页显示 Connected 后才进入配对。Offline / Wi-Fi failed 会提示网络名或密码可能错误以及断开/忘记网络后的重试步骤。协议核对确认当前固件必须释放 BLE 后才能开始 Wi-Fi,因此真正自动回传 auth_failed 仍需要后续 ESP32 协议配套,本提交先保证 SDK 不误导且用户有明确判断入口。相关 125 项测试、mypy 与 diff check 通过。 |
🤖 Luxiao PR 审查报告🤖 PR 审查报告 PR: fix(cli): 补齐配网异常恢复与自动 ID 说明 维度一:代码质量🏗️ 架构视角 —
|
将 setup 蓝牙扫描的十秒上限定义为单一代码常量并显式传递给 provisioning 层,确保进度文案与真实行为使用同一契约。扫描等待被取消或异常中断时,主动取消并回收后台任务,避免残留蓝牙扫描占用后续重试。 明确 Wi-Fi 确认兼容策略:纯引导流程等待用户确认 Connected;显式提供 pairing-code 时仍展示联网未验证说明,但不增加 Enter 阻塞。补充扫描超时传参、任务回收和全参数 TTY 无新增提示测试。 验证相关 126 项测试、mypy 与 diff check 通过。
|
已在 1a05533 处理扫描审查条件:十秒上限改为单一常量并显式传入 scan_devices;取消/异常时主动 cancel + await 回收扫描任务;纯引导模式等待 Connected 确认,显式提供 --pairing-code 时保留警告但不新增 Enter 阻塞。新增实际超时传参、扫描任务回收和全参数 TTY 兼容测试。相关 126 项测试、mypy 与 diff check 通过。hello_robot_test 是用户本次真实复现名,用于锁定该输入生成 local.hello_robot_test,并非规避测试隔离。 |
🤖 Luxiao PR 审查报告🤖 PR 审查报告 PR: fix(cli): 补齐配网异常恢复与自动 ID 说明 维度一:代码质量🏗️ 架构视角 — ✅整体分层合理:
需要留意两个兼容性点:
以上属于需要确认的兼容边界,不构成当前 diff 中已经确定的架构缺陷。 🎨 产品视角 — ✅这是本 PR 最有价值的部分。 原来的单行 JSON 对普通用户几乎没有恢复价值;现在针对以下状态提供了明确、可执行的下一步:
交互改进也基本合理:
有一个非阻塞的产品风险: 当用户显式传入 📏 规范视角 — ✅规范性整体较好:
测试方面有两点可以继续加强:
另外,
|
- 使用蓝、绿、黄、红、青分别表达进行中、成功、待确认、失败和设备标识 - 仅在交互式终端启用颜色,支持 NO_COLOR 与 FORCE_COLOR,并保持重定向输出无 ANSI 控制码 - 将 colorama 声明为直接依赖,自动适配 Windows PowerShell 控制台 - 补充成功、失败、禁色场景测试以及中英文 CLI 文档 验证:139 项相关测试通过;mypy、pip check 与 git diff --check 通过
将配网成功语义从凭据已保存调整为机器人已确认联网。SDK 在收到 cfg.wifi.set 应答后继续监听同一蓝牙会话,通过 command_id 和 SSID 关联状态,直到 connected 或明确失败。 CLI 以语义颜色展示发送、连接中和连接成功状态;针对密码错误、找不到网络、固件超时及 SDK 侧保护超时提供不同恢复建议,并移除依赖用户手动确认机器人屏幕的步骤。同步更新中英文 CLI 与蓝牙配网文档。 测试覆盖连接中到成功、三类固件终态、SDK 保护超时、消息相关性、敏感信息不泄漏、清理流程和 setup 交互;全量 pytest、mypy 与 pip check 均通过。
|
已补齐 ESP32 ↔ SDK 的 Wi-Fi 联网终态闭环,并完成 COM20 实机端到端验收。 配套固件 PR:orulink-ai/WatcheRobot_esp32#165 本 PR 新增:
实机验证:COM20 机器人连接 |
🤖 Luxiao PR 审查报告🤖 PR 审查报告 PR: fix(cli): 补齐配网异常恢复与自动 ID 说明 维度一:代码质量🏗️ 架构视角 — 🔴CLI 引导层的拆分整体合理:
但该 PR 实际上不只是 CLI 修复,而是修改了核心 provisioning API 和固件协议语义: ProvisioningState = Literal["connected"]替换了原来的: ProvisioningState = Literal["credentials_saved"]同时 这属于 SDK 公共接口和设备协议行为的破坏性变更,不应隐藏在
建议将核心协议升级单独拆分,明确兼容策略、版本边界和迁移说明。当前范围过大,无法作为单纯的 CLI 异常恢复修复合并。 阻断问题:状态关联并不严格
if message.command_id not in {None, command_id}:
continue
if message.ssid is not None and message.ssid != ssid:
continue这意味着以下事件都可能被接受:
但文档明确声称:
以及:
实现与协议承诺不一致。缺失 既然当前代码已经要求 ACK 必须具有 if ack.command_id is None:
raise ProvisioningProtocolError(...)那么后续终态也应严格要求: if message.command_id != command_id:
continue如果确实需要兼容旧固件的无 🎨 产品视角 —
|
背景
机器人首次配置原先在写入 Wi-Fi 凭据后就结束,用户需要自行观察机器人屏幕,SDK 无法判断密码错误、找不到网络或连接超时。扫描、设备选择、蓝牙异常和 Application ID 初始化也缺少面向普通用户的完整引导。
改动
首次配网引导
watcherobot robot setup扫描前提示打开电脑蓝牙并进入机器人Settings > Wi-FiWi-Fi 双向状态闭环
cfg.wifi.setACK 后保持 BLE 会话,继续等待机器人真实联网终态connecting、connected、auth_failed、network_not_found、timeoutcommand_id和 SSID 关联本次配置,SDK 侧另设 25 秒保护期限交互与项目初始化
NO_COLOR/FORCE_COLORwatcherobot app init <目录>自动生成稳定的local.<项目名>Application ID配套固件
文档
已同步更新中英文 CLI 参考、蓝牙配网说明、源码安装与正式安装相关引导。
验证
orulink故意输入错误密码,ESP32 将 reason=15 回传为auth_failed,SDK 正确显示密码错误及恢复步骤