V6.7.5_beta

This commit is contained in:
2026-07-22 11:47:13 +08:00
parent e90e80000f
commit 50c4999d90
26 changed files with 798 additions and 743 deletions
+217
View File
@@ -0,0 +1,217 @@
# m_RightBtn(喷嘴开启)可用性真值表
## 0) 你要的重点:只整理“上层可点(E=true)”
这一节只看上层传给 `setReclaimOpenBtnStatus(E)` 的 E,不包含底层拦截(airPushing / RFID)。
关键调用位置:
- [mainwidget.cpp](mainwidget.cpp#L863)
- [InkJetPrinter.cpp](InkJetPrinter.cpp#L1094)
- [InkJetPrinter.cpp](InkJetPrinter.cpp#L2555)
- [InkJetPrinter.cpp](InkJetPrinter.cpp#L2581)
上层 E=true 的来源只有 4 类:
- 停止打印后:`currReclaimTankPos == 0` 时传 true。
- 自检完成瞬间:直接传 true。
- 回收槽状态机:`reclaimTankstatus == 2` 时传 true。
- 回收槽状态机:`reclaimTankstatus == 4` 时传 true。
## 0.1) 上层 E=true 精简真值表(不含 A/R)
定义四个上层布尔量:
- S:自检完成事件(self check done edge)
- T:停止打印事件且 `currReclaimTankPos == 0`
- R2:`reclaimTankstatus == 2`
- R4:`reclaimTankstatus == 4`
则上层可点条件:
E = S OR T OR R2 OR R4
只看 E=true 的最小真值表(命中任一来源即可):
| S | T | R2 | R4 | E |
|---|---|---|---|---|
| 1 | 0 | 0 | 0 | 1 |
| 0 | 1 | 0 | 0 | 1 |
| 0 | 0 | 1 | 0 | 1 |
| 0 | 0 | 0 | 1 | 1 |
说明:
- 这 4 行是“最小命中表”。多项同时为 1(例如 T=1 且 R2=1)也仍然是 E=1。
## 0.2) 上层 E=false 的主要覆盖路径(帮助你理解为何看起来复杂)
下面这些路径会频繁把 E 拉回 false:
- 开始打印后立即置 false:[mainwidget.cpp](mainwidget.cpp#L824)
- 打印中周期置 false:[mainwidget.cpp](mainwidget.cpp#L2594)
- 自检启动/进行中置 false:[InkJetPrinter.cpp](InkJetPrinter.cpp#L1059)
- 排气过程周期置 false:[mainwidget.cpp](mainwidget.cpp#L1034)
- 齿轮泵未进入运行态时置 false:[InkJetPrinter.cpp](InkJetPrinter.cpp#L710)
- 关机流程置 false:[mainwidget.cpp](mainwidget.cpp#L219)
所以“上层 E=true”通常是阶段性信号,可能很快被其他流程覆盖为 false。
## 0.3) 我建议的上层简化口径(先统一 E,再叠加底层拦截)
你可以把现有分散调用统一理解为两步:
1) 先算上层意图 E:
```cpp
bool upperEnable = selfCheckDoneEdge
|| (stopPrint && currReclaimTankPos == 0)
|| (reclaimTankstatus == 2)
|| (reclaimTankstatus == 4);
```
2) 再算最终可点:
```cpp
bool finalEnable = upperEnable && !airPushing && !rfidBlocked;
```
这样分层后,排查会非常直接:
- 先问“上层想不想给点”(E)
- 再问“底层有没有拦截”(A/R)
## 1) 最终判定公式
m_RightBtn 最终是否可用,不只看调用处传入的 enable,还会在 MainWidget 内再次过滤。
关键实现位置:
- [setReclaimOpenBtnStatus 定义](mainwidget.cpp#L959)
- [RFID 条件过滤](mainwidget.cpp#L961)
- [airPushing 条件过滤](mainwidget.cpp#L968)
- [最终 setEnabled](mainwidget.cpp#L971)
可用公式:
FinalEnabled = E AND (NOT A) AND (NOT R)
变量定义:
- E:上层调用 setReclaimOpenBtnStatus(E) 时传入的 enable
- A:sysPara->status.airPushing(是否正在排气)
- R:RFID 层拦截(仅在编译启用 __RFID_CARD 时有效)
- inkCardTimeOut 或 solventCardTimeOut 或 needMaintenance 任一为真,则 R=1
说明:
- 若未启用 __RFID_CARD,R 恒为 0。
## 2) 最终可用真值表(硬条件)
| E | A | R | FinalEnabled |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 0 |
| 1 | 1 | 1 | 0 |
结论:
- 唯一能点的组合是 E=1、A=0、R=0。
## 2.1) 只看“按钮可用=true”的最小真值表
如果你只关心“什么时候能点”,那真值表可以压缩成 1 行:
| E | A | R | FinalEnabled |
|---|---|---|---|
| 1 | 0 | 0 | 1 |
反向速记(现场排查更快):
- 只要满足以下任一条件,按钮就一定不可用:
- E=0(上层当前不允许)
- A=1(正在排气)
- R=1(RFID 拦截)
## 2.2) 工程化简化版(建议你按这个理解)
把复杂条件改写成一个“守卫函数”,先算出 3 个阻塞原因,再统一决定可用性。
建议逻辑:
```cpp
// 只表达逻辑,不改变现有业务行为
bool blockedByRFID = hasRFIDGuard && (inkCardTimeOut || solventCardTimeOut || needMaintenance);
bool blockedByAirPush = airPushing;
bool blockedByUpperLayer = !upperEnable;
bool finalEnabled = !blockedByRFID && !blockedByAirPush && !blockedByUpperLayer;
```
对应到 UI 语义:
- 可用态:Ready
- 不可用态:BlockedByUpperLayer / BlockedByAirPush / BlockedByRFID
这样简化后的好处:
- 读代码时从“多处 setReclaimOpenBtnStatus(true/false)”切换为“先看谁在设置阻塞原因”。
- 打日志更清晰:可直接输出第一个阻塞原因,而不是只看到按钮被置灰。
- 后续扩展更稳:新增条件只需新增一个 blockedByX,不会到处散落 if。
建议落地步骤(不改行为,只提可维护性):
- 第一步:在 MainWidget 内新增一个 `computeReclaimOpenBtnEnabled()`,所有按钮状态更新都走它。
- 第二步:在 `setReclaimOpenBtnStatus` 里补充调试日志(仅 debug),打印 E/A/R。
- 第三步:把状态机处的“直接 true/false”改成“设置上层意图 upperEnable”,统一在一个点算最终值。
## 3) E(上层 enable)常见取值来源表
| 场景 | 调用代码 | 传入 E |
|---|---|---|
| 开始打印后 | [mainwidget.cpp](mainwidget.cpp#L824) | 0 |
| 停止打印后,按回收槽位置决定 | [mainwidget.cpp](mainwidget.cpp#L863) | currReclaimTankPos == 0 |
| 关机流程(回收槽未关) | [mainwidget.cpp](mainwidget.cpp#L219) | 0 |
| 排气进行中(周期) | [mainwidget.cpp](mainwidget.cpp#L1034) | 0 |
| 打印中且自检完成(周期) | [mainwidget.cpp](mainwidget.cpp#L2594) | 0 |
| 自检开始 | [InkJetPrinter.cpp](InkJetPrinter.cpp#L1059) | 0 |
| 自检完成 | [InkJetPrinter.cpp](InkJetPrinter.cpp#L1094) | 1 |
| 回收槽状态机:状态=1或2 时 | [InkJetPrinter.cpp](InkJetPrinter.cpp#L2555) | reclaimTankstatus == 2 |
| 回收槽状态机:状态=4(保持) | [InkJetPrinter.cpp](InkJetPrinter.cpp#L2581) | 1 |
| 齿轮泵未进入运行态 | [InkJetPrinter.cpp](InkJetPrinter.cpp#L710) | 0 |
## 4) 按回收槽状态机的可用性(忽略 A/R 时的 E)
这张表只表示状态机“想给”的 E,最终仍需经过第 2 节硬条件过滤。
| reclaimTankstatus | 语义 | E(状态机给值) | 代码位置 |
|---|---|---|---|
| 1 | 开槽中 | 0 | [InkJetPrinter.cpp](InkJetPrinter.cpp#L2555) |
| 2 | 关槽中 | 1 | [InkJetPrinter.cpp](InkJetPrinter.cpp#L2555) |
| 4 | 保持 | 1 | [InkJetPrinter.cpp](InkJetPrinter.cpp#L2581) |
| 5 | 开到位 | 未在该分支直接设置 E(通常由其他逻辑接管) | [InkJetPrinter.cpp](InkJetPrinter.cpp#L2520) |
| 6 | 关到位 | 未在该分支直接设置 E(通常随后可再次开槽) | [InkJetPrinter.cpp](InkJetPrinter.cpp#L2561) |
| 0x11/0x12 | 卡滞/异常 | 不会给出稳定可用态,偏禁用与告警处理 | [InkJetPrinter.cpp](InkJetPrinter.cpp#L2546) |
## 5) 点击行为补充(按钮可用后点下去会发生什么)
入口:
- [on_m_RightBtn_clicked](mainwidget.cpp#L1266)
行为分支:
- 若 reclaimTankBlockedAppending 为真:先弹告警确认,不直接开槽。
- [mainwidget.cpp](mainwidget.cpp#L1300)
- 若 canRunAirPushing 为真 且 currReclaimTankPos==0:先排气,再开槽。
- [mainwidget.cpp](mainwidget.cpp#L1270)
- 其他情况:直接调用 reclaimTanOpen。
- [mainwidget.cpp](mainwidget.cpp#L1298)
补充状态位来源:
- canRunAirPushing 在开槽动作中会被置为 false。
- [mainwidget.cpp](mainwidget.cpp#L1135)
- 自检完成、关槽完成后会恢复为 true。
- [InkJetPrinter.cpp](InkJetPrinter.cpp#L1098)
- [InkJetPrinter.cpp](InkJetPrinter.cpp#L2571)
## 6) 一句话版本
m_RightBtn 可用的必要且充分条件是:上层当前允许开启(E=1)+ 不在排气(A=0)+ RFID 不拦截(R=0)。在实际运行中,E 主要由“自检状态、打印状态、回收槽状态机、故障流程”共同驱动。
## 7) 给现场同事的超短口令
先看 E,再看 A,再看 R:
- E 由业务状态机决定“想不想让你点”。
- A/R 决定“即使想让你点,也要不要强制拦截”。
- 只有 E=1 且 A=0 且 R=0,m_RightBtn 才会真的可点。