Files
linuxcncWebWASM/docs/linuxcnc-web-wasm-frontend-communication-design.md

36 KiB
Raw Permalink Blame History

LinuxCNC Web/WASM 仿真前端与通信详细设计

文档状态:Draft v0.1 适用基线:LinuxCNC 2.10.0~pre0;浏览器运行时、WASM 核心、Pyodide、OPFS 和 Web UI 采用同一 context_id 上层路线:技术路线 源码关联:功能与源程序关联目录 覆盖验收:仿真全功能覆盖矩阵 执行治理:项目执行与交付策略 总控执行:移植总控执行手册

本文件把“浏览器前端”和“LinuxCNC 仿真核心之间的边界”定义为可实现、可测试、可版本化的契约。前端不直接调用 WASM 内部指针、不直接写 OPFS、不直接改变仿真状态;所有命令、状态、事件、日志、快照和恢复操作都通过 Worker 通信层完成。LinuxCNC 的解释器、TP、motion、HAL、IO、Python 和数字孪生是状态权威;前端是命令发起者、状态投影者和用户工作流编排者。

1. 设计目标与不可变原则

1.1 目标

  1. 覆盖 LinuxCNC 仿真用户的完整工作流:工程选择、配置加载、G-code 编辑/预览/运行、MDI、jog、home、override、主轴、换刀、冷却、探针、报警、HAL、ClassicLadder、工具表、参数、日志、快照、恢复、导入导出和离线运行。
  2. 前端在 Chromium、Firefox、Safari 支持范围内保持一致的命令语义和状态显示;不要求桌面 GUI 像素级复制,但必须保持工作流、状态、错误和结果等价。
  3. 主线程只处理输入、布局、可视化和状态投影;WASM、Python、HAL 周期、文件系统、journal、快照和恢复全部在 Worker 侧执行。
  4. 通信协议可录制、回放、限流、取消、重试和恢复;断网、标签页挂起、Worker 重启、回答中断或工具结果丢失不得产生重复副作用或跳过步骤。
  5. UI 功能条目与 LinuxCNC 源文件、配置入口、测试和 oracle 互相可追溯,纳入覆盖矩阵和发布门禁。

1.2 不可变原则

原则 约束
Worker 权威 前端显示的运行状态必须来自 Worker 快照或事件;前端本地乐观状态只能标记为 pending,不能当作仿真已执行
单写者 一个仿真会话只允许一个 Worker 实例写入 WASM 状态和 OPFS journal;多标签页只能观察或显式取得租约
固定顺序 命令按 seq 排序,WASM step、HAL thread、事件和 OPFS commit 在会话内串行
版本化边界 命令、事件、快照、能力、工程格式和错误码均带 schema_version;未知版本拒绝而不猜测
可重放 任何影响仿真结果的命令都可记录输入、tick、结果和状态哈希;调试 UI 不得改变执行顺序
本地优先 网络不可用不影响已缓存资源和 OPFS 工程的本地仿真;远程同步是可选功能
安全排除 不把宿主路径、shell、真实设备、原始 socket、动态库或任意 Python 宿主能力暴露给前端插件

2. 技术路线与实现方法

2.1 前端技术栈

React + TypeScript
  ├─ AppShell / Router / PermissionBoundary
  ├─ Domain stores(session、program、motion、hal、io、workspace、recovery)
  ├─ WorkerClient(postMessage、序列、超时、重试和协议校验)
  ├─ Command UX(命令表单、pending、ack、result、错误和取消)
  ├─ Editors(G-code、INI、HAL、工具表、ClassicLadder、VCP schema)
  ├─ Machine UI(状态、MDI、jog、home、override、报警、工具和 I/O)
  ├─ Visualization(Three.js/WebGL/WebGPU 适配、轨迹、坐标、毛坯和模型)
  └─ Diagnostics(HAL graph/scope、事件、日志、差异和能力报告)
                │ structured clone / transferable ArrayBuffer
                ▼
Dedicated sim.worker.ts
  ├─ ProtocolGateway / TaskLedger
  ├─ SessionManager / CapabilityRegistry
  ├─ SimScheduler / LinuxCncCompat
  ├─ WasmRuntime / PythonRuntime
  ├─ WorkspaceRuntime / OpfsJournal
  ├─ SnapshotManager / RecoveryManager
  └─ StatePublisher / BackpressureController

推荐采用 TypeScript 严格模式、运行时 schema 校验(例如手工生成的校验器或项目选定的 schema 工具)、结构化日志和可测试的纯 reducer。React 组件不能直接依赖 postMessage;所有消息经过 WorkerClient,所有 UI 状态经过 domain store。Three.js 只消费轨迹/姿态快照,不读取 WASM 内存。

2.2 分层责任

