feat(v1): add local alerts, screenshot and JSONL event log
AlertDispatcher de-duplicates by event_id and fires each side effect once per CONFIRMED: annotated screenshot, one JSONL line (config_version, source_id, no rtsp/credentials), sound and popup via injectable sink. 44 tests pass; real-frame artifact smoke verified. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -206,3 +206,12 @@
|
||||
- 阻塞:无任务内 blocker;声音播放与 Qt 弹窗需 Windows 桌面,见决策。
|
||||
- 决策:报警派发按 `event_id` 去重,只对首次 CONFIRMED 触发一次副作用;截图标注与 JSONL 写入在本环境用 pytest 真实覆盖;声音与弹窗抽象为可注入 sink,Windows 侧提供真实实现。JSONL 与截图文件名不含 RTSP 地址、凭证或客户姓名,只用事件 ID 与日期目录。
|
||||
- 下一步:先写去重、JSONL 字段与截图落盘的失败测试,再实现最小报警工件模块。
|
||||
|
||||
## 【2026-07-21】T-202 实现本地报警、弹窗、截图和 JSONL 日志(完成)
|
||||
|
||||
- 状态:DONE
|
||||
- 变更:新增 `v1/alerts.py`:`annotate_frame` 用 OpenCV 在帧上叠加 box/骨架/关键点/标签,CONFIRMED 时加红色外框(红色专属确认摔倒);`EventArtifactWriter` 按 `artifacts/events/YYYYMMDD/FALL-xxxxxx.png` 保存带标注截图并向 `events.jsonl` 追加一行含 `event_id/track_id/config_version/source_id/state/confirmed_at_utc/单调时间/latency/相对截图路径` 的记录;`AlertDispatcher` 按 `event_id` 去重,对首次 CONFIRMED 只触发一次副作用。声音与弹窗抽象为 `AlertSink`;`v1/gui.py` 新增 `QtAlertSink`(`QApplication.beep` + 一次性非阻塞“我已知晓”弹窗),`v1/app.py` 在开始监控时构建 writer/dispatcher 并在每帧派发 `analysis.events`,窗口仍只渲染。
|
||||
- 验证:新增 `v1/tests/test_alerts.py` 5 项,覆盖同一事件只写一次截图/JSONL 且 sink 各调用一次、JSONL 字段正确且无 rtsp/password、缺图不产生副作用、不同事件写两行、annotate 仅对 CONFIRMED 画红框;`python3 -m pytest v1/tests -q` 为 44 passed;`python3 -m compileall -q v1 demo` 退出码 0。真实帧冒烟:用 `demo/1.mp4` 首帧(848×480)经 `AlertDispatcher` 落盘,截图可被 `cv2.imread` 读回为 480×848×3、约 330 KB,重复派发返回 0,JSONL 一行且 `screenshot=20260721/FALL-000001.png`、含 `config_version`、`source_id`,行内无 `rtsp`。
|
||||
- 阻塞:无任务内 blocker。声音播放与 Qt 弹窗需 Windows + PyQt5 桌面执行冒烟;本环境已真实验证截图标注、JSONL 落盘与去重逻辑。
|
||||
- 决策:事件副作用严格按 `event_id` 幂等;报警记录以 `FallEvent` 的 `config_version` 追溯运行配置,不在写入时重新推导;工件文件名只用事件 ID 与日期目录,绝不含来源地址、凭证或客户姓名。
|
||||
- 下一步:T-203,接入海康 RTSP 与断流恢复;因需现场真实流,标为 BLOCKED 等现场资源。
|
||||
|
||||
Reference in New Issue
Block a user