完善 xyzbc-trt OPFS 与 AXIS 首屏等效

This commit is contained in:
mes123456
2026-07-02 10:10:54 -04:00
parent 1c8908e3ab
commit 52e54f8089
16 changed files with 925 additions and 28 deletions

View File

@@ -62,7 +62,10 @@
throw new Error(`task/HAL runtime should run in worker: ${JSON.stringify(taskHal)}`);
}
await api.machineFileSeedReady;
const seedResult = await api.machineFileSeedReady;
if (seedResult?.save?.storageMode !== "opfs") {
throw new Error(`machine file seed did not use OPFS: ${JSON.stringify(seedResult?.save || seedResult)}`);
}
await waitFor(() => {
const state = api.getState();
return !state.interpreterExecutionPending
@@ -80,6 +83,13 @@
if (state.machineFileStaging?.profileId !== "xyzbc-trt") {
throw new Error(`staging profile mismatch: ${state.machineFileStaging?.profileId}`);
}
if (
state.machineFileStaging?.storageMode !== "opfs" ||
state.machineFileStaging?.storageCapability?.opfsAvailable !== true ||
state.machineFileStaging?.storageCapability?.reason !== "opfs_available"
) {
throw new Error(`machine files must use browser OPFS: ${JSON.stringify(state.machineFileStaging?.storageCapability)}`);
}
if (!state.machineFileStaging?.gcodeSources?.some((source) => source.filename === "xyzbc_switchkins.ngc")) {
throw new Error("staged sources missing xyzbc_switchkins.ngc");
}
@@ -89,6 +99,69 @@
if (state.programExecution?.summary?.motionEventCount < 1) {
throw new Error(`default program did not produce canonical motion: ${JSON.stringify(state.programExecution?.summary)}`);
}
const selectedSource = state.machineFileStaging.gcodeSources.find((source) => source.filename === "xyzbc_switchkins.ngc");
const opfsProgramText = await readOpfsText(win.navigator.storage, selectedSource.opfsPath);
if (!opfsProgramText.includes("M428") || !opfsProgramText.includes("M429")) {
throw new Error(`OPFS staged program text did not contain switchkins commands: ${selectedSource.opfsPath}`);
}
const savedSession = await api.saveSession();
if (savedSession.storageMode !== "opfs" || savedSession.storageCapability?.opfsAvailable !== true) {
throw new Error(`session save must use browser OPFS: ${JSON.stringify(savedSession.storageCapability)}`);
}
const sessionText = await readOpfsText(win.navigator.storage, savedSession.path);
if (!sessionText.includes('"machineProfile": "xyzbc-trt"')) {
throw new Error(`OPFS session snapshot did not persist xyzbc-trt profile: ${savedSession.path}`);
}
const savedToolDb = await api.saveToolDb();
if (savedToolDb.storageMode !== "opfs" || savedToolDb.storageCapability?.opfsAvailable !== true) {
throw new Error(`tool table save must use browser OPFS: ${JSON.stringify(savedToolDb.storageCapability)}`);
}
const toolTableText = await readOpfsText(win.navigator.storage, savedToolDb.path);
if (!toolTableText.includes("T2") || !toolTableText.includes("Z10")) {
throw new Error(`OPFS tool table save did not contain T2/Z10: ${savedToolDb.path}`);
}
const expectedAxisSections = {
".preview-panel": "preview-toolpath-and-machine-model",
".dro-panel": "coordinates-dro",
".gcode-panel": "program-and-mdi",
".status-sidebar": "status-mode-and-switchkins",
".info-tabs": "execution-tool-and-runtime-state",
".override-panel": "feed-rapid-override",
".spindle-coolant-panel": "spindle-coolant",
".bottom-controls": "run-jog-home-controls",
};
for (const [selector, section] of Object.entries(expectedAxisSections)) {
const element = doc.querySelector(selector);
if (!element) {
throw new Error(`missing AXIS UI section ${selector}`);
}
if (
element.dataset.axisUiSection !== section ||
element.dataset.axisUiProfile !== "xyzbc-trt" ||
element.dataset.axisUiCoordinates !== "XYZBC"
) {
throw new Error(`AXIS section dataset mismatch ${selector}: ${JSON.stringify(element.dataset)}`);
}
}
const firstScreen = await waitFor(
() => doc.querySelector('[data-axis-main-equivalence="xyzbc_trt_axis_first_screen_program_coordinates_status_mdi_switchkins_override_tool_preview_execution"]'),
"AXIS first-screen summary",
);
const capabilities = Array.from(firstScreen.querySelectorAll("[data-axis-ui-capability]"));
const capabilityIds = capabilities.map((element) => element.dataset.axisUiCapability);
for (const id of ["program", "coordinates", "status", "mdi", "switchkins", "override", "tool", "preview", "execution", "axis-buttons"]) {
if (!capabilityIds.includes(id)) {
throw new Error(`missing first-screen capability ${id}: ${capabilityIds.join(",")}`);
}
}
if (firstScreen.dataset.axisFirstScreenReady !== "true") {
throw new Error(`first-screen summary not ready: ${firstScreen.dataset.axisFirstScreenMissing}`);
}
if (!doc.querySelector('[data-action="mdi-command"]') || !doc.querySelector('[data-action="kins-tcp"]')) {
throw new Error("MDI input or switchkins TCP control missing from first screen");
}
const canvas = await waitFor(() => doc.querySelector("[data-five-axis-canvas]"), "preview canvas");
await waitFor(() => canvas.dataset.threeReady === "true" && Number(canvas.dataset.threePathPoints || 0) > 0, "Three.js dataset");
@@ -172,6 +245,19 @@
}
}
async function readOpfsText(storage, path) {
if (!storage?.getDirectory) {
throw new Error("browser OPFS getDirectory is unavailable");
}
let current = await storage.getDirectory();
const parts = String(path).split("/").filter(Boolean);
for (const part of parts.slice(0, -1)) {
current = await current.getDirectoryHandle(part);
}
const fileHandle = await current.getFileHandle(parts.at(-1));
return fileHandle.getFile().then((file) => file.text());
}
runSmoke().catch((error) => {
result.textContent = `xyzbc_trt_browser_smoke=fail ${error.stack || error.message || error}`;
});