按规划持续工作
This commit is contained in:
@@ -67,6 +67,22 @@ const eventCountNode = document.getElementById("event-count");
|
||||
const wasmBadge = document.getElementById("wasm-badge");
|
||||
const interpBadge = document.getElementById("interp-badge");
|
||||
const opfsBadge = document.getElementById("opfs-badge");
|
||||
const runProgressNode = document.getElementById("run-progress");
|
||||
const runProgressLabelNode = document.getElementById("run-progress-label");
|
||||
const runMotionNode = document.getElementById("run-motion");
|
||||
const runLineNode = document.getElementById("run-line");
|
||||
const runStatementNode = document.getElementById("run-statement");
|
||||
const axisNodes = {
|
||||
x: document.getElementById("axis-x"),
|
||||
y: document.getElementById("axis-y"),
|
||||
z: document.getElementById("axis-z"),
|
||||
a: document.getElementById("axis-a"),
|
||||
b: document.getElementById("axis-b"),
|
||||
c: document.getElementById("axis-c"),
|
||||
u: document.getElementById("axis-u"),
|
||||
v: document.getElementById("axis-v"),
|
||||
w: document.getElementById("axis-w"),
|
||||
};
|
||||
|
||||
const fields = {
|
||||
machine: document.getElementById("field-machine"),
|
||||
@@ -88,6 +104,7 @@ let iniSdk = null;
|
||||
let interpSdk = null;
|
||||
let loadedSession = null;
|
||||
let canonicalEventText = "";
|
||||
let runPlaybackTimer = null;
|
||||
|
||||
function setBadge(node, text, className = "badge") {
|
||||
node.className = className;
|
||||
@@ -119,6 +136,109 @@ function setField(name, value) {
|
||||
fields[name].textContent = value ?? "-";
|
||||
}
|
||||
|
||||
function nextFrame() {
|
||||
return new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
}
|
||||
|
||||
function formatAxisValue(value) {
|
||||
return Number.isFinite(value) ? value.toFixed(3) : "0.000";
|
||||
}
|
||||
|
||||
function clearRunPlayback() {
|
||||
if (runPlaybackTimer) {
|
||||
clearInterval(runPlaybackTimer);
|
||||
runPlaybackTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function setRunMonitor(progress, label, axes = {}, motionText = "idle", lineText = "line -", statement = "-") {
|
||||
runProgressNode.value = Math.max(0, Math.min(100, progress));
|
||||
runProgressLabelNode.textContent = label;
|
||||
runMotionNode.textContent = motionText;
|
||||
runLineNode.textContent = lineText;
|
||||
runStatementNode.textContent = statement;
|
||||
for (const [axis, node] of Object.entries(axisNodes)) {
|
||||
node.textContent = formatAxisValue(axes[axis] ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
function readCanonicalNumber(line, name) {
|
||||
const match = line.match(new RegExp(`(?:^| )${name}=([-+0-9.eE]+)`));
|
||||
return match ? Number(match[1]) : null;
|
||||
}
|
||||
|
||||
function programLineMap(programText) {
|
||||
const lines = new Map();
|
||||
programText.split(/\r?\n/).forEach((line, index) => {
|
||||
lines.set(index + 1, line.trim() || "(blank)");
|
||||
});
|
||||
return lines;
|
||||
}
|
||||
|
||||
function parseRunMotion(resultText, programText) {
|
||||
const axes = { x: 0, y: 0, z: 0, a: 0, b: 0, c: 0, u: 0, v: 0, w: 0 };
|
||||
const snapshots = [];
|
||||
const sourceLines = programLineMap(programText);
|
||||
|
||||
for (const line of resultText.split("\n")) {
|
||||
const motion = line.match(/^canon_event=(STRAIGHT_TRAVERSE|STRAIGHT_FEED|ARC_FEED)\b/);
|
||||
if (!motion) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const axis of Object.keys(axes)) {
|
||||
const value = readCanonicalNumber(line, axis);
|
||||
if (value !== null && Number.isFinite(value)) {
|
||||
axes[axis] = value;
|
||||
}
|
||||
}
|
||||
|
||||
const sourceLine = readCanonicalNumber(line, "line");
|
||||
snapshots.push({
|
||||
type: motion[1],
|
||||
line: sourceLine,
|
||||
statement: Number.isFinite(sourceLine) ? (sourceLines.get(sourceLine) ?? "-") : "-",
|
||||
axes: { ...axes },
|
||||
});
|
||||
}
|
||||
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
function showRunSnapshot(snapshot, index, total) {
|
||||
const progress = total > 0 ? Math.round(((index + 1) / total) * 100) : 0;
|
||||
const lineText = Number.isFinite(snapshot.line) ? `line ${snapshot.line}` : "line -";
|
||||
setRunMonitor(
|
||||
progress,
|
||||
`${progress}%`,
|
||||
snapshot.axes,
|
||||
`${snapshot.type} ${lineText} (${index + 1}/${total})`,
|
||||
lineText,
|
||||
snapshot.statement,
|
||||
);
|
||||
}
|
||||
|
||||
function playRunMotion(resultText, programText) {
|
||||
clearRunPlayback();
|
||||
const snapshots = parseRunMotion(resultText, programText);
|
||||
if (snapshots.length === 0) {
|
||||
setRunMonitor(100, "100%", {}, "complete; no axis motion");
|
||||
return;
|
||||
}
|
||||
|
||||
let index = 0;
|
||||
showRunSnapshot(snapshots[index], index, snapshots.length);
|
||||
runPlaybackTimer = setInterval(() => {
|
||||
index += 1;
|
||||
if (index >= snapshots.length) {
|
||||
clearRunPlayback();
|
||||
showRunSnapshot(snapshots[snapshots.length - 1], snapshots.length - 1, snapshots.length);
|
||||
return;
|
||||
}
|
||||
showRunSnapshot(snapshots[index], index, snapshots.length);
|
||||
}, 220);
|
||||
}
|
||||
|
||||
function requireIniSdk() {
|
||||
if (!iniSdk) {
|
||||
throw new Error("INI WASM module is not ready yet.");
|
||||
@@ -287,10 +407,15 @@ document.getElementById("run-gcode").addEventListener("click", async () => {
|
||||
const interp = requireInterpSdk();
|
||||
const programText = await loadGcodeProgram(GCODE_FILENAME);
|
||||
interp.writeTextFile(GCODE_WASM_FILE, programText);
|
||||
clearRunPlayback();
|
||||
setField("runStatus", "running");
|
||||
setRunMonitor(5, "running", {}, "running");
|
||||
await nextFrame();
|
||||
const result = interp.runFileWithIni(GCODE_WASM_FILE, loadedSession.ini.wasmPath);
|
||||
setField("sessionGcode", GCODE_WASM_FILE);
|
||||
setField("runStatus", "ok");
|
||||
setCanonicalEvents(result.trim());
|
||||
playRunMotion(result.trim(), programText);
|
||||
setLog(
|
||||
[
|
||||
"Ran G-code through LinuxCNC interpreter WASM.",
|
||||
@@ -302,6 +427,8 @@ document.getElementById("run-gcode").addEventListener("click", async () => {
|
||||
} catch (error) {
|
||||
setField("runStatus", "failed");
|
||||
setCanonicalEvents("");
|
||||
clearRunPlayback();
|
||||
setRunMonitor(0, "failed", {}, "failed");
|
||||
setLog(`G-code run failed: ${error.message}`, true);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user