import { createSimulationStore } from "./state/store.js"; import { mountGmoccapyShell } from "./ui/gmoccapy-shell.js"; import { createLinuxCncInterpreterRuntime } from "./runtime/linuxcnc-interpreter-runtime.js"; import { createLinuxCncInterpreterWorkerRuntime } from "./runtime/linuxcnc-interpreter-worker-client.js"; import { createLinuxCncKinematicsRuntime } from "./runtime/linuxcnc-kinematics-runtime.js"; import { createLinuxCncKinematicsWorkerRuntime } from "./runtime/linuxcnc-kinematics-worker-client.js"; import { loadLinuxCncIniConfig } from "./runtime/linuxcnc-ini-runtime.js"; import { createLinuxCncTaskHalRuntime } from "./runtime/linuxcnc-task-hal-runtime.js"; import { createLinuxCncTaskHalWorkerRuntime } from "./runtime/linuxcnc-task-hal-worker-client.js"; const app = document.querySelector("#app"); if (!app) { throw new Error("Missing #app mount point"); } const store = createSimulationStore(); const shell = mountGmoccapyShell(app, store); const iniConfigReady = attachProfileIniConfig(store, store.getState().profile); const kinematicsRuntimeReady = attachDefaultKinematicsRuntime(store, store.getState().profile.kinematicsModuleId || store.getState().machineProfile); const interpreterRuntimeReady = attachDefaultInterpreterRuntime(store); const taskHalRuntimeReady = attachDefaultTaskHalRuntime(store); let attachedKinematicsProfile = store.getState().machineProfile; let attachedIniProfile = store.getState().machineProfile; store.subscribe((state) => { if (state.machineProfile !== attachedIniProfile) { attachedIniProfile = state.machineProfile; attachProfileIniConfig(store, state.profile).catch(() => {}); } if (state.machineProfile !== attachedKinematicsProfile) { attachedKinematicsProfile = state.machineProfile; attachDefaultKinematicsRuntime(store, state.profile.kinematicsModuleId || state.machineProfile).catch(() => {}); } }); window.webRtcp5AxisSimulation = { getState: store.getState, dispatch: store.dispatch, refreshKinematicsFrame: store.refreshKinematicsFrame, saveSession: store.saveSession, restoreSession: store.restoreSession, stageMachineFiles: store.stageMachineFiles, runFullBoundaryAudit: store.runFullBoundaryAudit, getRegions: shell.getRegions, iniConfigReady, kinematicsRuntimeReady, interpreterRuntimeReady, taskHalRuntimeReady, }; store.dispatch({ type: "BOOT_READY" }); async function attachProfileIniConfig(store, profile) { try { const iniConfig = await loadLinuxCncIniConfig(profile); store.dispatch({ type: "ATTACH_INI_CONFIG", profileId: profile.id, iniConfig }); return store.getState().iniConfigReadiness; } catch (error) { store.dispatch({ type: "INI_CONFIG_FAILED", path: profile.iniPath, error: error.message }); return store.getState().iniConfigReadiness; } } async function attachDefaultKinematicsRuntime(store, moduleId = "xyzac-trt") { const sdkModuleUrls = [ new URL("../../../wasm-port/runtime/sdk/src/linuxcnc-kinematics.js", import.meta.url).href, new URL("../wasm-port/runtime/sdk/src/linuxcnc-kinematics.js", import.meta.url).href, ]; const errors = []; for (const sdkModuleUrl of sdkModuleUrls) { if (typeof Worker === "function") { try { const runtime = await createLinuxCncKinematicsWorkerRuntime({ moduleId, sdkModuleUrl }); store.dispatch({ type: "ATTACH_KINEMATICS_RUNTIME", runtime }); await store.refreshKinematicsFrame({ operatorMessage: `LinuxCNC kinematics ${runtime.moduleId} worker ready` }); return runtime.readiness(); } catch (error) { errors.push(`${sdkModuleUrl} worker: ${error.message}`); } } try { const runtime = await createLinuxCncKinematicsRuntime({ moduleId, sdkModuleUrl }); store.dispatch({ type: "ATTACH_KINEMATICS_RUNTIME", runtime }); return runtime.readiness(); } catch (error) { errors.push(`${sdkModuleUrl}: ${error.message}`); } } try { const runtime = await createLinuxCncKinematicsRuntime({ moduleId }); store.dispatch({ type: "ATTACH_KINEMATICS_RUNTIME", runtime }); return runtime.readiness(); } catch (error) { errors.push(`default runtime: ${error.message}`); store.dispatch({ type: "SET_FRAME_SOURCE", sourceMode: "fixture-ui-only", operatorMessage: `LinuxCNC kinematics runtime unavailable: ${errors.join(" | ")}`, }); return { apiName: "web-rtcp-5axis-linuxcnc-kinematics-runtime-readiness", moduleId, loaded: false, sourceMode: "fixture-ui-only", error: errors.join(" | "), }; } } async function attachDefaultInterpreterRuntime(store) { const sdkModuleUrls = [ new URL("../../../wasm-port/runtime/sdk/src/linuxcnc-interp.js", import.meta.url).href, new URL("../wasm-port/runtime/sdk/src/linuxcnc-interp.js", import.meta.url).href, ]; const errors = []; for (const sdkModuleUrl of sdkModuleUrls) { if (typeof Worker === "function") { try { const runtime = await createLinuxCncInterpreterWorkerRuntime({ sdkModuleUrl }); store.dispatch({ type: "ATTACH_INTERPRETER_RUNTIME", runtime }); return runtime.readiness(); } catch (error) { errors.push(`${sdkModuleUrl} worker: ${error.message}`); } } try { const runtime = await createLinuxCncInterpreterRuntime({ sdkModuleUrl }); store.dispatch({ type: "ATTACH_INTERPRETER_RUNTIME", runtime }); return runtime.readiness(); } catch (error) { errors.push(`${sdkModuleUrl}: ${error.message}`); } } try { const runtime = await createLinuxCncInterpreterRuntime(); store.dispatch({ type: "ATTACH_INTERPRETER_RUNTIME", runtime }); return runtime.readiness(); } catch (error) { errors.push(`default runtime: ${error.message}`); return { apiName: "web-rtcp-5axis-linuxcnc-interpreter-runtime-readiness", loaded: false, sourceMode: "fixture-line-playback", error: errors.join(" | "), }; } } async function attachDefaultTaskHalRuntime(store) { const sdkModuleUrls = [ new URL("../../../wasm-port/runtime/sdk/src/linuxcnc-task-hal.js", import.meta.url).href, new URL("../wasm-port/runtime/sdk/src/linuxcnc-task-hal.js", import.meta.url).href, ]; const errors = []; for (const sdkModuleUrl of sdkModuleUrls) { if (typeof Worker === "function") { try { const runtime = await createLinuxCncTaskHalWorkerRuntime({ sdkModuleUrl }); const readiness = await runtime.readiness(); store.dispatch({ type: "ATTACH_TASK_HAL_RUNTIME", runtime, readiness }); return readiness; } catch (error) { errors.push(`${sdkModuleUrl} worker: ${error.message}`); } } try { const runtime = await createLinuxCncTaskHalRuntime({ sdkModuleUrl }); const readiness = runtime.readiness(); store.dispatch({ type: "ATTACH_TASK_HAL_RUNTIME", runtime, readiness }); return readiness; } catch (error) { errors.push(`${sdkModuleUrl}: ${error.message}`); } } store.dispatch({ type: "TASK_HAL_RUNTIME_FAILED", error: errors.join(" | ") }); return { apiName: "web-rtcp-5axis-linuxcnc-task-hal-runtime-readiness", loaded: false, taskRuntimeReady: false, motionRuntimeReady: false, halRuntimeReady: false, error: errors.join(" | "), }; }