层 责任 允许访问 禁止访问
View/UI 用户输入、布局、无障碍、键盘/触摸、状态投影 domain store、WorkerClient 的只读结果 WASM、OPFS、网络写入、直接修改 authoritative state
Domain store 规范化状态、reducer、派生选择器、pending/error 状态 已校验 Worker 消息 猜测未收到的状态、直接持久化
WorkerClient 握手、序列、超时、取消、重试、消息校验、传输统计 postMessage、transferable buffer 修改仿真语义、跳过 ack、吞掉错误
ProtocolGateway schema、权限、幂等键、命令路由和能力检查 Worker 内模块 未版本化命令、跨会话写入
SimRuntime WASM、Python、HAL、IO、固定 tick、状态快照 Worker 内 WASM/虚拟 FS DOM、真实硬件、宿主命令
WorkspaceRuntime OPFS、journal、checkpoint、导入导出、配额 Worker OPFS API UI 线程同步句柄、未提交覆盖
StatePublisher 快照、事件、轨迹、采样、背压、丢弃策略 Worker 状态 改变核心状态或重排事件

2.3 状态管理方法

Worker 发布三种数据:

  1. 权威快照:完整或增量的当前状态,带 simulation_tick 和状态哈希;UI 刷新、重连和恢复以此为基准。
  2. 领域事件:报警、错误、模式变化、换刀、主轴到速、探针触发、HAL 变化、恢复进度和命令结果;事件不可替代缺失的权威快照。
  3. 高频流:轨迹点、HAL sample、位置/速度/电流等,可按订阅和背压丢弃中间样本;流末端必须有序号和时间范围,不能丢失最终状态。

前端 store 保存 authoritative、pending、last_error、last_verified_tick 和 stream_cursor。任何本地编辑先进入 draft;保存成功后才更新 committed 版本。仿真状态、工程文件状态和 UI 偏好分开存储。

3. 前端功能设计

3.1 应用壳和导航

功能 前端行为 通信依赖
启动/能力检查 显示浏览器、WASM、Pyodide、OPFS、WebGL/WebGPU、跨源隔离和缓存状态 HELLO、CAPABILITIES
会话选择 打开、创建、复制、重命名、导入、导出工程;显示租约和最近快照 WORKSPACE_LIST、SESSION_CREATE、PROJECT_*
运行态导航 控制台、程序、预览、HAL、PLC、工具、配置、日志和差异视图 STATE_SNAPSHOT、领域订阅
多视图同步 一个主控视图,其他视图只读订阅;切换不重启仿真 SUBSCRIBE、SNAPSHOT_REQUEST
权限边界 插件和 Python VCP 只能访问 manifest 授权的 pins、命令和文件 CAPABILITIES、PLUGIN_*

3.2 程序、MDI 和编辑器

  • G-code 编辑器:语法高亮、行号、错误定位、程序资源树、搜索、跳转行、保存草稿和版本比较。
  • 程序预览:解析状态、轨迹、刀具、坐标系、毛坯、当前行和首个差异 tick;预览必须明确“仅解析”或“已运行”。
  • 程序控制:加载、运行、暂停、单步、可选停止、恢复、从行运行、重启、清空队列和中止。
  • MDI:输入、历史、状态、返回结果、队列破坏和错误行;提交后显示 pending → ack → result。
  • 宏/remap:显示调用栈、参数、返回值、Python 异常、资源限制和 real_hardware_excluded 错误。

3.3 手动操作和机床控制

  • 模式:manual、mdi、auto、teleop、joint、world、emergency stop、off、on、homing。
  • Jog:轴/关节选择、连续/增量、速度、方向、按下/释放、键盘/触控/手轮事件去抖和释放保护。
  • Home/limit:单轴和全部回零、序列、共享开关、锁定转台、软限位/硬限位和跟随误差报警。
  • Override:feed、spindle、rapid、adaptive、feed hold、feed inhibit、spindle brake 和急停;每个变更显示来源、范围和确认结果。
  • 主轴/IO:方向、转速、定向、齿轮、冷却、润滑、换刀、探针、等离子 torch/arc-ok、激光功率和故障注入。

3.4 HAL、PLC 和诊断

  • HAL browser:组件、pin、signal、param、类型、方向、线程、函数、连接和当前值。
  • HAL command console:loadrt、addf、setp、sets、net、unlinkp、show、save、source 的受控子集。
  • HAL scope/streamer:订阅通道、采样频率、触发、缩放、暂停、导出、回放和丢样本标记。
  • ClassicLadder:工程加载/保存、section、symbol、变量、梯形图、顺序图、扫描周期、虚拟寄存器和调试状态。
  • 诊断:事件时间线、报警确认、配置错误、Worker overrun、OPFS 错误、配额、能力报告和原生/WASM 差异。

