Ver Fonte

docs(阶段2): 监控补全/受护栏停止/借串口让路 实现+真机自验回写

待验证清单 D2-01☑(监控/status三块,harness验)/D2-03☑(受护栏停机释放硬件)/D2-02◑(借串口让路验,调试页完整驱动待命令代理设计);
工作计划表+进度状态.yaml+进度数据.js+交接卡 全对齐。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
huangjie há 2 dias atrás
pai
commit
99ca241471

+ 19 - 0
项目文档/进度/交接卡.md

@@ -165,3 +165,22 @@
 - **还原**:两处脚手架已还原(`git diff` 两文件 vs 已提交=空),operate Release 重编 0 错误。
 - **核实**:进程时序(operate 先、control 后 10s)、control /status、operate 存活=登录成功、杀 operate 后 control 续命,均实测。
 - **下一步**:阶段2(监控补全 /status + 借串口 /serial/pause|resume + 受护栏停止 /shutdown)。**安全红线**(设计文档 §line178):调试借串口的电机驱动验证需用户在场,绝不无人值守驱动电机——我实现代码 + 自验不驱动电机的部分(/status、/shutdown、/serial 让路即停轮询)。
+
+---
+
+## 2026-06-22 · 阶段2 实现 + 真机自验(监控补全 / 借串口让路 / 受护栏停止)
+
+- **背景**:接 /goal 续做"一次性完成所有工作计划"。阶段2 三件:监控补全、调试借串口、受护栏停止。按设计文档 §5.4/§6。安全红线:不无人值守驱动电机。
+- **控制端(已提交,真机全验)**:
+  - `ControlHttpServer` 扩展:`GET /status` 返回完整 `MonitorSnapshot`(rich);`POST /shutdown`(token)+ `/serial/pause`|`/serial/resume`(houseSn),含 POST body JSON 解析。
+  - `MonitorSnapshot/HouseMonitorRow` 补 §6 三块(只读):`WorkingType/ValveState/CapturePausedByGate`;`GetMonitorSnapshot` 填充。
+  - `Program`:`BuildRichStatus` + `HandleShutdown`(口令 tl13579→`SafeShutdown`:`HAL.ShutdownAll`+`_exitEvent.Set`)+ `HandleSerialPause/Resume`(`HAL.GetHouseGate.PauseCapture/ResumeCapture`,接已有 `HouseBin` 让路:`CapturePausedByGate`+采集主循环 `if(IsDebug||CapturePausedByGate)` 不发串口)。
+  - **真机自验**:/status 三块字段+心跳 LastMqttOkAt;`/serial/pause houseSn=2`→舱2 CapturePausedByGate=true 且 COM4 停发(让路,**不驱动电机**)→ resume 恢复;`/shutdown` 错口令 403、对口令 tl13579 安全停机(进程退出 + 7 COM 口全释放)。6 单测仍过。
+- **operate 端(已提交)**:
+  - 新增 `Helpers/ControlClient.cs`:跨进程 HTTP 客户端(/status 取快照、/ping、/shutdown、/serial/pause|resume),全 try 兜底。**拆分后 operate 进程内无 control 实时 AppData,监控/调试必须经此**。
+  - `ServiceMonitorViewModel.Refresh`:数据源由同进程 `ControlAppData.Instance.GetMonitorSnapshot()` 改为 `ControlClient.GetStatusSnapshot()`(HTTP);映射三块;加 `ShutdownControlCommand`(二次确认+`Microsoft.VisualBasic.InputBox` 口令→/shutdown)。
+  - `ServiceMonitorView.xaml`:舱行加三列(活动/排气阀/借用让路)+ 底部受护栏停止按钮。operate Release 编译 0 错误。
+  - **operate 端自验(harness 实跑真 ControlClient.cs)**:`GetStatusSnapshot` 往返反序列化 10 舱(真温 37℃+三块);`SerialPause(2)`→快照 House2 Paused=true→`SerialResume`,跨进程借串口让路实证。
+- **诚实边界 — 调试页完整借串口(D2-02 ◑)**:debug 页原 `gate.Acquire(OperateDebug)` 借**同进程 HAL 同一物理句柄**驱动(`HouseDebugPageViewModel:256`,`_halLease.Serial/Camera`)。拆分后 operate 进程 HAL 是空单例、拿不到 control 持有的串口/相机——要在拆分下让调试页驱动,需 **control 暴露串口/相机命令代理**(逐操作:电机移动/读写EEPROM/LED/相机预览…一个大代理面,**当前设计文档未细化**)或端口让渡。这是独立子任务,且驱动电机受安全红线(§178 需用户在场)。**本阶段交付让路契约(/serial/pause|resume,已验)作基础**;调试页完整驱动 = 需设计(命令代理)+ 受监督真机验。
+- **核实**:控制端三端点真机实测;operate ControlClient harness 实跑;两端编译 0 错误;6 单测过。控制端+operate端阶段2 已分两次提交。
+- **下一步**:阶段3(退役删 ivf_tl_ControlTest + operate 开机自启 + ComBin 两套栈去重〔含 D1-10 oplog〕+ 部署文档)。调试页借串口命令代理 + M-01~M-07 留专项。

