推进 INI 面板 run G-code workflow helper

This commit is contained in:
2026-06-14 21:38:37 +08:00
parent 8e8a319d78
commit 75818c1379
7 changed files with 412 additions and 66 deletions

View File

@@ -29,16 +29,16 @@ import {
machineFileSaveLogLines,
} from "./machine-file-summary.js";
import {
createRunSummary,
summarizeRunResult,
} from "./run-summary.js";
import {
runGcodeSessionWorkflow,
} from "./run-workflow.js";
import {
createMachineSessionLoadSummary,
machineSessionLoadLogLines,
} from "./session-load-summary.js";
import {
createSessionSnapshotSummary,
sessionSnapshotMetadataLogLines,
sessionSnapshotSummaryLogLines,
} from "./session-summary.js";
import {
@@ -361,19 +361,6 @@ function sessionSnapshotMetadata() {
};
}
function sessionMetadataLogLines(metadata = {}) {
return sessionSnapshotMetadataLogLines(createSessionSnapshotSummary({ metadata }));
}
function runSessionContextLogLines(program, snapshot = restoredSessionSnapshot) {
return [
`Program: ${program.opfsPath} -> ${program.wasmPath}`,
`Program source: ${program.source}`,
`Snapshot: ${snapshot ? sessionSnapshotLabel(snapshot.sessionId) : "-"}`,
...sessionMetadataLogLines(snapshot?.metadata),
];
}
function clearLastRunSummary() {
window.linuxCncIniPanelLastRunSummary = null;
setField("runSource", "-");
@@ -383,15 +370,7 @@ function clearLastRunSummary() {
setField("runWasmPath", "-");
}
function setLastRunSummary(program, runtime = {}, snapshot = restoredSessionSnapshot) {
const summary = createRunSummary(
program,
{
...runtime,
snapshotLabel: snapshot ? sessionSnapshotLabel(snapshot.sessionId) : null,
},
snapshot,
);
function setLastRunSummary(summary) {
window.linuxCncIniPanelLastRunSummary = summary;
setField("runSource", summary.programSource);
setField("runSnapshot", summary.snapshotLabel ?? "-");
@@ -401,29 +380,6 @@ function setLastRunSummary(program, runtime = {}, snapshot = restoredSessionSnap
return summary;
}
async function loadSelectedGcodeProgram() {
const opfsPath = restoredSessionSnapshot?.payload?.files?.gcode;
let filename = UI_SESSION.defaultGcodeFilename;
let selectedOpfsPath = defaultGcodeOpfsPath();
let source = "default";
if (typeof opfsPath === "string") {
try {
filename = gcodeFilenameFromProgramPath(opfsPath);
selectedOpfsPath = opfsPath;
source = "snapshot";
} catch {
filename = UI_SESSION.defaultGcodeFilename;
}
}
return {
filename,
opfsPath: selectedOpfsPath,
source,
wasmPath: UI_SESSION.gcodeWasmPath,
text: await loadGcodeProgram(filename),
};
}
async function restoreSessionSnapshotToEditor() {
const snapshot = await loadMachineSessionSnapshot(
UI_SESSION.snapshotId,
@@ -682,25 +638,33 @@ document.getElementById("run-gcode").addEventListener("click", async () => {
clearLastRunSummary();
setRunMonitor(5, "running", {}, "running");
await nextFrame();
const result = interp.runFileWithIni(program.wasmPath, loadedSession.ini.wasmPath);
const trimmedResult = result.trim();
const motionSnapshots = parseRunMotion(trimmedResult, program.text);
const runResultSummary = summarizeRunResult(trimmedResult, motionSnapshots);
setField("sessionGcode", program.opfsPath);
setField("runStatus", "ok");
setLastRunSummary(program, {
runStatus: "ok",
iniWasmPath: loadedSession.ini.wasmPath,
...runResultSummary,
const workflow = await runGcodeSessionWorkflow({
interp,
loadedSession,
snapshot: restoredSessionSnapshot,
defaultFilename: UI_SESSION.defaultGcodeFilename,
defaultOpfsPath: defaultGcodeOpfsPath(),
wasmPath: UI_SESSION.gcodeWasmPath,
gcodeFilenameFromProgramPath,
loadGcodeProgram,
snapshotLabel: restoredSessionSnapshot ? sessionSnapshotLabel(restoredSessionSnapshot.sessionId) : null,
summarizeRun: (resultText, programText) => {
const motionSnapshots = parseRunMotion(resultText, programText);
return {
...summarizeRunResult(resultText, motionSnapshots),
motionSnapshots,
};
},
});
setCanonicalEvents(trimmedResult);
playRunMotion(trimmedResult, program.text, motionSnapshots);
setField("sessionGcode", workflow.fields.sessionGcode);
setField("runStatus", workflow.fields.runStatus);
setLastRunSummary(workflow.summary);
setCanonicalEvents(workflow.resultText);
playRunMotion(workflow.resultText, workflow.program.text, workflow.motionSnapshots);
setLog(
[
"Ran G-code through LinuxCNC interpreter WASM.",
...runSessionContextLogLines(program),
`INI: ${loadedSession.ini.wasmPath}`,
trimmedResult,
...workflow.logLines,
].join("\n"),
);
} catch (error) {

View File

@@ -0,0 +1,109 @@
import {
createRunSummary,
} from "./run-summary.js";
import {
createSessionSnapshotSummary,
sessionSnapshotMetadataLogLines,
} from "./session-summary.js";
export function selectSessionGcodeProgram({
snapshot = null,
defaultFilename,
defaultOpfsPath,
wasmPath,
gcodeFilenameFromProgramPath,
}) {
const snapshotOpfsPath = snapshot?.payload?.files?.gcode;
if (typeof snapshotOpfsPath === "string") {
try {
return {
filename: gcodeFilenameFromProgramPath(snapshotOpfsPath),
opfsPath: snapshotOpfsPath,
source: "snapshot",
wasmPath,
};
} catch {
// Invalid snapshot program paths fall back to the UI default program.
}
}
return {
filename: defaultFilename,
opfsPath: defaultOpfsPath,
source: "default",
wasmPath,
};
}
export function runSessionContextLogLines(program, snapshot = null, snapshotLabel = null) {
const summary = createSessionSnapshotSummary({
metadata: snapshot?.metadata ?? {},
});
return [
`Program: ${program.opfsPath} -> ${program.wasmPath}`,
`Program source: ${program.source}`,
`Snapshot: ${snapshot ? (snapshotLabel ?? snapshot?.metadata?.snapshotLabel ?? snapshot?.sessionId) : "-"}`,
...sessionSnapshotMetadataLogLines(summary),
];
}
export async function runGcodeSessionWorkflow({
interp,
loadedSession,
snapshot = null,
defaultFilename,
defaultOpfsPath,
wasmPath,
gcodeFilenameFromProgramPath,
loadGcodeProgram,
summarizeRun = () => ({}),
snapshotLabel = null,
}) {
if (!loadedSession) {
throw new Error("Load a machine session before running G-code.");
}
const program = selectSessionGcodeProgram({
snapshot,
defaultFilename,
defaultOpfsPath,
wasmPath,
gcodeFilenameFromProgramPath,
});
const programText = await loadGcodeProgram(program.filename);
interp.writeTextFile(program.wasmPath, programText);
const resultText = interp.runFileWithIni(program.wasmPath, loadedSession.ini.wasmPath).trim();
const runResultSummary = summarizeRun(resultText, programText);
const { motionSnapshots = [], ...runCounts } = runResultSummary;
const summary = createRunSummary(
program,
{
runStatus: "ok",
iniWasmPath: loadedSession.ini.wasmPath,
snapshotLabel: snapshot ? snapshotLabel : null,
...runCounts,
},
snapshot,
);
return {
program: {
...program,
text: programText,
},
resultText,
motionSnapshots,
summary,
fields: {
sessionGcode: program.opfsPath,
runStatus: summary.runStatus,
runSource: summary.programSource,
runSnapshot: summary.snapshotLabel ?? "-",
runWorkflow: summary.workflow ?? "-",
runOpfsPath: summary.programOpfsPath,
runWasmPath: summary.programWasmPath,
},
logLines: [
...runSessionContextLogLines(program, snapshot, summary.snapshotLabel),
`INI: ${loadedSession.ini.wasmPath}`,
resultText,
],
};
}