import assert from "node:assert/strict"; import { createGmoccapyHalSummary, gmoccapyHalModel, resolveGmoccapyHardwareButton, } from "../../app/src/runtime/gmoccapy-hal-model.js"; const model = gmoccapyHalModel; assert.equal(model.apiName, "web-rtcp-5axis-gmoccapy-hal-model"); assert.equal(model.profileId, "gmoccapy-xyzab"); assert.equal(model.nativeConfigPath.endsWith("gmoccapy_XYZAB.ini"), true); assert.equal(model.semanticBoundary, "gmoccapy_hal_pin_postgui_reference_web_diagnostic_only"); assert.equal(model.halFiles.length, 4); assert.equal(model.halFiles.some((file) => file.path.endsWith("core_sim_XYZAB.hal") && file.stage === "HALFILE"), true); assert.equal(model.halFiles.some((file) => file.path.endsWith("spindle_sim.hal") && file.stage === "HALFILE"), true); assert.equal(model.halFiles.some((file) => file.path.endsWith("simulated_home.hal") && file.stage === "HALFILE"), true); assert.equal(model.halFiles.some((file) => file.path.endsWith("gmoccapy_postgui.hal") && file.requiresHalcompReady), true); const groups = new Map(model.nativePins.map((group) => [group.group, group])); for (const groupName of [ "hard-buttons", "jog", "override", "operator-inputs", "settings", "tool", "program", "message", "spindle-postgui", ]) { assert.equal(groups.has(groupName), true, `${groupName} missing`); } assert.equal(groups.get("hard-buttons").pins.includes("gmoccapy.h-button.button-0"), true); assert.equal(groups.get("hard-buttons").pins.includes("gmoccapy.v-button.button-6"), true); assert.equal(groups.get("jog").pins.includes("gmoccapy.jog.axis.jog-b-minus"), true); assert.equal(groups.get("jog").pins.includes("gmoccapy.jog.jog-inc-5"), true); assert.equal(groups.get("jog").pins.includes("gmoccapy.jog.turtle-jog"), true); assert.equal(groups.get("override").pins.includes("gmoccapy.rapid.rapid-override.direct-value"), true); assert.equal(groups.get("override").pins.includes("gmoccapy.feed.feed-override.count-enable"), true); assert.equal(groups.get("override").pins.includes("gmoccapy.spindle.reset-spindle-override"), true); assert.equal(groups.get("operator-inputs").pins.includes("gmoccapy.ignore-limits"), true); assert.equal(groups.get("operator-inputs").pins.includes("gmoccapy.optional-stop"), true); assert.equal(groups.get("operator-inputs").pins.includes("gmoccapy.blockdelete"), true); assert.equal(groups.get("settings").pins.includes("gmoccapy.unlock-settings"), true); assert.equal(groups.get("tool").pins.includes("gmoccapy.toolchange-changed"), true); assert.equal(groups.get("tool").pins.includes("gmoccapy.probeheight"), true); assert.equal(groups.get("tool").pins.includes("gmoccapy.blockheight"), true); assert.equal(groups.get("tool").pins.includes("gmoccapy.toolmeasurement"), true); assert.equal(groups.get("program").pins.includes("gmoccapy.program.current-line"), true); assert.equal(groups.get("message").pins.includes("gmoccapy.error"), true); assert.equal(groups.get("spindle-postgui").pins.includes("gmoccapy.spindle_at_speed_led"), true); assert.equal(model.coreNets.length, 10); assert.equal(model.coreNets.some((net) => net.signal === "Xpos" && net.target === "joint.0.motor-pos-fb"), true); assert.equal(model.coreNets.some((net) => net.signal === "Bpos" && net.target === "joint.4.motor-pos-fb"), true); assert.equal(model.coreNets.some((net) => net.signal === "estop-loop"), true); assert.equal(model.coreNets.some((net) => net.signal === "tool-change-loop"), true); assert.equal(model.spindleNets.length, 4); assert.equal(model.spindleNets.some((net) => net.signal === "spindle-speed-cmd"), true); assert.equal(model.spindleNets.some((net) => net.signal === "spindle-at-speed"), true); assert.equal(model.postguiNets.length, 5); assert.equal(model.postguiNets.every((net) => net.requiresHalcompReady), true); assert.equal(model.postguiNets.some((net) => net.target === "gmoccapy.spindle_feedback_bar"), true); assert.equal(model.postguiNets.some((net) => net.target === "gmoccapy.tooloffset-x"), true); assert.equal(model.postguiNets.some((net) => net.simulationLoop && net.signal === "tool-change-loop"), true); assert.equal(model.hardwareButtons.source.methods.includes("_button_pin_changed"), true); assert.equal(model.hardwareButtons.behavior.edge, "rising-edge-only"); assert.equal(model.hardwareButtons.behavior.insensitiveTarget, "ignored"); assert.deepEqual(model.hardwareButtons.verticalMain.map((button) => button.nativeWidget), [ "tbtn_estop", "tbtn_on", "rbt_manual", "rbt_mdi", "rbt_auto", "tbtn_user_tabs", "tbtn_setup", ]); assert.deepEqual(model.hardwareButtons.verticalMain.map((button) => button.pin), [ "gmoccapy.v-button.button-0", "gmoccapy.v-button.button-1", "gmoccapy.v-button.button-2", "gmoccapy.v-button.button-3", "gmoccapy.v-button.button-4", "gmoccapy.v-button.button-5", "gmoccapy.v-button.button-6", ]); assert.equal(model.hardwareButtons.bottomMain.find((button) => button.index === 0).nativeWidget, "btn_homing"); assert.equal(model.hardwareButtons.bottomMain.find((button) => button.index === 0).webDispatch.type, "HOME"); assert.equal(resolveGmoccapyHardwareButton("gmoccapy.v-button.button-4", model).webDispatch.mode, "auto"); assert.equal(resolveGmoccapyHardwareButton({ location: "bottom", index: 0 }, model).webDispatch.type, "HOME"); assert.equal(resolveGmoccapyHardwareButton({ location: "right", index: 6 }, model).webDispatch.pageId, "setup"); assert.equal(resolveGmoccapyHardwareButton("gmoccapy.h-button.button-9", model), null); assert.equal(resolveGmoccapyHardwareButton({ location: "right", index: 5 }, model).webDispatch.type, "GMOCAPY_NATIVE_PAGE"); assert.equal(resolveGmoccapyHardwareButton({ location: "right", index: 5 }, model).webDispatch.pageId, "user-tabs"); assert.equal(resolveGmoccapyHardwareButton({ location: "bottom", index: 3 }, model).webDispatch.pageId, "tool-editor"); assert.equal(model.nativePages.filePage.nativeWidget, "IconFileSelection1"); assert.equal(model.nativePages.filePage.boundary, "native_GtkIconFileSelection_not_embedded_in_browser"); assert.equal(model.nativePages.macroPage.macros.length, 5); assert.equal(model.nativePages.macroPage.macros.find((macro) => macro.name === "increment").args.length, 2); assert.equal(model.nativePages.macroPage.boundary.includes("MDI"), true); assert.equal(model.nativePages.toolEditorPage.editableInWeb, false); assert.equal(model.nativePages.toolEditorPage.toolCount, 17); assert.equal(model.nativePages.implementationMatrix.some((page) => page.pageId === "setup" && page.implementation === "diagnostic-only"), true); assert.equal(model.nativePages.implementationMatrix.some((page) => page.pageId === "edit" && page.implementation === "native-only"), true); assert.equal(model.nativePages.behavior.hardButtonsDoNotFakeNativePages, true); assert.equal(model.nativePages.behavior.toolEditorKeepsIocontrolLoopback, true); assert.equal(model.halPinActions.source.methods.includes("_optional_blocks"), true); assert.equal(model.halPinActions.source.methods.includes("_blockdelete"), true); assert.equal(model.halPinActions.source.methods.includes("_on_pin_jog_changed"), true); assert.equal(model.halPinActions.source.methods.includes("_on_pin_incr_changed"), true); assert.equal(model.halPinActions.source.methods.includes("_del_message_changed"), true); assert.equal(model.halPinActions.source.methods.includes("_on_unlock_settings_changed"), true); assert.equal(model.halPinActions.source.methods.includes("_check_toolmeasurement"), true); assert.equal(model.halPinActions.source.methods.includes("_init_user_messages"), true); assert.equal(model.halPinActions.jogPins.axes.length, 5); assert.equal(model.halPinActions.jogPins.axes.find((entry) => entry.axis === "b").minus, "gmoccapy.jog.axis.jog-b-minus"); assert.equal(model.halPinActions.jogPins.increments.length, 6); assert.equal(model.halPinActions.jogPins.increments[0].distance, 0); assert.equal(model.halPinActions.jogPins.increments[5].pin, "gmoccapy.jog.jog-inc-5"); assert.equal(model.halPinActions.jogPins.increments[5].distance, 31.3563); assert.equal(model.halPinActions.jogPins.turtlePin, "gmoccapy.jog.turtle-jog"); assert.equal(model.halPinActions.operatorPins.find((pin) => pin.pin === "gmoccapy.optional-stop").webState, "gmoccapyGui.optionalBlocks"); assert.equal(model.halPinActions.operatorPins.find((pin) => pin.pin === "gmoccapy.blockdelete").webState, "gmoccapyGui.optionalStop"); assert.equal(model.halPinActions.settingsPins.find((pin) => pin.pin === "gmoccapy.unlock-settings").prefDefault, "unlock_way=use"); assert.equal(model.halPinActions.overridePins.find((pin) => pin.target === "feed").countEnable, "gmoccapy.feed.feed-override.count-enable"); assert.equal(model.halPinActions.overridePins.find((pin) => pin.target === "spindle").reset, "gmoccapy.spindle.reset-spindle-override"); assert.equal(model.halPinActions.overridePins.find((pin) => pin.target === "jogVelocity").scalePref, "scale_jog_vel=140.4"); assert.equal(model.halPinActions.behavior.optionalStopPinCrossesToBlockDelete, true); assert.equal(model.halPinActions.behavior.blockdeletePinCrossesToOptionalStop, true); assert.equal(model.halPinActions.behavior.unlockSettingsLevelDriven, true); assert.equal(model.halPinActions.behavior.jogAxisPinsPressRelease, true); assert.equal(model.halPinActions.behavior.jogPinsUseTaskPolicyGate, true); assert.equal(model.halPinActions.behavior.jogIncrementPinsRisingEdgeOnly, true); assert.equal(model.halPinActions.behavior.jogIncrementZeroIsContinuous, true); assert.equal(model.halPinActions.behavior.turtleJogLevelDriven, true); assert.equal(model.halPinActions.behavior.countInputRequiresEnable, true); assert.equal(model.halPinActions.behavior.directValueRequiresAnalogEnable, true); assert.equal(model.halPinActions.behavior.resetPinsRisingEdgeOnly, true); assert.equal(model.halPinActions.messagePins.find((pin) => pin.pin === "gmoccapy.delete-message").nativeCallback, "_del_message_changed"); assert.equal(model.halPinActions.messagePins.find((pin) => pin.pin === "gmoccapy.warning-confirm").nativeCallback, "dialogs.warning_dialog periodic confirm_pin poll"); assert.equal(model.halPinActions.behavior.deleteMessageRisingEdgeOnly, true); assert.equal(model.halPinActions.behavior.warningConfirmLevelPolled, true); assert.equal(model.halPinActions.toolMeasurementPins.toolsensorConfigured, false); assert.equal(model.halPinActions.toolMeasurementPins.pins.length, 5); assert.equal(model.halPinActions.toolMeasurementPins.pins.find((pin) => pin.pin === "gmoccapy.toolmeasurement").direction, "HAL_OUT"); assert.equal(model.halPinActions.userMessages.configured, false); assert.equal(model.halPinActions.userMessages.dynamicPinPatterns.includes("gmoccapy.messages.-response"), true); assert.equal(model.halPinActions.behavior.toolMeasurementPinsAreHalOut, true); assert.equal(model.halPinActions.behavior.toolMeasurementDisabledWithoutToolsensor, true); assert.equal(model.halPinActions.behavior.userMessagesDynamicIniOnly, true); assert.equal(model.toolChange.strategy, "iocontrol-loopback"); assert.equal(model.toolChange.manualGmoccapyPinsConnected, false); assert.deepEqual(model.toolChange.remapCodes, ["M6", "M61"]); assert.equal(model.toolChange.postguiUnlinks.map((entry) => entry.pin).join(","), "iocontrol.0.tool-change,iocontrol.0.tool-changed,iocontrol.0.tool-prep-number"); assert.equal(model.toolChange.commentedManualGuiNets.some((net) => net.target === "gmoccapy.toolchange-change"), true); assert.equal(model.toolChange.commentedManualGuiNets.some((net) => net.source === "gmoccapy.toolchange-changed"), true); assert.equal(model.toolChange.activeLoop.signal, "tool-change-loop"); assert.equal(model.toolChange.activeLoop.stage, "POSTGUI_HALFILE"); assert.equal(model.toolChange.semanticBoundary, "gmoccapy_xyzab_iocontrol_tool_change_loop_no_manual_gui_dialog"); const summary = createGmoccapyHalSummary(model); assert.equal(summary.apiName, "web-rtcp-5axis-gmoccapy-hal-model-summary"); assert.equal(summary.profileId, "gmoccapy-xyzab"); assert.equal(summary.halFileCount, 4); assert.equal(summary.nativePinGroupCount, 9); assert.equal(summary.nativePinCount >= 58, true); assert.equal(summary.coreNetCount, 10); assert.equal(summary.spindleNetCount, 4); assert.equal(summary.postguiNetCount, 5); assert.equal(summary.postguiRequiresHalcompReady, true); assert.equal(summary.hasToolChangeSimulationLoop, true); assert.equal(summary.toolChangeStrategy, "iocontrol-loopback"); assert.equal(summary.manualToolChangeGuiConnected, false); assert.equal(summary.postguiToolUnlinkCount, 3); assert.equal(summary.commentedManualToolChangeNetCount, 3); assert.equal(summary.hardwareButtonVerticalCount, 7); assert.equal(summary.hardwareButtonBottomMainCount, 4); assert.equal(summary.mappedHardwareButtonCount, 6); assert.equal(summary.hardwareButtonEdge, "rising-edge-only"); assert.equal(summary.hardwareButtonInsensitiveTarget, "ignored"); assert.equal(summary.operatorInputPinCount, 3); assert.equal(summary.settingsInputPinCount, 1); assert.equal(summary.overridePinTargetCount, 4); assert.equal(summary.jogAxisPinCount, 10); assert.equal(summary.jogIncrementPinCount, 6); assert.equal(summary.messageInputPinCount, 3); assert.equal(summary.toolMeasurementPinCount, 5); assert.equal(summary.toolMeasurementEnabled, false); assert.equal(summary.toolsensorConfigured, false); assert.equal(summary.userMessagePinCount, 0); assert.equal(summary.userMessagesConfigured, false); assert.equal(summary.optionalStopPinCrossesToBlockDelete, true); assert.equal(summary.blockdeletePinCrossesToOptionalStop, true); assert.equal(summary.unlockSettingsLevelDriven, true); assert.equal(summary.jogAxisPinsPressRelease, true); assert.equal(summary.jogPinsUseTaskPolicyGate, true); assert.equal(summary.jogIncrementPinsRisingEdgeOnly, true); assert.equal(summary.jogIncrementZeroIsContinuous, true); assert.equal(summary.turtleJogLevelDriven, true); assert.equal(summary.countInputRequiresEnable, true); assert.equal(summary.directValueRequiresAnalogEnable, true); assert.equal(summary.resetPinsRisingEdgeOnly, true); assert.equal(summary.deleteMessageRisingEdgeOnly, true); assert.equal(summary.warningConfirmLevelPolled, true); assert.equal(summary.toolMeasurementPinsAreHalOut, true); assert.equal(summary.toolMeasurementDisabledWithoutToolsensor, true); assert.equal(summary.userMessagesDynamicIniOnly, true); assert.equal(summary.nativePageCount, 12); assert.equal(summary.implementedNativePageCount, 1); assert.equal(summary.partialNativePageCount, 4); assert.equal(summary.diagnosticOnlyNativePageCount, 5); assert.equal(summary.nativeOnlyPageCount, 2); assert.equal(summary.filePageImplementation, "partial"); assert.equal(summary.macroCount, 5); assert.equal(summary.macroButtonsUseMdiGate, true); assert.equal(summary.toolEditorImplementation, "diagnostic-only"); assert.equal(summary.toolEditorWritebackDisabled, true); assert.equal(summary.hardButtonsDoNotFakeNativePages, true); assert.equal(summary.unimplementedPagesDiagnosticOnly, true); assert.equal(summary.semanticBoundary, model.semanticBoundary); console.log("gmoccapy_hal_model_smoke=ok");