3.5 工程、工具和配置

  • 工程文件树:INI/HAL/TBL/VAR/NGC/PY/XML/TCL/CLP、模型和材料表;显示版本、哈希、未保存变更和冲突。
  • 配置编辑器:section/键类型、include 图、HALFILE 顺序、资源引用、能力映射、警告和仿真排除项。
  • 工具表:pocket/tool、几何、磨损、角度、方向、数据库查询、备份、迁移和换刀预览。
  • 快照/恢复:运行态 checkpoint、事件增量、恢复点、差异和回滚;UI 不得把未提交 draft 当作已恢复。
  • 导入/导出:工程包、manifest、golden、日志和兼容报告;导入先校验哈希、版本、路径和权限。

3.6 可视化与响应式设计

  • 三栏工作布局:左侧工程/程序资源,中部程序与 3D 主视图,右侧状态/报警/工具面板;窄屏切换为标签页和底部控制栏。
  • 关键状态使用稳定区域:模式、急停、运行/暂停、当前行、坐标、进给、主轴、报警和恢复状态不能因消息刷新跳动。
  • 轨迹数据使用 transferable ArrayBuffer;渲染线程只处理最新可绘制帧,中间帧可丢弃并显示采样间隙。
  • 所有控制支持键盘和触摸;急停、停止、释放 jog 等高风险操作需要可见状态和二次确认策略。
  • 前端不使用“看起来完成”的乐观动画;命令尚未 verified 时显示 pending,错误必须保留来源和操作 ID。

4. 前端与 LinuxCNC 通信协议

4.1 通信通道

UI thread
  └─ WorkerClient.postMessage()
       ├─ control channel: command/ack/result/error/recovery
       ├─ state channel: snapshot/event/alarm/capability
       └─ stream channel: trajectory/HAL samples/log chunks (transferable buffers)

第一版使用 Dedicated Worker 的 postMessage 和结构化克隆;大块轨迹、日志和快照使用 transferable ArrayBuffer。SharedArrayBuffer 只作为后续性能优化,必须保持相同命令顺序和结果。通信不使用真实 NML socket;NML 消息类型和状态语义在 LinuxCncCompat 中映射到版本化 message bus。

4.2 通用消息信封

所有消息都包含以下字段;事件和流也必须带 seq 和 simulation_tick,不能使用裸 JSON:

type MessageEnvelope<T> = {
  schema_version: 1;
  kind: string;
  context_id: string;
  session_id: string;
  seq: number;
  operation_id?: string;
  simulation_tick?: number;
  sent_at_monotonic_ms?: number;
  payload: T;
};

seq 在会话内单调递增;operation_id 对所有有副作用命令必填;sent_at_monotonic_ms 只用于诊断,不参与仿真结果。消息大小、数组长度、字符串长度、订阅数量和命令速率均由 capability/limits 下发并由 Worker 再次校验。

4.3 握手和能力协商

UI -> HELLO { client_version, supported_schema_versions, requested_features }
Worker -> CAPABILITIES { context_id, abi, snapshot, commands, streams, limits, exclusions }
UI -> SESSION_ATTACH { session_id?, project_id, lease_token? }
Worker -> SESSION_READY { session_id, state_hash, simulation_tick, subscriptions }

握手失败不得降级到未版本化协议。CAPABILITIES 必须列出支持的 G/M/O、HAL 组件、kinematics、Python 模块、UI 插件、最大程序大小、最大快照、可用流和 REAL-EXCLUDED 能力。前端按能力隐藏或禁用控制,并显示原因,不把缺失能力伪装成运行时错误。

4.4 命令分类

命令族 示例 副作用 处理要求
生命周期 SESSION_CREATE、LOAD_PROJECT、START、STOP、RESET、DESTROY 是 prepare/verify/commit;租约和状态机检查
程序 PROGRAM_LOAD、PROGRAM_RUN、PROGRAM_PAUSE、PROGRAM_RESUME、PROGRAM_ABORT、PROGRAM_STEP、PROGRAM_SEEK 是 记录程序哈希、当前行和 tick;不允许跳过队列语义
MDI/运动 MDI_EXECUTE、JOG_START、JOG_STOP、HOME、SET_MODE 是 jog 必须有 stop/释放;重复 operation_id 返回原结果
倍率/IO SET_OVERRIDE、SPINDLE_COMMAND、COOLANT_COMMAND、TOOL_PREPARE、TOOL_CHANGE、PROBE_CONFIG 是 能力、范围、模式和虚拟设备状态校验
HAL/PLC HAL_COMMAND、HAL_SET、HAL_SUBSCRIBE、PLC_START/STOP 是 受控白名单、pin 类型检查、周期和权限检查
工作区 PROJECT_SAVE、IMPORT、EXPORT、CHECKPOINT、RECOVER 是 OPFS journal;结果带版本和哈希
查询/诊断 SNAPSHOT_REQUEST、HAL_READ、LOG_QUERY、DIFF_QUERY、CAPABILITIES 否/只读 可取消、可重复;不改变仿真状态
控制 SUBSCRIBE、UNSUBSCRIBE、CANCEL、PING 订阅有状态 明确 cursor、采样率、背压和取消结果

