import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { getFiveAxisProfile } from "../../app/src/profiles/index.js"; import { createLinuxCncKinematicsRuntime } from "../../app/src/runtime/linuxcnc-kinematics-runtime.js"; import { applyIniConfigToProfile, parseLinuxCncIni, } from "../../app/src/runtime/linuxcnc-ini-runtime.js"; import { stageProfileMachineFiles } from "../../app/src/runtime/linuxcnc-machine-file-staging.js"; import { buildTaskHalSessionFromMachineFiles } from "../../app/src/runtime/linuxcnc-task-hal-runtime.js"; import { createSimulationStore, validateRunPreconditions, } from "../../app/src/state/store.js"; const cases = [ { profileId: "xyzac-trt", machineName: "sim-xyzac-trt-kins (switchkins)", coordinates: "XYZAC", kinematicsName: "xyzac-trt-kins", kinematicsModuleId: "xyzac-trt", wasmFile: "linuxcnc_xyzac_trt_kinematics.wasm", sourceRel: "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc", }, { profileId: "xyzbc-trt", machineName: "sim-xyzbc-trt-kins (switchkins)", coordinates: "XYZBC", kinematicsName: "xyzbc-trt-kins", kinematicsModuleId: "xyzbc-trt", wasmFile: "linuxcnc_xyzbc_trt_kinematics.wasm", sourceRel: "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/boat-xyzbc.ngc", }, ]; for (const item of cases) { const baseProfile = getFiveAxisProfile(item.profileId); const iniText = await readLinuxCncFile(baseProfile.iniPath); const iniConfig = parseLinuxCncIni(iniText, { path: baseProfile.iniPath, profileId: item.profileId, }); assert.equal(iniConfig.profileId, item.profileId); assert.equal(iniConfig.machineName, item.machineName); assert.equal(iniConfig.traj.coordinates, item.coordinates); assert.equal(iniConfig.kinematics.name, item.kinematicsName); assert.equal(iniConfig.kinematicsModuleId, item.kinematicsModuleId); assert.equal(iniConfig.validation.ready, true); const profile = applyIniConfigToProfile(baseProfile, iniConfig); assert.equal(profile.traj.coordinates, item.coordinates); assert.equal(profile.kinematicsModuleId, item.kinematicsModuleId); assert.equal(profile.axisLimits[item.coordinates[0]].max > 0, true); assert.equal(profile.jointConfig.length, item.coordinates.length); const kinematicsRuntime = await createLinuxCncKinematicsRuntime({ moduleId: item.kinematicsModuleId }); assert.equal(kinematicsRuntime.readiness().moduleId, item.kinematicsModuleId); assert.equal(kinematicsRuntime.wasmFile, item.wasmFile); assert.equal(kinematicsRuntime.frameForJoints([10, 20, 30, 5, 15]).moduleId, item.kinematicsModuleId); const staged = await stageProfileMachineFiles(profile); const selectedPlan = staged.plan.selectedProgramSourceRel === item.sourceRel ? staged.plan : { ...staged.plan, wasmProgramPath: staged.save.files.find((file) => file.sourceRel === item.sourceRel)?.wasmPath, selectedProgramSourceRel: item.sourceRel, }; const session = buildTaskHalSessionFromMachineFiles({ profile, plan: selectedPlan, save: staged.save, selectedProgramRel: item.sourceRel, }); assert.equal(session.profileId, item.profileId); assert.equal(session.iniPath.endsWith(`${item.profileId}.ini`), true); assert.equal(session.programSourceRel, item.sourceRel); assert.equal(session.programPath.endsWith(item.sourceRel.split("/").at(-1)), true); } const initialStore = createSimulationStore(); let check = validateRunPreconditions(initialStore.getState(), { requireTaskHalRuntime: false, requireTaskHalSession: false, }); assert.equal(check.ok, false); assert.equal(check.operatorMessage, "run blocked: LinuxCNC INI not loaded"); const profile = getFiveAxisProfile("xyzac-trt"); const iniText = await readLinuxCncFile(profile.iniPath); const iniConfig = parseLinuxCncIni(iniText, { path: profile.iniPath, profileId: profile.id, }); const store = createSimulationStore(); store.dispatch({ type: "ATTACH_INI_CONFIG", profileId: profile.id, iniConfig }); store.dispatch({ type: "ATTACH_KINEMATICS_RUNTIME", runtime: await createLinuxCncKinematicsRuntime({ moduleId: "xyzac-trt" }), }); await store.stageMachineFiles(); store.dispatch({ type: "LOAD_LINUXCNC_GCODE_SOURCE", sourceRel: "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzac_switchkins_test_1.ngc", }); check = validateRunPreconditions(store.getState(), { requireTaskHalRuntime: false, requireTaskHalSession: false, }); assert.equal(check.ok, true); assert.equal(check.profileId, "xyzac-trt"); assert.equal(check.coordinates, "XYZAC"); assert.equal(check.kinematicsModuleId, "xyzac-trt"); assert.equal(check.selectedGcodeSourceRel.endsWith("xyzac_switchkins_test_1.ngc"), true); check = validateRunPreconditions(store.getState(), { requireTaskHalRuntime: true, requireTaskHalSession: false, }); assert.equal(check.ok, false); assert.equal(check.operatorMessage, "run blocked: task/HAL runtime not ready"); console.log("run_preconditions_ini_profile_smoke=ok"); console.log("run_preconditions_kinematics_smoke=ok"); console.log("run_preconditions_machine_file_smoke=ok"); async function readLinuxCncFile(sourceRel) { return readFile(new URL(`../../../wasm-port/vendor/linuxcnc/${sourceRel}`, import.meta.url), "utf8"); }