接上一轮,按接续文件继续执行

结论:Three.js 程序预览和刀具执行显示已收口,公网 HTTP/IP 下 Save/Restore Session 已支持 memory-fallback 降级并通过 node/browser gate。
This commit is contained in:
2026-06-22 06:56:34 +08:00
parent bd11a5f8d6
commit 8321055934
9 changed files with 631 additions and 221 deletions

View File

@@ -76,11 +76,14 @@
if (
canvas.dataset.threeReady !== "true" ||
canvas.dataset.threeFrameApi !== "web-rtcp-5axis-motion-frame" ||
canvas.dataset.threeSceneMode !== "program-preview-and-tool-execution" ||
canvas.dataset.threeCameraControls !== "orbit-pan-zoom" ||
Number(canvas.dataset.threePathPoints ?? 0) < 64 ||
Number(canvas.dataset.threeSceneObjects ?? 0) < 12 ||
Number(canvas.dataset.threeSceneObjects ?? 0) < 5 ||
!canvas.dataset.threeToolhead ||
!canvas.dataset.threeToolAxis ||
!canvas.dataset.threeTcpPose
!canvas.dataset.threeTcpPose ||
canvas.dataset.threeToolExecutionMarker !== "true"
) {
throw new Error(`Three.js preview did not expose ready render state: ${JSON.stringify(canvas.dataset)}`);
}
@@ -269,6 +272,14 @@
if (win.webRtcp5AxisSimulation.getState().programRuntimeFeedback?.semanticBoundary !== "linuxcnc_tp_run_cycle_feedback_without_hardware") {
throw new Error(`initial runtime feedback did not use LinuxCNC TP sample: ${JSON.stringify(win.webRtcp5AxisSimulation.getState().programRuntimeFeedback)}`);
}
canvas = doc.querySelector("[data-five-axis-canvas]");
if (
canvas.dataset.threeProgramPreviewSource !== "linuxcnc-interpreter-wasm" ||
Number(canvas.dataset.threePathPoints ?? 0) < win.webRtcp5AxisSimulation.getState().programExecution.summary.motionEventCount ||
Number(canvas.dataset.threeExecutedPathPoints ?? 0) < 1
) {
throw new Error(`Three.js preview did not consume LinuxCNC program execution path: ${JSON.stringify(canvas.dataset)}`);
}
if (!doc.querySelector('[data-program-execution-source]')?.textContent.includes("linuxcnc-interpreter-wasm")) {
throw new Error("program execution source DOM did not render interpreter source");
}
@@ -369,9 +380,15 @@
if (savedSession.snapshot.format !== "web-rtcp-5axis-session-snapshot") {
throw new Error("saveSession did not write a five-axis session snapshot");
}
if (!["opfs", "memory-fallback"].includes(savedSession.storageMode)) {
throw new Error(`saveSession used unexpected storage mode: ${savedSession.storageMode}`);
}
if (!doc.querySelector('[data-session-persistence="status"]')?.textContent.includes("saved")) {
throw new Error("session save status did not render");
}
if (!doc.querySelector('[data-session-persistence="status"]')?.textContent.includes(savedSession.storageMode)) {
throw new Error("session save status did not render storage mode");
}
if (doc.querySelector('[data-active-program-line]')?.textContent !== "Current line 2") {
throw new Error("loaded program did not render first LinuxCNC motion line");
}
@@ -393,6 +410,13 @@
if (Number(doc.querySelector(".gcode-row.active")?.dataset.programLine || 0) < 2) {
throw new Error("RUN did not highlight a LinuxCNC task/HAL motion line");
}
canvas = doc.querySelector("[data-five-axis-canvas]");
if (
Number(canvas.dataset.threeExecutedPathPoints ?? 0) < 1 ||
canvas.dataset.threeToolExecutionMarker !== "true"
) {
throw new Error(`Three.js preview did not display tool execution progress: ${JSON.stringify(canvas.dataset)}`);
}
const taskHalRunState = win.webRtcp5AxisSimulation.getState();
if (taskHalRunState.fullExecutionBoundary?.semanticBoundary !== "linuxcnc_task_motion_hal_wasm_simulation_runtime") {
throw new Error(`full execution boundary did not promote task/HAL simulation runtime: ${JSON.stringify(taskHalRunState.fullExecutionBoundary)}`);
@@ -504,6 +528,23 @@
if (!doc.querySelector('[data-session-persistence="status"]')?.textContent.includes("restored")) {
throw new Error("session restore status did not render");
}
if (!doc.querySelector('[data-session-persistence="status"]')?.textContent.includes(savedSession.storageMode)) {
throw new Error("session restore status did not preserve storage mode");
}
doc.querySelector('[data-action="SAVE_SESSION"]').click();
await wait(120);
const uiSavedSession = win.webRtcp5AxisSimulation.getState().sessionPersistence;
if (uiSavedSession.status !== "saved" || !["opfs", "memory-fallback"].includes(uiSavedSession.storageMode)) {
throw new Error(`UI Save Session did not use a supported storage mode: ${JSON.stringify(uiSavedSession)}`);
}
doc.querySelector('[data-action="JOG_X_POS"]').click();
await wait(50);
doc.querySelector('[data-action="RESTORE_SESSION"]').click();
await wait(180);
const uiRestoredSession = win.webRtcp5AxisSimulation.getState().sessionPersistence;
if (uiRestoredSession.status !== "restored" || uiRestoredSession.storageMode !== uiSavedSession.storageMode) {
throw new Error(`UI Restore Session did not restore from default storage fallback: ${JSON.stringify(uiRestoredSession)}`);
}
if (win.webRtcp5AxisSimulation.getState().machine.allHomed !== true) {
doc.querySelector('[data-action="mode-manual"]').click();
await wait(50);
@@ -569,11 +610,46 @@
if (win.webRtcp5AxisSimulation.getState().preview.selectedView !== "x") {
throw new Error("preview view button did not update state");
}
canvas = doc.querySelector("[data-five-axis-canvas]");
canvas.dispatchEvent(new WheelEvent("wheel", { deltaY: -120, bubbles: true, cancelable: true }));
canvas.dispatchEvent(new PointerEvent("pointerdown", {
pointerId: 1,
clientX: 180,
clientY: 120,
button: 0,
bubbles: true,
}));
canvas.dispatchEvent(new PointerEvent("pointermove", {
pointerId: 1,
clientX: 220,
clientY: 135,
button: 0,
bubbles: true,
}));
canvas.dispatchEvent(new PointerEvent("pointerup", {
pointerId: 1,
clientX: 220,
clientY: 135,
button: 0,
bubbles: true,
}));
await wait(50);
if (canvas.dataset.threeCameraControls !== "orbit-pan-zoom") {
throw new Error("Three.js preview did not expose orbit/pan/zoom controls");
}
assertCanvasNonblank(canvas, "interactive Three.js preview");
doc.querySelector('[data-action="clear-preview"]').click();
await wait(50);
if (win.webRtcp5AxisSimulation.getState().preview.pathPoints !== 0) {
throw new Error("clear preview button did not update path points");
}
canvas = doc.querySelector("[data-five-axis-canvas]");
if (Number(canvas.dataset.threePathPoints ?? -1) !== 0) {
throw new Error(`Three.js preview did not clear toolpath points: ${JSON.stringify(canvas.dataset)}`);
}
if (Number(canvas.dataset.threeExecutedPathPoints ?? -1) !== 0) {
throw new Error(`Three.js preview did not clear executed toolpath points: ${JSON.stringify(canvas.dataset)}`);
}
doc.querySelector('[data-action="RELOAD"]').click();
await wait(50);
if (win.webRtcp5AxisSimulation.getState().preview.pathPoints !== 8) {