每条命令经过 validate → authorize → ledger_prepare → execute → verify → ledger_commit → ack/result。ACK 只表示 Worker 已接收和排队,不表示仿真完成;UI 只有收到 COMMAND_RESULT 或明确的 ERROR 才结束 pending。

4.5 状态、事件和流

消息 频率 内容 丢失策略
STATE_SNAPSHOT 20-60 Hz 或请求 task/motion/interpreter/IO/HAL/tool/Python/alarms/恢复状态 不可丢最终快照;按 cursor 重取
EVENT/ALARM 事件驱动 状态变化、错误、换刀、探针、主轴、配置和恢复事件 不可静默丢;持久化 event log,缺号触发恢复
TRAJECTORY_CHUNK 订阅 tick 范围、坐标/姿态、刀具、采样和差异标记 可丢中间块;保留范围和 gap,最终位置来自快照
HAL_SAMPLE 订阅 通道定义、采样值、tick、丢样本数 可按背压降采样;触发和边界样本不可丢
LOG_CHUNK 请求/批量 级别、来源、操作 ID、错误码和文本 可滚动;错误和恢复日志不可丢
RECOVERY_STATUS 恢复期间 checkpoint、重放、对账、冲突、可继续状态 不可丢,UI 必须阻塞依赖状态的命令

4.6 典型消息

{
  "schema_version": 1,
  "kind": "MDI_EXECUTE",
  "context_id": "linuxcnc-2.10.0-pre0-wasm-c1",
  "session_id": "s-42",
  "seq": 184,
  "operation_id": "op-184-9fd1",
  "payload": { "line": "G0 X10 Y5", "source": "mdi", "queue_policy": "queue_buster" }
}
{
  "schema_version": 1,
  "kind": "COMMAND_RESULT",
  "context_id": "linuxcnc-2.10.0-pre0-wasm-c1",
  "session_id": "s-42",
  "seq": 184,
  "operation_id": "op-184-9fd1",
  "simulation_tick": 93210,
  "payload": {
    "status": "verified",
    "state_hash": "sha256:...",
    "canonical_events": 1,
    "error": null,
    "ledger_commit": "journal/184.commit"
  }
}

4.7 错误、取消和超时

错误码分为 protocol_*、capability_*、config_*、interpreter_*、motion_*、hal_*、python_*、workspace_*、recovery_* 和 real_hardware_excluded。错误必须包含 code、message_key、参数、来源文件/行、operation_id、simulation_tick、可重试性和建议动作。

取消分为 requested、accepted、draining、cancelled、too_late;已经提交的有副作用命令不能回滚成“未执行”。超时只表示客户端尚未收到确认,WorkerClient 必须进入 awaiting_reconcile 并查询账本/状态,而不是直接重发。

4.8 背压、流控和性能预算

  1. 控制命令使用有界队列;超过上限返回 protocol_backpressure,不丢弃已经接收的副作用命令。
  2. 快照发布采用“最新优先”;事件、报警、恢复状态和命令结果采用“顺序优先”,不可用快照降采样替代。
  3. 轨迹和 HAL 流按订阅者独立限速;Worker 返回 cursor、sample_period、dropped_count 和 tick 范围。
  4. 单次消息、单工程、单快照、单流和订阅数量上限在 CAPABILITIES.limits 中声明,并在 Worker 和 UI 双重检查。
  5. 前端只渲染当前可见窗口和最近快照;日志、轨迹和波形使用虚拟列表/分块,不把无限历史放入 React state。
  6. M1 建立命令确认 P95/P99、快照延迟、流吞吐、UI 主线程阻塞和 Worker overrun 基线;超过预算必须阻止里程碑。

4.9 LinuxCNC 源程序和通信映射

ProtocolGateway 不能直接调用零散 LinuxCNC 函数;每个命令族先映射到 LinuxCncCompat 的稳定接口,再由兼容层访问对应源码状态机。以下关联必须写入 manifest 的 source_files、source_symbols、protocol_messages 和 state_fields:

