Files
VX5_KRO_GearPump/m_RightBtn_availability_truth_table.md
T
2026-07-22 11:47:13 +08:00

8.3 KiB
Raw Blame History

m_RightBtn(喷嘴开启)可用性真值表

0) 你要的重点:只整理“上层可点(E=true)”

这一节只看上层传给 setReclaimOpenBtnStatus(E) 的 E,不包含底层拦截(airPushing / RFID)。

关键调用位置:

上层 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:

所以“上层 E=true”通常是阶段性信号,可能很快被其他流程覆盖为 false。

0.3) 我建议的上层简化口径(先统一 E,再叠加底层拦截)

你可以把现有分散调用统一理解为两步:

  1. 先算上层意图 E:
bool upperEnable = selfCheckDoneEdge
                || (stopPrint && currReclaimTankPos == 0)
                || (reclaimTankstatus == 2)
                || (reclaimTankstatus == 4);
  1. 再算最终可点:
bool finalEnable = upperEnable && !airPushing && !rfidBlocked;

这样分层后,排查会非常直接:

  • 先问“上层想不想给点”(E)
  • 再问“底层有没有拦截”(A/R)

1) 最终判定公式

m_RightBtn 最终是否可用,不只看调用处传入的 enable,还会在 MainWidget 内再次过滤。

关键实现位置:

可用公式:

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 个阻塞原因,再统一决定可用性。

建议逻辑:

// 只表达逻辑,不改变现有业务行为
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 0
停止打印后,按回收槽位置决定 mainwidget.cpp currReclaimTankPos == 0
关机流程(回收槽未关) mainwidget.cpp 0
排气进行中(周期) mainwidget.cpp 0
打印中且自检完成(周期) mainwidget.cpp 0
自检开始 InkJetPrinter.cpp 0
自检完成 InkJetPrinter.cpp 1
回收槽状态机:状态=1或2 时 InkJetPrinter.cpp reclaimTankstatus == 2
回收槽状态机:状态=4(保持) InkJetPrinter.cpp 1
齿轮泵未进入运行态 InkJetPrinter.cpp 0

4) 按回收槽状态机的可用性(忽略 A/R 时的 E)

这张表只表示状态机“想给”的 E,最终仍需经过第 2 节硬条件过滤。

reclaimTankstatus 语义 E(状态机给值) 代码位置
1 开槽中 0 InkJetPrinter.cpp
2 关槽中 1 InkJetPrinter.cpp
4 保持 1 InkJetPrinter.cpp
5 开到位 未在该分支直接设置 E(通常由其他逻辑接管) InkJetPrinter.cpp
6 关到位 未在该分支直接设置 E(通常随后可再次开槽) InkJetPrinter.cpp
0x11/0x12 卡滞/异常 不会给出稳定可用态,偏禁用与告警处理 InkJetPrinter.cpp

5) 点击行为补充(按钮可用后点下去会发生什么)

入口:

行为分支:

  • 若 reclaimTankBlockedAppending 为真:先弹告警确认,不直接开槽。
  • 若 canRunAirPushing 为真 且 currReclaimTankPos==0:先排气,再开槽。
  • 其他情况:直接调用 reclaimTanOpen。

补充状态位来源:

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 才会真的可点。