+ 1 - 1
项目文档/进度/工作计划表.md

@@ -26,7 +26,7 @@
 | 阶段 | 内容 | 状态 | 出口验收 |
 |------|------|------|----------|
 | **阶段1** | control 独立进程骨架 | 🟢 代码完成·真机闭环打通(待并 main) | control 独立 exe 能起✓、HTTP探活/读状态✓、续命✓、单实例✓、硬件获取✓、**真机自控环运行✓**;阻塞闭环的 D1-08 串口握手死锁已修复 |
-| **阶段2** | 监控补全 + 调试借串口 + 受护栏停止 | ☐ 未开始 | 监控页显示完整(各舱活动/线程心跳/串口借用);调试页跨进程借串口(control 让路)调完恢复;受护栏停止按钮能安全停 control |
+| **阶段2** | 监控补全 + 调试借串口 + 受护栏停止 | 🟢 监控/受护栏停止/借串口让路 已实现+真机验;调试页完整驱动待设计 | 监控页跨进程 /status 显示完整✓;受护栏 /shutdown 安全停✓;/serial 让路✓(调试页完整借串口需命令代理设计+受监督真机) |
 | **阶段3** | 清理老壳 + 装机收尾 | ☐ 未开始 | 退役删 ivf_tl_ControlTest;operate 开机自启;ComBin 两套栈去重;部署文档;全新部署一次到位 |
 
 ---

+ 9 - 4
项目文档/进度/待验证清单.md

@@ -29,13 +29,18 @@
 > - ✗ **D1-10 oplog 缺口(归阶段3,非闭环阻塞)**:核查发现全 `OperationLogger` 埋点都在 **operate 侧**(ivf_tl_Operate + operate 的 ivf_tl_Services/HttpHelper + operate 的 ivf_tl_Entity 的 Camera/ComBin),**control 子树零埋点**。control 硬件操作的 oplog 收口本就挂在 operate 的**另一套 ComBin/Camera 栈**(=阶段3 "ComBin 两套栈去重 G1-2")——故给 ControlHost 单加 `InitOperationLog` 也不会产 oplog(control 自己串口栈无埋点)。归阶段3 两栈去重一并处理。control 诊断走 `RunRecord/HouseComRecord` 文件日志(本次定位全程靠它),业务数据入库走 MQTT,**闭环不受影响**。
 > - 旁注:`ServiceDishAndBalanceData 接口返回失败`=无皿时服务器无培养记录、回退本地,正常非缺陷。
 
-## 阶段2 · 监控补全 + 调试借串口 + 受护栏停止(待阶段2拆计划后补全)
+## 阶段2 · 监控补全 + 调试借串口 + 受护栏停止
 
 | 编号 | 验证项 | 门控 | 状态 |
 |------|--------|------|------|