前端通信域 LinuxCNC 源程序 Worker/WASM 适配接口 前端消息/状态
生命周期和 Task linuxcnc/src/emc/task/emctaskmain.cc、taskclass.cc、taskintf.cc、emctask.cc SimTask.create/load/start/stop/reset/destroy SESSION_*、START/STOP/RESET、task.state
程序和解释器 linuxcnc/src/emc/rs274ngc/interp_read.cc、interp_execute.cc、interp_queue.cc、interp_convert.cc、modal_state.cc Interpreter.load/run/step/abort/seek PROGRAM_*、interpreter.*、canonical.*
MDI 和 canonical linuxcnc/src/emc/task/emccanon.cc、linuxcnc/src/emc/nml_intf/interpl.cc、linuxcnc/src/emc/rs274ngc/interp_queue.cc SimTask.mdi、CanonicalQueue MDI_EXECUTE、command_result、当前行/队列
Motion/jog/home/limit linuxcnc/src/emc/motion/command.c、control.c、homing.c、motion.c、motion_struct.h SimMotion.command/jog/home/snapshot JOG_*、HOME、SET_MODE、motion.*、homing.*
TP 和轨迹 linuxcnc/src/emc/tp/tp.c、tc.c、tcq.c、blendmath.c、spherical_arc.c TrajectoryPlanner.step/readChunk TRAJECTORY_CHUNK、位置/速度/加速度、queue depth
Kinematics/姿态 linuxcnc/src/emc/kinematics/*kins.c、*kins.cc、kins_util.c、trtfuncs.c Kinematics.forward/inverse/select kinematics.*、joint/axis/pose、singularity error
IO/主轴/换刀/冷却 linuxcnc/src/emc/iotask/ioControl.cc、ioControl_v2.cc;linuxcnc/src/emc/tooldata/** SimIo.command/snapshot、ToolService SPINDLE_*、TOOL_*、COOLANT_*、io.*、tool.*
HAL/halui linuxcnc/src/hal/hal_lib.c、hal.h、hal_priv.h、halmodule.cc;linuxcnc/src/emc/usr_intf/halui.cc SimHal.execute/read/subscribe HAL_COMMAND/SET/SUBSCRIBE、hal.*、HAL_SAMPLE
ClassicLadder linuxcnc/src/hal/classicladder/classicladder.c、calc.c、calc_sequential.c、files_project.c、module_hal.c SimPlc.load/start/stop/step PLC_*、PLC section/variable/scan state
NML 状态/命令/错误 linuxcnc/src/emc/nml_intf/emc.cc、emc.hh、emc_nml.hh;linuxcnc/src/libnml/nml/stat_msg.cc、cmd_msg.cc LinuxCncCompat.translateCommand/publishStatus envelope、STATE_SNAPSHOT、EVENT、ALARM
Python/remap/VCP linuxcnc/src/emc/pythonplugin/python_plugin.cc;linuxcnc/src/emc/rs274ngc/interp_python.cc、interp_remap.cc;linuxcnc/lib/python/hal.py、qtvcp/**、gladevcp/** PythonRuntime.invoke、虚拟 linuxcnc/hal 模块 PLUGIN_*、Python result/error、VCP pin/event
工程和参数 linuxcnc/src/libnml/inifile/**、linuxcnc/src/emc/ini/**、linuxcnc/src/emc/tooldata/** WorkspaceRuntime、ConfigService PROJECT_*、IMPORT/EXPORT、配置/工具/参数状态

前端所需但 LinuxCNC 原生状态中不存在的字段,例如 pending、operation_id、lease_token、recovery_progress 和 dropped_count,属于 Web 适配状态,必须明确标记为 SIM-ADAPTER,不能写回 LinuxCNC 核心结构。

4.10 快照状态契约

快照按领域分区,允许通过位图和版本号发送增量;增量必须基于已确认的 base_snapshot_id,基线缺失时前端请求完整快照:

type SimSnapshotV1 = {
  snapshot_id: string;
  base_snapshot_id?: string;
  full: boolean;
  simulation_tick: number;
  state_hash: string;
  task: { state: string; mode: string; interp_state: string; current_line: number };
  motion: { axes: number[]; joints: number[]; velocity: number[]; homed: boolean[]; limits: number };
  coordinates: { machine: number[]; relative: number[]; g5x: number; g92: number[]; tool_offset: number[] };
  spindle: Array<{ enabled: boolean; direction: number; commanded: number; actual: number; at_speed: boolean }>;
  io: { coolant: number; lube: boolean; digital: number[]; analog: number[]; probe: boolean };
  tool: { current: number; prepared: number; pocket: number; change_state: string };
  overrides: { feed: number; rapid: number; spindle: number[]; adaptive: number; feed_hold: boolean };
  hal: { graph_revision: number; changed_values?: ArrayBuffer };
  alarms: Array<{ id: string; severity: string; code: string; acknowledged: boolean }>;
  recovery: { status: string; last_verified_seq: number; checkpoint_tick: number };
};

实际编码可以是生成的二进制 schema,但字段语义必须保持。浮点数组的轴顺序、单位、NaN/Infinity 策略、位掩码和空值语义必须在 schema 中固定;前端不能根据数组长度猜测机床配置。

4.11 Worker 到 WASM C ABI 调用规则

Worker 操作 C ABI 调用规则 结果
创建核心 sim_create(config, len) 握手和配置校验后调用一次;失败则不创建会话 错误码、能力基础和初始状态
挂载工程 sim_load_workspace(root_path) WorkspaceRuntime 完成 journal 恢复和 /workspace 挂载后调用 配置诊断、资源图和可启动状态
发送命令 sim_command(cmd, len) ProtocolGateway 编码已校验命令;每个 operation_id 最多进入核心一次 入队/拒绝错误;最终结果从事件或快照确认
推进仿真 sim_step(cycles) 仅 SimScheduler 调用;UI 不得直接指定墙钟结果 新 tick、事件和可发布状态
读取快照 sim_read_snapshot(out, capacity) 先查询/预分配容量;复制到 Worker 所有的 buffer,再转移给 UI STATE_SNAPSHOT 或容量错误
读取事件 sim_read_event(out, capacity) 循环读取到空或有界批次上限;保持核心顺序 EVENT、ALARM、COMMAND_RESULT
导出运行态 sim_export_state(out, capacity) 在安全 tick 暂停写入,生成带 schema/context 的 checkpoint WorkspaceRuntime prepare/commit
导入运行态 sim_import_state(data, len) 校验 context、schema、工程哈希后导入;导入失败保留旧实例 RECOVERY_STATUS 和完整快照
销毁核心 sim_destroy() 关闭订阅、flush journal、关闭句柄后调用;幂等 SESSION_DESTROYED

WASM 内存由 WasmRuntime 独占。输入 buffer 在调用返回前有效;输出在下一次核心调用前复制到 Worker buffer;TypeScript 不长期保存 WASM heap view。C ABI 返回值统一映射为版本化错误码,禁止用异常字符串作为协议。sim_step、sim_command、状态导入导出和销毁不能并发执行。

5. 生命周期、恢复和离线通信

5.1 会话生命周期

new → handshaking → attaching → loading → ready
ready → running ↔ paused
running/paused → stopping → stopped
任何状态 → recovering → ready | blocked
任何状态 → destroying → destroyed

状态转换由 Worker 权威决定。UI 可以请求转换,但不能本地伪造转换。每次转换发送 STATE_TRANSITION 事件并写入任务账本;非法转换返回 state_transition_invalid。

5.2 刷新、Worker 重启和回答中断

Worker 启动后先发送 RECOVERY_REQUIRED 或 SESSION_READY。UI 在收到 RECOVERY_STATUS=verified 前禁用依赖运行态的运行、jog、MDI 和工具命令,只允许恢复、导出、查看日志和取消。WorkerClient 维护未完成操作表;重连时按 operation_id 查询结果,已 commit 的操作只关联原结果,未 commit 的操作从 checkpoint 继续。

5.3 断网和重新联网

前端的网络状态不能决定本地仿真状态。Service Worker 缓存应用壳、WASM、Pyodide、协议 schema 和样例;Worker 继续使用 OPFS journal、快照和本地命令。重新联网只执行缓存更新或可选同步,必须先比较 context_id、工程哈希、最后 seq、tick 和状态哈希;冲突时保留本地版本并显示差异。

5.4 多标签页与租约

默认一个工程只能有一个写入会话。主标签页持有 lease_token 和 heartbeat;其他标签页以只读模式订阅快照。主标签页崩溃后,候选标签页读取 lease expiry、校验 checkpoint 和 journal,再通过 SESSION_CLAIM 取得新租约。两个写者不允许同时运行;无法确定租约时进入 blocked 而不是并发写入。

6. 安全、权限和兼容性

  • Worker 对命令、文件、组件、Python 模块和插件能力做白名单检查;UI 隐藏按钮不是安全边界。
  • 工程路径统一规范化为 /workspace 相对路径,拒绝 ..、绝对宿主路径、符号链接和未授权扩展名。
  • Python remap、filter 和 VCP 只访问虚拟 linuxcnc、hal、INI、参数、时间和 I/O API;fork/exec/subprocess/threading/socket/设备 返回明确错误。
  • 所有外部输入(导入工程、G-code、HAL、XML/UI、插件)先解析、限制资源、记录来源哈希,再提交给 Worker。
  • 前端显示 REAL-EXCLUDED 时必须说明“不连接真实硬件、不提供安全保证”,禁止使用“在线”“已连接”等误导状态。
  • schema/ABI/工程格式升级采用新版本号、双读迁移和 context lock;旧版本不能静默解释新字段。

7. 详细实施任务

任务标题统一使用 [WS-x][Mx],每个任务绑定 source map/coverage manifest 条目、固定上下文包和测试证据。

WS-5 前端与可视化任务

任务 ID 任务 交付物 依赖 验收
FE-01 应用壳、路由、响应式布局和主题变量 AppShell、导航、布局断点、无障碍基础 无 首次启动、窄屏、键盘和只读模式通过
FE-02 WorkerClient 和协议校验 信封类型、schema 校验、序列、超时、取消、重试 COM-01 非法/未知消息拒绝;重复操作不重复副作用
FE-03 会话/工程工作流 工程选择、租约、导入导出、恢复向导 WS-3、COM-02 刷新、Worker 重启、无网、冲突恢复通过
FE-04 程序编辑器和预览 G-code 编辑、诊断、轨迹预览、当前行和差异 WS-1、COM-02 语法/运行错误定位,预览与 golden 一致
FE-05 控制台和手动操作 MDI、run/pause/step/abort、jog/home/override WS-2、COM-02 模式状态机、释放保护、命令结果完整
FE-06 工具、IO、报警和状态面板 工具表、主轴、冷却、换刀、探针、报警 WS-2、WS-3 正常/故障/恢复工作流通过
FE-07 HAL/PLC/诊断界面 pin 图、命令控制台、scope、Ladder、日志 WS-2、WS-4 订阅、触发、回放和权限限制通过
FE-08 Three.js 机床和毛坯 模型、姿态、轨迹、坐标、切削层 FE-04、COM-03 非空渲染、采样背压、最终姿态一致
FE-09 VCP/插件 schema 运行时 XML/descriptor 转 Web Component、权限和生命周期 WS-4、COM-02 样例面板、pin 回调、异常隔离通过
FE-10 前端性能和可观测性 虚拟列表、帧预算、消息统计、录制回放 FE-01..09 P95/P99 和主线程预算满足门禁

WS-2/COM 通信与状态任务

任务 ID 任务 交付物 依赖 验收
COM-01 schema 和 C/TS 类型生成 protocol.v1、命令/事件/错误/能力定义 WS-0 schema 版本锁定,未知字段策略明确
COM-02 ProtocolGateway/TaskLedger 路由、权限、幂等、prepare/commit、恢复 WS-1、WS-3 超时、确认丢失、重复响应和重启恢复通过
COM-03 SnapshotPublisher/流控 快照、事件、轨迹、HAL sample、cursor、背压 WS-2 事件不丢、流可降采样、最终快照可重取
COM-04 LinuxCncCompat message bus NML command/status/error 到 Worker 消息映射 WS-1 消息类型、顺序、错误和状态 golden 对照
COM-05 能力/限制注册表 G/M/O、组件、kinematics、Python、UI、limits WS-0、WS-1..4 UI 正确启用/禁用,排除项可解释
COM-06 浏览器和故障矩阵 Playwright 通讯、离线、租约、刷新、背压测试 COM-01..05 Chromium/Firefox/Safari 目标矩阵通过

7.3 实施批次和依赖顺序

批次 并行任务 串行依赖/冻结点 可演示结果
B0 规范和基线 COM-01、COM-05、FE-01 冻结 protocol.v1、能力 ID、错误码和 UI 信息架构 mock Worker 可完成握手、能力显示和错误页
B1 最小通信闭环 COM-02、COM-04、FE-02 必须先有 sim_create/load/command/step/snapshot ABI 加载最小工程、发送命令、显示权威快照
B2 核心操作 FE-04、FE-05、COM-03 interpreter/motion 状态字段冻结 G-code、MDI、jog、home、override、轨迹闭环
B3 持久化恢复 FE-03、COM-06 的恢复子集 WorkspaceRuntime、TaskLedger、checkpoint schema 冻结 刷新、Worker 重启、断网和确认丢失自动接续
B4 设备和工具 FE-06、FE-07 HAL/IO/tool/PLC schema 和虚拟设备能力冻结 主轴、换刀、探针、报警、HAL/PLC 工作流
B5 可视化和插件 FE-08、FE-09 轨迹/姿态流和插件权限冻结 Three.js 机床、毛坯、VCP/QtVCP 等价工作流
B6 稳定发布 FE-10、COM-06 全矩阵 全量 manifest、浏览器和性能门禁 可离线发布候选、兼容/差异/性能报告

B0-B2 可以使用只读 mock/golden 驱动 UI 开发,但到对应里程碑退出时必须切换真实 Worker/WASM 状态;mock 不能作为功能完成证据。B3 以后不得修改 protocol.v1 语义,只能增加向后兼容字段;破坏性变更必须创建 protocol.v2 并回退到 FE-M0 评审。

8. 里程碑和退出条件

里程碑 目标 关键输出 必须通过的退出条件
FE-M0 协议冻结 定义前端、Worker、WASM 和 OPFS 边界 protocol.v1、能力模型、错误码、UI 信息架构、source/coverage 关联 所有消息有 envelope/schema;命令权限和状态转换无歧义
FE-M1 可启动垂直切片 工程加载、状态显示、最小 G-code 运行 AppShell、WorkerClient、create/load/step/snapshot、最小 3 轴页面 浏览器可加载缓存样例;命令 ack/result、快照和错误完整
FE-M2 操作闭环 程序、MDI、jog、home、override、报警 控制台、程序编辑/预览、手动操作、状态面板 正常/边界/错误/暂停恢复与原生 golden 对照通过
FE-M3 工程和恢复 OPFS、快照、断网、重启、租约 工程树、导入导出、TaskLedger、恢复 UI、离线 PWA 半提交、配额不足、确认丢失、标签页抢占和冲突均不丢数据
FE-M4 全部仿真工作流 HAL/PLC/工具/IO/Python/VCP/3D scope、Ladder、工具、数字孪生、插件和机床视图 覆盖矩阵所有 Web/API 条目有 source/test/oracle,关键交互通过
FE-M5 发布候选 稳定、离线、高效和可诊断 浏览器报告、性能报告、兼容报告、迁移/回滚和离线包 G0-G5 全绿;无孤儿来源、无未覆盖 UI 工作流、无静默降级

每个里程碑都必须附固定 context lock、上下文包、源程序关联 diff、manifest diff、测试日志、golden/difference、性能指标和回滚步骤。发现协议、状态或源文件范围变化时,回退到最早受影响的 FE/COM 里程碑重新验证。

FE 里程碑与项目里程碑映射如下:FE-M0 属于 M0,FE-M1 属于 M1,FE-M2 属于 M2,FE-M3 属于 M3,FE-M4 属于 M4,FE-M5 属于 M5。项目里程碑未通过时,对应 FE 里程碑不能单独签署完成。

9. 前端验收与覆盖矩阵绑定

前端功能不得脱离 LinuxCNC 功能条目单独宣布完成。每个前端任务至少绑定:

feature_id → source_files/source_symbols
           → config_inputs
           → worker command/event schema
           → UI workflow test
           → native/WASM oracle or Web-equivalent oracle
           → recovery/offline test
           → context_id + evidence artifact

前端与 LinuxCNC 通信条目应使用 WEB-EQUIV 或 SIM-ADAPTER;Python/VCP 回调使用 PY-WASM;虚拟主轴、探针、换刀、等离子、激光、编码器和限位使用 SIM-DEVICE。真实设备、真实实时性和安全认证继续使用 REAL-EXCLUDED,但其仿真可观察行为必须由数字孪生条目覆盖。

只有以下条件全部满足,才能声明“前端仿真工作流完成”:

  1. 能力协商正确反映当前构建和配置,不显示未实现功能。
  2. 命令从 UI 到 Worker 到 LinuxCNC 兼容层的顺序、参数、错误和结果可追踪。
  3. 快照、事件、流和最终状态在正常、暂停、恢复、断网和 Worker 重启后保持一致。
  4. 每个操作具备 pending/ack/result/error 状态,超时先对账,重试不重复副作用。
  5. UI、API、Python、HAL 和 OPFS 证据都进入 manifest,且无孤儿来源或未覆盖交互。

10. 详细测试矩阵

测试层 重点用例 自动化方式 阻断条件
Schema/类型 全部命令、事件、快照、未知版本、缺字段、超限数据 TS 单测 + C/TS 编解码 round-trip 任一消息无法双向解析或错误码不稳定
WorkerClient seq、operation_id、ack/result、timeout、cancel、重复/迟到响应 假 Worker、确定性时钟 重复副作用、pending 泄漏或错误被吞掉
ProtocolGateway 权限、状态机、能力、prepare/commit、幂等 Worker 单测 + WASM stub 未授权命令进入核心或账本不一致
C ABI create/load/command/step/snapshot/event/export/import/destroy Node/WASM harness 和浏览器 Worker 内存越界、顺序变化、错误映射不一致
Domain store 完整/增量快照、事件乱序、流 gap、恢复覆盖 reducer/property tests UI 状态无法由消息历史重建
UI 工作流 工程、程序、MDI、jog、home、override、工具、HAL、PLC、报警 Playwright + 页面对象 任一覆盖条目没有正常/错误/恢复路径
可视化 轨迹、姿态、坐标、毛坯、resize、隐藏/恢复 Playwright screenshot + canvas pixel checks 空画布、姿态错误、遮挡或动态内容改变布局
离线/恢复 首次缓存、启动无网、中途断网、刷新、Worker 崩溃、租约转移 Playwright context/service-worker fault injection 已提交数据丢失、重复命令、无法继续
性能/背压 大 G-code、多 HAL pin、高采样、长日志、快速模式 browser benchmark + trace P95/P99 超预算、无界队列、主线程长任务
浏览器兼容 Chromium、Firefox、Safari 支持矩阵 CI/browser farm 或锁定本地环境 必选工作流在任一目标浏览器失败

每个测试输出 context_id、浏览器、协议版本、工程哈希、最后 seq/tick、状态哈希和产物路径。视觉截图只验证布局和渲染,不能替代 LinuxCNC 状态和轨迹 golden。