169 lines
6.7 KiB
JavaScript
169 lines
6.7 KiB
JavaScript
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";
|
|
import { gateLinuxCncTaskAction } from "../../app/src/state/linuxcnc-task-policy.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");
|
|
|
|
let gate = gateLinuxCncTaskAction(store.getState(), { type: "RUN" });
|
|
assert.equal(gate.allowed, false);
|
|
assert.equal(gate.operatorMessage, "run blocked: machine must be on");
|
|
|
|
store.dispatch({ type: "TOGGLE_POWER" });
|
|
gate = gateLinuxCncTaskAction(store.getState(), { type: "RUN" });
|
|
assert.equal(gate.allowed, false);
|
|
assert.equal(gate.operatorMessage, "run blocked: switch to auto mode first");
|
|
|
|
store.dispatch({ type: "SET_MODE", mode: "auto" });
|
|
gate = gateLinuxCncTaskAction(store.getState(), { type: "RUN" });
|
|
assert.equal(gate.allowed, false);
|
|
assert.equal(gate.operatorMessage, "run blocked: home machine first");
|
|
|
|
store.dispatch({ type: "HOME" });
|
|
store.dispatch({ type: "SET_MODE", mode: "manual" });
|
|
gate = gateLinuxCncTaskAction(store.getState(), { type: "RUN" });
|
|
assert.equal(gate.allowed, false);
|
|
assert.equal(gate.operatorMessage, "run blocked: switch to auto mode first");
|
|
|
|
const unopenedStore = createSimulationStore();
|
|
unopenedStore.dispatch({ type: "ATTACH_INI_CONFIG", profileId: profile.id, iniConfig });
|
|
unopenedStore.dispatch({
|
|
type: "ATTACH_KINEMATICS_RUNTIME",
|
|
runtime: await createLinuxCncKinematicsRuntime({ moduleId: "xyzac-trt" }),
|
|
});
|
|
await unopenedStore.stageMachineFiles();
|
|
check = validateRunPreconditions(unopenedStore.getState(), {
|
|
requireTaskHalRuntime: false,
|
|
requireTaskHalSession: false,
|
|
});
|
|
assert.equal(check.ok, false);
|
|
assert.equal(check.operatorMessage, "run blocked: no machine-file G-code opened for task/HAL session");
|
|
|
|
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");
|
|
}
|