-| D2-01 | 监控页跨进程显示完整(各舱实时活动/线程心跳/串口借用) | 运行 | ☐ |
-| D2-02 | operate 调试页跨进程借串口:control 让路→调试可用→退出恢复采集(原 V-012) | **真机** | ☐ |
-| D2-03 | 受护栏停止按钮(二次确认+工程师口令)能安全停 control | 运行 | ☐ |
+| D2-01 | 监控页跨进程显示完整(/status 三块:活动/阀态/借用让路 + 心跳/磁盘/链路) | 运行 | ☑ 真机验证 |
+| D2-02 | 调试借串口:control 让路(暂停该舱采集)→ 恢复(原 V-012) | **真机** | ◑ 让路契约已验/调试页完整驱动待设计 |
+| D2-03 | 受护栏停止(二次确认+工程师口令)能安全停 control | 运行 | ☑ 真机验证 |
+
+> **2026-06-22 阶段2 实测说明(详见交接卡同日段)**:
+> - **D2-01 ☑**:control 端 `/status` 返回完整 `MonitorSnapshot`(补 §6 三块:`WorkingType/ValveState/CapturePausedByGate`);operate 端 `ControlClient.GetStatusSnapshot()`(harness 实跑真代码)往返反序列化 10 舱、真温 37℃、三块字段正确;`ServiceMonitorViewModel.Refresh` 已由"同进程 AppData"改为 HTTP /status;监控页 XAML 加三列。
+> - **D2-03 ☑**:`/shutdown` 错口令→403 拒绝、对口令 `tl13579`→200 安全停机(`HAL.ShutdownAll` 关硬件 + 进程退出 + 7 COM 口全释放,非僵尸);operate 端 `ShutdownControlCommand`(二次确认+`Microsoft.VisualBasic.InputBox` 口令)+ 监控页受护栏按钮。
+> - **D2-02 ◑**:`/serial/pause {houseSn}` 实测——舱2 `CapturePausedByGate=true` 且 COM4 串口停发(control 让路,**不驱动电机**)→ `/serial/resume` 恢复;operate `ControlClient.SerialPause/Resume` 验证生效。**但调试页完整借串口驱动在拆分下断链**:debug 页原 `gate.Acquire` 借**同进程 HAL 同一物理句柄**(`HouseDebugPageViewModel:256`),拆分后 operate 进程 HAL 是空单例、拿不到 control 持有的串口——需 **control 暴露串口/相机命令代理**(当前设计文档未细化的大改面)+ 驱动电机受安全红线门控(设计 §178 需用户在场)。让路契约(/serial/pause|resume)已就位作基础,调试页完整驱动列独立子任务(需设计+受监督真机验)。
 
 ## 阶段3 · 清理 + 装机(待阶段3拆计划后补全)
 

+ 9 - 13
项目文档/进度/进度数据.js

