修复:设备的"清零已生效"确认从未被记录(worker 的 on_reset_applied 没有接线)
- What: `SessionController.ensure_workers` 现在把 `on_reset_applied=self.note_reset_applied` 交给两个 worker,并在控制器上补回 `note_reset_applied()`(转发给记录通道的 `recording.note_reset`)。窗口侧保留 `_on_reset_applied` 作为一层转发——tests 通过它 模拟设备确认。 - Fix: 这是一个真实缺陷,不是重构副作用。请求路径一直是通的(`_on_reset` → worker.reset()),确认路径却从来没有人接:worker 的 `on_reset_applied` 默认 None, 于是设备回报的 frame_id / mono_t 被丢掉,`recording.note_reset` 不会执行, `_drain_reset_events()` 也永远没有事件可发。后果是真机上按「清零」只会看到「指令已发出」, 录制里不会留下 zeroing 事件(`session.json` 的 events 少一条),而 test_ui_smoke 里那条 `test_a_zeroing_is_recorded_only_after_the_worker_confirms_it` 之所以一直是绿的,是因为 它自己把 `stuck.on_reset_applied = window._on_reset_applied` 手工接上了——测试补上了 产品缺的那根线。 - What: 新增 apps/studio/tests/test_session_controller.py:8 个用例直接驱动控制器 (假 worker、假记录通道)——清零确认与标定确认都会到达记录、两个 worker 都挂上记录 sink 与三维 sink、detach_sinks 会摘掉、一次运行从 connecting 到 running 到 idle 的 相位与遥测(结束后旧遥测不可读、session id 递增)、connecting 时停止会被如实告知、 慢连接提示只说一次、丢帧批次只报一次、采集率短少必须有实测值才判定且一会话只说一次。 - Why: 记录要说真话。清零在实验里是一个事件("这一刻起力被归零"),设备既然回报了 它就应当进入记录;把接线补在控制器(A2 搬进来的那个所有者)而不是窗口里,也让 "谁在跑、报了什么"这条链路只有一个所有者。 - Verification: pytest shared/tests apps/studio/tests(offscreen)644 passed / 0 failed / 15 skipped(原 636 + 新增 8);apps/studio/tools/ui_check.py 587 项检查 0 失败; .repro/locale_check.py 0 缺失。真机上的验收仍未做(本机没有设备), 已知边界:SDK worker 的 `_on_reset_applied` 只在 `sensor.reset()` 返回后调用, 异常路径本来就不会报告确认——这一点没有改动。 - Not in this change: 不改变 `_on_reset` 的请求语义与状态栏文案;`_drain_reset_events` 仍在窗口(它只是把事件变成一行状态)。
This commit is contained in:
@@ -1590,8 +1590,13 @@ class StudioMainWindow(QMainWindow):
|
||||
self.recording.note_calibration_applied(path, version, frame_id, mono_t, session)
|
||||
|
||||
def _on_reset_applied(self, frame_id: int, mono_t: float, session: int) -> None:
|
||||
"""Called from the acquisition thread once a zeroing took effect."""
|
||||
self.recording.note_reset(frame_id, mono_t, session)
|
||||
"""The device confirmed a zeroing.
|
||||
|
||||
The workers hand this to the session controller (which is what actually records
|
||||
it); the window keeps the entry point because the tests drive the confirmation
|
||||
through it.
|
||||
"""
|
||||
self.session.note_reset_applied(frame_id, mono_t, session)
|
||||
|
||||
def _drain_calibration_events(self) -> None:
|
||||
"""Publish confirmed calibration changes on the UI thread."""
|
||||
|
||||
@@ -226,12 +226,18 @@ class SessionController(QObject):
|
||||
on_error=self.note_error,
|
||||
on_status=self.note_status,
|
||||
on_calibration_applied=self.note_calibration_applied,
|
||||
# A confirmed zeroing has to reach the record as well: without this the
|
||||
# device's own "reset took effect" never became an event, so a session
|
||||
# that was zeroed mid-run recorded no evidence of it (the status line
|
||||
# that says so is published from the same event).
|
||||
on_reset_applied=self.note_reset_applied,
|
||||
)
|
||||
if self._finger_worker is None:
|
||||
self._finger_worker = FingerAcquisitionWorker(
|
||||
on_error=self.note_error,
|
||||
on_status=self.note_status,
|
||||
on_calibration_applied=self.note_calibration_applied,
|
||||
on_reset_applied=self.note_reset_applied,
|
||||
)
|
||||
self.wire_sinks()
|
||||
|
||||
@@ -347,6 +353,14 @@ class SessionController(QObject):
|
||||
"""Called from the acquisition thread once new coefficients are loaded."""
|
||||
self._recording.note_calibration_applied(path, version, frame_id, mono_t, session)
|
||||
|
||||
def note_reset_applied(self, frame_id: int, mono_t: float, session: int) -> None:
|
||||
"""Called from the acquisition thread once a zeroing took effect.
|
||||
|
||||
This is the *confirmation*, not the request: the device reports the frame and
|
||||
the time it zeroed at, and the record channel keeps them as an event.
|
||||
"""
|
||||
self._recording.note_reset(frame_id, mono_t, session)
|
||||
|
||||
def note_sample_telemetry(self, packet: Any) -> None:
|
||||
"""Adopt one frame's own numbers. Called on the UI thread, once per new frame.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user