export const gmoccapyCommunicationModel = { apiName: "web-rtcp-5axis-gmoccapy-communication-model", profileId: "gmoccapy-xyzab", nativeConfigPath: "linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.ini", cycleTimeMs: 100, semanticBoundary: "native_gmoccapy_nml_hal_reference_web_store_runtime_mapping", nativePaths: { command: { label: "NML command", path: ["gmoccapy", "linuxcnc.command()", "NML emcCommand", "milltask"], notes: "GUI commands are written to the NML command buffer and consumed by milltask.", }, status: { label: "NML status/error", path: ["milltask", "NML emcStatus/emcError", "linuxcnc.stat()", "linuxcnc.error_channel()", "gmoccapy"], notes: "gmoccapy polls status and error channels at DISPLAY CYCLE_TIME.", }, hal: { label: "HAL shared memory", path: ["gmoccapy.* pins", "HAL shared memory", "halui/iocontrol/motmod/spindle_sim"], notes: "postgui HAL connects gmoccapy pins after halcomp.ready().", }, hardwareButtons: { label: "HAL hardware buttons", path: ["external HAL bit", "gmoccapy.h-button/v-button pin", "_button_pin_changed", "visible sensitive GTK button", "linuxcnc.command()"], notes: "gmoccapy maps rising-edge hard-button pins to the current visible software button; insensitive or hidden targets are ignored.", }, halPins: { label: "HAL input pins", path: ["external HAL value", "gmoccapy.* input pin", "hal_glib.GPin value_changed", "gmoccapy callback", "linuxcnc.command() or GTK widget state"], notes: "jog pins, jog increment pins, settings unlock, ignore-limits, optional-stop/blockdelete, override counts/direct-value, reset and message pins enter gmoccapy through HAL callbacks; tool measurement pins are HAL_OUT diagnostics in XYZAB.", }, remap: { label: "Interpreter REMAP", path: ["milltask", "RS274NGC", "Python remap prolog/ngc/epilog"], notes: "M6/M61 remap executes on the task/interpreter side, not inside the GUI event loop.", }, filePage: { label: "Native file page", path: ["btn_load", "_show_iconview_tab(True)", "IconFileSelection1", "hal_action_open.load_file(path)", "GStat file-loaded"], notes: "gmoccapy uses Gtk/IconFileSelection and PROGRAM_PREFIX; the Web shell maps this to OPEN_FILE plus staged LinuxCNC G-code source diagnostics.", }, macroPage: { label: "Native macro buttons", path: ["[MACROS]", "_make_macro_button", "_on_btn_macro_pressed", "command.mdi(O call [args])", "interp idle/run sensitivity"], notes: "The XYZAB config defines five macros; Web macro dispatch must use MDI gates instead of bypassing task state.", }, toolEditorPage: { label: "Native tool editor", path: ["btn_tool", "_show_tooledit_tab(True)", "tooledit1.reload()", "tool.tbl", "M61 Q? or T? M6"], notes: "Native gmoccapy can edit and save tool.tbl; Web keeps writeback diagnostic-only while preserving iocontrol-loopback tool-change semantics.", }, nativePages: { label: "Native GTK page matrix", path: ["gmoccapy.glade notebooks", "tbtn_setup/user tabs/tool/touch/load-file", "button callback", "Web implementation matrix", "operator diagnostic"], notes: "Unimplemented native GTK pages are reported as diagnostic-only or native-only and must not be presented as completed Web actions.", }, }, webPath: { label: "Web simulation", path: ["button", "store.dispatch", "linuxcnc-task-policy", "runtime/status snapshot", "UI/Three.js"], notes: "The browser does not attach to native NML buffers or HAL shared memory.", }, startupStages: [ { order: 1, id: "parse-ini", nativeStep: "linuxcnc script parses gmoccapy_XYZAB.ini", webEquivalent: "profile/source map selection" }, { order: 2, id: "linuxcncsvr", nativeStep: "linuxcncsvr -ini ", webEquivalent: "not connected; reference only" }, { order: 3, id: "realtime-hal", nativeStep: "start realtime/RTAPI/HAL", webEquivalent: "task/HAL runtime simulation boundary where available" }, { order: 4, id: "milltask", nativeStep: "halcmd loadusr -Wn inihal milltask -ini ", webEquivalent: "store task policy and optional task/HAL runtime" }, { order: 5, id: "halui", nativeStep: "halcmd loadusr -Wn halui halui -ini ", webEquivalent: "HALUI pins listed as reference diagnostics" }, { order: 6, id: "halfiles", nativeStep: "run core_sim_XYZAB.hal, spindle_sim.hal, simulated_home.hal", webEquivalent: "HAL model diagnostics" }, { order: 7, id: "hal-start", nativeStep: "halcmd start", webEquivalent: "not a browser realtime thread" }, { order: 8, id: "gmoccapy", nativeStep: "gmoccapy -ini ", webEquivalent: "gmoccapy Web shell" }, { order: 9, id: "postgui", nativeStep: "halcomp.ready(), then gmoccapy_postgui.hal", webEquivalent: "postgui model shown after gmoccapy pins exist" }, ], actionMappings: [ { actionId: "estop", webAction: "ESTOP", nativeCommand: "command.state(STATE_ESTOP)", nativeStatus: "task_state STATE_ESTOP", gate: "always available as abortive safety action", }, { actionId: "estop-reset", webAction: "RESET", nativeCommand: "command.state(STATE_ESTOP_RESET)", nativeStatus: "task_state STATE_ESTOP_RESET", gate: "allowed from estop", }, { actionId: "power-on", webAction: "TOGGLE_POWER", nativeCommand: "command.state(STATE_ON)", nativeStatus: "task_state STATE_ON", gate: "blocked while STATE_ESTOP", }, { actionId: "mode-manual", webAction: "SET_MODE manual", nativeCommand: "command.mode(MODE_MANUAL)", nativeStatus: "task_mode MODE_MANUAL", gate: "blocked when AUTO interpreter is not idle", }, { actionId: "mode-mdi", webAction: "SET_MODE mdi", nativeCommand: "command.mode(MODE_MDI)", nativeStatus: "task_mode MODE_MDI", gate: "machine on and homed when NO_FORCE_HOMING=0", }, { actionId: "mode-auto", webAction: "SET_MODE auto", nativeCommand: "command.mode(MODE_AUTO)", nativeStatus: "task_mode MODE_AUTO", gate: "machine on and homed when NO_FORCE_HOMING=0", }, { actionId: "jog", webAction: "JOG", nativeCommand: "command.jog(JOG_CONTINUOUS/JOG_INCREMENT/JOG_STOP)", nativeStatus: "motion/joint feedback", gate: "machine on, manual mode, not running", }, { actionId: "home", webAction: "HOME", nativeCommand: "command.home(-1) or command.home(joint)", nativeStatus: "all-homed", gate: "machine on, manual mode, no conflicting homing command", }, { actionId: "mdi", webAction: "RUN_MDI", nativeCommand: "command.mdi(command)", nativeStatus: "interp reading/idle", gate: "machine on, MDI mode, homed when NO_FORCE_HOMING=0", }, { actionId: "auto-run", webAction: "RUN", nativeCommand: "command.auto(AUTO_RUN, start_line)", nativeStatus: "interp reading/waiting/idle", gate: "INI loaded, program loaded, machine on, homed, AUTO, interpreter idle, runtime ready", }, { actionId: "auto-pause", webAction: "PAUSE", nativeCommand: "command.auto(AUTO_PAUSE)", nativeStatus: "interp paused", gate: "AUTO or MDI with machine on", }, { actionId: "auto-resume", webAction: "RESUME", nativeCommand: "command.auto(AUTO_RESUME)", nativeStatus: "interp reading", gate: "interpreter paused", }, { actionId: "abort", webAction: "STOP/ABORT", nativeCommand: "command.abort()", nativeStatus: "interp idle after abort", gate: "available across most states", }, { actionId: "spindle", webAction: "spindle controls", nativeCommand: "command.spindle(direction, rpm)", nativeStatus: "spindle.0.forward/reverse/speed-out/speed-in", gate: "blocked in estop/off and restricted during interpreter reading/waiting", }, { actionId: "coolant", webAction: "TOGGLE_COOLANT", nativeCommand: "command.flood()/command.mist()", nativeStatus: "iocontrol.0.coolant-flood/mist", gate: "blocked in estop/off", }, { actionId: "hardware-button", webAction: "explicit data-gmoccapy-hal-pin button mapping", nativeCommand: "_button_pin_changed -> GtkButton emit clicked/pressed/toggled", nativeStatus: "same status as the target software button", gate: "rising-edge pin ignored when target button is hidden or insensitive", }, { actionId: "hal-pin-input", webAction: "GMOCAPY_HAL_PIN", nativeCommand: "_ignore_limits/_optional_blocks/_blockdelete/_on_counts_changed/_on_analog_value_changed/_reset_override/_del_message_changed", nativeStatus: "ignore-limits, block delete, optional stop, feed/rapid/spindle/jog override widget state and operator message state", gate: "counts require count-enable, direct-value requires analog-enable, reset/delete-message pins are rising-edge only", }, { actionId: "hal-settings-unlock", webAction: "GMOCAPY_HAL_PIN unlock-settings", nativeCommand: "_on_unlock_settings_changed", nativeStatus: "tbtn_setup sensitivity when rbt_hal_unlock is active", gate: "level-driven pin only gates setup access when unlock_way/rbt_hal_unlock selects HAL unlock", }, { actionId: "hal-jog-pin", webAction: "GMOCAPY_HAL_PIN jog.axis/jog-inc", nativeCommand: "_on_pin_jog_changed/_on_pin_incr_changed", nativeStatus: "manual jog command, active jog increment and gmoccapy.jog.jog-increment HAL OUT", gate: "axis pins use press/release level, task must be on and manual; increment pins are rising-edge only", }, { actionId: "hal-tool-measurement", webAction: "GMOCAPY_HAL_PIN tool measurement diagnostics", nativeCommand: "_check_toolmeasurement/on_chk_use_tool_measurement_toggled/on_btn_block_height_clicked", nativeStatus: "probeheight, blockheight, toolmeasurement, searchvel and probevel HAL_OUT pins", gate: "XYZAB has no [TOOLSENSOR], so auto tool measurement controls are disabled and Web records these pins as diagnostics", }, { actionId: "hal-user-message", webAction: "GMOCAPY_HAL_PIN messages.* diagnostics", nativeCommand: "_init_user_messages/_show_user_message", nativeStatus: "dynamic messages., waiting and response pins when MESSAGE_* entries exist", gate: "gmoccapy_XYZAB.ini defines no MESSAGE_* entries, so no dynamic user message pins are created", }, { actionId: "hal-warning-confirm", webAction: "GMOCAPY_HAL_PIN warning-confirm", nativeCommand: "dialogs.warning_dialog confirm_pin polling", nativeStatus: "active warning dialog response", gate: "level-polled while warning dialog is active", }, { actionId: "file-page", webAction: "LOAD_PROGRAM / LOAD_LINUXCNC_GCODE_SOURCE / GMOCAPY_PAGE_ACTION file-load", nativeCommand: "on_btn_load_clicked -> IconFileSelection1 -> hal_action_open.load_file", nativeStatus: "file-loaded signal updates gmoccapy.program.length/current-line/progress", gate: "blocked while interpreter is running; native GTK file chooser is represented as Web file/staged-source diagnostics", }, { actionId: "macro-page", webAction: "GMOCAPY_RUN_MACRO", nativeCommand: "_on_btn_macro_pressed -> command.mdi(O call [args])", nativeStatus: "macro buttons disabled during interpreter run and re-enabled at interp idle", gate: "same as RUN_MDI: machine on, MDI-capable, homed when NO_FORCE_HOMING=0, interpreter idle", }, { actionId: "tool-editor-page", webAction: "GMOCAPY_TOOL_EDITOR_ACTION", nativeCommand: "_init_tooleditor/_show_tooledit_tab/on_btn_selected_tool_clicked", nativeStatus: "tool.tbl rows, selected tool, active tool, tool offsets and M6/M61 commands", gate: "Web writeback is disabled; tool-change actions remain diagnostic and preserve iocontrol-loopback", }, { actionId: "native-page-diagnostic", webAction: "GMOCAPY_NATIVE_PAGE", nativeCommand: "tbtn_setup/tbtn_user_tabs/btn_touch/btn_tool/tbtn_switch_mode native page callbacks", nativeStatus: "implementation matrix and operator diagnostic message", gate: "diagnostic-only pages do not emit fake GTK page transitions or native file/tool writes", }, ], }; export function createGmoccapyCommunicationSummary(model = gmoccapyCommunicationModel) { return { apiName: `${model.apiName}-summary`, profileId: model.profileId, nativeConfigPath: model.nativeConfigPath, nativePathCount: Object.keys(model.nativePaths).length, startupStageCount: model.startupStages.length, actionCount: model.actionMappings.length, pagePathCount: ["filePage", "macroPage", "toolEditorPage", "nativePages"] .filter((key) => Boolean(model.nativePaths[key])).length, postguiAfterHalcompReady: model.startupStages.findIndex((stage) => stage.id === "postgui") > model.startupStages.findIndex((stage) => stage.id === "gmoccapy"), hasNativeNmlCommandPath: model.nativePaths.command.path.includes("NML emcCommand"), hasNativeHalPath: model.nativePaths.hal.path.includes("HAL shared memory"), hasNativeHardwareButtonPath: model.nativePaths.hardwareButtons.path.includes("_button_pin_changed"), hasNativeHalPinInputPath: model.nativePaths.halPins.path.includes("hal_glib.GPin value_changed"), hasWebStorePath: model.webPath.path.includes("store.dispatch"), semanticBoundary: model.semanticBoundary, }; }