Make machine configuration authoritative and restore native checkpoints exactly
This commit is contained in:
@@ -61,7 +61,7 @@ export function normalizeAxisState(input = {}) {
|
||||
const hasEditor = input.has_editor !== false;
|
||||
return Object.freeze({
|
||||
taskState, interpState, mode, motionMode, programStatus, queue, queueLimit,
|
||||
taskFile, hasEditor, onAnyLimit: Boolean(limits), toolLoaded: toolNumber > 0,
|
||||
taskFile, hasEditor, onAnyLimit: Boolean(limits), toolLoaded: toolNumber > 0, motionQueueDepth: number(motion.queue_depth),
|
||||
allHomed: homed.length > 0 && homed.every(Boolean), homed, fault,
|
||||
});
|
||||
}
|
||||
@@ -101,6 +101,13 @@ export function axisGate(action, input = {}) {
|
||||
case "restart": enabled = machineOn && idle && state.taskFile; reason = enabled ? "axis_restart_available" : !machineOn ? "axis_machine_off" : !state.taskFile ? "axis_taskfile_missing" : "axis_restart_state_gate"; break;
|
||||
case "mdi": enabled = machineOn && state.queue < state.queueLimit && (idle || state.mode === "MDI"); reason = enabled ? "axis_mdi_available" : estop ? "axis_estop_active" : !machineOn ? "axis_machine_off" : state.queue >= state.queueLimit ? "axis_mdi_queue_full" : "axis_interp_running"; break;
|
||||
case "jogStart": case "jogStop": case "home": case "spindle": case "coolant": enabled = manualOk && state.mode === "MANUAL"; reason = enabled ? "axis_manual_available" : estop ? "axis_estop_active" : !machineOn ? "axis_machine_off" : state.mode !== "MANUAL" ? "axis_manual_mode_required" : "axis_manual_state_gate"; break;
|
||||
// Direct operator tool commands must wait for the interpreter and motion.
|
||||
// emcTaskCheckPreconditions waits for IO on PREPARE and motion+IO on LOAD;
|
||||
// the IO handler below this gate owns prepared/changed acknowledgements.
|
||||
case "tool": case "toolPrepare": case "toolChange":
|
||||
enabled = machineOn && idle && state.motionQueueDepth === 0 && ["MANUAL", "MDI"].includes(state.mode);
|
||||
reason = estop ? "axis_estop_active" : !machineOn ? "axis_machine_off" : !idle ? "axis_interp_running" : state.motionQueueDepth > 0 ? "axis_motion_active" : !["MANUAL", "MDI"].includes(state.mode) ? "axis_tool_operator_mode_required" : "axis_tool_available";
|
||||
break;
|
||||
case "touchOff": enabled = manualOk && state.mode === "MANUAL" && trajectoryTouchOffAllowed; reason = !manualOk ? "axis_manual_state_gate" : state.mode !== "MANUAL" ? "axis_manual_mode_required" : !trajectoryTouchOffAllowed ? "axis_joint_mode_required" : "axis_touch_off_available"; break;
|
||||
case "toolTouchOff": enabled = manualOk && state.mode === "MANUAL" && trajectoryTouchOffAllowed && state.toolLoaded; reason = !state.toolLoaded ? "axis_tool_missing" : state.mode !== "MANUAL" ? "axis_manual_mode_required" : !trajectoryTouchOffAllowed ? "axis_joint_mode_required" : !manualOk ? "axis_manual_state_gate" : "axis_tool_touch_off_available"; break;
|
||||
case "overrideLimits": enabled = state.onAnyLimit; reason = enabled ? "axis_limit_override_available" : "axis_no_active_limit"; break;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
export const AXIS_ASSET_ROOT = "/linuxcnc/share/axis/images";
|
||||
import { WEB_SETTINGS, axisImagePath } from "../workspace/web-settings.mjs";
|
||||
export const AXIS_ASSET_ROOT = `./${WEB_SETTINGS.assets.axis_images}`;
|
||||
|
||||
export function axisAsset(name) {
|
||||
return `${AXIS_ASSET_ROOT}/${name}`;
|
||||
return axisImagePath(name);
|
||||
}
|
||||
|
||||
export function appendAxisIcon(document, button, asset, label) {
|
||||
|
||||
@@ -31,4 +31,14 @@ assert.equal(axisGate("overrideLimits", limit).enabled, true);
|
||||
assert.equal(axisGateMatrix(ready).run.reason, "axis_run_available");
|
||||
assert.equal(AXIS_COMMANDS.run, "PROGRAM_RUN");
|
||||
assert.equal(AXIS_BOUNDARIES.physicalHardware, "REAL-EXCLUDED");
|
||||
for (const action of ["tool", "toolPrepare", "toolChange"]) {
|
||||
assert.equal(axisGate(action, ready).enabled, true);
|
||||
assert.equal(axisGate(action, running).enabled, false);
|
||||
assert.equal(axisGate(action, paused).enabled, false);
|
||||
assert.equal(axisGate(action, estop).enabled, false);
|
||||
assert.equal(axisGate(action, { ...ready, task: { ...ready.task, state: "OFF" } }).enabled, false);
|
||||
assert.equal(axisGate(action, { ...ready, motion: { ...ready.motion, queue_depth: 1 } }).reason, "axis_motion_active");
|
||||
assert.equal(axisGate(action, { ...ready, devices: { fault: true } }).reason, "axis_fault_active");
|
||||
assert.equal(axisGate(action, { ...ready, task: { ...ready.task, mode: "AUTO" } }).enabled, false);
|
||||
}
|
||||
console.log(JSON.stringify({ schema: "axis-contract-sample.v1", status: "verified", commands: Object.keys(AXIS_COMMANDS).length, matrix: Object.keys(axisGateMatrix(ready)).length, blocked_reasons: [axisGate("mdi", queueFull).reason, axisGate("jogStart", estop).reason] }));
|
||||
|
||||
Reference in New Issue
Block a user