# External user-M / Tool DB Web 仿真实施方案 生成日期:2026-07-01 ## 1. 目标 本文件把图中红框 `external user-M/tool DB process` 从“明确不包含”推进为 Web/WASM 仿真边界内的可验证能力: ```text toolDbProcessReady=true for web_simulation_only externalUserMProcessReady=true for web_simulation_only hardwareDrive=false hostRealtimeKernel=false arbitraryHostProcessExecution=false ``` 该能力只表示浏览器仿真可以读取、编辑、保存 tool table,并能执行受控白名单 user-M/remap 事件。它不启动 host native LinuxCNC 外部进程,不执行任意 shell 脚本, 不接入真实 HAL shared memory,不驱动真实机床 IO。 ## 2. LinuxCNC 对标源程序 ### 2.1 Tool DB / tool table 主要参考: ```text linuxcnc/src/emc/task/taskclass.cc linuxcnc/src/emc/task/taskclass.hh linuxcnc/src/emc/tooldata/tooldata.hh linuxcnc/src/emc/tooldata/tooldata_common.cc linuxcnc/src/emc/tooldata/tooldata_mmap.cc linuxcnc/src/emc/tooldata/tooldata_db.cc linuxcnc/src/emc/tooldata/tooldata_nml.cc linuxcnc/src/emc/nml_intf/emc.hh linuxcnc/src/emc/usr_intf/axis/extensions/emcmodule.cc ``` 关键 LinuxCNC 语义: - `[EMCIO] TOOL_TABLE` 指向 tool table 文件。 - `[EMCIO] DB_PROGRAM` 存在时,native LinuxCNC 会启用工具数据库进程模式,并可能忽略普通 tool table 文件。 - `Task::emcToolPrepare()` 设置 `iocontrol.0.tool-prepare`、`tool-prep-number`、`tool-prep-pocket`、`tool-prep-index`。 - `Task::emcToolLoad()` 设置 `iocontrol.0.tool-change`,等待 `iocontrol.0.tool-changed`。 - `Task::read_tool_inputs()` 在 `tool-prepared` 或 `tool-changed` 输入到达后更新 `toolInSpindle`、`toolFromPocket`、`pocketPrepped` 并复位 HAL pin。 - `Task::emcToolSetOffset()` 更新 tool offset、diameter、front/back angle、orientation,并保存 tool table。 - `Task::emcToolSetNumber()` 对应 `M61` 设置当前刀具号。 本项目第一阶段只实现上述语义的 Web 仿真子集,不实现 LinuxCNC native DB_PROGRAM 外部进程协议。 ### 2.2 user-M / remap 主要参考: ```text linuxcnc/src/emc/rs274ngc/interp_* # user M / remap 解释入口 linuxcnc/src/emc/task/emctask.cc linuxcnc/src/emc/task/emccanon.cc linuxcnc/src/emc/nml_intf/emc.hh linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc linuxcnc/configs/sim/qtaxis/non-trivial/scara/remap_subs/428remap.ngc linuxcnc/configs/sim/qtaxis/non-trivial/scara/remap_subs/429remap.ngc linuxcnc/configs/sim/qtaxis/non-trivial/scara/remap_subs/430remap.ngc ``` 关键 LinuxCNC 语义: - native user-M 可以调用外部可执行文件或 remap 子程序。 - `M428/M429/M430` 在 TRT/switchkins 配置中通过 remap 子程序、`M68`、`M66` 和 HAL pin 同步 `motion.switchkins-type`。 - 任意 user-M 外部程序可能访问文件、HAL、IO 或系统命令,不能在浏览器中直接执行。 本项目只允许白名单 user-M/remap 行为。白名单事件必须能追溯到 vendored LinuxCNC 配置或 remap 文件,并在 Worker/WASM/Web runtime 中输出结构化 event 和 HAL/state patch。 ## 3. Web 仿真功能范围 ### 3.1 Tool DB Web/WASM simulation 必须支持: - 读取 staged `tool.tbl`。 - 解析 `T`、`P`、`X/Y/Z/A/B/C/U/V/W`、`D`、`I`、`J`、`Q`、`; comment`。 - 查询工具号、刀袋、直径、长度/坐标偏置。 - 编辑并保存工具号、刀袋、刀长、刀径。 - OPFS 可用时持久保存;OPFS 不可用时使用 memory fallback,范围限定为当前页面生命周期。 - 按 LinuxCNC `CANON_TOOL_TABLE` 字段建模:`toolno`、`pocketno`、`offset`、`diameter`、`frontangle`、`backangle`、`orientation`、`comment`。 - 按 LinuxCNC 非随机换刀器语义区分内部 `idx` 与真实 `pocketno`: - staged `tool.tbl` 中的 `P` 保留为 `pocketno`; - Web tool table 内部从 `idx=1` 顺序装载; - `idx=0` 固定为 spindle pocket。 - 接入 `Tn/M6/G43/M61` 的仿真状态: - `Tn`:按 `tooldata_find_index_for_tool()` 语义找到内部 `idx`,设置 `tool_prep_*` HAL pins。 - HAL loopback:`read_tool_inputs()` 语义把 `tool_prepared` 转换为 `pocketPrepped`。 - `M6`:按 `Task::emcToolLoad()` 和 `read_tool_inputs()` 把已准备刀具复制到 spindle pocket `idx=0`,设置 `toolInSpindle`、`toolFromPocket`、`tool_number`。 - `G43 Hn`:按 `convert_tool_length_offset()` 使用 tool table offset,设置 `activeToolOffset` 和 #5400/#5401-#5413 参数快照。 - `M61 Qn`:直接设置当前刀具号。 - 保存时按 LinuxCNC `tooldata_format_toolline()` 风格输出,例如 `T4 P44 D+12.500000 Z+42.250000`。 - UI diagnostics 显示 `toolDbProcessReady=true for web_simulation_only`。 第一阶段不支持: - LinuxCNC native `DB_PROGRAM` 外部工具数据库进程。 - 随机刀库完整换刀策略。 - 任意 host 文件系统写入。 - 真实 IO 或真实换刀机构。 ### 3.2 受控 user-M simulation 必须支持: - 不执行任意系统脚本。 - 只允许白名单内的 vendored M-code/remap 行为。 - 在 Worker/WASM/Web runtime 边界输出结构化 event: ```text code allowed sourceRel semanticBoundary halPatch statePatch promotionScope=web_simulation_only hostExecution=false ``` 第一批白名单: | code | 来源 | Web 仿真效果 | | --- | --- | --- | | `M428` | TRT `428remap.ngc` / switchkins config | `motion.switchkins-type=1`,RTCP/TCP on | | `M429` | TRT `429remap.ngc` / switchkins config | `motion.switchkins-type=0`,identity | | `M430` | TRT `430remap.ngc` / switchkins config | `motion.switchkins-type=2`,userk | | `M128` | millturn/user-M reference | 受控事件,switchkins/tool state 可追溯,不执行 host script | | `M129` | millturn/user-M reference | 受控事件,switchkins/tool state 可追溯,不执行 host script | 不在白名单内的 `M100-M199` 或任意外部程序必须 blocked,并输出 blocked evidence。 ## 4. 代码落点 建议新增: ```text app/src/runtime/tool-db-simulation.js app/src/runtime/controlled-user-m-simulation.js tests/node/verify_tool_db_user_m_simulation.mjs ``` 建议更新: ```text app/src/runtime/full-execution-boundary.js app/src/state/store.js app/src/ui/gmoccapy-shell.js app/package.json docs/implementation-plan.md docs/program-implementation-guide.md docs/native-task-hal-sync-implementation-steps.md docs/development-continuation.md docs/traceability-matrix.md docs/linuxcnc-parity-matrix.md docs/docs-directory-file-guide.md docs/diagram-assets/02-linuxcnc-to-web-simulation-flow.mmd/png docs/diagram-assets/04-native-task-hal-flow.mmd/png ``` ## 5. 验收 gate Node smoke: ```text node web-rtcp-5axis-sim-plan/tests/node/verify_tool_db_web_simulation.mjs node web-rtcp-5axis-sim-plan/tests/node/verify_tool_db_user_m_simulation.mjs npm --prefix web-rtcp-5axis-sim-plan/app run smoke:node ``` 必须输出: ```text tool_db_web_simulation_smoke=ok staged_tool_tbl_loaded=1 tool_db_query_edit_save=1 tool_db_t_m6_g43_state=1 tool_db_memory_fallback_save=1 host_tool_db_process=0 tool_db_user_m_simulation_smoke=ok tool_db_process_ready_web_simulation_only=1 external_user_m_process_ready_web_simulation_only=1 arbitrary_user_m_blocked=1 host_process_execution=0 ``` UI 必须显示: ```text Tool DB/User-M: tool DB web simulation ready / controlled user-M ready Host/native: hardware drive false / host realtime false / external user-M web simulation only / tool DB web simulation only ``` ## 6. 边界声明 完成后允许: ```text toolDbProcessReady=true externalUserMProcessReady=true toolDbProcessScope=web_simulation_only externalUserMProcessScope=web_simulation_only ``` 仍必须保持: ```text hardwareDrive=false hostRealtimeKernel=false hostToolDbProcess=false hostExternalUserMProcess=false arbitraryUserMExecution=false ```