fix(camera): allow PPCS when OT discovery fails - #444
Conversation
|
👋 感谢提交 PR @lixiangnlp!维护者会尽快 review。 提交前请确认:
|
PR #444: fix(camera): allow PPCS when OT discovery fails作者: lixiangnlp 修改方案要解决的问题:部分平台(尤其 macOS)上摄像头答不上 MiOT/OT 局域网探测( 整体方案(四条正交主线):
关键设计原则:
本轮 ci 闭环:
问题本轮无新增 🔴 / 🟡 / 🔵。上一轮唯一 🟡 已修复并有真实回归用例守护。 补充核验(均通过,未构成问题):
结论LGTM — 后端 OT-gate 放宽 + 失败流轮换主逻辑自洽(健康度取自 SDK 现取真实连接态、冷却有限可自愈、≤4 路不淘汰,边界均有测试守护),前端开关/批量口径已与后端对齐、删除的 i18n 键全仓无残留。上一轮多摄空转 🟡 已在 由 review-pr skill v1.6 生成 |
|
感谢详细审查!对于 |
在 XiaoMi#439(双摄多通道全拆)的 per-channel 模型上重新表达 OT-gate 放宽与失败流轮换。 冲突解决要点: - filter.py: select_active 保留 main 的通道展开 + 合成 did 返回;健康度三档排序 叠加在其上。健康集合按**物理 did** 记(native/PPCS 会话整台一条),_rank 里把 合成 did 归一回物理 did 再查——否则降权对多摄相机静默失效。 - client.py: refresh_cameras 先算 eligible_channels(cap=False) → 归一为物理 did 喂给 _advance_camera_selection_health,再带健康集合算 active_channels,最后 归一为 active 做 manager 建销。newly_demoted 全程按物理 did。 - service.py: 删掉 main 的「局域网不可达,无法开启」硬拒;上限统计的可用谓词去掉 _lan 一维(OT 未发现的相机仍会尝试 PPCS、仍真占一条解码线程,算作不占名额会 让实际拉流数超上限)。list_cameras_with_state 在 per-channel 行上补 lan_detected, lan_reachable 改为 OT已发现 or PPCS已连接。 - HeroNow.tsx: 状态点三态逻辑移入 XiaoMi#439 抽出的 ChannelStateDots;单开/全开去掉 lanReachable 硬门(switchBlockedReasonKey 已不接受该字段)。 补测试 test_health_sets_are_keyed_by_physical_did_across_channels:多摄整台降权时 两路一起让位、整台已连通时两路一起占名额。已用变异测试确认该用例能抓到回归。 顺带补上 AI Review 的 🔵:list_cameras_with_state docstring 点明 connected(感知已订阅, per-channel)与 lan_reachable(native 会话已建立,per-camera)口径不同、可短暂不一致。 验证: - backend 相机相关 92 passed;全量 2599 passed / 81 failed,其中 81 个失败在干净的 origin/main 上同样复现(schedule/task_record/observability/node_monitor 的环境问题), 本次合并未引入新失败。 - web 221 passed / 1 skipped;tsc --noEmit、vite build、ruff check 均通过。 - 已删 i18n 键 stateLanOk / stateLanOffline / disabledLanHint 全仓无残留引用。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI review 抓到的跨层缺口:sync_devices 的 `expected` 键是**合成 did**(XiaoMi#439 全拆后 discover_devices 按通道展开),而 `_camera_img_managers` 的键是**物理 did** (client.py:620 用 camera_info.did 建键)。`is_camera_stream_connected` 直接拿合成 did 查字典,对任何 channel_count>1 的相机恒返回 False: managers = {"dual": <connected manager>} is_camera_stream_connected("dual:ch0") -> managers.get("dual:ch0") -> None -> False 后果是一台**已 PPCS 连上、健康拉流**的双摄相机,两路都被判进 disconnected, gate 恒真 → 每满 10 秒空转一次 refresh_cameras(含 get_cameras_async 网络往返), 与本 PR 自陈的「已连接相机不触发刷新」直接矛盾。 修在 is_camera_stream_connected 内部做归一(而非调用点),杜绝其他调用方重蹈—— 这与 filter._rank 里健康集合按物理 did 查是同一条不变量:native/PPCS 会话每物理 相机一条,凡是拿会话状态说事的地方,合成 did 都要先归一。 健康记账本身不受此 bug 影响:_advance_camera_selection_health 直接遍历 _camera_img_managers.items() 拿物理 did,不会误降权;坏的只是 sync 侧触发判据。 补 test_no_refresh_for_connected_multi_channel_camera:**不 mock** is_camera_stream_connected(原有用例全 mock 掉了它,且都是单摄裸 did,恰好等于 物理 did,测不到这条分叉),manager 按物理 did 建键 + connected=True,断言 refresh_cameras 未被 await。已变异测试确认:还原成 .get(did) 时该用例失败。 验证:相机相关 1196 passed;ruff check 通过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
本轮 XiaoMi#444 合并进 XiaoMi#439(双摄全拆)时,同一条不变量被踩中两次——活跃集健康排序拿 合成 did 查物理 did 键的健康集合、拉流健康查询拿合成 did 查物理 did 键的 manager 字典。两次都不抛异常、不打日志,单摄用例全绿,只在多摄相机上静默失配。 perception-pipeline.md 加一条关键设计决策,写清两个 id 的分界线(按镜头算 vs 按会话算)与归一函数位置,并点明「单摄恰好相等」正是它难被发现的原因; 「如果我要修改」表补一行指向 select_active_camera_dids 这个单一口径。 dev-guide.md 开发工作流加一条自查:全绿不等于有覆盖。两种典型假绿——mock 掉被测 对象本身、只覆盖退化场景——都在本轮真实发生过(守护该路径的用例既 mock 了 is_camera_stream_connected 又只用单摄)。给出成本极低的判定手段:把刚修的那行故意 改回错的,确认新增用例会失败。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs job 跑 prettier --check "knowledge/**/*.md",新增表格行的尾部空格数与 prettier 的列对齐不符。纯格式,无内容变化。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary
lan_detected, while reporting established PPCS sessions as reachablerequire_lan=TrueProblem
On platforms such as macOS, a camera can fail MiOT/OT discovery while libmiss can still connect using the cloud-provided local IP or PPCS relay. The previous LAN gate prevented the native manager from being created, so the video handshake never had a chance to recover and the camera remained permanently disconnected.
Tests
uv run pytest miloco/tests/perception/test_online_connected_separation.py miloco/tests/test_miot_filter_and_cameras.py -qDashboard 与失败流轮换补齐
本 PR 现已补齐 AI Review 指出的跨层缺口,并处理超过 4 路时失败摄像机长期占位的问题:
lan_detected(原始 OT 发现)与lan_reachable(OT 已发现或 PPCS/native 已连接),仅用于状态展示和诊断。新增验证: