Files
cnc_wams/wasm-port/working/12-status-json-LinuxCNC对标方案.md
2026-07-09 18:12:01 -04:00

235 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 12-status JSON LinuxCNC对标方案
## 目标
本方案用于后续在 WASM 中完善 `status JSON`:对标 LinuxCNC 的 `EMC_STAT` / status buffer 模型,在 WASM/C++ 内维护结构化 status 事实源,再把最后一次 status write 序列化为 JSON 给 JS/SDK/UI 读取。
`status JSON` 不是 LinuxCNC 语义实现层。它是浏览器/Node host 无法直接读取 native NML/CMS status channel 时的外部通信格式。
## LinuxCNC对标基线
上游 LinuxCNC 的 status 模型来自:
- `/home/mes123456/cnc_wams/linuxcnc/src/emc/nml_intf/emc.hh`
- 定义 `EMC_TASK_MODE``EMC_TASK_STATE``EMC_TASK_EXEC``EMC_TASK_INTERP``EMC_TRAJ_MODE` 等枚举。
- 定义 `EMC_STAT_TYPE``EMC_TASK_STAT_TYPE``EMC_MOTION_STAT_TYPE``EMC_IO_STAT_TYPE` 等 NML 类型编号。
- `/home/mes123456/cnc_wams/linuxcnc/src/emc/nml_intf/emc_nml.hh`
- `EMC_STAT` 聚合 `EMC_TASK_STAT task``EMC_MOTION_STAT motion``EMC_IO_STAT io`
- `EMC_TASK_STAT` 保存 task mode/state、exec/interp state、program line、file、active G/M code、offset、program units、pause 等状态。
- `EMC_MOTION_STAT` 保存 `EMC_TRAJ_STAT traj`、joint、axis、spindle、synch IO、analog IO、soft limit、heartbeat 等状态。
- `EMC_TRAJ_STAT` 保存 enabled、inpos、queue、activeQueue、queueFull、id、paused、single_stepping、position、actualPosition、current_vel、probe、kinematics 等轨迹状态。
- `EMC_IO_STAT` 保存 tool、coolant、aux、fault/reason 等 IO 状态。
上游 GUI 读取的是 status channel 中的 `EMC_STAT` 快照,不是在 GUI 层重建 task/motion 状态机。WASM 中的 JSON 应只模拟“读 status channel 后得到可展示快照”的边界。
## WASM中的等价模型
当前 WASM 侧已建立:
- `StandaloneEmcStatus`
- `StandaloneEmcTaskStatus`
- `StandaloneEmcMotionStatus`
- `StandaloneEmcIoStatus`
- `write_status_snapshot()`
- `lctask_read_status_json()`
后续完善时采用以下固定链路:
```text
LinuxCNC source semantics
-> WASM/C++ task cycle
-> LcmotStatusSnapshot
-> StandaloneEmcStatus
-> write_status_snapshot()
-> lctask_read_status_json()
-> JS/SDK/UI
```
禁止以下链路:
```text
motion JSON -> parse -> task state
status JSON -> parse -> task/motion state
JS/SDK -> compute LinuxCNC task/motion semantics
lctask_read_status_json() -> step servo / read fresh motion / consume command
```
## status JSON职责
`status JSON` 只承担四类职责:
1. 把最后一次 `write_status_snapshot()` 中的状态导出给 JS/SDK/UI。
2. 给浏览器 UI 提供稳定、可版本化的字段名。
3. 给 Node/WASM/browser 测试提供可断言的观察面。
4. 以更接近 `EMC_STAT``emcStatus` 对象作为唯一 task/motion/io 状态入口。
`status JSON` 不承担:
- task 状态机事实源。
- motion 状态机事实源。
- LinuxCNC planner/canon/interpreter 语义。
- queueFull、inpos、abort、estop、pause/resume/step 等语义判断。
## 推荐JSON结构
顶层只保留 runtime/readiness/source/schema 等边界字段task/motion/io/top 状态只进入 `emcStatus`
```json
{
"statusSource": "StandaloneEmcStatus",
"schemaVersion": 1,
"emcStatus": {
"source": "StandaloneEmcStatus",
"top": { "status": "DONE" },
"task": {},
"motion": {},
"io": {}
}
}
```
要求:
- `emcStatus` 是后续新增 LinuxCNC 对标字段的默认入口。
- 新字段优先落在 `emcStatus.task``emcStatus.motion.traj``emcStatus.motion.joint[]``emcStatus.motion.axis[]``emcStatus.io` 中。
- `taskTopLevelStatus``rcsStatus`、顶层 `task``servoCycle`、顶层 `motionStatus` 禁止再从 `lctask_read_status_json()` 输出。
## 字段映射方案
| LinuxCNC字段 | WASM事实源 | JSON位置 | 状态 |
| --- | --- | --- | --- |
| `EMC_STAT.status` / top RCS status | `StandaloneEmcStatus.top_rcs_status` | `emcStatus.top.status` | 已有 |
| `EMC_STAT.task.status` | `StandaloneEmcTaskStatus.rcs_status` | `emcStatus.task.status` | 已有 |
| `EMC_STAT.task.state` | `StandaloneEmcTaskStatus.state` | `emcStatus.task.state` | 已有 |
| `EMC_STAT.task.mode` | `StandaloneEmcTaskStatus.mode` | `emcStatus.task.mode` | 已有 |
| `EMC_STAT.task.execState` | `StandaloneEmcTaskStatus.exec_state` | `emcStatus.task.execState` | 已有 |
| `EMC_STAT.task.interpState` | `StandaloneEmcTaskStatus.interp_state` | `emcStatus.task.interpState` | 已有 |
| `EMC_STAT.task.task_paused` | `StandaloneEmcTaskStatus.task_paused` | `emcStatus.task.taskPaused` | 已有 |
| `EMC_STAT.task.file` | `StandaloneEmcTaskStatus.open_program` | `emcStatus.task.file` | 已有 |
| `EMC_STAT.task.currentLine/readLine/motionLine` | staged interpreter + motion snapshot | `emcStatus.task.currentLine/readLine/motionLine` | 已有 |
| `EMC_STAT.task.activeGCodes/activeMCodes/activeSettings` | vendored interpreter/canon state | `emcStatus.task.activeGCodes/activeMCodes/activeSettings` | 后续 |
| `EMC_STAT.task.g5x_offset/g92_offset/toolOffset` | vendored interpreter/canon state | `emcStatus.task.offsets` | 后续 |
| `EMC_STAT.motion.status` | `StandaloneEmcMotionStatus.rcs_status` | `emcStatus.motion.status` | 已有 |
| `EMC_STAT.motion.traj.enabled` | `LcmotStatusSnapshot.motion_enabled` | `emcStatus.motion.traj.enabled` | 已有 |
| `EMC_STAT.motion.traj.inpos` | `LcmotStatusSnapshot.in_position` | `emcStatus.motion.traj.inpos` | 已有 |
| `EMC_STAT.motion.traj.queue` | `LcmotStatusSnapshot.queue_count` | `emcStatus.motion.traj.queue` | 已有 |
| `EMC_STAT.motion.traj.activeQueue` | `LcmotStatusSnapshot.active_depth` | `emcStatus.motion.traj.activeQueue` | 已有 |
| `EMC_STAT.motion.traj.queueFull` | `LcmotStatusSnapshot.queue_full` | `emcStatus.motion.traj.queueFull` | 已有 |
| `EMC_STAT.motion.traj.id` | `LcmotStatusSnapshot.motion_id` | `emcStatus.motion.traj.id` | 已有 |
| `EMC_STAT.motion.traj.paused` | `LcmotStatusSnapshot.paused` | `emcStatus.motion.traj.paused` | 已有 |
| `EMC_STAT.motion.traj.single_stepping` | `LcmotStatusSnapshot.stepping` | `emcStatus.motion.traj.singleStepping` | 已有 |
| `EMC_STAT.motion.traj.position/actualPosition` | `LcmotStatusSnapshot.axis_cmd/axis_fb` | `emcStatus.motion.traj.position/actualPosition` | 已有 |
| `EMC_STAT.motion.traj.current_vel` | `LcmotStatusSnapshot.current_vel` | `emcStatus.motion.traj.currentVel` | 已有 |
| `EMC_STAT.motion.on_soft_limit` | `LcmotStatusSnapshot.on_soft_limit` | `emcStatus.motion.onSoftLimit` | 已有 |
| `EMC_STAT.motion.joint[]` | `LcmotStatusSnapshot.joint_cmd/joint_fb` | `emcStatus.motion.joint[]` | 已有 |
| `EMC_STAT.motion.axis[]` | `LcmotStatusSnapshot.axis_cmd/axis_fb` | `emcStatus.motion.axis[]` | 已有 |
| `EMC_STAT.io.status` | `StandaloneEmcIoStatus.rcs_status` | `emcStatus.io.status` | 已有 |
| `EMC_STAT.io.aux.estop` | task/io shim | `emcStatus.io.aux.estop` | 已有 |
| `EMC_STAT.io.fault/reason` | `StandaloneEmcIoStatus.error/reason` | `emcStatus.io.fault/reason` | 已有 |
## 后续实施批次
### SJ-1规范 `emcStatus.motion.traj`
状态:已完成,对应 T-051。
目标:把 motion snapshot 中已有的 queue、inpos、id、paused、stepping、currentVel 等字段,以 LinuxCNC `EMC_TRAJ_STAT` 名称归入 `emcStatus.motion.traj`
验收:
- `emcStatus.motion.traj.queue` 等于 `emcStatus.motion.queueDepth`
- `emcStatus.motion.traj.inpos` 等于 `emcStatus.motion.inPosition`
- `emcStatus.motion.traj.id` 等于 `emcStatus.motion.motionId`
- `lctask_read_status_json()` 不新增 motion read 或 servo step。
### SJ-2规范 task line 和 interpreter字段
状态:已完成,对应 T-052。active G/M code、active settings 和 offsets 仍按字段映射表保留为后续 source-anchored 扩展,不计入本 SJ-2 验收。
目标:对齐 `EMC_TASK_STAT.currentLine``readLine``motionLine``callLevel`,让 UI 和测试能分辨 interpreter 已读行、当前执行行和 motion 正在执行行。
验收:
- staged program RUN 后,`emcStatus.task.readLine/currentLine/motionLine` 与现有 plan read/execute/motion id evidence 一致。
- 顶层 `task` 兼容视图不得再存在。
### SJ-3规范 `motion.axis[]` 和 `motion.joint[]`
状态:已完成,对应 T-053。`emcStatus.motion.axis``emcStatus.motion.joint` 为数组;`emcStatus.motion.axisByName` 仅提供按名字读取的同对象辅助视图。
目标:把当前 axis x/y/z/a/b/c 和 joint0 字段扩展成数组结构,对标 `EMC_MOTION_STAT.axis[]``joint[]`
验收:
- 至少导出存在的 5/6 轴位置和 joint0 command/feedback。
- 顶层 `motionStatus` 兼容视图不得再存在。
### SJ-4规范 IO/aux/tool/coolant边界
状态:已完成,对应 T-054。tool/coolant 只暴露 shim/unsupported 边界,不提升 native IO readiness。
目标:将当前 IO shim 状态组织为 `emcStatus.io.aux``emcStatus.io.tool``emcStatus.io.coolant` 的窄对象,未实现字段显式标记为 shim/unsupported而不是省略成语义完成。
验收:
- `emcStatus.io.status``fault``reason``aux.estop` 可观测。
- readiness 仍保持 false不因 JSON 字段存在而宣称 native IO ready。
### SJ-5引入 schema gate
状态:已完成,对应 T-055。
目标:新增专用 gate例如 `tools/verify_task_status_json_contract.sh`,固定 status JSON 字段来自 `StandaloneEmcStatus`,并检查旧顶层状态字段不存在。
验收:
- gate 检查 `statusSource=StandaloneEmcStatus`
- gate 检查 `taskTopLevelStatus``rcsStatus`、顶层 `task``servoCycle`、顶层 `motionStatus` 不存在。
- gate 检查 `lctask_read_status_json()` 不调用 `lcmot_read_status_json()`
- gate 检查 JS/SDK 没有实现 task/motion 语义。
- gate 纳入 `tools/verify_task_full_closure.sh`
## 旧字段收口策略
禁止 `lctask_read_status_json()` 输出:
- `taskTopLevelStatus`
- `rcsStatus`
- `task`
- `servoCycle`
- `motionStatus`
新增字段默认进入:
- `emcStatus.top`
- `emcStatus.task`
- `emcStatus.motion`
- `emcStatus.motion.traj`
- `emcStatus.motion.axis`
- `emcStatus.motion.joint`
- `emcStatus.io`
旧字段不再作为兼容视图保留。新增测试必须优先断言 `emcStatus`,并在契约测试中继续对旧字段做负向断言。
## 文档和测试要求
每完成一个 SJ 批次,需要同步更新:
- `04-任务矩阵.md`
- `03-推进台账.md`
- `05-验收证据.md`
- `06-决策记录.md`
- `07-emctaskmain周期对标蓝图.md`
- `11-WASM核心状态机边界与后续完善路线.md`
- `docs/source-reuse-map.md`
- `docs/compatibility-validation.md`
- 对应 `tools/verify_task_*` gate
默认最终验收命令:
```bash
cd /home/mes123456/cnc_wams/wasm-port
./tools/verify_task_full_closure.sh
git diff --check
```