480 lines
19 KiB
Markdown
480 lines
19 KiB
Markdown
# 2026-07-07 AXIS 主控制按钮调用链与 Web 完善指南
|
||
|
||
## 1. 文档目标
|
||
|
||
本文在以下资料基础上整理一个可执行的 Web 项目完善指南:
|
||
|
||
- `/home/mes123456/cnc_wams/linuxcnc`
|
||
- `/home/mes123456/cnc_wams/wasm-port`
|
||
- `/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan`
|
||
- `/home/mes123456/cnc_wams/项目分析/AXIS主控制按钮调用链与WASM完善指南.md`
|
||
- `/home/mes123456/cnc_wams/项目分析/AXIS主界面按钮调用链与WASM完善建议.md`
|
||
|
||
重点覆盖 AXIS 主界面“急停、上电、Home、执行、暂停、单步执行”的调用链、先决条件、状态记录机制,以及 Web 项目后续应如何按 LinuxCNC task/motion 语义继续完善。
|
||
|
||
## 2. 总体结论
|
||
|
||
LinuxCNC AXIS 按钮不是直接修改界面状态,而是走统一控制链:
|
||
|
||
```text
|
||
AXIS Tcl/Tk 按钮
|
||
-> axis.py 回调
|
||
-> linuxcnc.command() Python C++ 扩展
|
||
-> EMC_* NML 命令
|
||
-> milltask/emctaskmain.cc emcTaskPlan()
|
||
-> emcTaskIssueCommand()
|
||
-> emctask.cc task 状态动作
|
||
-> taskintf.cc 写 EMCMOT_* motion 命令
|
||
-> motion/command.c、control.c、homing.c 更新实时状态
|
||
-> emcMotionUpdate()/emcTaskUpdate() 写 emcStatus
|
||
-> linuxcnc.stat().poll()
|
||
-> AXIS Tk 变量 trace 刷新按钮可用性
|
||
```
|
||
|
||
Web 项目必须把状态模型收敛到同一组事实字段,而不是只用 `runState` 或按钮 active 样式:
|
||
|
||
| LinuxCNC 字段 | Web 当前/目标字段 | 用途 |
|
||
|---|---|---|
|
||
| `task.state` | `machine.taskState` | `estop`、`estop-reset`、`on` 的主门禁 |
|
||
| `task.mode` | `machine.mode` | `manual`、`auto`、`mdi` 的命令门禁 |
|
||
| `task.interpState` | `machine.interpState` | `idle`、`reading`、`paused`、`waiting` |
|
||
| `task.task_paused` | `machine.taskPaused` | task/interpreter 层暂停 |
|
||
| `motion.traj.paused` | `machine.motionPaused` | motion/trajectory 层暂停 |
|
||
| `motion.traj.single_stepping` | 目标新增/统一为 `machine.singleStepping` | 单步执行可见状态 |
|
||
| `motion.joint[n].homed` | `machine.allHomed` 和目标 `machine.homed[]` | Home/Run 门禁 |
|
||
| IO estop + motion enabled | `estopActive` + `powerOn` 派生 `taskState` | 对标 `determineState()` |
|
||
|
||
## 3. AXIS UI 层按钮门禁
|
||
|
||
AXIS 的按钮可点状态在 `linuxcnc/share/axis/tcl/axis.tcl:update_state()` 集中维护:
|
||
|
||
| 按钮 | AXIS UI 可点条件 |
|
||
|---|---|
|
||
| 急停 | 始终可点;当前 ESTOP 时执行解除急停,否则执行急停 |
|
||
| 上电/下电 | `task_state != STATE_ESTOP`;但真正上电只在 `STATE_ESTOP_RESET` 分支 |
|
||
| Home/Unhome/Zero | `task_state == STATE_ON && interp_state == INTERP_IDLE` |
|
||
| Run | `task_state == STATE_ON && interp_state == INTERP_IDLE` |
|
||
| Step | `task_state == STATE_ON && taskfile != ""` |
|
||
| 菜单 Pause | `task_state == STATE_ON && interp_state in {READING, WAITING}` |
|
||
| 菜单 Resume | `task_state == STATE_ON && interp_state == PAUSED` |
|
||
| 工具栏 Pause/Resume | `task_state == STATE_ON && interp_state != IDLE` |
|
||
| Stop | `task_state == STATE_ON && interp_state != IDLE` |
|
||
|
||
Python 回调还有二次门禁,例如 `manual_ok()` 要求 `STATE_ON`,并要求解释器空闲或 MDI 队列可接收命令。Web 项目中的 `app/src/state/linuxcnc-task-policy.js` 应继续作为唯一按钮门禁入口,避免 UI 组件各自判断。
|
||
|
||
## 4. 急停
|
||
|
||
### 4.1 LinuxCNC 调用链
|
||
|
||
```text
|
||
axis.py estop_clicked()
|
||
-> s.poll()
|
||
-> 当前 STATE_ESTOP: c.state(STATE_ESTOP_RESET)
|
||
否则: c.state(STATE_ESTOP)
|
||
-> emcmodule.cc state()
|
||
-> EMC_TASK_SET_STATE
|
||
-> emctaskmain.cc emcTaskPlan()
|
||
-> emcTaskIssueCommand()
|
||
-> emctask.cc emcTaskSetState()
|
||
```
|
||
|
||
`EMC_TASK_SET_STATE` 在 ESTOP、ESTOP_RESET、OFF、ON 多状态下都是 immediate command,可在运动中触发。
|
||
|
||
### 4.2 task/motion 状态动作
|
||
|
||
`emcTaskSetState(ESTOP)` 的关键动作:
|
||
|
||
- `emcMotionAbort()` 中止 motion;
|
||
- `emcSpindleAbort()` 中止主轴;
|
||
- `emcAuxEstopOn()` 置 IO 急停;
|
||
- `emcTrajDisable()` 下发 `EMCMOT_DISABLE`;
|
||
- `emcTaskAbort()` 清解释器、队列、暂停、单步;
|
||
- `emcIoAbort(TASK_STATE_ESTOP)` 通知 IO;
|
||
- `emcJointUnhome(-2)` 清除 `VOLATILE_HOME` joint 的 homed;
|
||
- `emcTaskPlanSynch()` 同步解释器。
|
||
|
||
实际 `task.state` 由 `emctask.cc:determineState()` 周期推导:
|
||
|
||
```text
|
||
io.aux.estop == true -> ESTOP
|
||
io.aux.estop == false && motion enabled false -> ESTOP_RESET
|
||
io.aux.estop == false && motion enabled true -> ON
|
||
```
|
||
|
||
### 4.3 Web 完善要求
|
||
|
||
当前 `store.js` 已有 `ESTOP`/`RESET` 分支,但后续应补齐:
|
||
|
||
- 急停时同步清 `machine.motionPaused=false`、`machine.singleStepping=false`、`taskHalPauseLock=null`、`programRuntimeFeedback.currentVelocity=0`。
|
||
- 急停时只清 volatile home,而不是无条件清全部 Home;如果 Web 暂无 `VOLATILE_HOME` 配置,需在文档和 evidence 中声明 `xyzbc-trt` 的处理策略。
|
||
- `taskState` 不应由 `powerOn` 简单替代,应通过 `deriveTaskState({ estopActive, motionEnabled })` 一处派生。
|
||
- Task/HAL runtime 可用时,UI 先进入安全预期状态,但最终以 `readStatus()` 回写为准。
|
||
|
||
## 5. 上电/下电
|
||
|
||
### 5.1 LinuxCNC 调用链
|
||
|
||
```text
|
||
axis.py onoff_clicked()
|
||
-> 当前 STATE_ESTOP_RESET: c.state(STATE_ON)
|
||
否则: c.state(STATE_OFF)
|
||
-> emcmodule.cc state()
|
||
-> EMC_TASK_SET_STATE
|
||
-> emctask.cc emcTaskSetState(ON/OFF)
|
||
-> taskintf.cc emcTrajEnable()/emcTrajDisable()
|
||
-> motion/command.c EMCMOT_ENABLE/EMCMOT_DISABLE
|
||
```
|
||
|
||
上电不是“非急停即可开机”。AXIS 的 Python 分支要求当前正好是 `STATE_ESTOP_RESET`,否则按钮发送 `STATE_OFF`。
|
||
|
||
### 5.2 task/motion 状态动作
|
||
|
||
`emcTaskSetState(ON)`:
|
||
|
||
- `emcTrajEnable()` 写 `EMCMOT_ENABLE`;
|
||
- motion 侧要求 HAL `motion.enable` 输入为真,否则报错;
|
||
- enable 在 motion 控制周期中完成,随后 `determineState()` 才推导出 `STATE_ON`。
|
||
|
||
`emcTaskSetState(OFF)`:
|
||
|
||
- 中止 motion、主轴、IO;
|
||
- `emcTrajDisable()`;
|
||
- `emcTaskAbort()`;
|
||
- `emcJointUnhome(-2)`;
|
||
- 同步解释器。
|
||
|
||
### 5.3 Web 完善要求
|
||
|
||
`TOGGLE_POWER` 应严格保持:
|
||
|
||
- 只有 `machine.taskState === "estop-reset"` 时执行 ON;
|
||
- 当前为 `on` 时执行 OFF;
|
||
- 当前为 `estop` 时按钮应不可用或返回 `power blocked: reset ESTOP first`,不要把 ESTOP 下的点击伪装成上电。
|
||
|
||
建议在 `linuxcnc-task-policy.js` 增加 `canPowerToggle` 和 `powerAction`:
|
||
|
||
```text
|
||
taskState == estop -> disabled
|
||
taskState == estop-reset -> action ON
|
||
taskState == on -> action OFF
|
||
```
|
||
|
||
## 6. Home
|
||
|
||
### 6.1 LinuxCNC 调用链
|
||
|
||
```text
|
||
axis.py home_all_joints()/home_joint()
|
||
-> manual_ok()
|
||
-> ensure_mode(MODE_MANUAL)
|
||
-> go_home(-1 或 joint)
|
||
-> set_motion_teleop(0)
|
||
-> c.home(joint)
|
||
-> emcmodule.cc home()
|
||
-> EMC_JOINT_HOME
|
||
-> emctaskmain.cc emcTaskIssueCommand()
|
||
-> taskintf.cc emcJointHome()
|
||
-> motion/command.c EMCMOT_JOINT_HOME
|
||
-> homing.c do_home_joint()/do_homing()
|
||
```
|
||
|
||
motion 侧 `EMCMOT_JOINT_HOME` 要求:
|
||
|
||
- 当前 `motion_state == EMCMOT_MOTION_FREE`,即 joint/free mode;
|
||
- `motion.homing-inhibit` 为 false;
|
||
- 当前没有 homing 正在执行;
|
||
- motion enable 为真;
|
||
- `joint=-1` 表示 Home All。
|
||
|
||
### 6.2 状态记录方式
|
||
|
||
`homing.c` 用每关节 `H[jno]` 记录:
|
||
|
||
- `home_state`:`HOME_IDLE`、`HOME_START`、`HOME_SEARCH_*`、`HOME_FINISHED`、`HOME_ABORT` 等;
|
||
- `homing`:当前关节正在回零;
|
||
- `homed`:当前关节已回零;
|
||
- `homing_active`:全局回零状态。
|
||
|
||
`control.c` 周期把 `get_homing(joint)`、`get_homed(joint)` 写入 motion status,并更新 HAL `motion.is-all-homed`。
|
||
|
||
### 6.3 Web 完善要求
|
||
|
||
当前 Web 的 `HOME` 已设置 `allHomed` 和 home pose,但还应补齐:
|
||
|
||
- `machine.homed` 数组,长度来自 profile/INI joint 数;
|
||
- `machine.homing` 和 per-joint `homing` 短暂状态,即使仿真为零速回零,也应经过 `homing -> homed` 的状态事件;
|
||
- Home All 与单 joint Home 的命令对象应对应 `EMC_JOINT_HOME { joint: -1|n }`;
|
||
- Home 执行前强制切 `manual`,且 `manualPanel` 回到 manual/joint 语义;
|
||
- 非 identity kinematics 下按坐标轴 Home 应拒绝,提示使用 joint mode;
|
||
- 回零过程中禁止 Jog、Run、再次 Home。
|
||
|
||
## 7. 执行 Run
|
||
|
||
### 7.1 LinuxCNC 调用链
|
||
|
||
```text
|
||
axis.py task_run()
|
||
-> run_warn()/reload_file()
|
||
-> ensure_mode(MODE_AUTO)
|
||
-> c.auto(AUTO_RUN, program_start_line)
|
||
-> emcmodule.cc emcauto()
|
||
-> EMC_TASK_PLAN_RUN
|
||
-> emctaskmain.cc emcTaskPlan()
|
||
-> emcTaskIssueCommand()
|
||
-> all_homed() 检查
|
||
-> emcTaskPlanOpen()
|
||
-> programStartLine = run_msg->line
|
||
-> task.interpState = READING
|
||
-> task.task_paused = 0
|
||
-> readahead_reading()/emcTaskExecute()
|
||
-> canonical motion -> taskintf -> motion queue
|
||
```
|
||
|
||
task 层的关键硬门禁:
|
||
|
||
- 机器必须 `STATE_ON`;
|
||
- AUTO 模式;
|
||
- 解释器必须 `IDLE` 才能正常开始新 Run;
|
||
- 未全部回零且 `no_force_homing` 为 false 时拒绝:`Can't run a program when not homed`;
|
||
- 程序文件需要已打开,或 `task.file` 可被 `emcTaskPlanOpen()` 打开。
|
||
|
||
### 7.2 状态记录方式
|
||
|
||
Run 后 task 写:
|
||
|
||
- `interpState = READING`;
|
||
- `task_paused = 0`;
|
||
- `motion.traj.single_stepping = 0`;
|
||
- `stepping = 0`、`steppingWait = 0`;
|
||
- `programStartLine = run_msg->line`。
|
||
|
||
解释器完成、abort、错误或下级状态变为非 ON 时,再回到 `IDLE` 并清执行状态。
|
||
|
||
### 7.3 Web 完善要求
|
||
|
||
当前 Web 已有 `RUN_FROM_OPERATOR`、`RUN`、Task/HAL status loop、50ms 截图验证。后续要继续收敛:
|
||
|
||
- `RUN` 不应直接由 `runState` 决定,应以 `taskState/mode/interpState/allHomed/programOpen` 为准;
|
||
- `RUN_FROM_OPERATOR` 可以做引导序列,但最终应仍发 `SET_MODE AUTO` 和 `EMC_TASK_PLAN_RUN`;
|
||
- `programStartLine` 应统一为 LinuxCNC 行号语义,避免 UI 1-based 与 task `line=0` 混用;
|
||
- Task/HAL runtime 可用时,应从 `taskHalStatus.ui.activeLine` 和 `motion.program-line` 回写 `activeLine`;
|
||
- 结束时必须经过 `interpState=idle`、`runState=complete/idle`、`taskPaused=false`。
|
||
|
||
## 8. 暂停/恢复
|
||
|
||
### 8.1 LinuxCNC 调用链
|
||
|
||
菜单 Pause:
|
||
|
||
```text
|
||
axis.py task_pause()
|
||
-> 必须 MODE_AUTO 且 interp_state in {READING, WAITING}
|
||
-> c.auto(AUTO_PAUSE)
|
||
-> EMC_TASK_PLAN_PAUSE
|
||
```
|
||
|
||
工具栏 Pause/Resume:
|
||
|
||
```text
|
||
axis.py task_pauseresume()
|
||
-> 必须 MODE_AUTO 或 MODE_MDI
|
||
-> s.paused 为真: c.auto(AUTO_RESUME)
|
||
-> 否则 interp_state != IDLE: c.auto(AUTO_PAUSE)
|
||
```
|
||
|
||
task 执行:
|
||
|
||
```text
|
||
EMC_TASK_PLAN_PAUSE
|
||
-> emcTrajPause()
|
||
-> interpResumeState = 当前 interpState
|
||
-> task.interpState = PAUSED
|
||
-> task.task_paused = 1
|
||
|
||
EMC_TASK_PLAN_RESUME
|
||
-> emcTrajResume()
|
||
-> task.interpState = interpResumeState
|
||
-> task.task_paused = 0
|
||
-> motion.traj.single_stepping = 0
|
||
-> stepping = 0
|
||
```
|
||
|
||
motion 侧:
|
||
|
||
```text
|
||
EMCMOT_PAUSE -> tpPause(); motion.paused = 1
|
||
EMCMOT_RESUME -> tpResume(); motion.paused = 0; motion.stepping = 0
|
||
```
|
||
|
||
### 8.2 Web 完善要求
|
||
|
||
当前 `PAUSE`、`PAUSE_RESUME`、`RESUME` 已基本对标。后续补齐点:
|
||
|
||
- `s.paused` 对应 motion paused,不只是 `interpState=="paused"`;
|
||
- `taskPaused` 和 `motionPaused` 必须一起出现在状态面板、evidence 和测试断言;
|
||
- 暂停期间 `programExecutionSampleIndex`、`axisPose`、`toolAxisVector`、Vismach pins 必须冻结;
|
||
- 恢复时使用 `interpResumeState`,不要固定回 `reading`;
|
||
- `resume_inhibit` 如果 Web 暂不实现,应在策略状态中显式 `resumeInhibit=false`,并预留 gate。
|
||
|
||
## 9. 单步执行 Step
|
||
|
||
### 9.1 LinuxCNC 调用链
|
||
|
||
```text
|
||
axis.py task_step()
|
||
-> 如果不是 AUTO 或解释器非 IDLE,先清 highlight 并做 run_warn()
|
||
-> ensure_mode(MODE_AUTO)
|
||
-> c.auto(AUTO_STEP)
|
||
-> emcmodule.cc emcauto()
|
||
-> EMC_TASK_PLAN_STEP
|
||
-> emctaskmain.cc emcTaskPlan()
|
||
```
|
||
|
||
task 中分状态处理:
|
||
|
||
- `AUTO + IDLE`:把 Step 转成一次 `EMC_TASK_PLAN_RUN(line=0)`,随后立即 `emcTrajPause()`,`interpState=PAUSED`,`task_paused=1`;
|
||
- `AUTO + READING/WAITING`:设置 `motion.traj.single_stepping=1`、`stepping=1`、`steppingWait=0`;
|
||
- `AUTO + PAUSED`:若 motion queue 中有暂停运动,发 `emcTrajStep()`;否则恢复解释器到 `interpResumeState` 以读下一步。
|
||
|
||
motion 侧:
|
||
|
||
```text
|
||
EMCMOT_STEP
|
||
-> 如果 motion.paused:
|
||
idForStep = current id
|
||
motion.stepping = 1
|
||
tpResume()
|
||
motion.paused = 1
|
||
否则报错 "can't STEP while already executing"
|
||
|
||
control.c 周期:
|
||
if stepping && idForStep != current id:
|
||
tpPause()
|
||
stepping = 0
|
||
paused = 1
|
||
```
|
||
|
||
### 9.2 Web 完善要求
|
||
|
||
当前 `STEP` 会推进一个 sample 并设 paused。后续应改成更接近 LinuxCNC 的两层语义:
|
||
|
||
- 增加 `machine.singleStepping` 与 `machine.motionStepping`;
|
||
- 第一次 Step 在 IDLE 时等价于启动 Auto Run 后暂停;
|
||
- 已暂停且 motion queue 有待执行段时,Step 只释放到下一个 motion id/line,而不是简单固定一个 sample;
|
||
- Step 后状态应为 `interpState=paused`、`taskPaused=true`、`motionPaused=true`、`singleStepping=true/随后 false`;
|
||
- Resume 必须清 `singleStepping`。
|
||
|
||
## 10. WASM-port 完善方向
|
||
|
||
`wasm-port/SKILL.md` 的原则是:CNC 语义来自 LinuxCNC vendored source,JS/SDK 只做适配。针对本按钮状态机,建议按以下顺序补齐:
|
||
|
||
1. 在 `wasm-port` 的 task/HAL SDK 中暴露完整 task 状态:
|
||
- `state`、`mode`、`interpState`、`interpResumeState`、`taskPaused`、`singleStepping`、`programOpen`、`programStartLine`。
|
||
2. 暴露 motion 状态:
|
||
- `enabled`、`paused`、`stepping`、`idForStep`、`queueDepth`、`programLine`、`homing`、`homed[]`、`allHomed`。
|
||
3. 将 `EMC_TASK_SET_STATE`、`EMC_TASK_SET_MODE`、`EMC_JOINT_HOME`、`EMC_TASK_PLAN_RUN/PAUSE/RESUME/STEP` 作为 JSON command 的稳定 ABI。
|
||
4. 对照 LinuxCNC `emcTaskSetState()` 和 `emcTaskPlan()` 增加任务状态矩阵测试。
|
||
5. 对照 `motion/command.c` 增加 pause/resume/step motion id 测试。
|
||
6. 对照 `homing.c` 增加 Home All、重复 Home、homing-inhibit、正在 homing 时拒绝再次 Home 的测试。
|
||
|
||
Web 项目不要在 JS 中重新实现解释器、G-code、planner 语义;可以做 UI 预期状态,但最终要以 Task/HAL WASM status 回写为准。
|
||
|
||
## 11. web-rtcp 项目落地清单
|
||
|
||
### 11.1 应修改/复核的核心文件
|
||
|
||
| 文件 | 后续职责 |
|
||
|---|---|
|
||
| `app/src/state/linuxcnc-task-policy.js` | 唯一按钮门禁;补 `canPowerToggle`、`canStepStrict`、`resumeInhibit`、`singleStepping` |
|
||
| `app/src/state/store.js` | 按 EMC 命令语义更新状态;清理只依赖 `runState` 的残留判断 |
|
||
| `app/src/runtime/linuxcnc-task-hal-runtime.js` | 标准化 Task/HAL status,补 `enabled`、`homed[]`、`singleStepping` |
|
||
| `app/src/ui/axis-shell.js` | AXIS 按钮可用性只读 policy,不散落条件 |
|
||
| `tests/node/verify_xyzbc_trt_web_app.mjs` | 补逐按钮非法状态矩阵 |
|
||
| `tests/node/verify_rtcp_store.mjs` | 补状态记录和派生状态断言 |
|
||
| `tools/verify-estop-power-home-run-pause-50ms.mjs` | 扩展 Step、Home 过程状态和 motion freeze 断言 |
|
||
| `tools/collect-web-xyzbc-trt-evidence.mjs` | evidence 输出按钮状态矩阵和状态流 |
|
||
| `tools/compare-xyzbc-trt-evidence.mjs` | 对比 native/Web 的按钮先决条件、状态转移和暂停冻结 |
|
||
|
||
### 11.2 建议新增状态对象
|
||
|
||
```js
|
||
machine: {
|
||
taskState: "estop" | "estop-reset" | "on",
|
||
mode: "manual" | "auto" | "mdi",
|
||
interpState: "idle" | "reading" | "paused" | "waiting",
|
||
interpResumeState: "idle" | "reading" | "waiting",
|
||
taskPaused: boolean,
|
||
motionPaused: boolean,
|
||
singleStepping: boolean,
|
||
motionStepping: boolean,
|
||
motionEnabled: boolean,
|
||
homing: boolean,
|
||
homed: boolean[],
|
||
allHomed: boolean,
|
||
noForceHoming: boolean,
|
||
resumeInhibit: boolean
|
||
}
|
||
```
|
||
|
||
### 11.3 验收矩阵
|
||
|
||
| 场景 | 期望 |
|
||
|---|---|
|
||
| ESTOP 下点 Power | 不上电,提示先解除急停 |
|
||
| ESTOP_RESET 下点 Power | `taskState=on`、`motionEnabled=true` |
|
||
| ON 下点 Power | abort、disable、`taskState=estop-reset` |
|
||
| 未上电 Home | 拒绝 |
|
||
| AUTO/READING Home | 拒绝 |
|
||
| MANUAL/ON/IDLE Home All | 进入 homing,完成后 `homed[]` 全 true |
|
||
| 未 Home Run | 拒绝,除非 `noForceHoming=true` |
|
||
| ON/AUTO/IDLE Run | `interpState=reading`、`taskPaused=false` |
|
||
| AUTO/READING 菜单 Pause | `interpState=paused`、`taskPaused=true`、`motionPaused=true` |
|
||
| MANUAL 残留 running 点 Pause | 拒绝 |
|
||
| 工具栏 paused 点 Pause/Resume | Resume,恢复到 `interpResumeState` |
|
||
| IDLE Step | 等价启动 Run 后暂停 |
|
||
| PAUSED Step | 只推进到下一个 motion id/line 后再次暂停 |
|
||
| 急停 during Run | abort,清 pause/step,velocity=0,状态 ESTOP |
|
||
|
||
## 12. 推荐实施顺序
|
||
|
||
1. 先补 `linuxcnc-task-policy.js` 的严格状态矩阵,不改 UI。
|
||
2. 补 `store.js` 的 `deriveTaskState()`、`singleStepping`、`homed[]`、急停/下电清理。
|
||
3. 补 Task/HAL status normalization,使 WASM status 能覆盖 JS 预期状态。
|
||
4. 扩展 Node 测试覆盖非法状态矩阵。
|
||
5. 扩展 50ms Playwright 工具,加入 Step 和 Home 过程截图/evidence。
|
||
6. 更新 `collect-web` 与 `compare`,把按钮状态流纳入 `60/60` 之外的硬检查。
|
||
|
||
## 13. 当前判断
|
||
|
||
现有 Web 项目已经具备主干:`linuxcnc-task-policy.js`、`store.js`、Task/HAL runtime、50ms 截图验证和 native/Web compare。下一阶段的重点不是新增按钮,而是把按钮行为的状态来源从“Web 自定义运行态”进一步收敛到 LinuxCNC 的 `task.state + task.mode + interpState + motion status + homing status`,并让所有测试和 evidence 都能证明这一点。
|
||
|
||
## 14. 2026-07-07 实施完成记录
|
||
|
||
截至 2026-07-07 18:18 EDT,本指南中的 Web 完善清单已完成一轮落地:
|
||
|
||
- `linuxcnc-task-policy.js` 已作为主控制按钮唯一门禁入口,新增 `motionEnabled`、`homed[]`、`singleStepping`、`motionStepping`、`resumeInhibit`、`canPowerToggle`、`powerAction` 等状态输出。
|
||
- `store.js` 已把 `ESTOP/RESET/Power/Home/Run/Pause/Resume/Step` 收敛到 `taskState + mode + interpState + motion/home status`,并清理下电、急停、暂停、单步、回零的状态残留。
|
||
- Task/HAL WASM 已输出 `motionEnabled`、`homed[]`,并在 `EMC_TASK_PLAN_RUN` 中执行 ON、AUTO、IDLE、非 homing、已 Home、程序打开、motion plan 已加载的硬门禁。
|
||
- Home All 已具备 `homing -> homed` 瞬态记录;Run/Step/Pause/Resume 的 task/motion 状态与 Web policy、status loop 和 evidence 采集同步。
|
||
- `collect-web-xyzbc-trt-evidence.mjs` 已改为合法 Task/HAL 运行准备序列:`ON -> HOME -> cycle -> AUTO -> PLAN_RUN`。
|
||
|
||
本轮验证结果:
|
||
|
||
```text
|
||
linuxcnc_task_hal_wasm_build=ok
|
||
linuxcnc_task_runtime_smoke=ok
|
||
task_state_matrix=ok
|
||
linuxcnc_task_hal_sdk=ok
|
||
xyzbc_trt_web_app_smoke=ok
|
||
xyzbc_trt_browser_smoke=ok
|
||
gmoccapy_static_build=ok
|
||
compare_xyzbc_trt_status=pass
|
||
compare.summary.checkCount=60
|
||
compare.summary.passCount=60
|
||
compare.summary.failCount=0
|
||
compare.summary.blockers=[]
|
||
compare.requiredImprovements=[]
|
||
```
|
||
|
||
结论:本指南从“建议实施”转为“已实施并通过复验”。后续若继续扩展截图工具或 compare 检查,应在当前 T-078 基线之上追加新任务,而不是重新发散按钮状态来源。
|