Align Web execute-next-line with LinuxCNC
This commit is contained in:
@@ -145,6 +145,7 @@ export class SimSession {
|
||||
this.pendingProgramControl = 0;
|
||||
this.pendingTaskSync = 0;
|
||||
this.pendingXyzacMotion = null;
|
||||
this.xyzacStepTargetId = 0;
|
||||
this.pendingServoSync = 0;
|
||||
this.xyzacExecutionWaitNextMotion = false;
|
||||
this.xyzacExecutionWaitSamples = 0;
|
||||
@@ -2322,20 +2323,68 @@ export class SimSession {
|
||||
case "PROGRAM_STEP": {
|
||||
if (this.xyzacProgram) {
|
||||
try {
|
||||
const current = this.xyzacProgram.snapshot();
|
||||
const idle = !["RUNNING", "PAUSED"].includes(this.task.state.state);
|
||||
let current = this.xyzacProgram.snapshot();
|
||||
let queueDepth = Number(this.wasmMotion.read().state?.queue_depth ?? 0);
|
||||
let stepPhase = "source_line_pause";
|
||||
let stepWaitingForMotion = false;
|
||||
let stepSourceLine = current.execution_source_line ?? current.current_line ?? 0;
|
||||
let stepTargetId = null;
|
||||
let stepResult = null;
|
||||
let stepTrace = [];
|
||||
this.task.setMode("AUTO");
|
||||
this.wasmHomeLimit.setMode("COORD");
|
||||
if (this.wasmMotion.isStepping()) {
|
||||
const motion = this.wasmMotion.read();
|
||||
return finish(this.envelope("COMMAND_RESULT", input, { status: "verified", command: input.kind, step_phase: "motion_step_pending", step_waiting_for_motion: true, step_target_id: Number(motion.state.active_id ?? 0) || this.xyzacStepTargetId || null, program_steps: [], execution_trace: [], program: current, task: this.task.export(), wasm_motion: motion, motion: this.wasmMotionProjection(), motion_authority: "wasm", operation_id: input.operation_id ?? null }), "verified");
|
||||
}
|
||||
if (queueDepth > 0) {
|
||||
const targetId = Number(this.wasmMotion.read().state.active_id ?? 0) || this.xyzacStepTargetId;
|
||||
this.xyzacStepTargetId = targetId;
|
||||
if (current.status === 2) {
|
||||
const paused = this.xyzacProgram.pause();
|
||||
if (paused.status !== "verified") return finish(this.error(input, "program_pause", paused.code), "failed");
|
||||
if (this.task.state.state === "READY") this.task.transition("RUNNING");
|
||||
if (this.task.state.state === "RUNNING") this.task.transition("PAUSED");
|
||||
this.task.setProgram("paused", current.current_line);
|
||||
current = this.xyzacProgram.snapshot();
|
||||
}
|
||||
this.wasmMotion.stepLine();
|
||||
return finish(this.envelope("COMMAND_RESULT", input, { status: "verified", command: input.kind, step_phase: "motion_step", step_waiting_for_motion: true, step_target_id: targetId || null, step_source_line: current.execution_source_line ?? current.current_line, program_steps: [], execution_trace: [], program: current, task: this.task.export(), wasm_motion: this.wasmMotion.read(), motion: this.wasmMotionProjection(), motion_authority: "wasm", operation_id: input.operation_id ?? null }), "verified");
|
||||
}
|
||||
if (["completed", "aborted"].includes(current.program_status) && this.task.state.state === "STOPPED") {
|
||||
const reset = this.resetXyzacProgramToLoaded();
|
||||
if (reset.status !== "verified") return finish(this.error(input, "program_step", reset.code ?? "program_reload_failed"), "failed");
|
||||
this.wasmMotion.setPaused(false);
|
||||
this.xyzacProgramKinematicsMode = XYZAC_MODES.identity;
|
||||
if (typeof this.wasmMotion.setActiveKinematicsTag === "function") this.wasmMotion.setActiveKinematicsTag(XYZAC_MODES.identity);
|
||||
this.task.recover();
|
||||
this.task.setProgram("loaded", 0);
|
||||
current = this.xyzacProgram.snapshot();
|
||||
}
|
||||
const idle = !["RUNNING", "PAUSED"].includes(this.task.state.state) && ![2, 3].includes(current.status);
|
||||
if (idle) {
|
||||
const started = this.xyzacProgram.start();
|
||||
if (started.status !== "verified") return finish(this.error(input, "program_step", started.code), "failed");
|
||||
} else if (current.status === 3 && this.wasmMotion.queueDepth() > 0) {
|
||||
this.wasmMotion.stepLine();
|
||||
return finish(this.envelope("COMMAND_RESULT", input, { status: "verified", command: input.kind, program: current, task: this.task.export(), motion: this.wasmMotionProjection() }), "verified");
|
||||
stepPhase = "start_pause";
|
||||
stepSourceLine = 0;
|
||||
} else {
|
||||
if (current.status === 3) this.xyzacProgram.resume();
|
||||
if (current.status === 3) {
|
||||
const resumed = this.xyzacProgram.resume();
|
||||
if (resumed.status !== "verified") return finish(this.error(input, "program_resume", resumed.code), "failed");
|
||||
current = this.xyzacProgram.snapshot();
|
||||
if (current.status === 4) {
|
||||
this.task.setProgram("completed", current.current_line);
|
||||
if (["RUNNING", "PAUSED"].includes(this.task.state.state)) this.task.transition("STOPPED");
|
||||
return finish(this.envelope("COMMAND_RESULT", input, { status: "verified", command: input.kind, step_phase: "terminal", step_waiting_for_motion: false, step_source_line: current.current_line, program_steps: [], execution_trace: [], program: current, task: this.task.export(), wasm_motion: this.wasmMotion.read(), motion: this.wasmMotionProjection(), motion_authority: "wasm", operation_id: input.operation_id ?? null }), "verified");
|
||||
}
|
||||
if (current.status === 1) {
|
||||
const started = this.xyzacProgram.start();
|
||||
if (started.status !== "verified") return finish(this.error(input, "program_step", started.code), "failed");
|
||||
}
|
||||
}
|
||||
const stepped = this.xyzacProgram.step();
|
||||
if (stepped.status !== "verified") return finish(this.error(input, "program_step", stepped.code), "failed");
|
||||
stepResult = stepped;
|
||||
const sync = this.syncXyzacProgramSpindle(stepped.program);
|
||||
if (sync.status !== "verified" && sync.status !== "skipped") return finish(this.error(input, "program_spindle", sync.code), "failed");
|
||||
if (stepped.has_control && [428, 429, 430].includes(stepped.control_code)) {
|
||||
@@ -2346,20 +2395,30 @@ export class SimSession {
|
||||
stepped.motion.kinematics_mode = this.xyzacProgramKinematicsMode;
|
||||
const queued = this.wasmMotion.enqueue(stepped.motion);
|
||||
if (queued.status === "error") return finish(this.error(input, "motion_queue", queued.code), "failed");
|
||||
// AUTO_STEP releases the current trajectory line. The WASM TP
|
||||
// will stop again when its execution ID changes.
|
||||
this.wasmMotion.stepLine();
|
||||
stepTargetId = Number(stepped.motion.source_line ?? stepped.line ?? 0) || Number(this.wasmMotion.read().state.active_id ?? 0) || null;
|
||||
this.xyzacStepTargetId = stepTargetId ?? 0;
|
||||
stepPhase = "source_line_motion";
|
||||
stepWaitingForMotion = true;
|
||||
}
|
||||
stepSourceLine = stepped.program?.execution_source_line ?? stepped.line ?? stepSourceLine;
|
||||
stepTrace = [{ line: stepSourceLine, text: stepped.program?.execution_line_text ?? "", program_status: stepped.program?.program_status ?? null }].filter((entry) => Number.isSafeInteger(entry.line) && entry.line > 0);
|
||||
}
|
||||
if (this.xyzacProgram.snapshot().status === 4 && this.wasmMotion.read().state.queue_depth === 0) {
|
||||
this.task.setProgram("completed", this.xyzacProgram.snapshot().current_line);
|
||||
if (this.task.state.state !== "STOPPED") this.task.transition("STOPPED");
|
||||
return finish(this.envelope("COMMAND_RESULT", input, { status: "verified", command: input.kind, program: this.xyzacProgram.snapshot(), task: this.task.export(), motion: this.wasmMotionProjection() }), "verified");
|
||||
if (["RUNNING", "PAUSED"].includes(this.task.state.state)) this.task.transition("STOPPED");
|
||||
return finish(this.envelope("COMMAND_RESULT", input, { status: "verified", command: input.kind, step_phase: "terminal", step_waiting_for_motion: false, step_source_line: this.xyzacProgram.snapshot().current_line, program: this.xyzacProgram.snapshot(), task: this.task.export(), wasm_motion: this.wasmMotion.read(), motion: this.wasmMotionProjection(), motion_authority: "wasm", operation_id: input.operation_id ?? null }), "verified");
|
||||
}
|
||||
const paused = this.xyzacProgram.pause();
|
||||
if (paused.status !== "verified") return finish(this.error(input, "program_pause", paused.code), "failed");
|
||||
this.wasmMotion.setPaused(true);
|
||||
if (["READY", "STOPPED"].includes(this.task.state.state)) this.task.transition("RUNNING");
|
||||
if (!this.wasmMotion.isStepping()) this.wasmMotion.setPaused(true);
|
||||
if (this.task.state.state === "STOPPED") this.task.recover();
|
||||
if (this.task.state.state === "READY") this.task.transition("RUNNING");
|
||||
if (this.task.state.state === "RUNNING") this.task.transition("PAUSED");
|
||||
this.task.setProgram("paused", this.xyzacProgram.snapshot().current_line);
|
||||
return finish(this.envelope("COMMAND_RESULT", input, { status: "verified", command: input.kind, program: this.xyzacProgram.snapshot(), task: this.task.export(), motion: this.wasmMotionProjection() }), "verified");
|
||||
return finish(this.envelope("COMMAND_RESULT", input, { status: "verified", command: input.kind, step_phase: stepPhase, step_waiting_for_motion: stepWaitingForMotion || this.wasmMotion.isStepping(), step_source_line: stepSourceLine, step_target_id: stepTargetId, program_steps: stepResult ? [stepResult] : [], execution_trace: stepTrace, program: this.xyzacProgram.snapshot(), task: this.task.export(), wasm_motion: this.wasmMotion.read(), motion: this.wasmMotionProjection(), motion_authority: "wasm", operation_id: input.operation_id ?? null }), "verified");
|
||||
} catch (error) {
|
||||
return finish(this.error(input, "program_step", String(error?.message ?? error)), "failed");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user