@@ -1,25 +1,21 @@
 // 实时面板数据源(监控面板.html 读 window.PROGRESS_DATA)。每推进一步更新本文件。
 window.PROGRESS_DATA = {
   project: "operate/control 双进程拆分",
-  generatedAt: "2026-06-22 20:35",
-  phase: "阶段1 · control 独立进程骨架(代码完成·端到端闭环全实证,待并 main)",
-  currentTask: "Task1-7全过+D1-08死锁修复;operate→control真实代码实跑(拉起/复用/续命)+数据入库DB铁证(house_collect/alarm_data)",
-  note: "用户选A修死锁打通闭环。harness跑operate真实ControlProcessLauncher验证拉起/复用/续命;108库house_collect(37℃真温)+alarm_data新鲜入库实证。剩:operate WPF外壳实跑(僵尸门控/重启)+D1-09 SQLite+D1-10归阶段3两栈+M区+阶段2/3拆计划。",
+  generatedAt: "2026-06-22 22:30",
+  phase: "阶段2 已实现+真机自验(监控补全/受护栏停止/借串口让路);进阶段3",
+  currentTask: "阶段1全过+operate真外壳E2E+数据入库;阶段2控制端三端点(/status/shutdown/serial)真机全验+operate端ControlClient+监控页",
+  note: "阶段2:/status补全三块+/shutdown受护栏(口令安全停机释放硬件)+/serial借串口让路(不驱动电机) 真机全验;operate端ControlClient+监控页跨进程读+受护栏按钮(harness实跑)。调试页完整借串口待命令代理设计(安全红线门控)。下一步阶段3。",
   milestones: [
     { name: "阶段1 · control 独立进程骨架", tasks: [
-      { id: "Task1", name: "新建 ivf_tl_ControlHost 项目骨架", status: "☑" },
-      { id: "Task2", name: "HostArgs 命令行参数解析(4单测)", status: "☑" },
-      { id: "Task3", name: "StatusDto + /ping 返回体(2单测)", status: "☑" },
-      { id: "Task4", name: "内嵌 HttpListener(/ping /status)", status: "☑" },
-      { id: "Task5", name: "Program.cs 完整启动序(Mutex+启动序+HTTP驻留)", status: "☑" },
-      { id: "Task6", name: "operate 改为拉起独立 control", status: "☑" },
-      { id: "Task7", name: "[真机]端到端验证(起/连/续命/单实例/采集自控环/数据入库)全过", status: "☑" }
+      { id: "Task1-7", name: "全过+D1-08死锁修复+operate真外壳E2E+数据入库DB铁证", status: "☑" }
     ]},
     { name: "阶段2 · 监控补全+借串口+受护栏停止", tasks: [
-      { id: "阶段2", name: "待阶段1合并后拆计划", status: "☐" }
+      { id: "D2-01", name: "监控页跨进程/status三块(harness验证)", status: "☑" },
+      { id: "D2-03", name: "受护栏停止/shutdown(口令+安全停机释放硬件)", status: "☑" },
+      { id: "D2-02", name: "借串口/serial让路(验证);调试页完整驱动待命令代理设计", status: "◑" }
     ]},
     { name: "阶段3 · 清理老壳+装机收尾", tasks: [
-      { id: "阶段3", name: "退役ControlTest+开机自启+ComBin两栈去重(含D1-10 oplog)+部署文档", status: "☐" }
+      { id: "阶段3", name: "退役ControlTest+开机自启+ComBin两栈去重(含D1-10)+部署文档", status: "☐" }
     ]}
   ],
   pending: [

+ 17 - 14
项目文档/进度/进度状态.yaml

@@ -1,25 +1,28 @@
 # 续接断点状态(机器可解析)。换会话/换电脑后首先读它定位。
 # 状态取值: 未开始 / 进行中 / 完成 / 代码完成待验证
 # 纪律:本字段只存【当前断点】,历史细节进 交接卡.md(见 CLAUDE.md 第三节)。
-更新时间: 2026-06-22 阶段1 闭环打通:Task1-6 代码完成,Task7 真机自主验证全通过;D1-08 串口握手死锁(HAL借用ComBin重开不复活发送线程)已定位+修复+真机 red→green 验证(started:true/tlSn/温压门换气自控环运行)
+更新时间: 2026-06-22 阶段1完成(含operate真外壳E2E)+阶段2实现:控制端/status监控补全+/serial借串口让路+/shutdown受护栏停止 三端点真机全验,operate端ControlClient+监控页跨进程读+受护栏按钮(harness实跑验证)。调试页完整借串口待命令代理设计
 当前任务: >
-  【阶段1 进程拆分 = 代码完成 + 真机闭环打通(D1-07/08 通过)
-  · 已完成:Task1-6 全提交(6单测过);Task7 真机自主验证(UAC静默提权,无需用户配合):
-    control 独立起✓/HTTP✓/单实例✓/6相机+7COM硬件获取✓/续命✓;
-    用户选A方案,修复 ComBin.OpenPort 复活发送线程死锁→真机 started:true、自控环运行、HouseComRecord 恢复
-  · 顺带发现(预存,非死锁/非拆分):D1-09 control 本地 SQLite InitTables AUTOINCREMENT 建表失败(不阻塞运行)。
-  · 下一步:① 清僵尸20268(需重启)后复测 operate 端完整链路;② D1-09 SQLite专项;③ M-01~M-07 降级专项;
-    ④ 阶段2 拆计划。建议 feature 分支合并 main + 推送
-  续接读:本文件 + 交接卡末两段(阶段1落地 + D1-08死锁修复)+ 待验证清单 D1-01~D1-09 + 阶段1计划
+  【阶段2 已实现+真机自验(监控补全/受护栏停止/借串口让路);进阶段3
+  · 阶段1:Task1-7全过+D1-08死锁修复+operate真外壳E2E实跑(真operate→拉起control→续命)+数据入库DB铁证。
+  · 阶段2:控制端 /status(§6三块)+/shutdown(口令tl13579安全停机释放硬件)+/serial/pause|resume(让路停轮询不驱动电机)
+    三端点真机全验;operate端 ControlClient+ServiceMonitorViewModel跨进程读+受护栏停止按钮(harness实跑反序列化10舱+借串口让路验证)
+  · 阶段2余留:调试页完整借串口驱动——拆分后operate拿不到control持有的串口,需control暴露串口/相机命令代理(设计未细化)
+    +驱动电机受安全红线(§178需用户在场)。让路契约已就位作基础。
+  · 下一步:阶段3(退役删ivf_tl_ControlTest+operate开机自启+ComBin两栈去重〔含D1-10〕+部署文档)
+  续接读:本文件 + 交接卡末三段(阶段1落地/D1-08修复/operate外壳/阶段2)+ 待验证清单 D1/D2 + 设计文档§5-6
 说明: >
-  旧任务(三项目合并 M0-M8):合并代码完成、真机验收整体未做、有降级遗留(M-01~M-07)。
-  本次阶段1 真机实测**坐实并修复**了合并 control 的首个真机硬伤:serialBin/HAL 借用 ComBin 串口握手死锁
-  (旧 operate 僵尸 20268 卡死同处即此因),双进程改造骨架 + 真机采集自控环闭环已打通。
+  阶段2 控制端三端点(/status补全、/shutdown受护栏、/serial借串口让路)真机全验;operate端跨进程客户端+监控页+受护栏按钮已接。
+  调试页完整借串口在拆分下需额外设计(串口/相机命令代理),且驱动电机受安全红线门控,列独立子任务。
 阶段概览:
   - id: 阶段1
     名称: control 独立进程骨架(能起/能连/operate关了续命)
+    状态: 完成
+    备注: "Task1-7全过+D1-08死锁修复+operate真外壳E2E实跑+数据入库DB铁证。剩D1-09 SQLite/M-01~M-07专项。"
+  - id: 阶段2
+    名称: 监控补全 + 调试借串口 + 受护栏停止
     状态: 代码完成待验证
-    备注: "Task1-6 代码完成+提交;Task7 真机:独立起/HTTP/单实例/硬件获取/续命 全通过;D1-08 串口握手死锁已修复,真机 started:true、温压门换气自控环运行、闭环打通。剩 operate端完整链路复测(需清僵尸/重启)+ D1-09 SQLite专项。"
+    备注: "控制端/status补全+/shutdown受护栏+/serial让路 三端点真机全验;operate端ControlClient+监控页跨进程读+受护栏按钮(harness验证)。调试页完整借串口待命令代理设计+受监督真机。"
   - id: 阶段2
     名称: 监控补全 + 调试借串口 + 受护栏停止
     状态: 未开始
@@ -28,4 +31,4 @@
     名称: 清理老壳 + 装机收尾
     状态: 未开始
     备注: "退役删ivf_tl_ControlTest脏壳 + operate开机自启 + ComBin两套栈去重(G1-2) + 部署文档。待阶段2完成后拆计划"
-下一步: 清僵尸20268(需重启)后复测operate端完整链路 + D1-09 SQLite专项 + M-01~M-07降级专项 + 阶段2拆计划;建议feature合并main+推送
+下一步: 阶段3(退役删ivf_tl_ControlTest+operate开机自启+ComBin两栈去重〔含D1-10 oplog〕+部署文档);调试页借串口命令代理+M-01~M-07+D1-09 留专项;建议feature合并main+推送