fix: make Pause button pause running program
This commit is contained in:
@@ -282,6 +282,13 @@ const initialState = {
|
||||
override: 100,
|
||||
enabled: false,
|
||||
direction: "stop",
|
||||
halPins: {
|
||||
on: 0,
|
||||
forward: 0,
|
||||
reverse: 0,
|
||||
speedOut: 0,
|
||||
atSpeed: 0,
|
||||
},
|
||||
},
|
||||
coolant: {
|
||||
flood: false,
|
||||
@@ -1123,6 +1130,7 @@ export function createSimulationStore(seed = {}) {
|
||||
taskHalStatusLoop: {
|
||||
...state.taskHalStatusLoop,
|
||||
active: false,
|
||||
sequence: Number(state.taskHalStatusLoop?.sequence || 0) + 1,
|
||||
stopReason: action.reason || "stopped",
|
||||
lastError: action.error || null,
|
||||
},
|
||||
@@ -1279,7 +1287,7 @@ export function createSimulationStore(seed = {}) {
|
||||
rtcpState: turningOff ? "off" : state.rtcpState,
|
||||
feed: turningOff ? { ...state.feed, currentVelocity: 0 } : state.feed,
|
||||
coolant: turningOff ? { ...state.coolant, flood: false, mist: false } : state.coolant,
|
||||
spindle: turningOff ? { ...state.spindle, enabled: false, direction: "stop" } : state.spindle,
|
||||
spindle: turningOff ? stoppedSpindleState(state.spindle) : state.spindle,
|
||||
operatorMessage: turningOff ? "task/HAL machine power off" : "task/HAL machine power on",
|
||||
});
|
||||
runTaskHalCommandSequence([
|
||||
@@ -1303,7 +1311,7 @@ export function createSimulationStore(seed = {}) {
|
||||
rtcpState: turningOff ? "off" : state.rtcpState,
|
||||
feed: turningOff ? { ...state.feed, currentVelocity: 0 } : state.feed,
|
||||
coolant: turningOff ? { ...state.coolant, flood: false, mist: false } : state.coolant,
|
||||
spindle: turningOff ? { ...state.spindle, enabled: false, direction: "stop" } : state.spindle,
|
||||
spindle: turningOff ? stoppedSpindleState(state.spindle) : state.spindle,
|
||||
operatorMessage: turningOff ? "machine power off" : "machine power on",
|
||||
});
|
||||
}
|
||||
@@ -1333,9 +1341,7 @@ export function createSimulationStore(seed = {}) {
|
||||
mist: false,
|
||||
},
|
||||
spindle: {
|
||||
...state.spindle,
|
||||
enabled: false,
|
||||
direction: "stop",
|
||||
...stoppedSpindleState(state.spindle),
|
||||
},
|
||||
operatorMessage: "emergency stop active",
|
||||
});
|
||||
@@ -1362,9 +1368,7 @@ export function createSimulationStore(seed = {}) {
|
||||
mist: false,
|
||||
},
|
||||
spindle: {
|
||||
...state.spindle,
|
||||
enabled: false,
|
||||
direction: "stop",
|
||||
...stoppedSpindleState(state.spindle),
|
||||
},
|
||||
operatorMessage: "estop reset; machine off",
|
||||
});
|
||||
@@ -1619,6 +1623,18 @@ export function createSimulationStore(seed = {}) {
|
||||
setState({ operatorMessage: preconditions.operatorMessage });
|
||||
break;
|
||||
}
|
||||
setState({
|
||||
machine: {
|
||||
...state.machine,
|
||||
mode: "auto",
|
||||
manualPanel: null,
|
||||
interpState: "reading",
|
||||
interpResumeState: "reading",
|
||||
taskPaused: false,
|
||||
},
|
||||
runState: "running",
|
||||
operatorMessage: "task/HAL program run requested",
|
||||
});
|
||||
runValidatedTaskHalProgramRun().catch(() => {});
|
||||
break;
|
||||
}
|
||||
@@ -1718,11 +1734,22 @@ export function createSimulationStore(seed = {}) {
|
||||
break;
|
||||
}
|
||||
const direction = normalizeSpindleDirection(action.direction);
|
||||
const spindleEnabled = direction !== "stop";
|
||||
const spindleActualRpm = spindleEnabled
|
||||
? Number(state.spindle.rpm || 0) * (Number(state.spindle.override || 100) / 100)
|
||||
: 0;
|
||||
setState({
|
||||
spindle: {
|
||||
...state.spindle,
|
||||
enabled: direction !== "stop",
|
||||
enabled: spindleEnabled,
|
||||
direction,
|
||||
halPins: {
|
||||
on: spindleEnabled ? 1 : 0,
|
||||
forward: direction === "forward" ? 1 : 0,
|
||||
reverse: direction === "reverse" ? 1 : 0,
|
||||
speedOut: spindleActualRpm,
|
||||
atSpeed: spindleEnabled ? 1 : 0,
|
||||
},
|
||||
},
|
||||
operatorMessage: direction === "stop" ? "spindle stopped" : `spindle ${direction}`,
|
||||
});
|
||||
@@ -1737,9 +1764,29 @@ export function createSimulationStore(seed = {}) {
|
||||
}
|
||||
if (state.taskHalRuntime?.loaded) {
|
||||
stopTaskHalStatusLoop("paused", { operatorMessage: "task/HAL pause requested" });
|
||||
const pausedMachine = {
|
||||
...state.machine,
|
||||
interpResumeState: state.machine.interpState === "paused"
|
||||
? state.machine.interpResumeState
|
||||
: state.machine.interpState || "reading",
|
||||
interpState: "paused",
|
||||
taskPaused: true,
|
||||
};
|
||||
setState({
|
||||
machine: pausedMachine,
|
||||
runState: "paused",
|
||||
feed: {
|
||||
...state.feed,
|
||||
currentVelocity: 0,
|
||||
},
|
||||
operatorMessage: "task/HAL pause requested",
|
||||
});
|
||||
runTaskHalCommandSequence([
|
||||
{ type: "EMC_TASK_PLAN_PAUSE" },
|
||||
], { operatorMessage: "task/HAL program paused" }).catch(() => {});
|
||||
], {
|
||||
operatorMessage: "task/HAL program paused",
|
||||
preserveMachine: pausedMachine,
|
||||
}).catch(() => {});
|
||||
break;
|
||||
}
|
||||
setState({
|
||||
@@ -1756,6 +1803,26 @@ export function createSimulationStore(seed = {}) {
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "PAUSE_RESUME":
|
||||
{
|
||||
const interpState = state.machine?.interpState || state.linuxCncTaskPolicy?.interpState || "idle";
|
||||
const taskMode = state.machine?.mode || state.linuxCncTaskPolicy?.taskMode || "manual";
|
||||
const taskIsRunning = state.runState === "running" || state.runState === "stepping";
|
||||
if (state.machine?.taskPaused === true || interpState === "paused" || state.runState === "paused") {
|
||||
if (taskMode === "auto" || taskMode === "mdi") {
|
||||
dispatch({ type: "RESUME" });
|
||||
break;
|
||||
}
|
||||
setState({ operatorMessage: "resume blocked: task mode must be auto or MDI" });
|
||||
break;
|
||||
}
|
||||
if ((taskMode === "auto" || taskMode === "mdi") && (interpState !== "idle" || taskIsRunning)) {
|
||||
dispatch({ type: "PAUSE", source: "pauseresume" });
|
||||
break;
|
||||
}
|
||||
setState({ operatorMessage: "pause ignored: interpreter is idle" });
|
||||
}
|
||||
break;
|
||||
case "RESUME":
|
||||
{
|
||||
const gate = gateLinuxCncTaskAction(state, action);
|
||||
@@ -1764,10 +1831,25 @@ export function createSimulationStore(seed = {}) {
|
||||
break;
|
||||
}
|
||||
if (state.taskHalRuntime?.loaded) {
|
||||
const resumeState = state.machine.interpResumeState === "idle" || state.machine.interpResumeState === "paused"
|
||||
? "reading"
|
||||
: state.machine.interpResumeState || "reading";
|
||||
const resumedMachine = {
|
||||
...state.machine,
|
||||
interpState: resumeState,
|
||||
interpResumeState: resumeState,
|
||||
taskPaused: false,
|
||||
};
|
||||
setState({
|
||||
machine: resumedMachine,
|
||||
runState: resumeState === "reading" ? "running" : "idle",
|
||||
operatorMessage: "task/HAL resume requested",
|
||||
});
|
||||
runTaskHalCommandSequence([
|
||||
{ type: "EMC_TASK_PLAN_RESUME" },
|
||||
], {
|
||||
operatorMessage: "task/HAL program resumed",
|
||||
preserveMachine: resumedMachine,
|
||||
}).then((status) => {
|
||||
if (shouldContinueTaskHalStatusLoop(state, status)) {
|
||||
startTaskHalStatusLoop({
|
||||
@@ -1801,11 +1883,44 @@ export function createSimulationStore(seed = {}) {
|
||||
}
|
||||
if (state.taskHalRuntime?.loaded) {
|
||||
stopTaskHalStatusLoop("step", { operatorMessage: "task/HAL step requested" });
|
||||
const playback = nextProgramRuntimeSamplePlayback(state, 1);
|
||||
const playbackPatch = applyProgramPlaybackUiPatch(state, {
|
||||
activeLine: playback.activeLine,
|
||||
axisPose: playback.axisPose,
|
||||
kinsType: playback.kinsType,
|
||||
rtcpState: playback.rtcpState,
|
||||
motionIndex: playback.motionIndex,
|
||||
sampleIndex: playback.sampleIndex,
|
||||
runtimeFeedback: playback.runtimeFeedback,
|
||||
});
|
||||
const steppedMachine = {
|
||||
...state.machine,
|
||||
mode: "auto",
|
||||
manualPanel: null,
|
||||
interpResumeState: state.machine.interpState === "paused"
|
||||
? state.machine.interpResumeState || "reading"
|
||||
: state.machine.interpState || "reading",
|
||||
interpState: "paused",
|
||||
taskPaused: true,
|
||||
};
|
||||
setState({
|
||||
machine: steppedMachine,
|
||||
runState: "stepping",
|
||||
...playbackPatch,
|
||||
programElapsedSeconds: playback.timing.elapsedSeconds,
|
||||
programRemainingSeconds: playback.timing.remainingSeconds,
|
||||
feed: {
|
||||
...state.feed,
|
||||
currentVelocity: playback.timing.currentVelocity,
|
||||
},
|
||||
operatorMessage: `task/HAL step requested line ${playback.activeLine}`,
|
||||
});
|
||||
runTaskHalCommandSequence([
|
||||
{ type: "EMC_TASK_PLAN_STEP" },
|
||||
], {
|
||||
taskCycles: 1,
|
||||
operatorMessage: "task/HAL stepped one cycle",
|
||||
preserveMachine: steppedMachine,
|
||||
}).catch(() => {});
|
||||
break;
|
||||
}
|
||||
@@ -2047,6 +2162,10 @@ export function createSimulationStore(seed = {}) {
|
||||
spindle: {
|
||||
...state.spindle,
|
||||
override: clampPercent(state.spindle.override + action.delta, 0, 150),
|
||||
halPins: spindleHalPinsForState({
|
||||
...state.spindle,
|
||||
override: clampPercent(state.spindle.override + action.delta, 0, 150),
|
||||
}),
|
||||
},
|
||||
gmoccapyGui: {
|
||||
...state.gmoccapyGui,
|
||||
@@ -2399,10 +2518,13 @@ export function createSimulationStore(seed = {}) {
|
||||
}
|
||||
dispatch({ type: "TASK_HAL_SESSION_READY", session });
|
||||
const status = await state.taskHalRuntime.readStatus();
|
||||
const statusPreserveMachine = isTaskHalRunPausedByOperator(state)
|
||||
? { ...state.machine }
|
||||
: preserveMachine;
|
||||
dispatch({
|
||||
type: "TASK_HAL_STATUS_APPLIED",
|
||||
status,
|
||||
preserveMachine,
|
||||
preserveMachine: statusPreserveMachine,
|
||||
operatorMessage: `LinuxCNC task/HAL session ready ${session.programPath || "-"}`,
|
||||
});
|
||||
return session;
|
||||
@@ -2418,8 +2540,14 @@ export function createSimulationStore(seed = {}) {
|
||||
const expectedProgramPath = expectedTaskHalProgramPathForState(state);
|
||||
if (!state.taskHalSession || (expectedProgramPath && state.taskHalSession.programPath !== expectedProgramPath)) {
|
||||
await initializeTaskHalSession({ openProgram: true });
|
||||
if (isTaskHalRunPausedByOperator(state)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
const loadedMotionPlan = await loadTaskHalMotionPlanForSession(state.taskHalSession);
|
||||
if (isTaskHalRunPausedByOperator(state)) {
|
||||
return null;
|
||||
}
|
||||
if (!loadedMotionPlan) {
|
||||
setState({ operatorMessage: "run blocked: task/HAL feed motion plan not loaded" });
|
||||
return null;
|
||||
@@ -2430,10 +2558,16 @@ export function createSimulationStore(seed = {}) {
|
||||
setState({ operatorMessage: ready.operatorMessage });
|
||||
return null;
|
||||
}
|
||||
if (isTaskHalRunPausedByOperator(state)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
stopTaskHalStatusLoop("restarted", {
|
||||
operatorMessage: "task/HAL status loop restarting",
|
||||
});
|
||||
if (isTaskHalRunPausedByOperator(state)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const status = await runTaskHalCommandSequence([
|
||||
{ type: "EMC_TASK_SET_STATE", state: "ON" },
|
||||
@@ -2444,6 +2578,9 @@ export function createSimulationStore(seed = {}) {
|
||||
operatorMessage: `task/HAL program run ${ready.profileId} ${ready.kinematicsModuleId}`,
|
||||
allowFixtureSession: false,
|
||||
});
|
||||
if (isTaskHalRunPausedByOperator(state)) {
|
||||
return status;
|
||||
}
|
||||
if (shouldContinueTaskHalStatusLoop(state, status)) {
|
||||
startTaskHalStatusLoop({
|
||||
profileId: ready.profileId,
|
||||
@@ -2548,20 +2685,26 @@ export function createSimulationStore(seed = {}) {
|
||||
mode: "auto",
|
||||
manualPanel: null,
|
||||
allHomed: true,
|
||||
interpState: "idle",
|
||||
interpResumeState: "idle",
|
||||
interpState: "reading",
|
||||
interpResumeState: "reading",
|
||||
taskPaused: false,
|
||||
},
|
||||
runState: "idle",
|
||||
runState: "running",
|
||||
operatorMessage: "RUN ready: motion plan source ready; preparing task/HAL session",
|
||||
});
|
||||
const expectedProgramPath = expectedTaskHalProgramPathForState(state);
|
||||
if (!state.taskHalSession || (expectedProgramPath && state.taskHalSession.programPath !== expectedProgramPath)) {
|
||||
setState({ operatorMessage: "RUN preparing: initializing task/HAL session" });
|
||||
await initializeTaskHalSession({ openProgram: true });
|
||||
if (isTaskHalRunPausedByOperator(state)) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
setState({ operatorMessage: "RUN preparing: loading task/HAL motion plan" });
|
||||
const loadedMotionPlan = await loadTaskHalMotionPlanWithSessionRetry();
|
||||
if (isTaskHalRunPausedByOperator(state)) {
|
||||
return state;
|
||||
}
|
||||
if (!loadedMotionPlan) {
|
||||
setState({ operatorMessage: "run blocked: task/HAL feed motion plan not loaded" });
|
||||
return state;
|
||||
@@ -2571,9 +2714,15 @@ export function createSimulationStore(seed = {}) {
|
||||
setState({ operatorMessage: ready.operatorMessage });
|
||||
return state;
|
||||
}
|
||||
if (isTaskHalRunPausedByOperator(state)) {
|
||||
return state;
|
||||
}
|
||||
stopTaskHalStatusLoop("restarted", {
|
||||
operatorMessage: "task/HAL status loop restarting",
|
||||
});
|
||||
if (isTaskHalRunPausedByOperator(state)) {
|
||||
return state;
|
||||
}
|
||||
setState({
|
||||
activeLine: state.programStartLine || 1,
|
||||
programExecutionMotionIndex: 0,
|
||||
@@ -2592,6 +2741,9 @@ export function createSimulationStore(seed = {}) {
|
||||
operatorMessage: `task/HAL program run ${ready.profileId} ${ready.kinematicsModuleId}`,
|
||||
allowFixtureSession: false,
|
||||
});
|
||||
if (isTaskHalRunPausedByOperator(state)) {
|
||||
return state;
|
||||
}
|
||||
if (shouldContinueTaskHalStatusLoop(state, status)) {
|
||||
startTaskHalStatusLoop({
|
||||
profileId: ready.profileId,
|
||||
@@ -2703,7 +2855,7 @@ export function createSimulationStore(seed = {}) {
|
||||
taskCycles: loop.batchSize,
|
||||
});
|
||||
const status = await state.taskHalRuntime.readStatus();
|
||||
if (state.taskHalStatusLoop?.sequence !== sequence) {
|
||||
if (state.taskHalStatusLoop?.sequence !== sequence || state.taskHalStatusLoop?.active !== true) {
|
||||
return status;
|
||||
}
|
||||
dispatch({
|
||||
@@ -3187,6 +3339,7 @@ function createLinuxCncProcessMonitor(state = {}) {
|
||||
const spindleActualRpm = state.spindle?.enabled
|
||||
? spindleCommandRpm * (Number(state.spindle?.override || 100) / 100)
|
||||
: 0;
|
||||
const spindleHalPins = state.spindle?.halPins || {};
|
||||
const toolChange = {
|
||||
toolInSpindle: Number(toolRuntime.toolInSpindle || toolDb.toolInSpindle || 0),
|
||||
toolFromPocket: Number(toolRuntime.toolFromPocket || toolDb.toolFromPocket || 0),
|
||||
@@ -3280,10 +3433,11 @@ function createLinuxCncProcessMonitor(state = {}) {
|
||||
actualRpm: spindleActualRpm,
|
||||
overridePercent: Number(state.spindle?.override || 0),
|
||||
halPins: {
|
||||
on: Number(halPins["spindle.0.on"]?.value ?? (state.spindle?.enabled ? 1 : 0)),
|
||||
forward: Number(halPins["spindle.0.forward"]?.value ?? (state.spindle?.direction === "forward" ? 1 : 0)),
|
||||
reverse: Number(halPins["spindle.0.reverse"]?.value ?? (state.spindle?.direction === "reverse" ? 1 : 0)),
|
||||
speedOut: Number(halPins["spindle.0.speed-out"]?.value ?? spindleActualRpm),
|
||||
on: Number(spindleHalPins.on ?? halPins["spindle.0.on"]?.value ?? (state.spindle?.enabled ? 1 : 0)),
|
||||
forward: Number(spindleHalPins.forward ?? halPins["spindle.0.forward"]?.value ?? (state.spindle?.direction === "forward" ? 1 : 0)),
|
||||
reverse: Number(spindleHalPins.reverse ?? halPins["spindle.0.reverse"]?.value ?? (state.spindle?.direction === "reverse" ? 1 : 0)),
|
||||
speedOut: Number(spindleHalPins.speedOut ?? halPins["spindle.0.speed-out"]?.value ?? spindleActualRpm),
|
||||
atSpeed: Number(spindleHalPins.atSpeed ?? halPins["spindle.0.at-speed"]?.value ?? (state.spindle?.enabled ? 1 : 0)),
|
||||
},
|
||||
},
|
||||
feed: {
|
||||
@@ -3779,6 +3933,12 @@ function shouldContinueTaskHalStatusLoop(state = {}, status = {}) {
|
||||
return !aborted && !paused && !complete && (interpState === "reading" || taskMode === "mdi");
|
||||
}
|
||||
|
||||
function isTaskHalRunPausedByOperator(state = {}) {
|
||||
return state.runState === "paused"
|
||||
|| state.machine?.interpState === "paused"
|
||||
|| state.machine?.taskPaused === true;
|
||||
}
|
||||
|
||||
function createStoppedProgramStatePatch(state, {
|
||||
reason = "stopped",
|
||||
operatorMessage = "program stopped",
|
||||
@@ -4404,9 +4564,9 @@ function homeAxisPoseForState(state = {}) {
|
||||
if (state.profile?.id === "xyzac-trt" || state.profile?.id === "xyzbc-trt") {
|
||||
return clampAxisPoseToProfile({
|
||||
...initialAxisPose,
|
||||
x: 43,
|
||||
y: -32.15,
|
||||
z: -11.306,
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 10,
|
||||
}, state.profile);
|
||||
}
|
||||
const pose = { ...initialAxisPose };
|
||||
@@ -4489,6 +4649,12 @@ function executeMdiCommand(state, rawCommand) {
|
||||
rpm: parsed.spindleRpm ?? state.spindle.rpm,
|
||||
enabled: parsed.spindleEnabled ?? state.spindle.enabled,
|
||||
direction: parsed.spindleDirection ?? state.spindle.direction,
|
||||
halPins: spindleHalPinsForState({
|
||||
...state.spindle,
|
||||
rpm: parsed.spindleRpm ?? state.spindle.rpm,
|
||||
enabled: parsed.spindleEnabled ?? state.spindle.enabled,
|
||||
direction: parsed.spindleDirection ?? state.spindle.direction,
|
||||
}),
|
||||
}
|
||||
: state.spindle,
|
||||
coolant: parsed.coolantPatch
|
||||
@@ -4592,6 +4758,33 @@ function applyMdiMCode(parsed, value) {
|
||||
}
|
||||
}
|
||||
|
||||
function spindleHalPinsForState(spindle = {}) {
|
||||
const enabled = Boolean(spindle.enabled) && spindle.direction !== "stop";
|
||||
const speedOut = enabled
|
||||
? Number(spindle.rpm || 0) * (Number(spindle.override || 100) / 100)
|
||||
: 0;
|
||||
return {
|
||||
on: enabled ? 1 : 0,
|
||||
forward: spindle.direction === "forward" ? 1 : 0,
|
||||
reverse: spindle.direction === "reverse" ? 1 : 0,
|
||||
speedOut,
|
||||
atSpeed: enabled ? 1 : 0,
|
||||
};
|
||||
}
|
||||
|
||||
function stoppedSpindleState(spindle = {}) {
|
||||
return {
|
||||
...spindle,
|
||||
enabled: false,
|
||||
direction: "stop",
|
||||
halPins: spindleHalPinsForState({
|
||||
...spindle,
|
||||
enabled: false,
|
||||
direction: "stop",
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeSpindleDirection(direction) {
|
||||
const value = String(direction || "stop").toLowerCase();
|
||||
return value === "forward" || value === "reverse" ? value : "stop";
|
||||
|
||||
Reference in New Issue
Block a user