import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import createModule from "../../build-wasm/linuxcnc-sim-core.js"; import { loadSimulationCase, toWorkerConfiguration } from "../workspace/sim-case-loader.mjs"; import { SimSession, CONTEXT_ID } from "./sim-session.mjs"; const CASE = "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini"; const fetchImpl = async (url) => { try { const body = await readFile(new URL(`../../${String(url).replace(/^\//, "")}`, import.meta.url)); return { ok: true, text: async () => body.toString("utf8") }; } catch { return { ok: false, text: async () => "" }; } }; const bundle = await loadSimulationCase({ path: CASE, fetchImpl }); assert.equal(bundle.status, "ready"); const core = await createModule({ wasmBinary: await readFile(new URL("../../build-wasm/linuxcnc-sim-core.wasm", import.meta.url)) }); const session = new SimSession(core, { sessionId: "xyzac-feed-override" }); const base = { schema_version: 1, context_id: CONTEXT_ID, session_id: session.sessionId }; let seq = 0; const send = (kind, payload = {}) => session.accept({ ...base, kind, seq: ++seq, operation_id: `override-${seq}`, payload }); send("HELLO"); send("SESSION_ATTACH"); assert.equal(send("LOAD_WORKSPACE", { root_path: "/workspace", configuration: toWorkerConfiguration(bundle) }).payload.status, "verified"); assert.equal(send("PROGRAM_LOAD", { path: "feed-override.ngc", source: "G21 G90\nG1 X10 F100\nM2\n" }).payload.status, "verified"); assert.equal(send("POWER", { active: true }).payload.status, "verified"); assert.equal(send("HOME", { all: true }).payload.status, "verified"); const jogScale = send("SET_JOG_SCALE", { percent: 50 }); assert.equal(jogScale.payload.status, "verified"); assert.equal(jogScale.payload.motion.jog_scale, 0.5); const maxVelocity = send("SET_MAX_VELOCITY", { percent: 50 }); assert.equal(maxVelocity.payload.status, "verified"); assert.equal(maxVelocity.payload.motion.velocity_scale, 0.5); const spindleOverride = send("SET_SPINDLE_OVERRIDE", { spindle: 0, scale: 0.5 }); assert.equal(spindleOverride.payload.status, "verified"); assert.equal(spindleOverride.payload.device_io.state.spindles[0].override, 0.5); assert.equal(send("SET_OVERRIDE", { feed: 0.5 }).payload.status, "verified"); const half = send("PROGRAM_RUN"); assert.equal(half.payload.status, "verified"); const halfStep = send("SIM_STEP", { cycles: 3 }); assert.equal(halfStep.payload.status, "verified"); assert.equal(session.wasmMotion.controls.feed_override, 0.5); assert.equal(halfStep.payload.panel_snapshot.overrides.feed, 0.5); assert.ok(halfStep.payload.wasm_motion.state.velocity > 0, JSON.stringify(halfStep.payload.wasm_motion.state)); assert.equal(halfStep.payload.motion.velocity_mm_min, halfStep.payload.wasm_motion.state.velocity_mm_min); assert.ok(halfStep.payload.motion.velocity_mm_min > 0); const fullOverride = send("SET_OVERRIDE", { feed: 2 }); assert.equal(fullOverride.payload.status, "verified"); assert.equal(fullOverride.payload.panel_snapshot.overrides.feed, 2); const fullStep = send("SIM_STEP", { cycles: 1 }); assert.equal(session.wasmMotion.controls.feed_override, 2); assert.ok(fullStep.payload.wasm_motion.state.velocity > halfStep.payload.wasm_motion.state.velocity, JSON.stringify(fullStep.payload.wasm_motion.state)); const invalid = send("SET_OVERRIDE", { feed: 2.01 }); assert.equal(invalid.kind, "ERROR"); assert.equal(invalid.payload.code, "motion_override"); const checkpoint = send("CHECKPOINT"); assert.equal(checkpoint.payload.status, "verified"); const recovered = send("RECOVER", { checkpoint: checkpoint.payload.checkpoint }); assert.ok(["verified", "recovered"].includes(recovered.payload.status)); assert.equal(session.wasmMotion.controls.feed_override, 2); console.log(JSON.stringify({ schema: "xyzac-feed-override.v1", status: "verified", authority: "linuxcnc-source-tp-and-wasm-io", half: { requested: 50, base_feed_mm_min: 100, actual: halfStep.payload.wasm_motion.state.velocity, panel: halfStep.payload.panel_snapshot.overrides.feed }, full: { requested: 200, base_feed_mm_min: 100, actual: fullStep.payload.wasm_motion.state.velocity, panel: fullStep.payload.panel_snapshot.overrides.feed }, invalid: invalid.payload.message_key, recovery_feed: session.wasmMotion.controls.feed_override, jog_scale: jogScale.payload.motion.jog_scale, max_velocity_scale: maxVelocity.payload.motion.velocity_scale, spindle_override: spindleOverride.payload.device_io.state.spindles[0].override, }));