feat: complete working8 pause semantics

This commit is contained in:
wangdequan
2026-07-07 10:27:02 -04:00
parent 83402c506e
commit 4ba45b2ec5
987 changed files with 340641 additions and 65 deletions

View File

@@ -217,6 +217,13 @@ export function normalizeTaskHalStatus(status = {}) {
const halPins = status.halSnapshot?.pins || {};
const motionProgramLine = Number(motion.programLine || 0);
const halProgramLine = Number(halPins["motion.program-line"]?.value || 0);
const motionQueueDepth = Number(
status.motionStatus?.commandQueueDepth ??
motion.commandQueueDepth ??
status.motionStatus?.queueDepth ??
motion.queueDepth ??
0,
);
const activeLine = motionProgramLine > 0
? motionProgramLine
: halProgramLine > 0
@@ -242,10 +249,17 @@ export function normalizeTaskHalStatus(status = {}) {
taskState: String(status.task?.state || "ESTOP").toLowerCase(),
taskMode: String(status.task?.mode || "MANUAL").toLowerCase(),
interpState: String(status.task?.interpState || "IDLE").toLowerCase(),
interpResumeState: String(status.task?.interpResumeState || status.task?.interpState || "IDLE").toLowerCase(),
execState: String(status.task?.execState || "DONE").toLowerCase(),
taskPaused: status.task?.taskPaused === true,
singleStepping: status.task?.singleStepping === true,
taskCycle: Number(status.task?.taskCycle ?? status.taskCycle ?? 0),
servoCycle: Number(status.motionStatus?.cycle ?? status.task?.servoCycle ?? 0),
motionQueueDepth: Number(status.motionStatus?.queueDepth ?? motion.queueDepth ?? 0),
motionQueueDepth,
motionPaused: motion.paused === true,
motionStepping: motion.stepping === true,
motionId: Number(motion.motionId || 0),
idForStep: Number(motion.idForStep || 0),
halChangedPinCount: Array.isArray(status.halSnapshot?.changedPins)
? status.halSnapshot.changedPins.length
: Number(status.halSnapshot?.changedPinCount || 0),

View File

@@ -71,6 +71,14 @@ export function createLinuxCncTaskPolicyStatus(state) {
? Boolean(machineFileStaging.selectedGcodeSourceRel)
: Boolean(machineFileStaging.selectedGcodeSourceRel || state.activeProgram);
const interpIdle = interpState === "idle";
const motionPaused = state.machine?.motionPaused === true ||
state.taskHalStatus?.ui?.motionPaused === true ||
state.taskHalStatus?.motionStatus?.motion?.paused === true;
const taskPaused = state.machine?.taskPaused === true ||
state.taskHalStatus?.ui?.taskPaused === true ||
state.taskHalStatus?.task?.taskPaused === true;
const feedbackPaused = state.programRuntimeFeedback?.paused === true;
const paused = motionPaused || taskPaused || feedbackPaused || interpState === "paused" || state.runState === "paused";
const running = taskMode === "auto" &&
(state.runState === "running" || interpState === "reading" || interpState === "waiting");
const referenceOnly = state.profile?.tcpCapable === false || state.profile?.promotionAllowed === false;
@@ -81,6 +89,10 @@ export function createLinuxCncTaskPolicyStatus(state) {
taskMode,
interpState,
runState: state.runState || "idle",
motionPaused,
taskPaused,
feedbackPaused,
paused,
allHomed,
noForceHoming,
iniLoaded,
@@ -100,7 +112,7 @@ export function createLinuxCncTaskPolicyStatus(state) {
interpIdle && iniLoaded && machineFileStaged && machineFileOpened && taskHalRuntimeReady,
canExecuteMdi: taskState === "on" && taskMode === "mdi" && (allHomed || noForceHoming),
canPause: taskState === "on" && taskMode === "auto" && (interpState === "reading" || interpState === "waiting"),
canResume: taskState === "on" && (taskMode === "auto" || taskMode === "mdi") && interpState === "paused",
canResume: taskState === "on" && (taskMode === "auto" || taskMode === "mdi") && paused,
canAbort: true,
canSpindle: taskState === "on",
canCoolant: taskState === "on",
@@ -184,7 +196,7 @@ export function gateLinuxCncTaskAction(state, action) {
if (status.taskMode !== "auto" && status.taskMode !== "mdi" && status.runState !== "paused") {
return block(status, "resume blocked: task mode must be auto or MDI");
}
if (status.interpState !== "paused") return block(status, "resume blocked: interpreter is not paused");
if (!status.paused) return block(status, "resume blocked: program is not paused");
return allow(status);
case "STOP":
case "ABORT":

View File

@@ -171,6 +171,7 @@ const initialState = {
interpState: "idle",
interpResumeState: "idle",
taskPaused: false,
motionPaused: false,
manualPanel: "manual",
allHomed: false,
noForceHoming: false,
@@ -1762,6 +1763,7 @@ export function createSimulationStore(seed = {}) {
: state.machine.interpState || "reading",
interpState: "paused",
taskPaused: true,
motionPaused: true,
};
const pauseLock = createTaskHalPauseLock(state, "task-hal-plan-pause");
setState({
@@ -1794,6 +1796,7 @@ export function createSimulationStore(seed = {}) {
: state.machine.interpState,
interpState: "paused",
taskPaused: true,
motionPaused: true,
},
runState: "paused",
taskHalPauseLock: pauseLock,
@@ -1814,7 +1817,7 @@ export function createSimulationStore(seed = {}) {
setState({ operatorMessage: "pause blocked: task mode must be auto or MDI" });
break;
}
if (state.machine?.taskPaused === true || interpState === "paused" || state.runState === "paused") {
if (state.machine?.motionPaused === true || state.machine?.taskPaused === true || interpState === "paused" || state.runState === "paused") {
dispatch({ type: "RESUME", source: "pauseresume" });
break;
}
@@ -1843,6 +1846,7 @@ export function createSimulationStore(seed = {}) {
interpState: resumeState,
interpResumeState: resumeState,
taskPaused: false,
motionPaused: false,
};
setState({
machine: resumedMachine,
@@ -1875,6 +1879,7 @@ export function createSimulationStore(seed = {}) {
interpState: resumeState,
interpResumeState: resumeState,
taskPaused: false,
motionPaused: false,
},
runState: resumeState === "reading" ? "running" : "idle",
taskHalPauseLock: null,
@@ -1910,6 +1915,7 @@ export function createSimulationStore(seed = {}) {
: state.machine.interpState || "reading",
interpState: "paused",
taskPaused: true,
motionPaused: true,
};
setState({
machine: steppedMachine,
@@ -1953,6 +1959,7 @@ export function createSimulationStore(seed = {}) {
: state.machine.interpState,
interpState: "paused",
taskPaused: true,
motionPaused: true,
},
runState: "stepping",
taskHalPauseLock: null,
@@ -3791,7 +3798,17 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
const allHomed = Boolean(preserveMachine?.allHomed ?? state.machine.allHomed);
const activeLine = state.programStartLine + Math.max(Number(ui.activeLine || 1) - 1, 0);
const kinsType = resolveTaskHalKinsType(state, status, activeLine);
const paused = Boolean(pauseLock) || interpState === "paused" || motion.paused === true;
const motionPaused = Boolean(pauseLock) ||
ui.motionPaused === true ||
motion.paused === true ||
preserveMachine?.motionPaused === true;
const taskPaused = ui.taskPaused === true || task.taskPaused === true || preserveMachine?.taskPaused === true;
const paused = Boolean(pauseLock) || interpState === "paused" || motionPaused || taskPaused;
const interpResumeState = normalizeTaskHalInterpState(
ui.interpResumeState ||
task.interpResumeState ||
(paused ? state.machine.interpResumeState || "reading" : interpState),
);
const axisPose = pauseLock?.axisPose
? clampAxisPoseToProfile(pauseLock.axisPose, state.profile)
: paused
@@ -3917,8 +3934,9 @@ function applyTaskHalStatusPatch(state, status, operatorMessage, {
mode: taskMode,
manualPanel,
interpState,
interpResumeState: paused ? state.machine.interpResumeState || "reading" : interpState,
interpResumeState,
taskPaused: paused,
motionPaused,
allHomed,
noForceHoming: Boolean(state.machine.noForceHoming),
},
@@ -3952,7 +3970,11 @@ function shouldContinueTaskHalStatusLoop(state = {}, status = {}) {
const interpState = normalizeTaskHalInterpState(ui.interpState || task.interpState);
const taskMode = normalizeLinuxCncTaskMode(ui.taskMode || task.mode || state.machine?.mode);
const aborted = motion.aborted === true;
const paused = interpState === "paused" || motion.paused === true;
const paused = interpState === "paused" ||
ui.motionPaused === true ||
ui.taskPaused === true ||
motion.paused === true ||
task.taskPaused === true;
const openedProgramLineCount = Number(task.openedSourceLineCount || task.openedLineCount || 1);
const complete = interpState === "idle"
&& Number(task.nextProgramLine || 0) >= openedProgramLineCount;
@@ -3962,7 +3984,8 @@ function shouldContinueTaskHalStatusLoop(state = {}, status = {}) {
function isTaskHalRunPausedByOperator(state = {}) {
return state.runState === "paused"
|| state.machine?.interpState === "paused"
|| state.machine?.taskPaused === true;
|| state.machine?.taskPaused === true
|| state.machine?.motionPaused === true;
}
function programControlModeForMachine(machine = {}) {
@@ -3980,6 +4003,7 @@ function createPowerToggleMachinePatch(machine = {}, turningOn = false) {
interpState: "idle",
interpResumeState: "idle",
taskPaused: false,
motionPaused: false,
};
}
@@ -4137,7 +4161,11 @@ function createTaskHalRuntimeFeedback(state, status, axisPose, activeLine) {
const halProgramLine = Number(status?.halSnapshot?.pins?.["motion.program-line"]?.value || 0);
const motionProgramLine = Number(motion.programLine || 0);
const interpState = normalizeTaskHalInterpState(ui.interpState || status?.task?.interpState);
const paused = interpState === "paused" || motion.paused === true;
const paused = interpState === "paused" ||
ui.motionPaused === true ||
ui.taskPaused === true ||
motion.paused === true ||
status?.task?.taskPaused === true;
const currentVelocity = paused ? 0 : Number(ui.currentVelocity || 0);
const requestedVelocity = paused ? 0 : Number(motion.requestedVel || 0) * 60;
return {
@@ -4152,6 +4180,7 @@ function createTaskHalRuntimeFeedback(state, status, axisPose, activeLine) {
activeLineSource: ui.activeLineSource || (motionProgramLine > 0 ? "motion-status" : halProgramLine > 0 ? "hal-pin" : "fallback"),
activeLineHalSynced: motionProgramLine > 0 && halProgramLine > 0 && motionProgramLine === halProgramLine,
type: Number(motion.motionType || 0) === 3 ? "JOG" : "TASK_MOTION",
paused,
timeSeconds: Number(ui.taskCycle || 0) * 0.01,
axisPose,
currentVelocityMmPerMin: currentVelocity,
@@ -4546,6 +4575,7 @@ function normalizeTaskHalInterpState(value) {
const state = String(value || "").toLowerCase();
if (state === "paused") return "paused";
if (state === "reading") return "reading";
if (state === "waiting") return "waiting";
return "idle";
}
@@ -4583,6 +4613,7 @@ function normalizeMachineForLinuxCncTask(machine = {}, runState = "idle") {
interpState,
interpResumeState: machine.interpResumeState || (interpState === "paused" ? "reading" : interpState),
taskPaused: Boolean(machine.taskPaused || interpState === "paused"),
motionPaused: Boolean(machine.motionPaused || machine.taskPaused || interpState === "paused"),
powerOn: taskState === "on",
estopActive: taskState === "estop",
allHomed: Boolean(machine.allHomed),

View File

@@ -616,7 +616,9 @@ function updateToolbarButton(element, buttonId, action, title, active = false, i
function isProgramPaused(state) {
return state.runState === "paused" ||
state.machine?.interpState === "paused" ||
state.machine?.taskPaused === true;
state.machine?.taskPaused === true ||
state.machine?.motionPaused === true ||
state.programRuntimeFeedback?.paused === true;
}
function pauseResumeToolbarTitle(state) {