235 lines
11 KiB
Markdown
235 lines
11 KiB
Markdown
# 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
|
||
```
|