完善 working6 gmoccapy 页面诊断边界
This commit is contained in:
@@ -302,6 +302,7 @@ export const gmoccapyXyzabProfile = {
|
||||
...gmoccapyXyzabJogIncrementPins,
|
||||
"gmoccapy.jog.jog-increment",
|
||||
"gmoccapy.jog.turtle-jog",
|
||||
"gmoccapy.unlock-settings",
|
||||
"gmoccapy.feed.feed-override.counts",
|
||||
"gmoccapy.feed.feed-override.count-enable",
|
||||
"gmoccapy.feed.feed-override.analog-enable",
|
||||
@@ -326,8 +327,15 @@ export const gmoccapyXyzabProfile = {
|
||||
"gmoccapy.blockdelete",
|
||||
"gmoccapy.tooloffset-x",
|
||||
"gmoccapy.tooloffset-z",
|
||||
"gmoccapy.probeheight",
|
||||
"gmoccapy.blockheight",
|
||||
"gmoccapy.toolmeasurement",
|
||||
"gmoccapy.searchvel",
|
||||
"gmoccapy.probevel",
|
||||
"gmoccapy.toolchange-change",
|
||||
"gmoccapy.toolchange-changed",
|
||||
"gmoccapy.toolchange-number",
|
||||
"gmoccapy.toolchange-confirm",
|
||||
"gmoccapy.program.length",
|
||||
"gmoccapy.program.current-line",
|
||||
"gmoccapy.program.progress",
|
||||
@@ -341,6 +349,21 @@ export const gmoccapyXyzabProfile = {
|
||||
toolOffsetX: 0,
|
||||
toolOffsetZ: 0,
|
||||
},
|
||||
toolsensor: {
|
||||
configured: false,
|
||||
useToolMeasurementPref: false,
|
||||
blockHeightPref: 0,
|
||||
probeHeightPref: null,
|
||||
searchVelocityPref: null,
|
||||
probeVelocityPref: null,
|
||||
reason: "gmoccapy_XYZAB.ini has no [TOOLSENSOR] section; gmoccapy disables automatic tool measurement controls by default",
|
||||
},
|
||||
userMessages: {
|
||||
configured: false,
|
||||
count: 0,
|
||||
pins: [],
|
||||
reason: "gmoccapy_XYZAB.ini has no [DISPLAY] MESSAGE_* entries, so gmoccapy does not create dynamic messages.* HAL pins",
|
||||
},
|
||||
sourceReferences: sourceReferenceObjects.map((reference) => reference.path),
|
||||
sourceReferenceObjects,
|
||||
panelSchema: gmoccapyXyzabPanelSchema,
|
||||
@@ -373,6 +396,39 @@ export const gmoccapyXyzabProfile = {
|
||||
"increment xinc yinc",
|
||||
"go_to_position X-pos Y-pos Z-pos",
|
||||
],
|
||||
nativePages: {
|
||||
filePage: {
|
||||
configured: true,
|
||||
programPrefix: "../../nc_files/",
|
||||
nativeWidget: "IconFileSelection1",
|
||||
webImplementation: "partial",
|
||||
boundary: "native GtkIconFileSelection is represented by Web file input and staged G-code source selector",
|
||||
},
|
||||
macroPage: {
|
||||
configured: true,
|
||||
count: 5,
|
||||
subroutinePath: "./macros",
|
||||
webImplementation: "partial",
|
||||
macros: [
|
||||
{ name: "i_am_lost", args: [], command: "O<i_am_lost> call" },
|
||||
{ name: "halo_world", args: [], command: "O<halo_world> call" },
|
||||
{ name: "jog_around", args: [], command: "O<jog_around> call" },
|
||||
{ name: "increment", args: ["xinc", "yinc"], command: "O<increment> call [xinc] [yinc]" },
|
||||
{ name: "go_to_position", args: ["X-pos", "Y-pos", "Z-pos"], command: "O<go_to_position> call [X-pos] [Y-pos] [Z-pos]" },
|
||||
],
|
||||
boundary: "macros enter LinuxCNC through MDI O-word calls and use the same MDI gate as RUN_MDI",
|
||||
},
|
||||
toolEditor: {
|
||||
configured: true,
|
||||
toolTablePath: "linuxcnc/configs/sim/gmoccapy/tool.tbl",
|
||||
toolCount: 17,
|
||||
visibleAxes: ["X", "Y", "Z", "A", "B"],
|
||||
webImplementation: "diagnostic-only",
|
||||
writebackEnabled: false,
|
||||
boundary: "Web shows tool table and tool-change diagnostics but does not write tool.tbl",
|
||||
},
|
||||
implementationMatrixBoundary: "native GTK pages are classified as implemented, partial, diagnostic-only, or native-only",
|
||||
},
|
||||
samplePrograms: [
|
||||
"linuxcnc/nc_files/3D_Chips.ngc",
|
||||
],
|
||||
|
||||
@@ -28,13 +28,33 @@ export const gmoccapyCommunicationModel = {
|
||||
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, ignore-limits, optional-stop/blockdelete, override counts/direct-value, reset and message pins enter gmoccapy through HAL callbacks.",
|
||||
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<name> 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",
|
||||
@@ -172,6 +192,13 @@ export const gmoccapyCommunicationModel = {
|
||||
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",
|
||||
@@ -179,6 +206,20 @@ export const gmoccapyCommunicationModel = {
|
||||
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.<pinname>, 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",
|
||||
@@ -186,6 +227,34 @@ export const gmoccapyCommunicationModel = {
|
||||
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<macro> 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",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -197,6 +266,8 @@ export function createGmoccapyCommunicationSummary(model = gmoccapyCommunication
|
||||
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"),
|
||||
|
||||
@@ -115,17 +115,31 @@ export const gmoccapyHalModel = {
|
||||
webSource: "gmoccapyGui ignoreLimits, optionalBlocks, optionalStop",
|
||||
semanticBoundary: "native_ignore_limits_optional_stop_blockdelete_pin_reference_web_state_mapping",
|
||||
},
|
||||
{
|
||||
group: "settings",
|
||||
pins: [
|
||||
"gmoccapy.unlock-settings",
|
||||
],
|
||||
webSource: "gmoccapyGui settingsUnlockPin and setupSensitive",
|
||||
semanticBoundary: "native_settings_unlock_pin_reference_web_diagnostic_state",
|
||||
},
|
||||
{
|
||||
group: "tool",
|
||||
pins: [
|
||||
"gmoccapy.tooloffset-x",
|
||||
"gmoccapy.tooloffset-z",
|
||||
"gmoccapy.tool-diameter",
|
||||
"gmoccapy.probeheight",
|
||||
"gmoccapy.blockheight",
|
||||
"gmoccapy.toolmeasurement",
|
||||
"gmoccapy.searchvel",
|
||||
"gmoccapy.probevel",
|
||||
"gmoccapy.toolchange-change",
|
||||
"gmoccapy.toolchange-changed",
|
||||
"gmoccapy.toolchange-number",
|
||||
"gmoccapy.toolchange-confirm",
|
||||
],
|
||||
webSource: "toolPreview and disconnected manual tool-change diagnostics",
|
||||
webSource: "toolPreview, disconnected manual tool-change diagnostics, and disabled XYZAB tool measurement outputs",
|
||||
semanticBoundary: "native_tool_pin_reference_simulated_tool_loop",
|
||||
},
|
||||
{
|
||||
@@ -347,16 +361,17 @@ export const gmoccapyHalModel = {
|
||||
index: 5,
|
||||
pin: "gmoccapy.v-button.button-5",
|
||||
nativeWidget: "tbtn_user_tabs",
|
||||
webAction: "SET_MODE manual",
|
||||
webDispatch: { type: "SET_MODE", mode: "jog" },
|
||||
webSelector: '[data-action="mode-jog"]',
|
||||
gate: "machine on and manual page available",
|
||||
webAction: "GMOCAPY_NATIVE_PAGE user-tabs",
|
||||
webDispatch: { type: "GMOCAPY_NATIVE_PAGE", pageId: "user-tabs", nativeWidget: "tbtn_user_tabs" },
|
||||
webSelector: null,
|
||||
gate: "native user tabs page is diagnostic-only in the Web shell",
|
||||
},
|
||||
{
|
||||
index: 6,
|
||||
pin: "gmoccapy.v-button.button-6",
|
||||
nativeWidget: "tbtn_setup",
|
||||
webAction: "UI_CONTROL",
|
||||
webAction: "GMOCAPY_NATIVE_PAGE setup",
|
||||
webDispatch: { type: "GMOCAPY_NATIVE_PAGE", pageId: "setup", nativeWidget: "tbtn_setup" },
|
||||
webSelector: null,
|
||||
gate: "native setup page is diagnostic-only in the Web shell",
|
||||
},
|
||||
@@ -375,7 +390,8 @@ export const gmoccapyHalModel = {
|
||||
index: 1,
|
||||
pin: "gmoccapy.h-button.button-1",
|
||||
nativeWidget: "btn_touch",
|
||||
webAction: "UI_CONTROL",
|
||||
webAction: "GMOCAPY_NATIVE_PAGE touch-off",
|
||||
webDispatch: { type: "GMOCAPY_NATIVE_PAGE", pageId: "touch-off", nativeWidget: "btn_touch" },
|
||||
webSelector: null,
|
||||
gate: "touch-off page not implemented in Web shell",
|
||||
},
|
||||
@@ -383,7 +399,8 @@ export const gmoccapyHalModel = {
|
||||
index: 3,
|
||||
pin: "gmoccapy.h-button.button-3",
|
||||
nativeWidget: "btn_tool",
|
||||
webAction: "UI_CONTROL",
|
||||
webAction: "GMOCAPY_NATIVE_PAGE tool-editor",
|
||||
webDispatch: { type: "GMOCAPY_NATIVE_PAGE", pageId: "tool-editor", nativeWidget: "btn_tool" },
|
||||
webSelector: null,
|
||||
gate: "tool editor page not implemented in Web shell",
|
||||
},
|
||||
@@ -391,7 +408,8 @@ export const gmoccapyHalModel = {
|
||||
index: 6,
|
||||
pin: "gmoccapy.h-button.button-6",
|
||||
nativeWidget: "tbtn_switch_mode",
|
||||
webAction: "SET_KINS_TYPE identity",
|
||||
webAction: "GMOCAPY_NATIVE_PAGE switchkins-mode",
|
||||
webDispatch: { type: "GMOCAPY_NATIVE_PAGE", pageId: "switchkins-mode", nativeWidget: "tbtn_switch_mode" },
|
||||
webSelector: null,
|
||||
gate: "native joint/world switch page position is diagnostic-only in the Web shell",
|
||||
},
|
||||
@@ -411,6 +429,13 @@ export const gmoccapyHalModel = {
|
||||
"_on_analog_value_changed",
|
||||
"_reset_override",
|
||||
"_del_message_changed",
|
||||
"_on_unlock_settings_changed",
|
||||
"_check_toolmeasurement",
|
||||
"on_chk_use_tool_measurement_toggled",
|
||||
"on_btn_block_height_clicked",
|
||||
"_on_blockheight_value_changed",
|
||||
"_init_user_messages",
|
||||
"_show_user_message",
|
||||
],
|
||||
prefPath: "linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.pref",
|
||||
},
|
||||
@@ -461,6 +486,16 @@ export const gmoccapyHalModel = {
|
||||
webState: "gmoccapyGui.optionalStop",
|
||||
},
|
||||
],
|
||||
settingsPins: [
|
||||
{
|
||||
pin: "gmoccapy.unlock-settings",
|
||||
nativeCallback: "_on_unlock_settings_changed",
|
||||
nativeCommand: "rbt_hal_unlock active gates tbtn_setup sensitivity from pin level",
|
||||
prefDefault: "unlock_way=use",
|
||||
webDispatch: { type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.unlock-settings" },
|
||||
webState: "gmoccapyGui.settingsUnlockPin",
|
||||
},
|
||||
],
|
||||
overridePins: [
|
||||
{
|
||||
target: "feed",
|
||||
@@ -527,9 +562,64 @@ export const gmoccapyHalModel = {
|
||||
webState: "gmoccapyGui.error",
|
||||
},
|
||||
],
|
||||
toolMeasurementPins: {
|
||||
toolsensorConfigured: false,
|
||||
useToolMeasurementPref: false,
|
||||
prefDefaults: {
|
||||
useToolMeasurement: "use_toolmeasurement=False",
|
||||
blockHeight: "blockheight=0.0",
|
||||
},
|
||||
disabledReason: "gmoccapy_XYZAB.ini has no [TOOLSENSOR] data, so _check_toolmeasurement disables the controls",
|
||||
pins: [
|
||||
{
|
||||
pin: "gmoccapy.probeheight",
|
||||
direction: "HAL_OUT",
|
||||
nativeCallback: "on_spbtn_probe_height_value_changed / on_chk_use_tool_measurement_toggled / on_btn_block_height_clicked",
|
||||
webState: "gmoccapyGui.probeHeight",
|
||||
},
|
||||
{
|
||||
pin: "gmoccapy.blockheight",
|
||||
direction: "HAL_OUT",
|
||||
nativeCallback: "on_btn_block_height_clicked / _on_blockheight_value_changed",
|
||||
webState: "gmoccapyGui.blockHeight",
|
||||
},
|
||||
{
|
||||
pin: "gmoccapy.toolmeasurement",
|
||||
direction: "HAL_OUT",
|
||||
nativeCallback: "on_chk_use_tool_measurement_toggled",
|
||||
webState: "gmoccapyGui.toolMeasurement",
|
||||
},
|
||||
{
|
||||
pin: "gmoccapy.searchvel",
|
||||
direction: "HAL_OUT",
|
||||
nativeCallback: "on_spbtn_search_vel_value_changed / on_chk_use_tool_measurement_toggled",
|
||||
webState: "gmoccapyGui.searchVelocity",
|
||||
},
|
||||
{
|
||||
pin: "gmoccapy.probevel",
|
||||
direction: "HAL_OUT",
|
||||
nativeCallback: "on_spbtn_probe_vel_value_changed / on_chk_use_tool_measurement_toggled",
|
||||
webState: "gmoccapyGui.probeVelocity",
|
||||
},
|
||||
],
|
||||
},
|
||||
userMessages: {
|
||||
configured: false,
|
||||
configuredMessageCount: 0,
|
||||
pins: [],
|
||||
source: "get_ini_info.get_user_messages()",
|
||||
disabledReason: "gmoccapy_XYZAB.ini has no MESSAGE_* entries, so _init_user_messages() returns without creating messages.* pins",
|
||||
dynamicPinPatterns: [
|
||||
"gmoccapy.messages.<pinname>",
|
||||
"gmoccapy.messages.<pinname>-waiting",
|
||||
"gmoccapy.messages.<pinname>-response",
|
||||
],
|
||||
supportedTypes: ["status", "okdialog", "yesnodialog"],
|
||||
},
|
||||
behavior: {
|
||||
optionalStopPinCrossesToBlockDelete: true,
|
||||
blockdeletePinCrossesToOptionalStop: true,
|
||||
unlockSettingsLevelDriven: true,
|
||||
jogAxisPinsPressRelease: true,
|
||||
jogPinsUseTaskPolicyGate: true,
|
||||
jogIncrementPinsRisingEdgeOnly: true,
|
||||
@@ -540,10 +630,124 @@ export const gmoccapyHalModel = {
|
||||
resetPinsRisingEdgeOnly: true,
|
||||
deleteMessageRisingEdgeOnly: true,
|
||||
warningConfirmLevelPolled: true,
|
||||
toolMeasurementPinsAreHalOut: true,
|
||||
toolMeasurementDisabledWithoutToolsensor: true,
|
||||
userMessagesDynamicIniOnly: true,
|
||||
directValueRange: "0..1",
|
||||
semanticBoundary: "native_gmoccapy_hal_pin_callbacks_to_web_store_actions",
|
||||
},
|
||||
},
|
||||
nativePages: {
|
||||
source: {
|
||||
path: "linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.py",
|
||||
gladePath: "linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.glade",
|
||||
methods: [
|
||||
"_init_IconFileSelection",
|
||||
"_init_file_to_load",
|
||||
"on_btn_load_clicked",
|
||||
"on_IconFileSelection1_selected",
|
||||
"on_hal_status_file_loaded",
|
||||
"_make_macro_button",
|
||||
"_on_btn_macro_pressed",
|
||||
"_init_tooleditor",
|
||||
"_show_tooledit_tab",
|
||||
"on_btn_tool_clicked",
|
||||
"on_btn_selected_tool_clicked",
|
||||
"on_btn_select_tool_by_no_clicked",
|
||||
"on_tbtn_setup_toggled",
|
||||
"on_tbtn_user_tabs_toggled",
|
||||
"on_btn_touch_clicked",
|
||||
],
|
||||
},
|
||||
filePage: {
|
||||
pageId: "file-load",
|
||||
nativeNotebookPage: "_BB_LOAD_FILE / ntb_preview page 3",
|
||||
nativeWidget: "IconFileSelection1",
|
||||
programPrefix: "../../nc_files/",
|
||||
defaultOpenPreference: "open_file",
|
||||
fileExtensions: [
|
||||
"*.ngc",
|
||||
"*.png",
|
||||
"*.gif",
|
||||
"*.jpg",
|
||||
"*.py",
|
||||
],
|
||||
nativeCallbacks: [
|
||||
"on_btn_load_clicked -> _show_iconview_tab(True)",
|
||||
"on_IconFileSelection1_selected -> hal_action_open.load_file(path)",
|
||||
"on_hal_status_file_loaded -> gmoccapy.program.length",
|
||||
"on_hal_status_line_changed -> gmoccapy.program.current-line/progress",
|
||||
],
|
||||
webSurface: "OPEN_FILE input, staged LinuxCNC G-code source selector and program preview",
|
||||
webAction: "GMOCAPY_PAGE_ACTION file-load diagnostics",
|
||||
implementation: "partial",
|
||||
boundary: "native_GtkIconFileSelection_not_embedded_in_browser",
|
||||
},
|
||||
macroPage: {
|
||||
pageId: "mdi-macros",
|
||||
nativeContainer: "hbtb_MDI",
|
||||
iniSection: "[MACROS]",
|
||||
macroLimit: 14,
|
||||
macros: [
|
||||
{ name: "i_am_lost", args: [], file: "macros/i_am_lost.ngc", commandTemplate: "O<i_am_lost> call" },
|
||||
{ name: "halo_world", args: [], file: "macros/halo_world.ngc", commandTemplate: "O<halo_world> call" },
|
||||
{ name: "jog_around", args: [], file: "macros/jog_around.ngc", commandTemplate: "O<jog_around> call" },
|
||||
{ name: "increment", args: ["xinc", "yinc"], file: "macros/increment.ngc", commandTemplate: "O<increment> call [xinc] [yinc]" },
|
||||
{ name: "go_to_position", args: ["X-pos", "Y-pos", "Z-pos"], file: "macros/go_to_position.ngc", commandTemplate: "O<go_to_position> call [X-pos] [Y-pos] [Z-pos]" },
|
||||
],
|
||||
nativeCallbacks: [
|
||||
"_make_macro_button -> get_ini_info.get_macros()",
|
||||
"_on_btn_macro_pressed -> command.mdi(O<name> call [args])",
|
||||
"on_hal_status_interp_idle enables macro buttons",
|
||||
"on_hal_status_interp_run disables macro buttons",
|
||||
],
|
||||
webAction: "GMOCAPY_RUN_MACRO",
|
||||
implementation: "partial",
|
||||
boundary: "macro_buttons_map_to_MDI_command_without_native_entry_dialogs",
|
||||
},
|
||||
toolEditorPage: {
|
||||
pageId: "tool-editor",
|
||||
nativeNotebookPage: "ntb_preview page 2 / _BB_TOOL",
|
||||
nativeWidget: "tooledit1",
|
||||
toolTablePath: "linuxcnc/configs/sim/gmoccapy/tool.tbl",
|
||||
visibleAxes: ["X", "Y", "Z", "A", "B"],
|
||||
toolCount: 17,
|
||||
nativeCallbacks: [
|
||||
"_init_tooleditor -> tooledit1.set_filename(tool.tbl)",
|
||||
"_show_tooledit_tab(True) -> tooledit1.reload()",
|
||||
"on_btn_selected_tool_clicked -> M61 Q? or T? M6",
|
||||
"on_btn_save_tool_changes_clicked -> tooledit1.save(None)",
|
||||
"on_btn_reload_tooltable_clicked -> tooledit1.reload(None)",
|
||||
],
|
||||
webAction: "GMOCAPY_TOOL_EDITOR_ACTION diagnostics",
|
||||
editableInWeb: false,
|
||||
implementation: "diagnostic-only",
|
||||
boundary: "tool_table_writeback_not_promoted_browser_keeps_iocontrol_loopback",
|
||||
},
|
||||
implementationMatrix: [
|
||||
{ pageId: "main", nativeWidget: "ntb_main page 0", implementation: "implemented", webSurface: "DRO/G-code/preview/main controls", hardButton: null },
|
||||
{ pageId: "manual-home", nativeWidget: "btn_homing / _BB_HOME", implementation: "partial", webSurface: "HOME action", hardButton: "gmoccapy.h-button.button-0" },
|
||||
{ pageId: "mdi-macros", nativeWidget: "hbtb_MDI macro buttons", implementation: "partial", webSurface: "MDI macro diagnostics and dispatch", hardButton: null },
|
||||
{ pageId: "auto-run", nativeWidget: "_BB_AUTO buttons", implementation: "partial", webSurface: "RUN/STOP/PAUSE/STEP controls", hardButton: null },
|
||||
{ pageId: "file-load", nativeWidget: "IconFileSelection1 / _BB_LOAD_FILE", implementation: "partial", webSurface: "OPEN_FILE input and staged source selector", hardButton: null },
|
||||
{ pageId: "tool-editor", nativeWidget: "btn_tool / tooledit1", implementation: "diagnostic-only", webSurface: "tool table summary and action diagnostics", hardButton: "gmoccapy.h-button.button-3" },
|
||||
{ pageId: "touch-off", nativeWidget: "btn_touch / offsetpage1", implementation: "diagnostic-only", webSurface: "touch-off boundary diagnostics", hardButton: "gmoccapy.h-button.button-1" },
|
||||
{ pageId: "setup", nativeWidget: "tbtn_setup / ntb_setup", implementation: "diagnostic-only", webSurface: "settings/unlock diagnostics", hardButton: "gmoccapy.v-button.button-6" },
|
||||
{ pageId: "user-tabs", nativeWidget: "tbtn_user_tabs / ntb_user_tabs", implementation: "diagnostic-only", webSurface: "user tab boundary diagnostics", hardButton: "gmoccapy.v-button.button-5" },
|
||||
{ pageId: "switchkins-mode", nativeWidget: "tbtn_switch_mode", implementation: "diagnostic-only", webSurface: "identity-only XYZAB switchkins diagnostic", hardButton: "gmoccapy.h-button.button-6" },
|
||||
{ pageId: "edit", nativeWidget: "_BB_EDIT / gcode_view editable", implementation: "native-only", webSurface: "not promoted", hardButton: null },
|
||||
{ pageId: "offset-editor", nativeWidget: "offsetpage1 edit offsets", implementation: "native-only", webSurface: "not promoted", hardButton: null },
|
||||
],
|
||||
behavior: {
|
||||
unimplementedPagesDiagnosticOnly: true,
|
||||
hardButtonsDoNotFakeNativePages: true,
|
||||
fileChooserNotNativeGtk: true,
|
||||
macroButtonsUseMdiGate: true,
|
||||
toolEditorWritebackDisabled: true,
|
||||
toolEditorKeepsIocontrolLoopback: true,
|
||||
semanticBoundary: "native_gmoccapy_page_matrix_web_diagnostic_boundary",
|
||||
},
|
||||
},
|
||||
toolChange: {
|
||||
strategy: "iocontrol-loopback",
|
||||
manualGmoccapyPinsConnected: false,
|
||||
@@ -619,12 +823,19 @@ export function createGmoccapyHalSummary(model = gmoccapyHalModel) {
|
||||
hardwareButtonEdge: model.hardwareButtons.behavior.edge,
|
||||
hardwareButtonInsensitiveTarget: model.hardwareButtons.behavior.insensitiveTarget,
|
||||
operatorInputPinCount: model.halPinActions.operatorPins.length,
|
||||
settingsInputPinCount: model.halPinActions.settingsPins.length,
|
||||
overridePinTargetCount: model.halPinActions.overridePins.length,
|
||||
jogAxisPinCount: (model.halPinActions.jogPins?.axes || []).length * 2,
|
||||
jogIncrementPinCount: model.halPinActions.jogPins?.increments?.length || 0,
|
||||
messageInputPinCount: model.halPinActions.messagePins.length,
|
||||
toolMeasurementPinCount: model.halPinActions.toolMeasurementPins.pins.length,
|
||||
toolMeasurementEnabled: model.halPinActions.toolMeasurementPins.useToolMeasurementPref,
|
||||
toolsensorConfigured: model.halPinActions.toolMeasurementPins.toolsensorConfigured,
|
||||
userMessagePinCount: model.halPinActions.userMessages.pins.length,
|
||||
userMessagesConfigured: model.halPinActions.userMessages.configured,
|
||||
optionalStopPinCrossesToBlockDelete: model.halPinActions.behavior.optionalStopPinCrossesToBlockDelete,
|
||||
blockdeletePinCrossesToOptionalStop: model.halPinActions.behavior.blockdeletePinCrossesToOptionalStop,
|
||||
unlockSettingsLevelDriven: model.halPinActions.behavior.unlockSettingsLevelDriven,
|
||||
jogAxisPinsPressRelease: model.halPinActions.behavior.jogAxisPinsPressRelease,
|
||||
jogPinsUseTaskPolicyGate: model.halPinActions.behavior.jogPinsUseTaskPolicyGate,
|
||||
jogIncrementPinsRisingEdgeOnly: model.halPinActions.behavior.jogIncrementPinsRisingEdgeOnly,
|
||||
@@ -635,6 +846,27 @@ export function createGmoccapyHalSummary(model = gmoccapyHalModel) {
|
||||
resetPinsRisingEdgeOnly: model.halPinActions.behavior.resetPinsRisingEdgeOnly,
|
||||
deleteMessageRisingEdgeOnly: model.halPinActions.behavior.deleteMessageRisingEdgeOnly,
|
||||
warningConfirmLevelPolled: model.halPinActions.behavior.warningConfirmLevelPolled,
|
||||
toolMeasurementPinsAreHalOut: model.halPinActions.behavior.toolMeasurementPinsAreHalOut,
|
||||
toolMeasurementDisabledWithoutToolsensor: model.halPinActions.behavior.toolMeasurementDisabledWithoutToolsensor,
|
||||
userMessagesDynamicIniOnly: model.halPinActions.behavior.userMessagesDynamicIniOnly,
|
||||
nativePageCount: model.nativePages.implementationMatrix.length,
|
||||
implementedNativePageCount: model.nativePages.implementationMatrix
|
||||
.filter((page) => page.implementation === "implemented").length,
|
||||
partialNativePageCount: model.nativePages.implementationMatrix
|
||||
.filter((page) => page.implementation === "partial").length,
|
||||
diagnosticOnlyNativePageCount: model.nativePages.implementationMatrix
|
||||
.filter((page) => page.implementation === "diagnostic-only").length,
|
||||
nativeOnlyPageCount: model.nativePages.implementationMatrix
|
||||
.filter((page) => page.implementation === "native-only").length,
|
||||
filePageImplementation: model.nativePages.filePage.implementation,
|
||||
filePageBoundary: model.nativePages.filePage.boundary,
|
||||
macroCount: model.nativePages.macroPage.macros.length,
|
||||
macroLimit: model.nativePages.macroPage.macroLimit,
|
||||
macroButtonsUseMdiGate: model.nativePages.behavior.macroButtonsUseMdiGate,
|
||||
toolEditorImplementation: model.nativePages.toolEditorPage.implementation,
|
||||
toolEditorWritebackDisabled: model.nativePages.behavior.toolEditorWritebackDisabled,
|
||||
hardButtonsDoNotFakeNativePages: model.nativePages.behavior.hardButtonsDoNotFakeNativePages,
|
||||
unimplementedPagesDiagnosticOnly: model.nativePages.behavior.unimplementedPagesDiagnosticOnly,
|
||||
semanticBoundary: model.semanticBoundary,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -253,9 +253,31 @@ const initialState = {
|
||||
jogIncrementOutput: 0,
|
||||
turtleJog: false,
|
||||
activeJogPin: null,
|
||||
settingsUnlockMode: "use",
|
||||
settingsUnlockPin: false,
|
||||
setupSensitive: true,
|
||||
toolsensorConfigured: false,
|
||||
toolMeasurement: false,
|
||||
probeHeight: 0,
|
||||
blockHeight: 0,
|
||||
searchVelocity: 0,
|
||||
probeVelocity: 0,
|
||||
userMessagesConfigured: false,
|
||||
userMessagePins: [],
|
||||
warningConfirm: false,
|
||||
error: false,
|
||||
deletedMessageCount: 0,
|
||||
activeNativePage: "main",
|
||||
nativePageMode: "implemented",
|
||||
filePageStatus: "main",
|
||||
filePageLastAction: null,
|
||||
macroPageConfigured: true,
|
||||
macroButtonsEnabled: true,
|
||||
macroLastCommand: null,
|
||||
macroLastName: null,
|
||||
toolEditorStatus: "closed",
|
||||
toolEditorWritebackEnabled: false,
|
||||
toolEditorLastAction: null,
|
||||
lastHalPin: null,
|
||||
lastHalPinValue: null,
|
||||
lastHalPinEffect: null,
|
||||
@@ -1022,6 +1044,34 @@ export function createSimulationStore(seed = {}) {
|
||||
setState(result.patch);
|
||||
}
|
||||
break;
|
||||
case "GMOCAPY_NATIVE_PAGE":
|
||||
{
|
||||
const patch = applyGmoccapyNativePagePatch(state, action, gmoccapyHalModel);
|
||||
setState(patch);
|
||||
}
|
||||
break;
|
||||
case "GMOCAPY_PAGE_ACTION":
|
||||
{
|
||||
const patch = applyGmoccapyPageActionPatch(state, action, gmoccapyHalModel);
|
||||
setState(patch);
|
||||
}
|
||||
break;
|
||||
case "GMOCAPY_RUN_MACRO":
|
||||
{
|
||||
const result = applyGmoccapyMacroPatch(state, action, gmoccapyHalModel);
|
||||
if (!result.applied) {
|
||||
setState({ operatorMessage: result.operatorMessage });
|
||||
break;
|
||||
}
|
||||
setState(result.patch);
|
||||
}
|
||||
break;
|
||||
case "GMOCAPY_TOOL_EDITOR_ACTION":
|
||||
{
|
||||
const patch = applyGmoccapyToolEditorPatch(state, action, gmoccapyHalModel);
|
||||
setState(patch);
|
||||
}
|
||||
break;
|
||||
case "TOGGLE_POWER":
|
||||
{
|
||||
const gate = gateLinuxCncTaskAction(state, action);
|
||||
@@ -3494,6 +3544,36 @@ function applyGmoccapyHalPinPatch(state, action, model = gmoccapyHalModel) {
|
||||
};
|
||||
}
|
||||
|
||||
if (pin === "gmoccapy.unlock-settings") {
|
||||
const enabled = Boolean(value);
|
||||
const halUnlockActive = action.halUnlockMode === true || state.gmoccapyGui?.settingsUnlockMode === "hal";
|
||||
if (!halUnlockActive) {
|
||||
return {
|
||||
applied: true,
|
||||
patch: {
|
||||
gmoccapyGui: halGuiPatch(state, pin, value, {
|
||||
settingsUnlockPin: enabled,
|
||||
setupSensitive: true,
|
||||
lastHalPinEffect: "unlock-settings ignored because unlock_way is not hal",
|
||||
}),
|
||||
operatorMessage: "gmoccapy HAL unlock-settings ignored: unlock_way is use",
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
applied: true,
|
||||
patch: {
|
||||
gmoccapyGui: halGuiPatch(state, pin, value, {
|
||||
settingsUnlockMode: "hal",
|
||||
settingsUnlockPin: enabled,
|
||||
setupSensitive: enabled,
|
||||
lastHalPinEffect: `unlock-settings ${enabled ? "enabled" : "disabled"} setup page sensitivity`,
|
||||
}),
|
||||
operatorMessage: `gmoccapy HAL unlock-settings ${enabled ? "enabled setup" : "disabled setup"}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const jogAxisPin = resolveGmoccapyJogAxisPin(pin, model);
|
||||
if (jogAxisPin) {
|
||||
return applyGmoccapyJogAxisHalPatch(state, pin, value, jogAxisPin);
|
||||
@@ -3566,6 +3646,18 @@ function applyGmoccapyHalPinPatch(state, action, model = gmoccapyHalModel) {
|
||||
};
|
||||
}
|
||||
|
||||
const toolMeasurementPin = resolveGmoccapyToolMeasurementPin(pin, model);
|
||||
if (toolMeasurementPin) {
|
||||
return applyGmoccapyToolMeasurementHalPatch(state, pin, value, toolMeasurementPin);
|
||||
}
|
||||
|
||||
if (pin.startsWith("gmoccapy.messages.")) {
|
||||
return {
|
||||
applied: false,
|
||||
operatorMessage: "gmoccapy HAL user message pin unmapped: gmoccapy_XYZAB.ini defines no MESSAGE_* entries",
|
||||
};
|
||||
}
|
||||
|
||||
const overrideTarget = findOverrideTargetForPin(pin);
|
||||
if (overrideTarget) {
|
||||
return applyGmoccapyOverrideHalPatch(state, pin, value, overrideTarget);
|
||||
@@ -3589,7 +3681,8 @@ function normalizeGmoccapyHalPin(pin) {
|
||||
}
|
||||
|
||||
function isKnownGmoccapyHalPin(pin, model = gmoccapyHalModel) {
|
||||
return model.nativePins.some((group) => group.pins.includes(pin));
|
||||
if (model.nativePins.some((group) => group.pins.includes(pin))) return true;
|
||||
return pin.startsWith("gmoccapy.messages.");
|
||||
}
|
||||
|
||||
function halGuiPatch(state, pin, value, patch = {}) {
|
||||
@@ -3601,6 +3694,149 @@ function halGuiPatch(state, pin, value, patch = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
function applyGmoccapyNativePagePatch(state, action, model = gmoccapyHalModel) {
|
||||
const pageId = String(action.pageId || action.page || "").trim();
|
||||
const page = model.nativePages?.implementationMatrix?.find((entry) => entry.pageId === pageId);
|
||||
if (!page) {
|
||||
return {
|
||||
operatorMessage: `gmoccapy native page unmapped: ${pageId || "unknown"}`,
|
||||
};
|
||||
}
|
||||
return {
|
||||
gmoccapyGui: {
|
||||
...state.gmoccapyGui,
|
||||
activeNativePage: page.pageId,
|
||||
nativePageMode: page.implementation,
|
||||
lastHalPin: null,
|
||||
lastHalPinValue: null,
|
||||
lastHalPinEffect: `${page.nativeWidget} ${page.implementation}`,
|
||||
},
|
||||
operatorMessage: page.implementation === "diagnostic-only" || page.implementation === "native-only"
|
||||
? `gmoccapy native page diagnostic-only: ${page.pageId}`
|
||||
: `gmoccapy native page ${page.pageId}`,
|
||||
};
|
||||
}
|
||||
|
||||
function applyGmoccapyPageActionPatch(state, action, model = gmoccapyHalModel) {
|
||||
const pageId = String(action.pageId || action.page || "").trim();
|
||||
const actionId = String(action.actionId || action.action || "open").trim();
|
||||
if (pageId === "file-load") {
|
||||
const running = state.machine?.interpState === "reading" || state.runState === "running";
|
||||
const status = running ? "blocked-running" : actionId;
|
||||
return {
|
||||
gmoccapyGui: {
|
||||
...state.gmoccapyGui,
|
||||
activeNativePage: "file-load",
|
||||
nativePageMode: model.nativePages.filePage.implementation,
|
||||
filePageStatus: status,
|
||||
filePageLastAction: actionId,
|
||||
lastHalPin: null,
|
||||
lastHalPinValue: null,
|
||||
lastHalPinEffect: running
|
||||
? "file load blocked while interpreter is running"
|
||||
: "IconFileSelection native page represented by Web file/staged-source controls",
|
||||
},
|
||||
operatorMessage: running
|
||||
? "gmoccapy file page blocked: interpreter running"
|
||||
: `gmoccapy file page ${actionId}: native Gtk chooser diagnostic`,
|
||||
};
|
||||
}
|
||||
return {
|
||||
operatorMessage: `gmoccapy page action unmapped: ${pageId || "unknown"}`,
|
||||
};
|
||||
}
|
||||
|
||||
function applyGmoccapyMacroPatch(state, action, model = gmoccapyHalModel) {
|
||||
const macroName = String(action.name || action.macro || "").trim();
|
||||
const macro = model.nativePages?.macroPage?.macros?.find((entry) => entry.name === macroName);
|
||||
if (!macro) {
|
||||
return {
|
||||
applied: false,
|
||||
operatorMessage: `gmoccapy macro unmapped: ${macroName || "unknown"}`,
|
||||
};
|
||||
}
|
||||
const gate = gateLinuxCncTaskAction(state, { type: "RUN_MDI" });
|
||||
if (!gate.allowed) {
|
||||
return {
|
||||
applied: true,
|
||||
patch: {
|
||||
gmoccapyGui: {
|
||||
...state.gmoccapyGui,
|
||||
macroButtonsEnabled: false,
|
||||
macroLastName: macro.name,
|
||||
lastHalPin: null,
|
||||
lastHalPinValue: null,
|
||||
lastHalPinEffect: `macro ${macro.name} blocked: ${gate.operatorMessage}`,
|
||||
},
|
||||
operatorMessage: `gmoccapy macro blocked: ${gate.operatorMessage}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
const command = buildGmoccapyMacroCommand(macro, action.args || action.parameters || {});
|
||||
const mdiResult = executeMdiCommand(state, command);
|
||||
return {
|
||||
applied: true,
|
||||
patch: {
|
||||
...mdiResult.patch,
|
||||
gmoccapyGui: {
|
||||
...state.gmoccapyGui,
|
||||
activeNativePage: "mdi-macros",
|
||||
nativePageMode: "partial",
|
||||
macroButtonsEnabled: false,
|
||||
macroLastName: macro.name,
|
||||
macroLastCommand: command,
|
||||
lastHalPin: null,
|
||||
lastHalPinValue: null,
|
||||
lastHalPinEffect: `macro ${macro.name} dispatched as MDI O-word call`,
|
||||
},
|
||||
operatorMessage: `gmoccapy macro MDI ${command}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function buildGmoccapyMacroCommand(macro, args = {}) {
|
||||
const values = Array.isArray(args)
|
||||
? args
|
||||
: macro.args.map((name) => args[name] ?? args[String(name).toLowerCase()] ?? 0);
|
||||
return [
|
||||
`O<${macro.name}> call`,
|
||||
...macro.args.map((name, index) => `[${values[index] ?? 0}]`),
|
||||
].join(" ");
|
||||
}
|
||||
|
||||
function applyGmoccapyToolEditorPatch(state, action, model = gmoccapyHalModel) {
|
||||
const actionId = String(action.actionId || action.action || "open").trim();
|
||||
const writableAction = ["save", "add", "delete", "touch-off"].includes(actionId);
|
||||
if (writableAction && model.nativePages?.toolEditorPage?.editableInWeb === false) {
|
||||
return {
|
||||
gmoccapyGui: {
|
||||
...state.gmoccapyGui,
|
||||
activeNativePage: "tool-editor",
|
||||
nativePageMode: "diagnostic-only",
|
||||
toolEditorStatus: "writeback-blocked",
|
||||
toolEditorLastAction: actionId,
|
||||
lastHalPin: null,
|
||||
lastHalPinValue: null,
|
||||
lastHalPinEffect: "tool editor writeback disabled in browser",
|
||||
},
|
||||
operatorMessage: `gmoccapy tool editor diagnostic-only: ${actionId} does not write tool.tbl`,
|
||||
};
|
||||
}
|
||||
return {
|
||||
gmoccapyGui: {
|
||||
...state.gmoccapyGui,
|
||||
activeNativePage: "tool-editor",
|
||||
nativePageMode: "diagnostic-only",
|
||||
toolEditorStatus: actionId,
|
||||
toolEditorLastAction: actionId,
|
||||
lastHalPin: null,
|
||||
lastHalPinValue: null,
|
||||
lastHalPinEffect: "tooledit1 native page represented by diagnostics",
|
||||
},
|
||||
operatorMessage: `gmoccapy tool editor ${actionId}: ${state.profile?.toolTable?.toolCount || 0} tools diagnostic-only`,
|
||||
};
|
||||
}
|
||||
|
||||
function findOverrideTargetForPin(pin) {
|
||||
return Object.entries(GMOCAPY_OVERRIDE_TARGETS)
|
||||
.find(([, target]) => [
|
||||
@@ -3612,6 +3848,10 @@ function findOverrideTargetForPin(pin) {
|
||||
].includes(pin)) || null;
|
||||
}
|
||||
|
||||
function resolveGmoccapyToolMeasurementPin(pin, model = gmoccapyHalModel) {
|
||||
return model.halPinActions?.toolMeasurementPins?.pins?.find((entry) => entry.pin === pin) || null;
|
||||
}
|
||||
|
||||
function resolveGmoccapyJogAxisPin(pin, model = gmoccapyHalModel) {
|
||||
for (const entry of model.halPinActions?.jogPins?.axes || []) {
|
||||
if (pin === entry.plus) return { axis: entry.axis, direction: 1 };
|
||||
@@ -3724,6 +3964,27 @@ function applyGmoccapyJogIncrementHalPatch(state, pin, value, jogIncrement) {
|
||||
};
|
||||
}
|
||||
|
||||
function applyGmoccapyToolMeasurementHalPatch(state, pin, value, toolMeasurementPin) {
|
||||
const nextValue = toolMeasurementPin.pin === "gmoccapy.toolmeasurement"
|
||||
? Boolean(value)
|
||||
: Number(value || 0);
|
||||
const patch = {
|
||||
lastHalPinEffect: "tool measurement HAL OUT pin recorded as diagnostic-only in Web",
|
||||
};
|
||||
if (toolMeasurementPin.pin === "gmoccapy.probeheight") patch.probeHeight = nextValue;
|
||||
if (toolMeasurementPin.pin === "gmoccapy.blockheight") patch.blockHeight = nextValue;
|
||||
if (toolMeasurementPin.pin === "gmoccapy.toolmeasurement") patch.toolMeasurement = nextValue;
|
||||
if (toolMeasurementPin.pin === "gmoccapy.searchvel") patch.searchVelocity = nextValue;
|
||||
if (toolMeasurementPin.pin === "gmoccapy.probevel") patch.probeVelocity = nextValue;
|
||||
return {
|
||||
applied: true,
|
||||
patch: {
|
||||
gmoccapyGui: halGuiPatch(state, pin, value, patch),
|
||||
operatorMessage: "gmoccapy HAL tool measurement output recorded; XYZAB has no [TOOLSENSOR]",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function applyGmoccapyOverrideHalPatch(state, pin, value, [targetName, target]) {
|
||||
if (pin === target.countEnablePin || pin === target.analogEnablePin) {
|
||||
const enabled = Boolean(value);
|
||||
|
||||
@@ -443,6 +443,10 @@ function renderInfoTabs(element, state) {
|
||||
<dt>gmoccapy comms:</dt><dd data-gmoccapy-comm="boundary">${gmoccapyCommunicationModel.semanticBoundary}</dd>
|
||||
<dt>NML command:</dt><dd data-gmoccapy-comm="native-command">${formatGmoccapyNativePath("command")}</dd>
|
||||
<dt>NML status:</dt><dd data-gmoccapy-comm="native-status">${formatGmoccapyNativePath("status")}</dd>
|
||||
<dt>Native file page:</dt><dd data-gmoccapy-page="file">${formatGmoccapyFilePage(halSummary, state)}</dd>
|
||||
<dt>Native macros:</dt><dd data-gmoccapy-page="macros">${formatGmoccapyMacroPage(halSummary, state)}</dd>
|
||||
<dt>Native tool editor:</dt><dd data-gmoccapy-page="tool-editor">${formatGmoccapyToolEditorPage(halSummary, state)}</dd>
|
||||
<dt>Native page matrix:</dt><dd data-gmoccapy-page="matrix">${formatGmoccapyNativePageMatrix(halSummary, state)}</dd>
|
||||
<dt>Web runtime:</dt><dd data-gmoccapy-comm="web-path">${gmoccapyCommunicationModel.webPath.path.join(" -> ")}</dd>
|
||||
<dt>postgui order:</dt><dd data-gmoccapy-comm="postgui">${commSummary.postguiAfterHalcompReady ? "halcomp.ready before POSTGUI_HALFILE" : "pending"}</dd>
|
||||
<dt>native RUN:</dt><dd data-gmoccapy-comm="auto-run">${formatGmoccapyActionMapping("auto-run")}</dd>
|
||||
@@ -452,8 +456,10 @@ function renderInfoTabs(element, state) {
|
||||
<dt>Hard buttons:</dt><dd data-gmoccapy-hal="hard-buttons">${formatGmoccapyHardButtons(halSummary)}</dd>
|
||||
<dt>HAL jog:</dt><dd data-gmoccapy-hal="jog-inputs">${formatGmoccapyJogInputs(halSummary, state)}</dd>
|
||||
<dt>HAL inputs:</dt><dd data-gmoccapy-hal="operator-inputs">${formatGmoccapyHalInputs(halSummary, state)}</dd>
|
||||
<dt>HAL settings:</dt><dd data-gmoccapy-hal="settings-inputs">${formatGmoccapySettingsInputs(halSummary, state)}</dd>
|
||||
<dt>HAL overrides:</dt><dd data-gmoccapy-hal="override-inputs">${formatGmoccapyOverrideInputs(halSummary, state)}</dd>
|
||||
<dt>HAL messages:</dt><dd data-gmoccapy-hal="message-inputs">${formatGmoccapyMessageInputs(halSummary, state)}</dd>
|
||||
<dt>HAL tool/user:</dt><dd data-gmoccapy-hal="tool-user-inputs">${formatGmoccapyToolUserInputs(halSummary, state)}</dd>
|
||||
<dt>postgui nets:</dt><dd data-gmoccapy-hal="postgui">${gmoccapyHalModel.postguiNets.map((net) => net.signal).join(" / ")}</dd>
|
||||
<dt>Tool loop:</dt><dd data-gmoccapy-hal="tool-loop">${halSummary.hasToolChangeSimulationLoop ? "simulated tool-change loop" : "pending"}</dd>
|
||||
<dt>Tool change:</dt><dd data-gmoccapy-hal="tool-change">${formatGmoccapyToolChange(halSummary)}</dd>
|
||||
@@ -922,6 +928,16 @@ function formatGmoccapyHalInputs(halSummary, state) {
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
function formatGmoccapySettingsInputs(halSummary, state) {
|
||||
return [
|
||||
`${halSummary.settingsInputPinCount} settings pins`,
|
||||
halSummary.unlockSettingsLevelDriven ? "unlock-settings level-driven" : "unlock-settings pending",
|
||||
`unlock-way ${state.gmoccapyGui.settingsUnlockMode}`,
|
||||
`pin ${state.gmoccapyGui.settingsUnlockPin ? "high" : "low"}`,
|
||||
`setup ${state.gmoccapyGui.setupSensitive ? "sensitive" : "locked"}`,
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
function formatGmoccapyJogInputs(halSummary, state) {
|
||||
return [
|
||||
`${halSummary.jogAxisPinCount} axis jog pins`,
|
||||
@@ -945,6 +961,19 @@ function formatGmoccapyOverrideInputs(halSummary, state) {
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
function formatGmoccapyToolUserInputs(halSummary, state) {
|
||||
return [
|
||||
`${halSummary.toolMeasurementPinCount} tool measurement HAL_OUT pins`,
|
||||
halSummary.toolMeasurementPinsAreHalOut ? "tool pins HAL_OUT" : "tool pins input",
|
||||
halSummary.toolMeasurementDisabledWithoutToolsensor ? "XYZAB no TOOLSENSOR" : "TOOLSENSOR configured",
|
||||
`toolmeasurement ${state.gmoccapyGui.toolMeasurement ? "on" : "off"}`,
|
||||
`blockheight ${state.gmoccapyGui.blockHeight}`,
|
||||
`${halSummary.userMessagePinCount} user message pins`,
|
||||
halSummary.userMessagesDynamicIniOnly ? "messages dynamic INI-only" : "messages static",
|
||||
halSummary.userMessagesConfigured ? "MESSAGE_* configured" : "no MESSAGE_*",
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
function formatGmoccapyMessageInputs(halSummary, state) {
|
||||
return [
|
||||
`${halSummary.messageInputPinCount} message pins`,
|
||||
@@ -956,6 +985,50 @@ function formatGmoccapyMessageInputs(halSummary, state) {
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
function formatGmoccapyFilePage(halSummary, state) {
|
||||
return [
|
||||
`file page ${halSummary.filePageImplementation}`,
|
||||
"PROGRAM_PREFIX ../../nc_files/",
|
||||
"native IconFileSelection",
|
||||
"Web OPEN_FILE/staged-source",
|
||||
halSummary.filePageBoundary,
|
||||
`status ${state.gmoccapyGui.filePageStatus}`,
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
function formatGmoccapyMacroPage(halSummary, state) {
|
||||
return [
|
||||
`${halSummary.macroCount} XYZAB macros`,
|
||||
`macro limit ${halSummary.macroLimit}`,
|
||||
halSummary.macroButtonsUseMdiGate ? "MDI gate" : "no MDI gate",
|
||||
"O-word call",
|
||||
`last ${state.gmoccapyGui.macroLastCommand || "none"}`,
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
function formatGmoccapyToolEditorPage(halSummary, state) {
|
||||
return [
|
||||
`tool editor ${halSummary.toolEditorImplementation}`,
|
||||
`${state.profile.toolTable?.toolCount || 0} tools`,
|
||||
"tool.tbl",
|
||||
halSummary.toolEditorWritebackDisabled ? "writeback disabled" : "writeback enabled",
|
||||
"iocontrol-loopback preserved",
|
||||
`status ${state.gmoccapyGui.toolEditorStatus}`,
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
function formatGmoccapyNativePageMatrix(halSummary, state) {
|
||||
return [
|
||||
`${halSummary.nativePageCount} native pages`,
|
||||
`${halSummary.implementedNativePageCount} implemented`,
|
||||
`${halSummary.partialNativePageCount} partial`,
|
||||
`${halSummary.diagnosticOnlyNativePageCount} diagnostic-only`,
|
||||
`${halSummary.nativeOnlyPageCount} native-only`,
|
||||
halSummary.hardButtonsDoNotFakeNativePages ? "hard-buttons diagnostic-only" : "hard-buttons may dispatch",
|
||||
`active ${state.gmoccapyGui.activeNativePage}`,
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
function formatGmoccapyHalLastInput(state) {
|
||||
if (!state.gmoccapyGui?.lastHalPin && !state.gmoccapyGui?.lastHalPinEffect) return "none";
|
||||
return [
|
||||
@@ -971,6 +1044,7 @@ function formatGmoccapyHardButtons(halSummary) {
|
||||
`${halSummary.mappedHardwareButtonCount} mapped Web buttons`,
|
||||
halSummary.hardwareButtonEdge,
|
||||
`insensitive ${halSummary.hardwareButtonInsensitiveTarget}`,
|
||||
`${halSummary.diagnosticOnlyNativePageCount} diagnostic-only native pages`,
|
||||
].join(" / ");
|
||||
}
|
||||
|
||||
|
||||
@@ -5747,3 +5747,486 @@ Outcome:
|
||||
- `917cec1 完善 working5 gmoccapy HAL 输入对标` 已同步到云仓库。
|
||||
- `ea50bf7 记录云仓库同步认证阻塞` 已同步到云仓库。
|
||||
- 因本日志是在推送成功后追加,还需要另行提交并推送本成功日志,保证日志文件也同步到云端。
|
||||
|
||||
## 2026-06-27 working5 接续执行日志:W5-200 低频 gmoccapy HAL pin 边界
|
||||
|
||||
用户请求:
|
||||
- 接续上一轮,继续完成 `/home/meswork/cnc_wams/work/working5` 的工作。
|
||||
|
||||
执行过程:
|
||||
- 恢复工作现场:
|
||||
- 命令:`pwd && rg --files work/working5 | sed -n '1,200p'`
|
||||
- 结果:当前目录为 `/home/meswork/cnc_wams`;`work/working5` 下 01-06 和 README 文件存在。
|
||||
- 命令:`git status --short`
|
||||
- 结果:初始工作树干净。
|
||||
- 命令:`tail -n 120 web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md`
|
||||
- 结果:确认上一轮 W5-190 已完成,并已同步到云仓库。
|
||||
- 读取工作控制文件:
|
||||
- 命令:`sed -n '1,240p' work/working5/04-任务矩阵.md`
|
||||
- 结果:W5-001 到 W5-190、W5-900 均为完成。
|
||||
- 命令:`sed -n '1,260p' work/working5/03-推进台账.md`
|
||||
- 结果:R6 下一步指向 `gmoccapy.unlock-settings`、tool measurement/blockheight/probeheight、INI user messages 等低频 HAL pins。
|
||||
- 命令:`sed -n '1,220p' work/working5/01-项目功能内容.md`、`sed -n '1,220p' work/working5/02-项目程序开发详细步骤.md`
|
||||
- 结果:确认仍以 LinuxCNC `gmoccapy_XYZAB.ini` 五轴仿真配置为行为基准。
|
||||
- 定位源码和现有实现:
|
||||
- 命令:`rg --files work/working5`、`rg -n "GMOCAPY_HAL_PIN|gmoccapyGui|delete-message|warning-confirm|jog\\.axis|unlock|block|probe|message" web-rtcp-5axis-sim-plan/app/src web-rtcp-5axis-sim-plan/tests -S`
|
||||
- 结果:确认上一轮已有 `GMOCAPY_HAL_PIN`,覆盖 operator、override、jog 和 message pins。
|
||||
- 命令:`find /home/meswork/cnc_wams -path '*/gmoccapy.py' -o -path '*/gmoccapy_XYZAB.ini' -o -path '*/gmoccapy_XYZAB.pref' -o -path '*/gmoccapy_postgui.hal'`
|
||||
- 结果:确认 LinuxCNC 源码副本在 `/home/meswork/cnc_wams/linuxcnc`,包括 `linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.py`、`linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.ini`、`linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.pref`。
|
||||
- 命令:`rg -n "unlock-settings|toolmeasurement|blockheight|probeheight|searchvel|probevel|MESSAGE_|newpin|halcomp|hal_glib" linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.py -S`
|
||||
- 结果:定位 `_on_unlock_settings_changed()`、`_check_toolmeasurement()`、`on_chk_use_tool_measurement_toggled()`、`on_btn_block_height_clicked()`、`_init_user_messages()`、`_show_user_message()` 和 `_make_hal_pins()` 中相关 pins。
|
||||
- 命令:`sed -n '1,260p' linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.ini`、`sed -n '1,260p' linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.pref`
|
||||
- 结果:确认 XYZAB INI 没有 `[TOOLSENSOR]`,没有 `[DISPLAY] MESSAGE_*`;pref 默认 `unlock_way=use`、`use_toolmeasurement=False`、`blockheight=0.0`。
|
||||
- 源码语义结论:
|
||||
- `gmoccapy.unlock-settings` 是 HAL input bit,但只有设置页选择 HAL unlock 时才控制 `tbtn_setup` 敏感性;默认 `unlock_way=use` 下不应锁定/解锁 setup。
|
||||
- `gmoccapy.probeheight`、`gmoccapy.blockheight`、`gmoccapy.toolmeasurement`、`gmoccapy.searchvel`、`gmoccapy.probevel` 是 tool measurement HAL_OUT pins,由 GUI/prefs 写出;当前 XYZAB 因无 `[TOOLSENSOR]` 默认禁用自动测刀。
|
||||
- `gmoccapy.messages.*` 是 INI user messages 的动态 pin,只有存在 `MESSAGE_*` 配置时才创建;当前 XYZAB 无配置。
|
||||
- 修改实现:
|
||||
- 修改 `web-rtcp-5axis-sim-plan/app/src/profiles/gmoccapy-xyzab.js`:
|
||||
- 补齐 `gmoccapy.unlock-settings`、`gmoccapy.probeheight`、`gmoccapy.blockheight`、`gmoccapy.toolmeasurement`、`gmoccapy.searchvel`、`gmoccapy.probevel`、`gmoccapy.toolchange-number`、`gmoccapy.toolchange-confirm`。
|
||||
- 新增 `toolsensor` 和 `userMessages` 配置摘要,记录 no `[TOOLSENSOR]` 与 no `MESSAGE_*` 原因。
|
||||
- 修改 `web-rtcp-5axis-sim-plan/app/src/runtime/gmoccapy-hal-model.js`:
|
||||
- 新增 `settings` pin group。
|
||||
- 扩展 `tool` pin group,纳入 tool measurement HAL_OUT pins 和 `toolchange-confirm`。
|
||||
- 新增 `settingsPins`、`toolMeasurementPins`、`userMessages`、相关 behavior flags 和 summary 字段。
|
||||
- 修改 `web-rtcp-5axis-sim-plan/app/src/runtime/gmoccapy-communication-model.js`:
|
||||
- 扩展 HAL path notes。
|
||||
- 新增 `hal-settings-unlock`、`hal-tool-measurement`、`hal-user-message` action mapping。
|
||||
- 修改 `web-rtcp-5axis-sim-plan/app/src/state/store.js`:
|
||||
- 在 `gmoccapyGui` 中新增 `settingsUnlockMode`、`settingsUnlockPin`、`setupSensitive`、`toolsensorConfigured`、`toolMeasurement`、`probeHeight`、`blockHeight`、`searchVelocity`、`probeVelocity`、`userMessagesConfigured`、`userMessagePins`。
|
||||
- 扩展 `GMOCAPY_HAL_PIN`:默认 `unlock_way=use` 时 `unlock-settings` 只记录 pin level;显式 HAL unlock 模式下按 level 控制 setup;tool measurement HAL_OUT pins 只作为诊断记录;当前 XYZAB 对 `gmoccapy.messages.*` 返回无 `MESSAGE_*` 配置提示。
|
||||
- 修改 `web-rtcp-5axis-sim-plan/app/src/ui/gmoccapy-shell.js`:
|
||||
- 新增 `HAL settings` 和 `HAL tool/user` 诊断行。
|
||||
- 修改 Node/browser tests:
|
||||
- `verify_gmoccapy_hal_model.mjs`
|
||||
- `verify_gmoccapy_communication_model.mjs`
|
||||
- `verify_gmoccapy_xyzab_profile.mjs`
|
||||
- `verify_gmoccapy_xyzab_gates.mjs`
|
||||
- `gmoccapy_shell_smoke.html`
|
||||
- 修改 working5 文档:
|
||||
- `work/working5/03-推进台账.md`
|
||||
- `work/working5/04-任务矩阵.md`
|
||||
- `work/working5/05-验收证据.md`
|
||||
- `work/working5/06-决策记录.md`
|
||||
- 验证过程:
|
||||
- 命令:`node --check web-rtcp-5axis-sim-plan/app/src/runtime/gmoccapy-hal-model.js && node --check web-rtcp-5axis-sim-plan/app/src/runtime/gmoccapy-communication-model.js && node --check web-rtcp-5axis-sim-plan/app/src/state/store.js && node --check web-rtcp-5axis-sim-plan/app/src/ui/gmoccapy-shell.js`
|
||||
- 结果:通过,无语法错误。
|
||||
- 命令:`cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app && node ../tests/node/verify_gmoccapy_hal_model.mjs && node ../tests/node/verify_gmoccapy_communication_model.mjs && node ../tests/node/verify_gmoccapy_xyzab_profile.mjs && node ../tests/node/verify_gmoccapy_xyzab_gates.mjs`
|
||||
- 结果:通过,输出 `gmoccapy_hal_model_smoke=ok`、`gmoccapy_communication_model_smoke=ok`、`gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok`。
|
||||
- 命令:`cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app && bash ../tests/browser/verify_gmoccapy_shell_browser.sh`
|
||||
- 结果:通过,输出 `gmoccapy_shell_smoke=ok`。
|
||||
- 命令:`cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app && npm run smoke:node`
|
||||
- 结果:通过,关键输出包含 `gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_communication_model_smoke=ok`、`gmoccapy_hal_model_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok`、`linear_unit_conversion_smoke=ok`。
|
||||
- 命令:`cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app && npm run build && npm run smoke`
|
||||
- 结果:通过,输出 `gmoccapy_static_build=ok`、`gmoccapy_shell_smoke=ok`、`gmoccapy_dist_smoke=ok`。
|
||||
- 命令:`git diff --check -- web-rtcp-5axis-sim-plan work/working5`
|
||||
- 结果:通过,无输出。
|
||||
- 工作树状态:
|
||||
- 命令:`git status --short --branch`
|
||||
- 结果:当前 `master...origin/master`,存在本轮修改文件,尚未 commit。
|
||||
- 命令:`git diff --stat -- web-rtcp-5axis-sim-plan work/working5`
|
||||
- 结果:14 个文件变更,包含 app/profile/runtime/state/ui、Node/browser tests 和 working5 文档。
|
||||
|
||||
结论:
|
||||
- W5-200 已完成。
|
||||
- Web 项目现在能按 gmoccapy 源码和 XYZAB 配置明确表达 `unlock-settings`、tool measurement HAL_OUT pins、动态 INI user message pins 的启用边界。
|
||||
- 当前 XYZAB 的 no `[TOOLSENSOR]`、no `MESSAGE_*`、默认 `unlock_way=use` 均已写入 profile、HAL model、communication model、store、UI 诊断和测试证据。
|
||||
- 没有执行 commit 或 push。
|
||||
|
||||
## 2026-06-27 working5 接续复核日志:任务矩阵闭环与完整验收重跑
|
||||
|
||||
用户请求:
|
||||
- 接续上一轮,继续完成 `/home/meswork/cnc_wams/work/working5` 的工作。
|
||||
|
||||
执行过程:
|
||||
- 恢复工作现场:
|
||||
- 命令:`pwd && ls -la /home/meswork/cnc_wams/work/working5`
|
||||
- 结果:当前工作区为 `/home/meswork/cnc_wams`;`working5` 目录下 README 和 01-06 工作控制文件均存在。
|
||||
- 命令:`git -C /home/meswork/cnc_wams/work/working5 status --short --branch`
|
||||
- 结果:当前分支为 `master...origin/master`;存在上一轮 app、tests、working5 文档和 `gpdlog.md` 修改。
|
||||
- 命令:`rg --files /home/meswork/cnc_wams/work/working5 | sed 's#^/home/meswork/cnc_wams/work/working5/##' | head -200`
|
||||
- 结果:确认 `04-任务矩阵.md`、`06-决策记录.md`、`03-推进台账.md`、`README.md`、`01-项目功能内容.md`、`05-验收证据.md`、`02-项目程序开发详细步骤.md` 存在。
|
||||
- 读取 working5 控制文档:
|
||||
- 命令:`sed -n '1,240p' /home/meswork/cnc_wams/work/working5/03-推进台账.md`
|
||||
- 结果:确认 R1-R7 已记录,R7 明确 W5-200 已完成,且 `npm run smoke:node`、`npm run build && npm run smoke`、`git diff --check -- web-rtcp-5axis-sim-plan work/working5` 均通过。
|
||||
- 命令:`sed -n '1,240p' /home/meswork/cnc_wams/work/working5/04-任务矩阵.md`
|
||||
- 结果:确认 W5-001 到 W5-200、W5-900 全部为“完成”。
|
||||
- 命令:`sed -n '1,260p' /home/meswork/cnc_wams/work/working5/05-验收证据.md`
|
||||
- 结果:确认 EV-W5-200、EV-W5-201 已覆盖 settings/tool/user-message 低频 HAL pin 诊断、完整 Node、静态构建和浏览器 smoke。
|
||||
- 命令:`sed -n '1,260p' /home/meswork/cnc_wams/work/working5/06-决策记录.md`
|
||||
- 结果:确认 DR-W5-007 已记录 `unlock-settings`、tool measurement HAL_OUT、动态 user messages 的配置启用边界。
|
||||
- 检查约束和项目脚本:
|
||||
- 命令:`sed -n '1,120p' /home/meswork/cnc_wams/AGENTS.md`
|
||||
- 结果:确认本工作区要求每次 GPT/Codex 执行完成后,将完整过程日志用中文追加到 `web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md`。
|
||||
- 命令:`sed -n '1,220p' /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/package.json`
|
||||
- 结果:确认 `smoke:node`、`build`、`smoke` 脚本定义。
|
||||
- 命令:`git -C /home/meswork/cnc_wams diff --stat -- web-rtcp-5axis-sim-plan work/working5`
|
||||
- 结果:确认当前主要变更仍集中在 gmoccapy profile/runtime/state/ui、Node/browser tests、working5 文档和过程日志。
|
||||
- 重新执行完整验收:
|
||||
- 命令:`cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app && npm run smoke:node`
|
||||
- 结果:通过,关键输出包含 `linuxcnc_kinematics_runtime_smoke=ok`、`linuxcnc_interpreter_runtime_smoke=ok`、`linuxcnc_ini_runtime_smoke=ok`、`linuxcnc_task_hal_runtime_smoke=ok`、`real_linuxcnc_5axis_program_cases_smoke=ok`、`gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_communication_model_smoke=ok`、`gmoccapy_hal_model_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok`、`linear_unit_conversion_smoke=ok`。
|
||||
- 命令:`cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app && npm run build && npm run smoke`
|
||||
- 结果:通过,输出 `gmoccapy_static_build=ok`、`gmoccapy_shell_smoke=ok`、`gmoccapy_dist_smoke=ok`。
|
||||
- 命令:`git diff --check -- web-rtcp-5axis-sim-plan work/working5`
|
||||
- 结果:通过,无输出。
|
||||
- 本次修改:
|
||||
- 未修改 app 源码、测试或 working5 控制文档。
|
||||
- 仅按 AGENTS.md 要求追加本中文过程日志。
|
||||
|
||||
结论:
|
||||
- `/home/meswork/cnc_wams/work/working5` 的任务矩阵已闭环。
|
||||
- 本次接续复核重新跑通完整 Node smoke、静态构建、浏览器 smoke 和 diff whitespace 检查。
|
||||
- 当前未执行 commit 或 push。
|
||||
|
||||
## 2026-06-27 working5 最终完成日志:低频 HAL pin 收口后的当前态复核
|
||||
|
||||
用户请求:
|
||||
- 完成 `/home/meswork/cnc_wams/work/working5` 的工作。
|
||||
|
||||
执行过程:
|
||||
- 读取工作区规则:
|
||||
- 命令:`pwd && rg --files -g 'AGENTS.md' -g '!node_modules' -g '!dist' -g '!build'`
|
||||
- 结果:当前目录为 `/home/meswork/cnc_wams`,找到 `AGENTS.md` 和 `wasm-port/AGENTS.md`。
|
||||
- 命令:`sed -n '1,220p' AGENTS.md`
|
||||
- 结果:确认每次 GPT/Codex 执行完成后,需要将中文完整过程日志追加到 `web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md`。
|
||||
- 检查 `working5` 文件和工作树状态:
|
||||
- 命令:`find /home/meswork/cnc_wams/work/working5 -maxdepth 3 -type f | sort`
|
||||
- 结果:确认 `README.md`、`01-项目功能内容.md`、`02-项目程序开发详细步骤.md`、`03-推进台账.md`、`04-任务矩阵.md`、`05-验收证据.md`、`06-决策记录.md` 均存在。
|
||||
- 命令:`git status --short`
|
||||
- 结果:工作树中已有 gmoccapy profile/runtime/state/ui、Node/browser tests、working5 文档和 `gpdlog.md` 修改;按规则不回滚既有改动。
|
||||
- 读取 `working5` 控制文档:
|
||||
- 命令:`sed -n '1,240p' work/working5/README.md`
|
||||
- 结果:确认本目录用于推进 `web-rtcp-5axis-sim-plan` 与 LinuxCNC `gmoccapy_XYZAB.ini` 五轴仿真流程一致性验证。
|
||||
- 命令:`sed -n '1,260p' work/working5/01-项目功能内容.md`
|
||||
- 结果:确认目标覆盖启动配置、task/status 互锁、HAL 仿真 IO、G-code/五轴运动和 gmoccapy UI 等范围。
|
||||
- 命令:`sed -n '1,320p' work/working5/02-项目程序开发详细步骤.md`
|
||||
- 结果:确认应按读取基准、执行测试、差异分析、修改实现、回归验收、更新台账的流程推进。
|
||||
- 命令:`sed -n '1,320p' work/working5/03-推进台账.md`
|
||||
- 结果:确认 R1-R7 已记录,W5-200 已完成,完整 Node、构建、浏览器 smoke 和 diff check 均已有历史证据。
|
||||
- 命令:`sed -n '1,360p' work/working5/04-任务矩阵.md`
|
||||
- 结果:确认 W5-001 到 W5-200、W5-900 均为“完成”。
|
||||
- 命令:`sed -n '1,420p' work/working5/05-验收证据.md`
|
||||
- 结果:确认 EV-W5-001 到 EV-W5-201 已覆盖各任务验收命令和断言摘要。
|
||||
- 命令:`sed -n '1,360p' work/working5/06-决策记录.md`
|
||||
- 结果:确认 DR-W5-001 到 DR-W5-007 已记录模式门控、换刀 HAL、hard-button、HAL input、jog/message、settings/tool/user-message 等关键取舍。
|
||||
- 检查项目脚本和新增实现覆盖点:
|
||||
- 命令:`sed -n '1,220p' package.json`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:确认 `smoke:node`、`build`、`smoke` 脚本可用于完整验收。
|
||||
- 命令:`rg -n "GMOCAPY_HAL_PIN|unlock-settings|tool-user-inputs|settings-inputs|messages\\.\\*|toolmeasurement|probeheight|blockheight" app/src tests -S`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan`
|
||||
- 结果:确认低频 HAL pin 实现和断言分布在 `gmoccapy-xyzab.js`、`gmoccapy-hal-model.js`、`gmoccapy-communication-model.js`、`store.js`、`gmoccapy-shell.js` 以及 Node/browser 测试中。
|
||||
- 命令:`git diff --check -- web-rtcp-5axis-sim-plan work/working5`
|
||||
- 结果:通过,无空白错误。
|
||||
- 执行当前态完整验收:
|
||||
- 命令:`npm run smoke:node`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出包含 `linuxcnc_kinematics_runtime_smoke=ok`、`linuxcnc_interpreter_runtime_smoke=ok`、`linuxcnc_ini_runtime_smoke=ok`、`linuxcnc_task_hal_runtime_smoke=ok`、`real_linuxcnc_5axis_program_cases_smoke=ok`、`gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_communication_model_smoke=ok`、`gmoccapy_hal_model_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok`、`linear_unit_conversion_smoke=ok`。
|
||||
- 命令:`npm run build`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_static_build=ok`。
|
||||
- 命令:`npm run smoke`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_shell_smoke=ok`、`gmoccapy_dist_smoke=ok`。
|
||||
- 更新 `working5` 收口文档:
|
||||
- 修改 `work/working5/03-推进台账.md`:新增 R8“working5 最终复核与验收收口”,记录当前态复核、变更文件和三项主验收命令结果。
|
||||
- 修改 `work/working5/05-验收证据.md`:新增 EV-W5-900 和 R8 命令记录,明确 `npm run smoke:node`、`npm run build`、`npm run smoke` 当前通过。
|
||||
- 未修改 app 源码和测试实现;本轮主要是核对、重跑验收和补齐收口证据。
|
||||
- 最后检查:
|
||||
- 命令:`git diff --check -- web-rtcp-5axis-sim-plan work/working5`
|
||||
- 结果:通过,无输出。
|
||||
- 命令:`git status --short`
|
||||
- 结果:仍有 gmoccapy profile/runtime/state/ui、测试、working5 文档和 `gpdlog.md` 修改,未执行 commit。
|
||||
- 命令:`git diff --stat -- web-rtcp-5axis-sim-plan work/working5`
|
||||
- 结果:变更集中在 15 个文件,包含 app/profile/runtime/state/ui、Node/browser tests、working5 文档和过程日志。
|
||||
|
||||
结论:
|
||||
- `/home/meswork/cnc_wams/work/working5` 已按当前任务矩阵完成并复核通过。
|
||||
- 当前工作区完整 Node 冒烟、静态构建、浏览器冒烟和 diff 空白检查均通过。
|
||||
- 本轮未执行 commit 或 push。
|
||||
|
||||
## 2026-06-27 working5 剩余工作查询日志
|
||||
|
||||
用户请求:
|
||||
- 询问 `/home/meswork/cnc_wams/work/working5` 还有哪些工作要做。
|
||||
|
||||
执行过程:
|
||||
- 读取任务矩阵:
|
||||
- 命令:`sed -n '1,220p' work/working5/04-任务矩阵.md`
|
||||
- 结果:确认 W5-001、W5-010、W5-020、W5-030、W5-040、W5-100、W5-110、W5-120、W5-130、W5-140、W5-150、W5-160、W5-170、W5-180、W5-190、W5-200、W5-900 状态均为“完成”。
|
||||
- 读取推进台账末尾:
|
||||
- 命令:`tail -n 90 work/working5/03-推进台账.md`
|
||||
- 结果:确认 R8 写明 `working5` 已按当前任务矩阵完成并复核通过,本轮不新增后续实现任务。
|
||||
- 搜索待办和后续关键词:
|
||||
- 命令:`rg -n "下一步|后续|待|未完成|完成|W5-900|EV-W5-900" work/working5`
|
||||
- 结果:确认验收证据中 EV-W5-900 记录最终复核通过;发现 `06-决策记录.md` 中 DR-W5-004 保留早期“未完成 optional-stop、blockdelete、ignore-limits”的历史影响描述,但对应工作已在 W5-180 完成,不是当前剩余任务。
|
||||
|
||||
结论:
|
||||
- 当前 `working5` 任务矩阵内没有剩余待办。
|
||||
- 可选深化方向仅是台账 R7 提到的 gmoccapy 文件/宏页面、tool editor 页面或 native GTK 未实现页面诊断边界;这些不属于当前 `working5` 已定义任务矩阵的未完成项。
|
||||
|
||||
## 2026-06-27 working6 控制文档创建日志
|
||||
|
||||
用户请求:
|
||||
- 为“gmoccapy 文件/宏页面、tool editor 页面、native GTK 未实现页面诊断边界”这些 working5 可选深化方向创建 7 个后续工作文档,写入 `/home/meswork/cnc_wams/work/working6`,便于后续按文档开展工作。
|
||||
|
||||
执行过程:
|
||||
- 检查目标目录和工作区规则:
|
||||
- 命令:`test -d /home/meswork/cnc_wams/work/working6 && find /home/meswork/cnc_wams/work/working6 -maxdepth 2 -type f | sort || true`
|
||||
- 结果:创建前 `working6` 无可见文件。
|
||||
- 命令:`sed -n '1,160p' AGENTS.md`
|
||||
- 结果:确认本工作区要求每次执行完成后将中文过程日志追加到 `web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md`。
|
||||
- 命令:`find /home/meswork/cnc_wams/work/working5 -maxdepth 1 -type f | sort`
|
||||
- 结果:确认 working5 的 README 和 01-06 文档可作为风格参照。
|
||||
- 创建目录:
|
||||
- 命令:`mkdir -p /home/meswork/cnc_wams/work/working6`
|
||||
- 结果:通过。
|
||||
- 创建 7 个文档:
|
||||
- 新增 `/home/meswork/cnc_wams/work/working6/README.md`,作为工作索引,列出前置工作、对标基准、工作文件和推进规则。
|
||||
- 新增 `/home/meswork/cnc_wams/work/working6/01-项目功能内容.md`,定义目标、对标范围、当前项目入口和非目标。
|
||||
- 新增 `/home/meswork/cnc_wams/work/working6/02-项目程序开发详细步骤.md`,按读取基准、建立映射、跑基线、补模型/状态/UI/测试、回归验收和更新文档拆分步骤。
|
||||
- 新增 `/home/meswork/cnc_wams/work/working6/03-推进台账.md`,记录 R1 创建控制文件、修改文件、待验证项和下一步。
|
||||
- 新增 `/home/meswork/cnc_wams/work/working6/04-任务矩阵.md`,创建 W6-001 到 W6-900 任务;W6-001 标为完成,其余标为待开始。
|
||||
- 新增 `/home/meswork/cnc_wams/work/working6/05-验收证据.md`,记录 EV-W6-001 和本轮命令/文件证据。
|
||||
- 新增 `/home/meswork/cnc_wams/work/working6/06-决策记录.md`,记录 working6 作为 working5 后续深化、未实现 native GTK 页面诊断化、文件/宏/tool editor 先按 XYZAB 配置边界建模等决策。
|
||||
- 验证创建结果:
|
||||
- 命令:`find /home/meswork/cnc_wams/work/working6 -maxdepth 1 -type f -printf '%f\\n' | sort`
|
||||
- 结果:确认 `README.md` 和 `01-项目功能内容.md` 到 `06-决策记录.md` 共 7 个文件存在。
|
||||
- 命令:`sed -n '1,220p' work/working6/04-任务矩阵.md`
|
||||
- 结果:确认任务矩阵包含 W6-001、W6-010、W6-020、W6-030、W6-040、W6-100、W6-110、W6-120、W6-130、W6-140、W6-150、W6-160、W6-900。
|
||||
- 命令:`git diff --check -- work/working6`
|
||||
- 结果:通过,无空白错误。
|
||||
- 命令:`git status --short -- work/working6`
|
||||
- 结果:显示 `?? work/working6/`,说明新增文档尚未提交。
|
||||
|
||||
结论:
|
||||
- `/home/meswork/cnc_wams/work/working6` 的 7 个控制文档已创建完成。
|
||||
- working6 后续可从 W6-010 开始,先建立 gmoccapy native 页面到 Web 模块的映射,再执行 Node/构建/浏览器基线。
|
||||
- 本轮未执行 app 源码修改、测试运行、commit 或 push。
|
||||
|
||||
## 2026-06-26 23:47 EDT working6 gmoccapy 页面诊断边界实现日志
|
||||
|
||||
用户请求:
|
||||
- 对标 `linuxcnc` 源程序中的 `gmoccapy` 五轴示例功能和实现方式,完善 `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan` 项目,并将完善后的文档格式参考和记录写入 `/home/meswork/cnc_wams/work/working6`。
|
||||
|
||||
执行过程:
|
||||
- 读取并确认后续工作文档:
|
||||
- 命令:`find /home/meswork/cnc_wams/work/working6 -maxdepth 1 -type f | sort`
|
||||
- 结果:确认 `README.md`、`01-项目功能内容.md` 到 `06-决策记录.md` 已存在。
|
||||
- 命令:`sed -n '1,240p' work/working6/04-任务矩阵.md`
|
||||
- 结果:确认 W6-010 到 W6-900 为本轮待推进任务。
|
||||
- 对标 LinuxCNC `gmoccapy` 五轴源程序和配置:
|
||||
- 读取 `linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.ini`,确认 `PROGRAM_PREFIX = ../../nc_files/`、`SUBROUTINE_PATH = ./macros`、`TOOL_TABLE = tool.tbl`,以及 5 个宏:`i_am_lost`、`halo_world`、`jog_around`、`increment xinc yinc`、`go_to_position X-pos Y-pos Z-pos`。
|
||||
- 读取 `linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.py`,确认文件页、宏按钮页、tool editor 页和 native GTK 页面切换的关键实现:`_init_IconFileSelection()`、`_init_file_to_load()`、`on_btn_load_clicked()`、`on_IconFileSelection1_selected()`、`_make_macro_button()`、`_on_btn_macro_pressed()`、`_init_tooleditor()`、`_show_tooledit_tab()`、`on_btn_tool_clicked()`。
|
||||
- 执行基线验证:
|
||||
- 命令:`npm run smoke:node`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,包含 `gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_communication_model_smoke=ok`、`gmoccapy_hal_model_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok` 等。
|
||||
- 命令:`npm run build`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_static_build=ok`。
|
||||
- 命令:`npm run smoke`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_shell_smoke=ok`、`gmoccapy_dist_smoke=ok`。
|
||||
- 修改 `app/src/runtime/gmoccapy-hal-model.js`:
|
||||
- 新增 `nativePages` 结构,覆盖文件页、宏页、tool editor 页和 native GTK 页面实现矩阵。
|
||||
- 文件页记录 `IconFileSelection1`、`PROGRAM_PREFIX`、文件扩展名、回调链和 Web 侧 partial 边界。
|
||||
- 宏页记录 5 个 `gmoccapy_XYZAB.ini` 宏、参数、O-word MDI 命令模板和 `RUN_MDI` 门控边界。
|
||||
- tool editor 页记录 `tool.tbl`、17 个工具、可见轴 `X/Y/Z/A/B`、诊断-only 实现和不写回 `tool.tbl` 的边界。
|
||||
- native GTK 实现矩阵区分 implemented、partial、diagnostic-only、native-only。
|
||||
- 将 `tbtn_user_tabs`、`tbtn_setup`、`btn_touch`、`btn_tool`、`tbtn_switch_mode` 等 hard button 从伪 DOM 映射调整为结构化 native page 诊断分发。
|
||||
- 扩展 `createGmoccapyHalSummary()`,输出 native page 数量、partial 数量、diagnostic-only 数量、macro 数量、tool editor 写回边界等摘要。
|
||||
- 修改 `app/src/profiles/gmoccapy-xyzab.js`:
|
||||
- 在 XYZAB profile 中加入 `nativePages.filePage`、`nativePages.macroPage`、`nativePages.toolEditor` 和诊断边界说明。
|
||||
- 明确文件页 `PROGRAM_PREFIX`、宏页 `SUBROUTINE_PATH`、tool editor 的 `tool.tbl` 路径、17 个工具和禁止浏览器写回。
|
||||
- 修改 `app/src/runtime/gmoccapy-communication-model.js`:
|
||||
- 新增 `filePage`、`macroPage`、`toolEditorPage`、`nativePages` 通信路径。
|
||||
- 新增 `file-page`、`macro-page`、`tool-editor-page`、`native-page-diagnostic` 动作映射。
|
||||
- 摘要新增 `pagePathCount`。
|
||||
- 修改 `app/src/state/store.js`:
|
||||
- 扩展 `gmoccapyGui` 初始状态,增加 active native page、file page、macro page、tool editor 的诊断状态字段。
|
||||
- 新增 `GMOCAPY_NATIVE_PAGE`、`GMOCAPY_PAGE_ACTION`、`GMOCAPY_RUN_MACRO`、`GMOCAPY_TOOL_EDITOR_ACTION` 分发处理。
|
||||
- 宏执行通过 `gateLinuxCncTaskAction(... RUN_MDI)` 门控后构造 `O<name> call [args]` 并复用既有 MDI 执行路径。
|
||||
- tool editor 的保存、增加、删除、touch-off 等写操作被诊断性阻断,保持不写 `tool.tbl` 和不破坏 iocontrol-loopback。
|
||||
- 修改 `app/src/ui/gmoccapy-shell.js`:
|
||||
- 在信息/诊断 tab 中增加 `data-gmoccapy-page="file"`、`macros`、`tool-editor`、`matrix` 行。
|
||||
- 新增文件页、宏页、tool editor 页、native page matrix 格式化输出。
|
||||
- hard button 诊断输出补充 diagnostic-only native page 数量。
|
||||
- 修改测试:
|
||||
- `tests/node/verify_gmoccapy_hal_model.mjs`:覆盖 hard button native page 分发、nativePages 结构、5 个宏、17 个工具、实现矩阵和摘要字段。
|
||||
- `tests/node/verify_gmoccapy_communication_model.mjs`:覆盖新增页面通信路径、动作映射和 `pagePathCount`。
|
||||
- `tests/node/verify_gmoccapy_xyzab_profile.mjs`:覆盖 profile 中 native page、宏、tool editor 配置。
|
||||
- `tests/node/verify_gmoccapy_xyzab_gates.mjs`:覆盖 native page 诊断、文件页动作、tool editor 写回阻断、宏门控和 MDI 命令生成。
|
||||
- `tests/browser/gmoccapy_shell_smoke.html`:覆盖新增诊断 DOM 行、native page 分发、文件页动作、tool editor 写回阻断和宏执行状态。
|
||||
- 执行语法和局部验证:
|
||||
- 命令:`node --check src/runtime/gmoccapy-hal-model.js && node --check src/runtime/gmoccapy-communication-model.js && node --check src/state/store.js && node --check src/ui/gmoccapy-shell.js`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过。
|
||||
- 命令:`node ../tests/node/verify_gmoccapy_hal_model.mjs && node ../tests/node/verify_gmoccapy_communication_model.mjs`
|
||||
- 结果:通过,输出 `gmoccapy_hal_model_smoke=ok`、`gmoccapy_communication_model_smoke=ok`。
|
||||
- 命令:`node ../tests/node/verify_gmoccapy_xyzab_profile.mjs && node ../tests/node/verify_gmoccapy_xyzab_gates.mjs`
|
||||
- 结果:通过,输出 `gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok`。
|
||||
- 命令:`bash ../tests/browser/verify_gmoccapy_shell_browser.sh`
|
||||
- 结果:通过,输出 `gmoccapy_shell_smoke=ok`。
|
||||
- 执行完整验收:
|
||||
- 命令:`npm run smoke:node`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过。
|
||||
- 命令:`npm run build`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_static_build=ok`。
|
||||
- 命令:`npm run smoke`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_shell_smoke=ok`、`gmoccapy_dist_smoke=ok`。
|
||||
- 更新 working6 文档:
|
||||
- 修改 `work/working6/04-任务矩阵.md`:将 W6-001、W6-010、W6-020、W6-030、W6-040、W6-100、W6-110、W6-120、W6-130、W6-140、W6-150、W6-160、W6-900 全部标记为完成。
|
||||
- 修改 `work/working6/03-推进台账.md`:新增 R2“实现 gmoccapy 页面级诊断边界”,记录对标内容、修改文件、验证结果和下一步。
|
||||
- 修改 `work/working6/05-验收证据.md`:新增 EV-W6-020、EV-W6-100、EV-W6-160、EV-W6-900 和 R2 命令证据。
|
||||
- 修改 `work/working6/06-决策记录.md`:新增 DR-W6-004、DR-W6-005、DR-W6-006,记录宏页按 O-word MDI 建模、tool editor 只做诊断不写回、native-only 页面用结构化诊断边界表达。
|
||||
- 最终检查:
|
||||
- 命令:`git diff --check -- web-rtcp-5axis-sim-plan work/working6`
|
||||
- 结果:通过,无输出。
|
||||
- 命令:`node ../tests/node/verify_gmoccapy_hal_model.mjs && node ../tests/node/verify_gmoccapy_communication_model.mjs && node ../tests/node/verify_gmoccapy_xyzab_profile.mjs && node ../tests/node/verify_gmoccapy_xyzab_gates.mjs`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_hal_model_smoke=ok`、`gmoccapy_communication_model_smoke=ok`、`gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok`。
|
||||
- 命令:`git status --short`
|
||||
- 结果:显示本轮修改集中在 gmoccapy profile/runtime/state/ui、Node/browser tests、working6 文档和 `gpdlog.md`;历史 working5 文档修改仍存在,未回退;未执行 commit 或 push。
|
||||
|
||||
结论:
|
||||
- `working6` 中定义的 gmoccapy 文件页、宏页、tool editor 页和 native GTK 未实现页面诊断边界任务已完成。
|
||||
- Web 项目已具备对 `gmoccapy_XYZAB.ini` 宏配置、文件页路径、tool editor 表和 native page 边界的结构化表达、状态分发、UI 诊断和测试覆盖。
|
||||
- 完整 Node 冒烟、静态构建、浏览器冒烟和 diff 空白检查均已通过。
|
||||
|
||||
## 2026-06-27 R3 接续 working6 最终复核过程日志
|
||||
|
||||
用户请求:
|
||||
|
||||
- 接续上一轮,继续完成 `/home/meswork/cnc_wams/work/working6` 的工作。
|
||||
|
||||
执行过程:
|
||||
|
||||
- 读取当前工作目录和 `work/working6` 文件清单,确认 `README.md`、`01-项目功能内容.md`、`02-项目程序开发详细步骤.md`、`03-推进台账.md`、`04-任务矩阵.md`、`05-验收证据.md`、`06-决策记录.md` 均存在。
|
||||
- 执行 `git status --short`,确认当前未提交改动集中在 `web-rtcp-5axis-sim-plan` 的 gmoccapy profile/runtime/state/ui/tests、`work/working6` 文档、`gpdlog.md`,并存在历史 `work/working5` 文档改动;未回退任何既有改动。
|
||||
- 读取 `work/working6/README.md`,确认本轮目标为 gmoccapy 文件页、宏页、tool editor 页和 native GTK 未实现页面诊断边界。
|
||||
- 读取 `work/working6/04-任务矩阵.md`,确认 W6-001、W6-010、W6-020、W6-030、W6-040、W6-100、W6-110、W6-120、W6-130、W6-140、W6-150、W6-160、W6-900 均已标记完成。
|
||||
- 读取 `work/working6/03-推进台账.md` 和 `work/working6/05-验收证据.md`,确认上一轮 R2 已记录实现内容和通过的基线、最小验收、回归命令。
|
||||
- 读取 `work/working6/01-项目功能内容.md`、`02-项目程序开发详细步骤.md`、`06-决策记录.md`,确认 W6 的非目标、开发步骤和决策边界:不实现完整 GTK 文件选择器、不写真实 `tool.tbl`、未实现 native GTK 页面必须 diagnostic-only。
|
||||
- 执行 `git diff -- web-rtcp-5axis-sim-plan/app/src/profiles/gmoccapy-xyzab.js`,复核 profile 已新增 `nativePages.filePage`、`nativePages.macroPage`、`nativePages.toolEditor`、toolsensor/userMessages 诊断边界和相关 HAL pin。
|
||||
- 执行 `git diff -- web-rtcp-5axis-sim-plan/app/src/runtime/gmoccapy-communication-model.js web-rtcp-5axis-sim-plan/app/src/runtime/gmoccapy-hal-model.js`,复核 communication model 已新增 file/macro/tool/native page 路径和 action mapping,HAL model 已新增 native page matrix、settings/tool measurement/user messages 诊断和 hard-button native page 分发。
|
||||
- 执行 `git diff -- web-rtcp-5axis-sim-plan/app/src/state/store.js`,复核 store 已新增 `GMOCAPY_NATIVE_PAGE`、`GMOCAPY_PAGE_ACTION`、`GMOCAPY_RUN_MACRO`、`GMOCAPY_TOOL_EDITOR_ACTION`,并确认宏执行复用 `RUN_MDI` gate、tool editor 写操作被诊断性阻断。
|
||||
- 执行 `git diff -- web-rtcp-5axis-sim-plan/app/src/ui/gmoccapy-shell.js`,复核 UI 已新增 `data-gmoccapy-page="file"`、`macros`、`tool-editor`、`matrix` 诊断行,以及 settings/tool/user HAL 诊断行。
|
||||
- 执行测试差异复核:
|
||||
- `git diff -- web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_communication_model.mjs web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_hal_model.mjs`
|
||||
- `git diff -- web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_xyzab_profile.mjs web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_xyzab_gates.mjs`
|
||||
- `git diff -- web-rtcp-5axis-sim-plan/tests/browser/gmoccapy_shell_smoke.html`
|
||||
确认 Node/browser 测试已覆盖页面模型、宏 count、tool table count、native page matrix、DOM 诊断、hard-button diagnostic-only 分发、宏 MDI 命令和 tool editor 写回阻断。
|
||||
- 执行完整 Node 冒烟:
|
||||
- 命令:`npm run smoke:node`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,关键输出包含 `gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_communication_model_smoke=ok`、`gmoccapy_hal_model_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok`、`linear_unit_conversion_smoke=ok`。
|
||||
- 执行静态构建:
|
||||
- 命令:`npm run build`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_static_build=ok`。
|
||||
- 执行浏览器冒烟:
|
||||
- 命令:`npm run smoke`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_shell_smoke=ok`、`gmoccapy_dist_smoke=ok`。
|
||||
- 执行空白检查:
|
||||
- 命令:`git diff --check -- web-rtcp-5axis-sim-plan work/working6`
|
||||
- 工作目录:`/home/meswork/cnc_wams`
|
||||
- 结果:通过,无输出。
|
||||
- 读取 workspace 级 `AGENTS.md`,确认需要在每次 GPT/Codex 执行结束后将中文过程日志追加到 `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md`。
|
||||
- 修改 `work/working6/03-推进台账.md`,追加 R3“接续复核 working6 完成状态”,记录本轮复核范围、验证命令和下一步建议。
|
||||
- 修改 `work/working6/05-验收证据.md`,追加 EV-W6-901 和 R3 命令记录,记录 `npm run smoke:node`、`npm run build`、`npm run smoke`、`git diff --check -- web-rtcp-5axis-sim-plan work/working6` 均通过。
|
||||
- 修改本文件 `web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md`,追加本轮中文过程日志。
|
||||
|
||||
结论:
|
||||
|
||||
- `working6` 当前任务已闭环,不需要新增功能代码补丁。
|
||||
- gmoccapy 文件页、宏页、tool editor 页、native GTK 未实现页面诊断边界在 profile、model、store、UI 和测试中均有结构化表达与验收覆盖。
|
||||
- 本轮最终回归中,Node 冒烟、静态构建、浏览器冒烟和 `git diff --check` 均已通过。
|
||||
|
||||
## 2026-06-27 R4 提交到云仓库过程日志
|
||||
|
||||
用户请求:
|
||||
|
||||
- 将当前工作提交到云仓库。
|
||||
|
||||
执行过程:
|
||||
|
||||
- 查看仓库根目录、当前分支和远端:
|
||||
- 命令:`git rev-parse --show-toplevel && git branch --show-current && git remote -v`
|
||||
- 结果:仓库根目录为 `/home/meswork/cnc_wams`,当前分支为 `master`,远端 `origin` 为 `http://154.8.160.151:3000/wangdequan/cnc_wams`。
|
||||
- 查看工作树:
|
||||
- 命令:`git status --short`
|
||||
- 结果:存在 gmoccapy profile/runtime/state/ui/tests 修改、`gpdlog.md` 修改、`work/working5` 文档修改和新增 `work/working6/`。
|
||||
- 查看改动统计:
|
||||
- 命令:`git diff --stat`
|
||||
- 结果:确认主要改动集中在 gmoccapy 页面级诊断边界、测试、working5/working6 文档和过程日志。
|
||||
- 查看最近提交:
|
||||
- 命令:`git log -5 --oneline --decorate`
|
||||
- 结果:当前 `HEAD`、`origin/master`、`origin/HEAD` 均在 `f964ced`。
|
||||
- 执行最终 Node 冒烟:
|
||||
- 命令:`npm run smoke:node`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,关键输出包含 `gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_communication_model_smoke=ok`、`gmoccapy_hal_model_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok`、`linear_unit_conversion_smoke=ok`。
|
||||
- 执行静态构建:
|
||||
- 命令:`npm run build`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_static_build=ok`。
|
||||
- 执行浏览器冒烟:
|
||||
- 命令:`npm run smoke`
|
||||
- 工作目录:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- 结果:通过,输出 `gmoccapy_shell_smoke=ok`、`gmoccapy_dist_smoke=ok`。
|
||||
- 执行空白检查:
|
||||
- 命令:`git diff --check`
|
||||
- 工作目录:`/home/meswork/cnc_wams`
|
||||
- 结果:通过,无输出。
|
||||
- 同步远端状态:
|
||||
- 命令:`git fetch origin master`
|
||||
- 结果:成功从 `origin/master` 获取。
|
||||
- 命令:`git rev-list --left-right --count HEAD...origin/master`
|
||||
- 结果:`0 0`,本地与远端无分叉。
|
||||
- 追加本过程日志到 `web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md`。
|
||||
- 下一步准备执行:
|
||||
- `git add -A`
|
||||
- `git commit -m "完善 working6 gmoccapy 页面诊断边界"`
|
||||
- `git push origin master`
|
||||
|
||||
阶段结论:
|
||||
|
||||
- 提交前验证全部通过。
|
||||
- 本地 `master` 与远端 `origin/master` 无分叉,可以直接提交并推送。
|
||||
|
||||
后续提交与推送结果:
|
||||
|
||||
- 执行提交:
|
||||
- 命令:`git add -A && git commit -m "完善 working6 gmoccapy 页面诊断边界"`
|
||||
- 结果:成功创建本地提交 `ef3247b 完善 working6 gmoccapy 页面诊断边界`,包含 22 个文件变更。
|
||||
- 尝试推送:
|
||||
- 命令:`git push origin master`
|
||||
- 结果:失败,错误为 `fatal: could not read Username for 'http://154.8.160.151:3000': No such device or address`。
|
||||
- 失败原因判断:
|
||||
- 当前远端使用 HTTP 地址 `http://154.8.160.151:3000/wangdequan/cnc_wams`。
|
||||
- 当前非交互执行环境没有可用的 Git credential helper、凭据文件、token 环境变量或 SSH 远端。
|
||||
- 上一次云仓库同步成功记录显示,当时通过 Git 终端提示输入用户名和密码完成认证;本次执行环境无法读取交互式用户名。
|
||||
- 当前仓库状态:
|
||||
- 本地 `master` 已比 `origin/master` 领先 1 个提交。
|
||||
- 云端推送未完成,阻塞点为 HTTP 认证。
|
||||
|
||||
最终结论:
|
||||
|
||||
- 本地提交已完成。
|
||||
- 云仓库推送尚未完成;需要配置 Git HTTP 凭据、改用可用 token/credential helper,或切换到已配置 SSH key 的远程地址后再执行 `git push origin master`。
|
||||
|
||||
补充最终状态:
|
||||
|
||||
- 为了把推送失败原因纳入同一笔提交,执行了:
|
||||
- `git add web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md && git commit --amend --no-edit`
|
||||
- amend 后本地提交哈希发生变化,最终提交以 `git log -1 --oneline` 为准,提交主题仍为 `完善 working6 gmoccapy 页面诊断边界`。
|
||||
- 最终检查:
|
||||
- 命令:`git status --short && git rev-list --left-right --count HEAD...origin/master && git log -1 --oneline --decorate`
|
||||
- 结果:工作树干净,本地 `master` 领先 `origin/master` 1 个提交,远端未领先本地。
|
||||
- 命令:`git diff --check HEAD~1..HEAD`
|
||||
- 结果:通过,无输出。
|
||||
|
||||
@@ -310,6 +310,41 @@
|
||||
if (!doc.querySelector('[data-gmoccapy-comm="web-path"]')?.textContent.includes("store.dispatch")) {
|
||||
throw new Error("missing gmoccapy Web runtime mapping");
|
||||
}
|
||||
const filePageDiagnostic = doc.querySelector('[data-gmoccapy-page="file"]')?.textContent || "";
|
||||
if (
|
||||
!filePageDiagnostic.includes("file page partial") ||
|
||||
!filePageDiagnostic.includes("PROGRAM_PREFIX ../../nc_files/") ||
|
||||
!filePageDiagnostic.includes("native IconFileSelection") ||
|
||||
!filePageDiagnostic.includes("Web OPEN_FILE/staged-source")
|
||||
) {
|
||||
throw new Error(`missing gmoccapy file page diagnostic: ${filePageDiagnostic}`);
|
||||
}
|
||||
const macroPageDiagnostic = doc.querySelector('[data-gmoccapy-page="macros"]')?.textContent || "";
|
||||
if (
|
||||
!macroPageDiagnostic.includes("5 XYZAB macros") ||
|
||||
!macroPageDiagnostic.includes("MDI gate") ||
|
||||
!macroPageDiagnostic.includes("O-word call")
|
||||
) {
|
||||
throw new Error(`missing gmoccapy macro page diagnostic: ${macroPageDiagnostic}`);
|
||||
}
|
||||
const toolEditorDiagnostic = doc.querySelector('[data-gmoccapy-page="tool-editor"]')?.textContent || "";
|
||||
if (
|
||||
!toolEditorDiagnostic.includes("tool editor diagnostic-only") ||
|
||||
!toolEditorDiagnostic.includes("17 tools") ||
|
||||
!toolEditorDiagnostic.includes("writeback disabled") ||
|
||||
!toolEditorDiagnostic.includes("iocontrol-loopback preserved")
|
||||
) {
|
||||
throw new Error(`missing gmoccapy tool editor diagnostic: ${toolEditorDiagnostic}`);
|
||||
}
|
||||
const nativePageMatrixDiagnostic = doc.querySelector('[data-gmoccapy-page="matrix"]')?.textContent || "";
|
||||
if (
|
||||
!nativePageMatrixDiagnostic.includes("12 native pages") ||
|
||||
!nativePageMatrixDiagnostic.includes("5 diagnostic-only") ||
|
||||
!nativePageMatrixDiagnostic.includes("2 native-only") ||
|
||||
!nativePageMatrixDiagnostic.includes("hard-buttons diagnostic-only")
|
||||
) {
|
||||
throw new Error(`missing gmoccapy native page matrix diagnostic: ${nativePageMatrixDiagnostic}`);
|
||||
}
|
||||
if (!doc.querySelector('[data-gmoccapy-hal="postgui"]')?.textContent.includes("tool-change-loop")) {
|
||||
throw new Error("missing gmoccapy HAL postgui diagnostic");
|
||||
}
|
||||
@@ -349,6 +384,24 @@
|
||||
) {
|
||||
throw new Error(`missing gmoccapy HAL message diagnostic: ${messageInputDiagnostic}`);
|
||||
}
|
||||
const settingsInputDiagnostic = doc.querySelector('[data-gmoccapy-hal="settings-inputs"]')?.textContent || "";
|
||||
if (
|
||||
!settingsInputDiagnostic.includes("1 settings pins") ||
|
||||
!settingsInputDiagnostic.includes("unlock-settings level-driven") ||
|
||||
!settingsInputDiagnostic.includes("unlock-way use") ||
|
||||
!settingsInputDiagnostic.includes("setup sensitive")
|
||||
) {
|
||||
throw new Error(`missing gmoccapy HAL settings diagnostic: ${settingsInputDiagnostic}`);
|
||||
}
|
||||
const toolUserDiagnostic = doc.querySelector('[data-gmoccapy-hal="tool-user-inputs"]')?.textContent || "";
|
||||
if (
|
||||
!toolUserDiagnostic.includes("5 tool measurement HAL_OUT pins") ||
|
||||
!toolUserDiagnostic.includes("XYZAB no TOOLSENSOR") ||
|
||||
!toolUserDiagnostic.includes("0 user message pins") ||
|
||||
!toolUserDiagnostic.includes("no MESSAGE_*")
|
||||
) {
|
||||
throw new Error(`missing gmoccapy HAL tool/user diagnostic: ${toolUserDiagnostic}`);
|
||||
}
|
||||
const hardButtonDiagnostic = doc.querySelector('[data-gmoccapy-hal="hard-buttons"]')?.textContent || "";
|
||||
if (
|
||||
!hardButtonDiagnostic.includes("7 right v-button pins") ||
|
||||
@@ -1090,14 +1143,107 @@
|
||||
if (halJogGuiState.deletedMessageCount !== 1 || halJogGuiState.warningConfirm !== true) {
|
||||
throw new Error(`gmoccapy HAL message pins did not update state: ${JSON.stringify(halJogGuiState)}`);
|
||||
}
|
||||
win.webRtcp5AxisSimulation.dispatch({
|
||||
type: "GMOCAPY_HAL_PIN",
|
||||
pin: "gmoccapy.unlock-settings",
|
||||
value: false,
|
||||
});
|
||||
await wait(25);
|
||||
if (win.webRtcp5AxisSimulation.getState().gmoccapyGui.setupSensitive !== true) {
|
||||
throw new Error("gmoccapy HAL unlock-settings should be ignored while unlock_way is use");
|
||||
}
|
||||
win.webRtcp5AxisSimulation.dispatch({
|
||||
type: "GMOCAPY_HAL_PIN",
|
||||
pin: "gmoccapy.unlock-settings",
|
||||
value: false,
|
||||
halUnlockMode: true,
|
||||
});
|
||||
await wait(25);
|
||||
if (win.webRtcp5AxisSimulation.getState().gmoccapyGui.setupSensitive !== false) {
|
||||
throw new Error("gmoccapy HAL unlock-settings low did not lock setup in HAL unlock mode");
|
||||
}
|
||||
win.webRtcp5AxisSimulation.dispatch({
|
||||
type: "GMOCAPY_HAL_PIN",
|
||||
pin: "gmoccapy.unlock-settings",
|
||||
value: true,
|
||||
});
|
||||
win.webRtcp5AxisSimulation.dispatch({
|
||||
type: "GMOCAPY_HAL_PIN",
|
||||
pin: "gmoccapy.blockheight",
|
||||
value: 12.5,
|
||||
});
|
||||
await wait(50);
|
||||
const toolUserState = win.webRtcp5AxisSimulation.getState().gmoccapyGui;
|
||||
if (toolUserState.setupSensitive !== true || toolUserState.blockHeight !== 12.5) {
|
||||
throw new Error(`gmoccapy HAL settings/tool pins did not update state: ${JSON.stringify(toolUserState)}`);
|
||||
}
|
||||
win.webRtcp5AxisSimulation.dispatch({
|
||||
type: "GMOCAPY_HAL_PIN",
|
||||
pin: "gmoccapy.messages.test",
|
||||
value: true,
|
||||
});
|
||||
await wait(25);
|
||||
if (!win.webRtcp5AxisSimulation.getState().operatorMessage.includes("no MESSAGE_*")) {
|
||||
throw new Error("gmoccapy HAL user message pin should report no MESSAGE_* entries");
|
||||
}
|
||||
const updatedJogDiagnostic = doc.querySelector('[data-gmoccapy-hal="jog-inputs"]')?.textContent || "";
|
||||
const updatedMessageDiagnostic = doc.querySelector('[data-gmoccapy-hal="message-inputs"]')?.textContent || "";
|
||||
const updatedSettingsDiagnostic = doc.querySelector('[data-gmoccapy-hal="settings-inputs"]')?.textContent || "";
|
||||
const updatedToolUserDiagnostic = doc.querySelector('[data-gmoccapy-hal="tool-user-inputs"]')?.textContent || "";
|
||||
if (!updatedJogDiagnostic.includes("turtle level-driven") || !updatedJogDiagnostic.includes("increment 0.100 mm=0.1")) {
|
||||
throw new Error(`gmoccapy HAL jog diagnostic did not refresh: ${updatedJogDiagnostic}`);
|
||||
}
|
||||
if (!updatedMessageDiagnostic.includes("deleted 1") || !updatedMessageDiagnostic.includes("confirm on")) {
|
||||
throw new Error(`gmoccapy HAL message diagnostic did not refresh: ${updatedMessageDiagnostic}`);
|
||||
}
|
||||
if (!updatedSettingsDiagnostic.includes("unlock-way hal") || !updatedSettingsDiagnostic.includes("pin high")) {
|
||||
throw new Error(`gmoccapy HAL settings diagnostic did not refresh: ${updatedSettingsDiagnostic}`);
|
||||
}
|
||||
if (!updatedToolUserDiagnostic.includes("blockheight 12.5") || !updatedToolUserDiagnostic.includes("no MESSAGE_*")) {
|
||||
throw new Error(`gmoccapy HAL tool/user diagnostic did not refresh: ${updatedToolUserDiagnostic}`);
|
||||
}
|
||||
win.webRtcp5AxisSimulation.dispatch({
|
||||
type: "GMOCAPY_HARDWARE_BUTTON",
|
||||
pin: "gmoccapy.v-button.button-6",
|
||||
value: true,
|
||||
});
|
||||
await wait(25);
|
||||
if (
|
||||
win.webRtcp5AxisSimulation.getState().gmoccapyGui.activeNativePage !== "setup" ||
|
||||
!win.webRtcp5AxisSimulation.getState().operatorMessage.includes("diagnostic-only: setup")
|
||||
) {
|
||||
throw new Error("gmoccapy native setup page diagnostic did not update from hard-button");
|
||||
}
|
||||
win.webRtcp5AxisSimulation.dispatch({
|
||||
type: "GMOCAPY_PAGE_ACTION",
|
||||
pageId: "file-load",
|
||||
actionId: "open",
|
||||
});
|
||||
win.webRtcp5AxisSimulation.dispatch({
|
||||
type: "GMOCAPY_TOOL_EDITOR_ACTION",
|
||||
actionId: "save",
|
||||
});
|
||||
await wait(50);
|
||||
const nativePageState = win.webRtcp5AxisSimulation.getState().gmoccapyGui;
|
||||
if (nativePageState.filePageStatus !== "open" || nativePageState.toolEditorStatus !== "writeback-blocked") {
|
||||
throw new Error(`gmoccapy native page actions did not update state: ${JSON.stringify(nativePageState)}`);
|
||||
}
|
||||
win.webRtcp5AxisSimulation.dispatch({ type: "TOGGLE_POWER" });
|
||||
win.webRtcp5AxisSimulation.dispatch({ type: "HOME" });
|
||||
win.webRtcp5AxisSimulation.dispatch({ type: "SET_MODE", mode: "mdi" });
|
||||
win.webRtcp5AxisSimulation.dispatch({
|
||||
type: "GMOCAPY_RUN_MACRO",
|
||||
name: "increment",
|
||||
args: { xinc: 1.25, yinc: 2.5 },
|
||||
});
|
||||
await wait(50);
|
||||
const macroDiagnostic = doc.querySelector('[data-gmoccapy-page="macros"]')?.textContent || "";
|
||||
if (
|
||||
win.webRtcp5AxisSimulation.getState().gmoccapyGui.macroLastCommand !== "O<increment> call [1.25] [2.5]" ||
|
||||
!macroDiagnostic.includes("O<increment> call [1.25] [2.5]")
|
||||
) {
|
||||
throw new Error(`gmoccapy macro dispatch did not update diagnostics: ${macroDiagnostic}`);
|
||||
}
|
||||
doc.querySelector('[data-action="toggle-flood"]').click();
|
||||
doc.querySelector('[data-action="toggle-mist"]').click();
|
||||
await wait(50);
|
||||
|
||||
@@ -20,6 +20,10 @@ assert.equal(model.nativePaths.hal.path.includes("HAL shared memory"), true);
|
||||
assert.equal(model.nativePaths.hardwareButtons.path.includes("_button_pin_changed"), true);
|
||||
assert.equal(model.nativePaths.halPins.path.includes("hal_glib.GPin value_changed"), true);
|
||||
assert.equal(model.nativePaths.remap.path.includes("Python remap prolog/ngc/epilog"), true);
|
||||
assert.equal(model.nativePaths.filePage.path.includes("IconFileSelection1"), true);
|
||||
assert.equal(model.nativePaths.macroPage.path.includes("_on_btn_macro_pressed"), true);
|
||||
assert.equal(model.nativePaths.toolEditorPage.path.includes("tooledit1.reload()"), true);
|
||||
assert.equal(model.nativePaths.nativePages.path.includes("Web implementation matrix"), true);
|
||||
assert.deepEqual(model.webPath.path, ["button", "store.dispatch", "linuxcnc-task-policy", "runtime/status snapshot", "UI/Three.js"]);
|
||||
|
||||
assert.equal(model.startupStages.length, 9);
|
||||
@@ -46,8 +50,15 @@ for (const actionId of [
|
||||
"coolant",
|
||||
"hardware-button",
|
||||
"hal-pin-input",
|
||||
"hal-settings-unlock",
|
||||
"hal-jog-pin",
|
||||
"hal-tool-measurement",
|
||||
"hal-user-message",
|
||||
"hal-warning-confirm",
|
||||
"file-page",
|
||||
"macro-page",
|
||||
"tool-editor-page",
|
||||
"native-page-diagnostic",
|
||||
]) {
|
||||
assert.equal(actionIds.includes(actionId), true, `${actionId} missing`);
|
||||
}
|
||||
@@ -80,6 +91,11 @@ assert.equal(halPinMapping.gate.includes("counts require count-enable"), true);
|
||||
assert.equal(halPinMapping.gate.includes("direct-value requires analog-enable"), true);
|
||||
assert.equal(halPinMapping.gate.includes("delete-message pins are rising-edge only"), true);
|
||||
|
||||
const settingsUnlockMapping = model.actionMappings.find((mapping) => mapping.actionId === "hal-settings-unlock");
|
||||
assert.equal(settingsUnlockMapping.nativeCommand, "_on_unlock_settings_changed");
|
||||
assert.equal(settingsUnlockMapping.gate.includes("unlock_way"), true);
|
||||
assert.equal(settingsUnlockMapping.gate.includes("HAL unlock"), true);
|
||||
|
||||
const halJogMapping = model.actionMappings.find((mapping) => mapping.actionId === "hal-jog-pin");
|
||||
assert.equal(halJogMapping.webAction, "GMOCAPY_HAL_PIN jog.axis/jog-inc");
|
||||
assert.equal(halJogMapping.nativeCommand.includes("_on_pin_jog_changed"), true);
|
||||
@@ -87,16 +103,44 @@ assert.equal(halJogMapping.nativeCommand.includes("_on_pin_incr_changed"), true)
|
||||
assert.equal(halJogMapping.gate.includes("press/release level"), true);
|
||||
assert.equal(halJogMapping.gate.includes("increment pins are rising-edge only"), true);
|
||||
|
||||
const toolMeasurementMapping = model.actionMappings.find((mapping) => mapping.actionId === "hal-tool-measurement");
|
||||
assert.equal(toolMeasurementMapping.nativeCommand.includes("_check_toolmeasurement"), true);
|
||||
assert.equal(toolMeasurementMapping.nativeStatus.includes("probeheight"), true);
|
||||
assert.equal(toolMeasurementMapping.gate.includes("no [TOOLSENSOR]"), true);
|
||||
|
||||
const userMessageMapping = model.actionMappings.find((mapping) => mapping.actionId === "hal-user-message");
|
||||
assert.equal(userMessageMapping.nativeCommand.includes("_init_user_messages"), true);
|
||||
assert.equal(userMessageMapping.nativeStatus.includes("messages.<pinname>"), true);
|
||||
assert.equal(userMessageMapping.gate.includes("no MESSAGE_*"), true);
|
||||
|
||||
const warningConfirmMapping = model.actionMappings.find((mapping) => mapping.actionId === "hal-warning-confirm");
|
||||
assert.equal(warningConfirmMapping.nativeCommand.includes("confirm_pin"), true);
|
||||
assert.equal(warningConfirmMapping.gate, "level-polled while warning dialog is active");
|
||||
|
||||
const filePageMapping = model.actionMappings.find((mapping) => mapping.actionId === "file-page");
|
||||
assert.equal(filePageMapping.nativeCommand.includes("IconFileSelection1"), true);
|
||||
assert.equal(filePageMapping.gate.includes("native GTK file chooser"), true);
|
||||
|
||||
const macroPageMapping = model.actionMappings.find((mapping) => mapping.actionId === "macro-page");
|
||||
assert.equal(macroPageMapping.webAction, "GMOCAPY_RUN_MACRO");
|
||||
assert.equal(macroPageMapping.nativeCommand.includes("command.mdi"), true);
|
||||
assert.equal(macroPageMapping.gate.includes("same as RUN_MDI"), true);
|
||||
|
||||
const toolEditorPageMapping = model.actionMappings.find((mapping) => mapping.actionId === "tool-editor-page");
|
||||
assert.equal(toolEditorPageMapping.nativeCommand.includes("_show_tooledit_tab"), true);
|
||||
assert.equal(toolEditorPageMapping.gate.includes("writeback is disabled"), true);
|
||||
|
||||
const nativePageMapping = model.actionMappings.find((mapping) => mapping.actionId === "native-page-diagnostic");
|
||||
assert.equal(nativePageMapping.webAction, "GMOCAPY_NATIVE_PAGE");
|
||||
assert.equal(nativePageMapping.gate.includes("do not emit fake GTK"), true);
|
||||
|
||||
const summary = createGmoccapyCommunicationSummary(model);
|
||||
assert.equal(summary.apiName, "web-rtcp-5axis-gmoccapy-communication-model-summary");
|
||||
assert.equal(summary.profileId, "gmoccapy-xyzab");
|
||||
assert.equal(summary.nativePathCount, 6);
|
||||
assert.equal(summary.nativePathCount, 10);
|
||||
assert.equal(summary.startupStageCount, 9);
|
||||
assert.equal(summary.actionCount, 19);
|
||||
assert.equal(summary.actionCount, 26);
|
||||
assert.equal(summary.pagePathCount, 4);
|
||||
assert.equal(summary.postguiAfterHalcompReady, true);
|
||||
assert.equal(summary.hasNativeNmlCommandPath, true);
|
||||
assert.equal(summary.hasNativeHalPath, true);
|
||||
|
||||
@@ -25,6 +25,7 @@ for (const groupName of [
|
||||
"jog",
|
||||
"override",
|
||||
"operator-inputs",
|
||||
"settings",
|
||||
"tool",
|
||||
"program",
|
||||
"message",
|
||||
@@ -44,7 +45,11 @@ assert.equal(groups.get("override").pins.includes("gmoccapy.spindle.reset-spindl
|
||||
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);
|
||||
@@ -90,14 +95,32 @@ assert.equal(model.hardwareButtons.bottomMain.find((button) => button.index ===
|
||||
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, undefined);
|
||||
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);
|
||||
@@ -107,11 +130,13 @@ 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);
|
||||
@@ -124,6 +149,14 @@ assert.equal(model.halPinActions.messagePins.find((pin) => pin.pin === "gmoccapy
|
||||
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.<pinname>-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);
|
||||
@@ -139,8 +172,8 @@ 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, 8);
|
||||
assert.equal(summary.nativePinCount >= 50, true);
|
||||
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);
|
||||
@@ -152,16 +185,23 @@ assert.equal(summary.postguiToolUnlinkCount, 3);
|
||||
assert.equal(summary.commentedManualToolChangeNetCount, 3);
|
||||
assert.equal(summary.hardwareButtonVerticalCount, 7);
|
||||
assert.equal(summary.hardwareButtonBottomMainCount, 4);
|
||||
assert.equal(summary.mappedHardwareButtonCount, 7);
|
||||
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);
|
||||
@@ -172,6 +212,21 @@ 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");
|
||||
|
||||
@@ -215,7 +215,8 @@ assert.equal(hardButtonStore.getState().machine.allHomed, true);
|
||||
hardButtonStore.dispatch({ type: "GMOCAPY_HARDWARE_BUTTON", pin: "gmoccapy.v-button.button-4", value: true });
|
||||
assert.equal(hardButtonStore.getState().machine.mode, "auto");
|
||||
hardButtonStore.dispatch({ type: "GMOCAPY_HARDWARE_BUTTON", pin: "gmoccapy.v-button.button-6", value: true });
|
||||
assert.equal(hardButtonStore.getState().operatorMessage, "gmoccapy hardware button diagnostic-only: gmoccapy.v-button.button-6");
|
||||
assert.equal(hardButtonStore.getState().gmoccapyGui.activeNativePage, "setup");
|
||||
assert.equal(hardButtonStore.getState().operatorMessage, "gmoccapy native page diagnostic-only: setup");
|
||||
hardButtonStore.dispatch({ type: "GMOCAPY_HARDWARE_BUTTON", pin: "gmoccapy.h-button.button-9", value: true });
|
||||
assert.equal(hardButtonStore.getState().operatorMessage, "gmoccapy hardware button unmapped: gmoccapy.h-button.button-9");
|
||||
|
||||
@@ -231,6 +232,25 @@ assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL optional-stop
|
||||
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.blockdelete", value: true });
|
||||
assert.equal(halPinStore.getState().gmoccapyGui.optionalStop, true);
|
||||
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL blockdelete -> optional stop on");
|
||||
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.unlock-settings", value: false });
|
||||
assert.equal(halPinStore.getState().gmoccapyGui.settingsUnlockPin, false);
|
||||
assert.equal(halPinStore.getState().gmoccapyGui.setupSensitive, true);
|
||||
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL unlock-settings ignored: unlock_way is use");
|
||||
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.unlock-settings", value: false, halUnlockMode: true });
|
||||
assert.equal(halPinStore.getState().gmoccapyGui.settingsUnlockMode, "hal");
|
||||
assert.equal(halPinStore.getState().gmoccapyGui.setupSensitive, false);
|
||||
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL unlock-settings disabled setup");
|
||||
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.unlock-settings", value: true });
|
||||
assert.equal(halPinStore.getState().gmoccapyGui.settingsUnlockPin, true);
|
||||
assert.equal(halPinStore.getState().gmoccapyGui.setupSensitive, true);
|
||||
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL unlock-settings enabled setup");
|
||||
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.blockheight", value: 12.5 });
|
||||
assert.equal(halPinStore.getState().gmoccapyGui.blockHeight, 12.5);
|
||||
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL tool measurement output recorded; XYZAB has no [TOOLSENSOR]");
|
||||
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.toolmeasurement", value: true });
|
||||
assert.equal(halPinStore.getState().gmoccapyGui.toolMeasurement, true);
|
||||
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.messages.test", value: true });
|
||||
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL user message pin unmapped: gmoccapy_XYZAB.ini defines no MESSAGE_* entries");
|
||||
|
||||
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.feed.feed-override.counts", value: 12 });
|
||||
assert.equal(halPinStore.getState().feed.feedOverride, 100);
|
||||
@@ -312,4 +332,41 @@ halMessageStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.warning-confi
|
||||
assert.equal(halMessageStore.getState().gmoccapyGui.warningConfirm, false);
|
||||
assert.equal(halMessageStore.getState().operatorMessage, "gmoccapy HAL warning-confirm cleared");
|
||||
|
||||
const nativePageStore = createSimulationStore();
|
||||
nativePageStore.dispatch({ type: "SET_PROFILE", profileId: "gmoccapy-xyzab" });
|
||||
nativePageStore.dispatch({ type: "GMOCAPY_HARDWARE_BUTTON", pin: "gmoccapy.v-button.button-6", value: true });
|
||||
assert.equal(nativePageStore.getState().gmoccapyGui.activeNativePage, "setup");
|
||||
assert.equal(nativePageStore.getState().gmoccapyGui.nativePageMode, "diagnostic-only");
|
||||
assert.equal(nativePageStore.getState().operatorMessage, "gmoccapy native page diagnostic-only: setup");
|
||||
nativePageStore.dispatch({ type: "GMOCAPY_HARDWARE_BUTTON", pin: "gmoccapy.h-button.button-3", value: true });
|
||||
assert.equal(nativePageStore.getState().gmoccapyGui.activeNativePage, "tool-editor");
|
||||
assert.equal(nativePageStore.getState().operatorMessage, "gmoccapy native page diagnostic-only: tool-editor");
|
||||
nativePageStore.dispatch({ type: "GMOCAPY_PAGE_ACTION", pageId: "file-load", actionId: "open" });
|
||||
assert.equal(nativePageStore.getState().gmoccapyGui.filePageStatus, "open");
|
||||
assert.equal(nativePageStore.getState().operatorMessage.includes("native Gtk chooser diagnostic"), true);
|
||||
nativePageStore.dispatch({ type: "GMOCAPY_TOOL_EDITOR_ACTION", actionId: "save" });
|
||||
assert.equal(nativePageStore.getState().gmoccapyGui.toolEditorStatus, "writeback-blocked");
|
||||
assert.equal(nativePageStore.getState().operatorMessage.includes("does not write tool.tbl"), true);
|
||||
|
||||
const macroBlockedStore = createSimulationStore();
|
||||
macroBlockedStore.dispatch({ type: "SET_PROFILE", profileId: "gmoccapy-xyzab" });
|
||||
macroBlockedStore.dispatch({ type: "GMOCAPY_RUN_MACRO", name: "halo_world" });
|
||||
assert.equal(macroBlockedStore.getState().gmoccapyGui.macroLastName, "halo_world");
|
||||
assert.equal(macroBlockedStore.getState().operatorMessage.includes("gmoccapy macro blocked"), true);
|
||||
|
||||
const macroReadyStore = createSimulationStore();
|
||||
macroReadyStore.dispatch({ type: "SET_PROFILE", profileId: "gmoccapy-xyzab" });
|
||||
macroReadyStore.dispatch({ type: "TOGGLE_POWER" });
|
||||
macroReadyStore.dispatch({ type: "HOME" });
|
||||
macroReadyStore.dispatch({ type: "SET_MODE", mode: "mdi" });
|
||||
macroReadyStore.dispatch({
|
||||
type: "GMOCAPY_RUN_MACRO",
|
||||
name: "increment",
|
||||
args: { xinc: 1.25, yinc: 2.5 },
|
||||
});
|
||||
assert.equal(macroReadyStore.getState().gmoccapyGui.activeNativePage, "mdi-macros");
|
||||
assert.equal(macroReadyStore.getState().gmoccapyGui.macroLastCommand, "O<increment> call [1.25] [2.5]");
|
||||
assert.equal(macroReadyStore.getState().machine.mdiCommand, "O<INCREMENT> CALL [1.25] [2.5]");
|
||||
assert.equal(macroReadyStore.getState().operatorMessage, "gmoccapy macro MDI O<increment> call [1.25] [2.5]");
|
||||
|
||||
console.log("gmoccapy_xyzab_gates_smoke=ok");
|
||||
|
||||
@@ -62,12 +62,37 @@ assert.equal(profile.halPins.includes("gmoccapy.jog.turtle-jog"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.ignore-limits"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.optional-stop"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.blockdelete"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.unlock-settings"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.feed.feed-override.count-enable"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.feed.reset-feed-override"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.spindle.reset-spindle-override"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.jog.jog-velocity.direct-value"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.delete-message"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.warning-confirm"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.probeheight"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.blockheight"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.toolmeasurement"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.searchvel"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.probevel"), true);
|
||||
assert.equal(profile.halPins.includes("gmoccapy.toolchange-confirm"), true);
|
||||
assert.equal(profile.toolsensor.configured, false);
|
||||
assert.equal(profile.toolsensor.useToolMeasurementPref, false);
|
||||
assert.equal(profile.toolsensor.blockHeightPref, 0);
|
||||
assert.equal(profile.toolsensor.reason.includes("no [TOOLSENSOR]"), true);
|
||||
assert.equal(profile.userMessages.configured, false);
|
||||
assert.equal(profile.userMessages.count, 0);
|
||||
assert.equal(profile.userMessages.reason.includes("no [DISPLAY] MESSAGE_*"), true);
|
||||
assert.equal(profile.nativePages.filePage.configured, true);
|
||||
assert.equal(profile.nativePages.filePage.programPrefix, "../../nc_files/");
|
||||
assert.equal(profile.nativePages.filePage.webImplementation, "partial");
|
||||
assert.equal(profile.nativePages.macroPage.configured, true);
|
||||
assert.equal(profile.nativePages.macroPage.count, 5);
|
||||
assert.equal(profile.nativePages.macroPage.macros.find((macro) => macro.name === "increment").args.length, 2);
|
||||
assert.equal(profile.nativePages.macroPage.macros.find((macro) => macro.name === "go_to_position").command, "O<go_to_position> call [X-pos] [Y-pos] [Z-pos]");
|
||||
assert.equal(profile.nativePages.toolEditor.configured, true);
|
||||
assert.equal(profile.nativePages.toolEditor.writebackEnabled, false);
|
||||
assert.equal(profile.nativePages.toolEditor.toolCount, 17);
|
||||
assert.equal(profile.nativePages.implementationMatrixBoundary.includes("diagnostic-only"), true);
|
||||
assert.equal(profile.toolTable.toolCount, 17);
|
||||
assert.equal(profile.macros.includes("go_to_position X-pos Y-pos Z-pos"), true);
|
||||
assert.equal(profile.panelSchema.id, "gmoccapy-xyzab-hal-component");
|
||||
|
||||
@@ -205,3 +205,67 @@
|
||||
下一步是什么:
|
||||
|
||||
- 可继续核对 `gmoccapy.unlock-settings`、tool measurement/blockheight/probeheight、INI user messages 等更低频 HAL pins;本轮 W5-190 已完成。
|
||||
|
||||
## 2026-06-27 R7:细化 gmoccapy 设置解锁、测刀输出和 INI user message 边界
|
||||
|
||||
做了什么:
|
||||
|
||||
- 对照 `gmoccapy.py` 的 `_on_unlock_settings_changed()`、`_check_toolmeasurement()`、`on_chk_use_tool_measurement_toggled()`、`on_btn_block_height_clicked()`、`_init_user_messages()` 和 `_show_user_message()`,确认 `unlock-settings` 只在设置页选择 HAL unlock 时控制 `tbtn_setup` 敏感性;tool measurement 相关 pin 是 HAL_OUT;INI user messages 只在配置 `MESSAGE_*` 后动态创建 `messages.*` pins。
|
||||
- 对照 `gmoccapy_XYZAB.ini` 和 `gmoccapy_XYZAB.pref`,确认本配置没有 `[TOOLSENSOR]`、没有 `[DISPLAY] MESSAGE_*`,且默认 `unlock_way=use`、`use_toolmeasurement=False`、`blockheight=0.0`。
|
||||
- 在 `gmoccapy-xyzab` profile 中补齐 `gmoccapy.unlock-settings`、`gmoccapy.probeheight`、`gmoccapy.blockheight`、`gmoccapy.toolmeasurement`、`gmoccapy.searchvel`、`gmoccapy.probevel`、`gmoccapy.toolchange-number`、`gmoccapy.toolchange-confirm`,并记录 toolsensor/user messages 默认未配置原因。
|
||||
- 扩展 HAL model 和 communication model,记录 settings pin、tool measurement HAL_OUT pins、动态 user message pins、XYZAB no `[TOOLSENSOR]` 和 no `MESSAGE_*` 边界。
|
||||
- 扩展 `GMOCAPY_HAL_PIN`:模拟 `unlock-settings` 在默认 `unlock_way=use` 下忽略、在 HAL unlock 模式下按 level 控制 setup;tool measurement pins 作为诊断输出记录;`messages.*` 在当前 XYZAB 无配置时返回明确 operator message。
|
||||
- 在 gmoccapy UI 诊断中新增 `HAL settings` 和 `HAL tool/user` 行,并补充 Node/浏览器断言。
|
||||
|
||||
改了哪些文件:
|
||||
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/src/profiles/gmoccapy-xyzab.js`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/src/runtime/gmoccapy-communication-model.js`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/src/runtime/gmoccapy-hal-model.js`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/src/state/store.js`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/src/ui/gmoccapy-shell.js`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/tests/browser/gmoccapy_shell_smoke.html`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_communication_model.mjs`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_hal_model.mjs`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_xyzab_gates.mjs`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_xyzab_profile.mjs`
|
||||
- `/home/meswork/cnc_wams/work/working5/03-推进台账.md`
|
||||
- `/home/meswork/cnc_wams/work/working5/04-任务矩阵.md`
|
||||
- `/home/meswork/cnc_wams/work/working5/05-验收证据.md`
|
||||
- `/home/meswork/cnc_wams/work/working5/06-决策记录.md`
|
||||
|
||||
验证了什么:
|
||||
|
||||
- `node ../tests/node/verify_gmoccapy_hal_model.mjs && node ../tests/node/verify_gmoccapy_communication_model.mjs && node ../tests/node/verify_gmoccapy_xyzab_profile.mjs && node ../tests/node/verify_gmoccapy_xyzab_gates.mjs` 通过。
|
||||
- `bash ../tests/browser/verify_gmoccapy_shell_browser.sh` 通过。
|
||||
- `npm run smoke:node` 通过。
|
||||
- `npm run build && npm run smoke` 通过。
|
||||
- `git diff --check -- web-rtcp-5axis-sim-plan work/working5` 通过,无输出。
|
||||
|
||||
下一步是什么:
|
||||
|
||||
- W5-200 已完成。后续如继续深化,可转向 gmoccapy 文件/宏页面、tool editor 页面或 native GTK 未实现页面的诊断边界,但当前任务矩阵内 HAL 输入细化项已闭环。
|
||||
|
||||
## 2026-06-27 R8:working5 最终复核与验收收口
|
||||
|
||||
做了什么:
|
||||
|
||||
- 重新读取 `working5` README、功能内容、开发步骤、推进台账、任务矩阵、验收证据和决策记录,确认 W5-001 到 W5-900 均已闭环。
|
||||
- 核对当前工作区改动范围,确认源码和测试改动仍集中在 gmoccapy XYZAB profile、HAL/communication model、store、UI shell 和对应 Node/browser 验收。
|
||||
- 在当前工作区重新执行完整 Node 冒烟、静态构建和浏览器冒烟,确认历史记录对应的实现仍可通过。
|
||||
|
||||
改了哪些文件:
|
||||
|
||||
- `/home/meswork/cnc_wams/work/working5/03-推进台账.md`
|
||||
- `/home/meswork/cnc_wams/work/working5/05-验收证据.md`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md`
|
||||
|
||||
验证了什么:
|
||||
|
||||
- `npm run smoke:node` 通过,关键输出包含 `gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_communication_model_smoke=ok`、`gmoccapy_hal_model_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok`、`linear_unit_conversion_smoke=ok`。
|
||||
- `npm run build` 通过,输出 `gmoccapy_static_build=ok`。
|
||||
- `npm run smoke` 通过,输出 `gmoccapy_shell_smoke=ok`、`gmoccapy_dist_smoke=ok`。
|
||||
|
||||
下一步是什么:
|
||||
|
||||
- `working5` 已按当前任务矩阵完成并复核通过;本轮不新增后续实现任务。
|
||||
|
||||
@@ -17,4 +17,5 @@
|
||||
| W5-170 | 细化外部 HAL hard-button pin 与 UI action 映射 | 完成 | profile/panel schema、HAL model、communication model、store 和浏览器 DOM 均明确 `gmoccapy.v-button.button-0..6`、`gmoccapy.h-button.button-0` 等硬件按钮 pin 的 rising-edge、可见敏感按钮映射和 Web gate 行为;相关 Node、构建、浏览器 smoke 通过 |
|
||||
| W5-180 | 细化 ignore-limits、optional-stop、blockdelete 与 override HAL input pin 语义 | 完成 | profile、HAL model、communication model、store 和浏览器 UI 均明确 `gmoccapy.ignore-limits`、`gmoccapy.optional-stop`、`gmoccapy.blockdelete`、override counts/direct-value/reset pins 的 Web 映射;Node、构建、浏览器 smoke 通过 |
|
||||
| W5-190 | 细化 jog、jog-increment、delete-message、warning-confirm HAL input pin 语义 | 完成 | profile、HAL model、communication model、store 和浏览器 UI 均明确 `gmoccapy.jog.axis.*`、`gmoccapy.jog.jog-inc-*`、`gmoccapy.jog.turtle-jog`、`gmoccapy.delete-message`、`gmoccapy.warning-confirm` 的 Web 映射;Node、构建、浏览器 smoke 通过 |
|
||||
| W5-200 | 细化 unlock-settings、tool measurement 和 INI user messages 低频 HAL pin 边界 | 完成 | profile、HAL model、communication model、store 和浏览器 UI 均明确 `gmoccapy.unlock-settings`、`gmoccapy.probeheight/blockheight/toolmeasurement/searchvel/probevel`、动态 `gmoccapy.messages.*` pins 的源码边界和 XYZAB 默认未启用原因;Node、构建、浏览器 smoke 通过 |
|
||||
| W5-900 | 更新验收证据和决策记录 | 完成 | 命令、结果、修改原因和后续项已记录 |
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
| EV-W5-181 | W5-020/W5-030/W5-040/W5-180 | 命令 | `npm run smoke:node`、`npm run build && npm run smoke` | 通过,完整 Node、静态构建、浏览器 gmoccapy shell/dist smoke 均覆盖新增 HAL input/override 诊断和 Web 控件 |
|
||||
| EV-W5-190 | W5-150/W5-190 | 命令 | `node ../tests/node/verify_gmoccapy_hal_model.mjs && node ../tests/node/verify_gmoccapy_communication_model.mjs`、`node ../tests/node/verify_gmoccapy_xyzab_profile.mjs && node ../tests/node/verify_gmoccapy_xyzab_gates.mjs`、`bash ../tests/browser/verify_gmoccapy_shell_browser.sh` | 通过,验证 `GMOCAPY_HAL_PIN` 对 jog axis press/release、jog increment rising-edge、turtle jog、delete-message、warning-confirm pins 的映射和 UI 诊断 |
|
||||
| EV-W5-191 | W5-020/W5-030/W5-040/W5-190 | 命令 | `npm run smoke:node`、`npm run build && npm run smoke` | 通过,完整 Node、静态构建、浏览器 gmoccapy shell/dist smoke 均覆盖新增 jog/message HAL pin 诊断和 Web 行为 |
|
||||
| EV-W5-200 | W5-150/W5-200 | 命令 | `node ../tests/node/verify_gmoccapy_hal_model.mjs && node ../tests/node/verify_gmoccapy_communication_model.mjs && node ../tests/node/verify_gmoccapy_xyzab_profile.mjs && node ../tests/node/verify_gmoccapy_xyzab_gates.mjs`、`bash ../tests/browser/verify_gmoccapy_shell_browser.sh` | 通过,验证 `gmoccapy.unlock-settings`、tool measurement HAL_OUT pins、动态 `messages.*` pin 边界和 UI 诊断 |
|
||||
| EV-W5-201 | W5-020/W5-030/W5-040/W5-200 | 命令 | `npm run smoke:node`、`npm run build && npm run smoke` | 通过,完整 Node、静态构建、浏览器 gmoccapy shell/dist smoke 均覆盖新增 settings/tool/user-message 低频 HAL pin 诊断和 Web 行为 |
|
||||
| EV-W5-900 | W5-900 | 命令 | `npm run smoke:node`、`npm run build`、`npm run smoke` | 通过,最终复核确认 working5 当前任务矩阵闭环,Node、静态构建、浏览器冒烟均在当前工作区通过 |
|
||||
|
||||
## 命令记录
|
||||
|
||||
@@ -297,6 +300,119 @@ npm run build && npm run smoke
|
||||
- `data-gmoccapy-hal="message-inputs"` 必须包含 `3 message pins`、`delete-message rising-edge-only`、`warning-confirm level-polled`。
|
||||
- 通过 `window.webRtcp5AxisSimulation.dispatch({ type: "GMOCAPY_HAL_PIN", ... })` 验证浏览器内 jog increment、axis jog press/release、turtle jog、delete-message 和 warning-confirm 状态。
|
||||
|
||||
### 2026-06-27 R7
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
node ../tests/node/verify_gmoccapy_hal_model.mjs && node ../tests/node/verify_gmoccapy_communication_model.mjs && node ../tests/node/verify_gmoccapy_xyzab_profile.mjs && node ../tests/node/verify_gmoccapy_xyzab_gates.mjs
|
||||
```
|
||||
|
||||
结果:通过,输出:
|
||||
|
||||
- `gmoccapy_hal_model_smoke=ok`
|
||||
- `gmoccapy_communication_model_smoke=ok`
|
||||
- `gmoccapy_xyzab_profile_smoke=ok`
|
||||
- `gmoccapy_xyzab_gates_smoke=ok`
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
bash ../tests/browser/verify_gmoccapy_shell_browser.sh
|
||||
```
|
||||
|
||||
结果:通过,输出:
|
||||
|
||||
- `gmoccapy_shell_smoke=ok`
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run smoke:node
|
||||
```
|
||||
|
||||
结果:通过。
|
||||
|
||||
关键输出摘要:
|
||||
|
||||
- `gmoccapy_xyzab_profile_smoke=ok`
|
||||
- `gmoccapy_communication_model_smoke=ok`
|
||||
- `gmoccapy_hal_model_smoke=ok`
|
||||
- `gmoccapy_xyzab_gates_smoke=ok`
|
||||
- `linear_unit_conversion_smoke=ok`
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run build && npm run smoke
|
||||
```
|
||||
|
||||
结果:通过,输出:
|
||||
|
||||
- `gmoccapy_static_build=ok`
|
||||
- `gmoccapy_shell_smoke=ok`
|
||||
- `gmoccapy_dist_smoke=ok`
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams
|
||||
git diff --check -- web-rtcp-5axis-sim-plan work/working5
|
||||
```
|
||||
|
||||
结果:通过,无输出。
|
||||
|
||||
本轮新增 Node 断言:
|
||||
|
||||
- `gmoccapy.unlock-settings` 是 settings pin;默认 `unlock_way=use` 时只记录 pin level,不锁定 setup;显式 HAL unlock 模式下按 level 控制 setup sensitive。
|
||||
- `gmoccapy.probeheight`、`gmoccapy.blockheight`、`gmoccapy.toolmeasurement`、`gmoccapy.searchvel`、`gmoccapy.probevel` 记录为 HAL_OUT tool measurement pins。
|
||||
- `gmoccapy_XYZAB.ini` 无 `[TOOLSENSOR]`,所以 auto tool measurement 默认禁用;`gmoccapy_XYZAB.pref` 默认 `use_toolmeasurement=False`、`blockheight=0.0`。
|
||||
- `gmoccapy_XYZAB.ini` 无 `[DISPLAY] MESSAGE_*`,所以动态 `gmoccapy.messages.*` pins 不创建;Web 对 `messages.*` dispatch 返回明确 operator message。
|
||||
|
||||
本轮新增浏览器断言:
|
||||
|
||||
- `data-gmoccapy-hal="settings-inputs"` 必须包含 `1 settings pins`、`unlock-settings level-driven`、`unlock-way use`、`setup sensitive`。
|
||||
- `data-gmoccapy-hal="tool-user-inputs"` 必须包含 `5 tool measurement HAL_OUT pins`、`XYZAB no TOOLSENSOR`、`0 user message pins`、`no MESSAGE_*`。
|
||||
- 通过 `window.webRtcp5AxisSimulation.dispatch({ type: "GMOCAPY_HAL_PIN", ... })` 验证浏览器内 `unlock-settings` 默认忽略和 HAL unlock level 行为、`blockheight` 诊断记录、`messages.*` 无配置提示。
|
||||
|
||||
### 2026-06-27 R8
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run smoke:node
|
||||
```
|
||||
|
||||
结果:通过。
|
||||
|
||||
关键输出摘要:
|
||||
|
||||
- `linuxcnc_kinematics_runtime_smoke=ok`
|
||||
- `linuxcnc_interpreter_runtime_smoke=ok`
|
||||
- `linuxcnc_ini_runtime_smoke=ok`
|
||||
- `linuxcnc_task_hal_runtime_smoke=ok`
|
||||
- `real_linuxcnc_5axis_program_cases_smoke=ok`
|
||||
- `gmoccapy_xyzab_profile_smoke=ok`
|
||||
- `gmoccapy_communication_model_smoke=ok`
|
||||
- `gmoccapy_hal_model_smoke=ok`
|
||||
- `gmoccapy_xyzab_gates_smoke=ok`
|
||||
- `linear_unit_conversion_smoke=ok`
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run build
|
||||
```
|
||||
|
||||
结果:通过,输出 `gmoccapy_static_build=ok`。
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run smoke
|
||||
```
|
||||
|
||||
结果:通过,输出:
|
||||
|
||||
- `gmoccapy_shell_smoke=ok`
|
||||
- `gmoccapy_dist_smoke=ok`
|
||||
|
||||
本轮复核结论:
|
||||
|
||||
- `04-任务矩阵.md` 中 W5-001 到 W5-900 均为完成。
|
||||
- 当前源码、测试和文档状态可通过完整 Node、构建和浏览器冒烟验收。
|
||||
|
||||
## 页面/截图/report/job 记录
|
||||
|
||||
本轮未生成截图、PDF、job_id 或 report_id。浏览器验收由 headless Chromium smoke 脚本完成。
|
||||
|
||||
@@ -136,3 +136,28 @@
|
||||
- `GMOCAPY_HAL_PIN` 现在覆盖 jog axis press/release、jog increment selection、turtle jog、delete-message 和 warning-confirm。
|
||||
- HAL model 和 communication model 现在能分别呈现 hard-button、operator/override input、jog input、message input 的不同语义。
|
||||
- UI 诊断增加 `HAL jog` 和 `HAL messages`,浏览器 smoke 通过 DOM 和公开 dispatch 验证这些语义。
|
||||
|
||||
## DR-W5-007:低频 settings/tool/user-message HAL pins 按配置启用边界建模
|
||||
|
||||
日期:2026-06-27
|
||||
|
||||
决策:
|
||||
|
||||
- `gmoccapy.unlock-settings` 作为 level-driven settings input pin 记录;默认 `gmoccapy_XYZAB.pref` 为 `unlock_way=use`,所以 Web 中默认只记录 pin level,不把 setup 锁定或解锁。
|
||||
- 当测试显式模拟 HAL unlock 模式时,`unlock-settings` 才按 pin level 控制 `setupSensitive`,对应源码 `_on_unlock_settings_changed()` 对 `rbt_hal_unlock` 的条件判断。
|
||||
- `gmoccapy.probeheight`、`gmoccapy.blockheight`、`gmoccapy.toolmeasurement`、`gmoccapy.searchvel`、`gmoccapy.probevel` 作为 tool measurement HAL_OUT pins 记录,不伪装成外部 HAL 输入。
|
||||
- 当前 `gmoccapy_XYZAB.ini` 没有 `[TOOLSENSOR]`,所以 profile、HAL model 和 UI 诊断明确自动测刀默认禁用,而不是暴露为可操作流程。
|
||||
- 动态 `gmoccapy.messages.*` pins 只在 INI 存在 `MESSAGE_*` 配置时创建;当前 XYZAB 没有这些配置,所以 Web 对 `messages.*` dispatch 返回“未配置”的明确 operator message。
|
||||
|
||||
原因:
|
||||
|
||||
- `gmoccapy.py` 中 `_on_unlock_settings_changed()` 会先检查初始化状态,再检查 `rbt_hal_unlock` 或 user mode;未选择 HAL unlock 时 pin 变化不应改变 setup 页面可用性。
|
||||
- `_check_toolmeasurement()` 需要有效 `[TOOLSENSOR]` 数据;缺少探针配置时会显示禁用提示、关闭 `chk_use_tool_measurement` 并使其不敏感。
|
||||
- `on_chk_use_tool_measurement_toggled()`、`on_spbtn_probe_height_value_changed()`、`on_btn_block_height_clicked()` 都是 GUI/prefs 侧写 HAL_OUT pins,不是外部 HAL 驱动 GUI 的输入边界。
|
||||
- `_init_user_messages()` 只有从 INI 读到 user messages 才创建 `messages.<pinname>`、`messages.<pinname>-waiting`、`messages.<pinname>-response`;当前 `gmoccapy_XYZAB.ini` 没有 `MESSAGE_*` 项。
|
||||
|
||||
影响:
|
||||
|
||||
- `gmoccapy-xyzab` profile 补齐 settings/tool measurement/toolchange confirm 相关 pins,并记录 no `[TOOLSENSOR]` 与 no `MESSAGE_*` 原因。
|
||||
- HAL model 和 communication model 能展示 settings input、tool measurement HAL_OUT、dynamic user message 三类不同边界。
|
||||
- Store 和浏览器 smoke 覆盖 `unlock-settings` 默认忽略、HAL unlock level 控制、`blockheight` 诊断记录和 `messages.*` 未配置提示。
|
||||
|
||||
64
work/working6/01-项目功能内容.md
Normal file
64
work/working6/01-项目功能内容.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# 01-项目功能内容
|
||||
|
||||
## 目标
|
||||
|
||||
在 `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan` 中补齐 gmoccapy 文件/宏页面、tool editor 页面、native GTK 未实现页面的诊断边界,让 Web 仿真能够明确表达哪些 gmoccapy 原生页面已经实现、哪些只做诊断映射、哪些因 XYZAB 配置或 Web 仿真边界暂不执行。
|
||||
|
||||
本轮不重复 working5 已完成的 HAL 输入、hard-button、模式门控、换刀回环和低频 HAL pin 工作;本轮聚焦页面级功能边界和可验收诊断。
|
||||
|
||||
## 对标范围
|
||||
|
||||
### gmoccapy 文件页面
|
||||
|
||||
- 对照 `gmoccapy.py` 和 `gmoccapy.glade` 中程序文件加载、最近文件、文件选择器、程序预览和自动运行入口。
|
||||
- 对照 `[DISPLAY] PROGRAM_PREFIX`、默认 NC 文件路径、文件过滤规则和最近文件行为。
|
||||
- Web 侧需要明确:
|
||||
- 当前可加载的演示/机床程序来源。
|
||||
- 文件选择、打开、关闭、最近文件、预览、运行之间的状态边界。
|
||||
- 与 Auto 模式、全轴回零、解释器 idle、运行中禁止切换文件等互锁关系。
|
||||
- 未实现的 native GTK file chooser 行为需要诊断说明,不伪装成完整桌面文件管理器。
|
||||
|
||||
### gmoccapy 宏页面
|
||||
|
||||
- 对照 gmoccapy 原生宏按钮、INI 中 macro 配置、MDI 命令发送路径和敏感状态。
|
||||
- Web 侧需要明确:
|
||||
- 当前 XYZAB 配置是否存在可用宏。
|
||||
- 宏按钮如何映射到 MDI 命令或诊断行。
|
||||
- 未回零、未上电、运行中、解释器非 idle 时宏执行的门控原因。
|
||||
- 未配置宏时应显示明确边界,而不是空白或误导性成功状态。
|
||||
|
||||
### tool editor 页面
|
||||
|
||||
- 对照 gmoccapy tool editor、LinuxCNC tool table、`M6`/`M61`、刀具号、刀补、手动换刀回环的状态显示。
|
||||
- Web 侧需要明确:
|
||||
- 当前 tool table 来源、读取状态、活动刀具、准备刀具、刀补显示。
|
||||
- 可编辑字段与只读诊断字段的边界。
|
||||
- Web 仿真是否允许直接写 tool table;若暂不写文件,需要显示只读/诊断原因。
|
||||
- 与 working5 中 `iocontrol-loopback` 换刀语义保持一致,不重新引入 gmoccapy 手动换刀弹窗。
|
||||
|
||||
### native GTK 未实现页面诊断边界
|
||||
|
||||
- 对照 `gmoccapy.glade` 中原生 notebooks、side buttons、bottom buttons 和 setup/user tabs/tool/touch 等页面。
|
||||
- Web 侧需要明确:
|
||||
- 已实现页面、部分实现页面、诊断-only 页面和未实现页面清单。
|
||||
- hard-button pin 对未实现 native 页面按钮的行为:只能诊断、不能伪装成真实页面动作。
|
||||
- 每个未实现页面的原因、风险和未来补齐入口。
|
||||
- 浏览器 UI 中提供可测试的 `data-*` 诊断节点,便于 smoke 脚本验收。
|
||||
|
||||
## 当前项目入口
|
||||
|
||||
- Web 应用:`/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app`
|
||||
- gmoccapy profile:`app/src/profiles/gmoccapy-xyzab.js`
|
||||
- gmoccapy HAL model:`app/src/runtime/gmoccapy-hal-model.js`
|
||||
- gmoccapy communication model:`app/src/runtime/gmoccapy-communication-model.js`
|
||||
- 状态存储:`app/src/state/store.js`
|
||||
- gmoccapy UI shell:`app/src/ui/gmoccapy-shell.js`
|
||||
- Node 验证:`tests/node`
|
||||
- 浏览器验证:`tests/browser`
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不在本轮实现完整桌面 GTK 文件选择器。
|
||||
- 不在本轮引入真实 LinuxCNC 外部进程、真实 HAL pin 写入或真实 tool table 持久化,除非后续任务矩阵明确升级。
|
||||
- 不回退 working5 已完成的 `GMOCAPY_HAL_PIN`、`GMOCAPY_HARDWARE_BUTTON` 和 gmoccapy XYZAB profile 行为。
|
||||
- 不把未实现 native 页面包装成可操作成功路径;必须明确诊断边界。
|
||||
87
work/working6/02-项目程序开发详细步骤.md
Normal file
87
work/working6/02-项目程序开发详细步骤.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# 02-项目程序开发详细步骤
|
||||
|
||||
## 步骤 1:建立工作控制文件
|
||||
|
||||
- 创建 README、功能内容、开发步骤、推进台账、任务矩阵、验收证据、决策记录。
|
||||
- 将 working5 后续深化方向拆分为文件/宏页面、tool editor 页面、native GTK 未实现页面诊断边界三条主线。
|
||||
|
||||
## 步骤 2:读取基准与现有实现
|
||||
|
||||
- 读取 `work/working5` 的任务矩阵、决策记录和验收证据,确认不可回退的既有行为。
|
||||
- 读取 `work/working3/gmoccapy_XYZAB_execution_analysis.md`。
|
||||
- 读取 LinuxCNC gmoccapy 源码和 Glade 文件:
|
||||
- `linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.py`
|
||||
- `linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.glade`
|
||||
- `linuxcnc/src/emc/usr_intf/gmoccapy/dialogs.py`
|
||||
- 读取 Web 项目 profile、runtime、state、UI shell 和 tests。
|
||||
|
||||
## 步骤 3:建立页面/按钮/状态映射
|
||||
|
||||
- 梳理 native gmoccapy notebook 页面和 Web gmoccapy shell 当前页面。
|
||||
- 建立文件页面映射:
|
||||
- native file chooser、program preview、recent files、program run action。
|
||||
- Web program source、preview、load/run/reset 状态。
|
||||
- 建立宏页面映射:
|
||||
- INI macro 配置、宏按钮、MDI command、执行 gate。
|
||||
- XYZAB 未配置宏时的诊断边界。
|
||||
- 建立 tool editor 映射:
|
||||
- tool table、active/prepared tool、offset、M6/M61 状态。
|
||||
- 只读诊断与可编辑字段边界。
|
||||
- 建立未实现 native 页面清单:
|
||||
- setup/user tabs/tool/touch 等按钮和页面。
|
||||
- hard-button pin 与诊断-only action 的映射。
|
||||
|
||||
## 步骤 4:执行现有测试
|
||||
|
||||
- 在 `app` 下运行 `npm run smoke:node`。
|
||||
- 运行构建:`npm run build`。
|
||||
- 运行浏览器冒烟:`npm run smoke`。
|
||||
- 如测试失败,先判断是环境问题、既有改动问题还是本轮新增行为问题。
|
||||
|
||||
## 步骤 5:补充模型和状态
|
||||
|
||||
- 在 profile 或 runtime model 中补充 gmoccapy 页面级 schema:
|
||||
- file page capability。
|
||||
- macro page capability。
|
||||
- tool editor capability。
|
||||
- native GTK page implementation matrix。
|
||||
- 在 store 中补充必要 action 或诊断状态:
|
||||
- 文件页面的 load/recent/preview gate。
|
||||
- 宏执行的 MDI gate 或未配置提示。
|
||||
- tool editor 的只读诊断状态。
|
||||
- native 未实现页面的 operator message。
|
||||
- 保持 action 命名和 existing gate 风格一致,避免绕过 LinuxCNC task policy。
|
||||
|
||||
## 步骤 6:补充 UI 诊断
|
||||
|
||||
- 在 gmoccapy shell 中增加可测试的诊断行或页面区块。
|
||||
- 所有新增诊断必须带稳定 `data-*` 属性。
|
||||
- 未实现页面必须显示“诊断-only/未实现/配置未启用”的明确状态。
|
||||
- 文件/宏/tool editor 控件不得在不满足 gate 时显示为可执行。
|
||||
|
||||
## 步骤 7:补充测试
|
||||
|
||||
- Node 测试:
|
||||
- profile 页面 schema 测试。
|
||||
- communication model 页面路径测试。
|
||||
- store gate 和 operator message 测试。
|
||||
- Browser 测试:
|
||||
- DOM 诊断行存在。
|
||||
- `data-*` 内容包含关键边界词。
|
||||
- 公开 dispatch 或按钮点击能触发预期状态和 gate。
|
||||
- 如改动 UI,运行 `npm run build && npm run smoke`。
|
||||
|
||||
## 步骤 8:回归验收
|
||||
|
||||
- 运行本轮相关最小测试。
|
||||
- 运行完整 `npm run smoke:node`。
|
||||
- 运行 `npm run build`。
|
||||
- 运行 `npm run smoke`。
|
||||
- 运行 `git diff --check -- web-rtcp-5axis-sim-plan work/working6`。
|
||||
|
||||
## 步骤 9:更新台账和证据
|
||||
|
||||
- 更新 `03-推进台账.md`。
|
||||
- 更新 `04-任务矩阵.md` 中任务状态。
|
||||
- 更新 `05-验收证据.md` 中命令、页面、截图、报告或输出摘要。
|
||||
- 如涉及架构、对标边界或兼容性取舍,更新 `06-决策记录.md`。
|
||||
94
work/working6/03-推进台账.md
Normal file
94
work/working6/03-推进台账.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# 03-推进台账
|
||||
|
||||
## 2026-06-27 R1:创建 working6 控制文件
|
||||
|
||||
做了什么:
|
||||
|
||||
- 创建 `working6` 工作目录。
|
||||
- 建立 README、功能内容、开发步骤、推进台账、任务矩阵、验收证据和决策记录。
|
||||
- 将 working5 的可选深化方向拆分为 gmoccapy 文件/宏页面、tool editor 页面、native GTK 未实现页面诊断边界三条主线。
|
||||
|
||||
改了哪些文件:
|
||||
|
||||
- `/home/meswork/cnc_wams/work/working6/README.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/01-项目功能内容.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/02-项目程序开发详细步骤.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/03-推进台账.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/04-任务矩阵.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/05-验收证据.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/06-决策记录.md`
|
||||
|
||||
验证了什么:
|
||||
|
||||
- 待执行现有 Node、构建和浏览器冒烟测试。
|
||||
- 待读取 gmoccapy 源码、Glade、INI 和当前 Web 实现后开始 W6-010。
|
||||
|
||||
下一步是什么:
|
||||
|
||||
- 按 `04-任务矩阵.md` 从 W6-010 开始,先建立 native gmoccapy 页面到 Web 模块的映射,再执行基线测试。
|
||||
|
||||
## 2026-06-27 R2:实现 gmoccapy 页面级诊断边界
|
||||
|
||||
做了什么:
|
||||
|
||||
- 对照 LinuxCNC `gmoccapy.py`、`gmoccapy.glade` 和 `gmoccapy_XYZAB.ini`,确认文件页使用 `IconFileSelection1`,宏页来自 `[MACROS]` 的 5 个 O-word MDI 宏,tool editor 读取 `tool.tbl` 并可在原生 GTK 中 add/delete/reload/save/change tool。
|
||||
- 在 Web profile、HAL model 和 communication model 中增加页面级 schema:file page、macro page、tool editor page、native GTK implementation matrix。
|
||||
- 在 store 中增加 `GMOCAPY_NATIVE_PAGE`、`GMOCAPY_PAGE_ACTION`、`GMOCAPY_RUN_MACRO`、`GMOCAPY_TOOL_EDITOR_ACTION`,用于表达 native 页面诊断、文件页边界、宏 MDI gate 和 tool editor 只读/写回阻塞。
|
||||
- 在 gmoccapy UI 诊断中新增 `data-gmoccapy-page="file"`、`macros`、`tool-editor`、`matrix` 四类稳定 DOM 证据。
|
||||
- 修正 hard-button 对 `tbtn_user_tabs`、`tbtn_setup`、`btn_touch`、`btn_tool`、`tbtn_switch_mode` 的 Web 行为:进入结构化 diagnostic-only 页面诊断,不再伪装为普通 Web Jog 或已实现工具页。
|
||||
|
||||
改了哪些文件:
|
||||
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/src/profiles/gmoccapy-xyzab.js`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/src/runtime/gmoccapy-communication-model.js`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/src/runtime/gmoccapy-hal-model.js`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/src/state/store.js`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app/src/ui/gmoccapy-shell.js`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/tests/browser/gmoccapy_shell_smoke.html`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_communication_model.mjs`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_hal_model.mjs`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_xyzab_gates.mjs`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/tests/node/verify_gmoccapy_xyzab_profile.mjs`
|
||||
- `/home/meswork/cnc_wams/work/working6/03-推进台账.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/04-任务矩阵.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/05-验收证据.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/06-决策记录.md`
|
||||
|
||||
验证了什么:
|
||||
|
||||
- 基线和回归 `npm run smoke:node` 均通过。
|
||||
- 基线和回归 `npm run build` 均通过。
|
||||
- 基线和回归 `npm run smoke` 均通过。
|
||||
- 新增最小测试 `node ../tests/node/verify_gmoccapy_hal_model.mjs && node ../tests/node/verify_gmoccapy_communication_model.mjs` 通过。
|
||||
- 新增最小测试 `node ../tests/node/verify_gmoccapy_xyzab_profile.mjs && node ../tests/node/verify_gmoccapy_xyzab_gates.mjs` 通过。
|
||||
- `bash ../tests/browser/verify_gmoccapy_shell_browser.sh` 通过。
|
||||
|
||||
下一步是什么:
|
||||
|
||||
- 当前 W6-010 到 W6-160、W6-900 已完成。后续如继续深化,可新增 working7 或扩展 W6 任务,转向真实文件浏览器交互、宏参数输入 UI、tool table 安全写回等可执行能力。
|
||||
|
||||
## 2026-06-27 R3:接续复核 working6 完成状态
|
||||
|
||||
做了什么:
|
||||
|
||||
- 接续上一轮后,重新读取 `work/working6` 的 README、任务矩阵、推进台账、验收证据、功能内容、开发步骤和决策记录。
|
||||
- 复核实际代码差异,确认 profile、HAL model、communication model、store、gmoccapy UI shell 和 Node/browser tests 已覆盖 W6 文件页、宏页、tool editor 页和 native GTK 页面诊断边界。
|
||||
- 复核 hard-button 对 `setup`、`user-tabs`、`touch-off`、`tool-editor`、`switchkins-mode` 的行为已进入 `GMOCAPY_NATIVE_PAGE` 结构化诊断,不再伪装为已实现页面。
|
||||
- 执行最终完整回归和空白检查。
|
||||
|
||||
改了哪些文件:
|
||||
|
||||
- `/home/meswork/cnc_wams/work/working6/03-推进台账.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/05-验收证据.md`
|
||||
- `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/gptlog-process/gpdlog.md`
|
||||
|
||||
验证了什么:
|
||||
|
||||
- `npm run smoke:node` 通过,包含 `gmoccapy_xyzab_profile_smoke=ok`、`gmoccapy_communication_model_smoke=ok`、`gmoccapy_hal_model_smoke=ok`、`gmoccapy_xyzab_gates_smoke=ok`。
|
||||
- `npm run build` 通过,输出 `gmoccapy_static_build=ok`。
|
||||
- `npm run smoke` 通过,输出 `gmoccapy_shell_smoke=ok`、`gmoccapy_dist_smoke=ok`。
|
||||
- `git diff --check -- web-rtcp-5axis-sim-plan work/working6` 通过,无输出。
|
||||
|
||||
下一步是什么:
|
||||
|
||||
- `working6` 当前任务闭环。后续若继续深化,建议新建 `working7`,聚焦真实文件浏览交互、宏参数输入 UI 或 tool table 安全写回的设计与实现。
|
||||
17
work/working6/04-任务矩阵.md
Normal file
17
work/working6/04-任务矩阵.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# 04-任务矩阵
|
||||
|
||||
| 任务编号 | 任务 | 状态 | 验收标准 |
|
||||
| --- | --- | --- | --- |
|
||||
| W6-001 | 创建 working6 工作控制文件 | 完成 | README 和 01-06 文件存在,内容可指导后续推进 |
|
||||
| W6-010 | 建立 gmoccapy native 页面到 Web 模块映射 | 完成 | 文件/宏/tool editor/native 未实现页面已映射到 profile、communication model、store、UI shell 和 tests |
|
||||
| W6-020 | 执行当前 Node 冒烟基线 | 完成 | `npm run smoke:node` 通过 |
|
||||
| W6-030 | 执行当前构建基线 | 完成 | `npm run build` 通过 |
|
||||
| W6-040 | 执行当前浏览器冒烟基线 | 完成 | `npm run smoke` 通过 |
|
||||
| W6-100 | 细化 gmoccapy 文件页面诊断边界 | 完成 | profile/model/store/UI 明确文件选择、最近文件、预览、加载、运行 gate 和 native file chooser 边界;Node/browser 测试通过 |
|
||||
| W6-110 | 细化 gmoccapy 宏页面诊断边界 | 完成 | 明确 XYZAB 5 个宏配置、宏按钮到 MDI 的 gate、运行中/未上电拦截;Node/browser 测试通过 |
|
||||
| W6-120 | 细化 tool editor 页面诊断边界 | 完成 | 明确 tool table 来源、active/prepared tool、offset、只读/可编辑边界、与 iocontrol-loopback 换刀语义一致;Node/browser 测试通过 |
|
||||
| W6-130 | 建立 native GTK 未实现页面 implementation matrix | 完成 | 已实现、部分实现、diagnostic-only、native-only 页面清单可在 model/UI 中稳定读取;浏览器 DOM 有 `data-*` 诊断 |
|
||||
| W6-140 | 细化 hard-button 对未实现 native 页面按钮的行为 | 完成 | `tbtn_setup`、user tabs、tool/touch 等未实现按钮只触发 `GMOCAPY_NATIVE_PAGE` 诊断,不伪装成已实现页面;store/browser 测试通过 |
|
||||
| W6-150 | 汇总 gmoccapy 页面级通信模型 | 完成 | communication model 展示 file/macro/tool/native page 的命令、状态、错误/诊断路径;Node 测试通过 |
|
||||
| W6-160 | 增加浏览器 UI 诊断验收 | 完成 | gmoccapy shell smoke 验证 file/macro/tool/native diagnostic rows、关键 `data-*` 属性和 gate 文案 |
|
||||
| W6-900 | 更新验收证据和决策记录 | 完成 | 命令、结果、修改原因、边界判断和后续项已记录 |
|
||||
186
work/working6/05-验收证据.md
Normal file
186
work/working6/05-验收证据.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# 05-验收证据
|
||||
|
||||
## 证据索引
|
||||
|
||||
| 证据编号 | 任务编号 | 类型 | 命令/页面/文件 | 结果 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| EV-W6-001 | W6-001 | 文件 | `/home/meswork/cnc_wams/work/working6` | 已创建 README 和 01-06 工作控制文件 |
|
||||
| EV-W6-020 | W6-020/W6-030/W6-040 | 命令 | `npm run smoke:node`、`npm run build`、`npm run smoke` | 基线通过,确认实现前项目当前态可运行 |
|
||||
| EV-W6-100 | W6-010/W6-100/W6-110/W6-120/W6-130/W6-140/W6-150 | 命令 | `node ../tests/node/verify_gmoccapy_hal_model.mjs && node ../tests/node/verify_gmoccapy_communication_model.mjs`、`node ../tests/node/verify_gmoccapy_xyzab_profile.mjs && node ../tests/node/verify_gmoccapy_xyzab_gates.mjs` | 通过,验证页面级模型、profile、communication model、store gate 和 diagnostic-only hard-button 行为 |
|
||||
| EV-W6-160 | W6-160 | 页面/命令 | `bash ../tests/browser/verify_gmoccapy_shell_browser.sh` | 通过,验证 `data-gmoccapy-page="file/macros/tool-editor/matrix"` 诊断行和公开 dispatch 页面行为 |
|
||||
| EV-W6-900 | W6-020/W6-030/W6-040/W6-900 | 命令 | `npm run smoke:node`、`npm run build`、`npm run smoke` | 回归通过,完整 Node、静态构建、浏览器 shell/dist smoke 均通过 |
|
||||
| EV-W6-901 | W6-900 | 命令 | `npm run smoke:node`、`npm run build`、`npm run smoke`、`git diff --check -- web-rtcp-5axis-sim-plan work/working6` | 接续复核通过,确认 working6 当前任务闭环且无空白错误 |
|
||||
|
||||
## 命令记录
|
||||
|
||||
### 2026-06-27 R1
|
||||
|
||||
```bash
|
||||
test -d /home/meswork/cnc_wams/work/working6 && find /home/meswork/cnc_wams/work/working6 -maxdepth 2 -type f | sort || true
|
||||
```
|
||||
|
||||
结果:创建前无可见文件。
|
||||
|
||||
```bash
|
||||
mkdir -p /home/meswork/cnc_wams/work/working6
|
||||
```
|
||||
|
||||
结果:通过,创建工作目录。
|
||||
|
||||
本轮创建文件:
|
||||
|
||||
- `/home/meswork/cnc_wams/work/working6/README.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/01-项目功能内容.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/02-项目程序开发详细步骤.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/03-推进台账.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/04-任务矩阵.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/05-验收证据.md`
|
||||
- `/home/meswork/cnc_wams/work/working6/06-决策记录.md`
|
||||
|
||||
### 2026-06-27 R2
|
||||
|
||||
基线命令:
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run smoke:node
|
||||
```
|
||||
|
||||
结果:通过。关键输出包含:
|
||||
|
||||
- `gmoccapy_xyzab_profile_smoke=ok`
|
||||
- `gmoccapy_communication_model_smoke=ok`
|
||||
- `gmoccapy_hal_model_smoke=ok`
|
||||
- `gmoccapy_xyzab_gates_smoke=ok`
|
||||
- `linear_unit_conversion_smoke=ok`
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run build
|
||||
```
|
||||
|
||||
结果:通过,输出 `gmoccapy_static_build=ok`。
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run smoke
|
||||
```
|
||||
|
||||
结果:通过,输出:
|
||||
|
||||
- `gmoccapy_shell_smoke=ok`
|
||||
- `gmoccapy_dist_smoke=ok`
|
||||
|
||||
新增最小验收:
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
node ../tests/node/verify_gmoccapy_hal_model.mjs && node ../tests/node/verify_gmoccapy_communication_model.mjs
|
||||
```
|
||||
|
||||
结果:通过,输出:
|
||||
|
||||
- `gmoccapy_hal_model_smoke=ok`
|
||||
- `gmoccapy_communication_model_smoke=ok`
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
node ../tests/node/verify_gmoccapy_xyzab_profile.mjs && node ../tests/node/verify_gmoccapy_xyzab_gates.mjs
|
||||
```
|
||||
|
||||
结果:通过,输出:
|
||||
|
||||
- `gmoccapy_xyzab_profile_smoke=ok`
|
||||
- `gmoccapy_xyzab_gates_smoke=ok`
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
bash ../tests/browser/verify_gmoccapy_shell_browser.sh
|
||||
```
|
||||
|
||||
结果:通过,输出 `gmoccapy_shell_smoke=ok`。
|
||||
|
||||
回归命令:
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run smoke:node
|
||||
```
|
||||
|
||||
结果:通过。
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run build
|
||||
```
|
||||
|
||||
结果:通过,输出 `gmoccapy_static_build=ok`。
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run smoke
|
||||
```
|
||||
|
||||
结果:通过,输出:
|
||||
|
||||
- `gmoccapy_shell_smoke=ok`
|
||||
- `gmoccapy_dist_smoke=ok`
|
||||
|
||||
本轮新增断言摘要:
|
||||
|
||||
- `gmoccapy_XYZAB.ini` 的 5 个 `[MACROS]` 被识别为 MDI O-word 宏,不再误判为未配置。
|
||||
- `IconFileSelection1` 文件页以 Web file input/staged source 诊断表达,不伪装成 native GTK chooser。
|
||||
- `tooledit1` tool editor 读取 `tool.tbl` 的 17 把刀,Web 写回被明确阻塞。
|
||||
- native GTK 页面矩阵包含 implemented、partial、diagnostic-only、native-only 四类。
|
||||
- `tbtn_setup`、`tbtn_user_tabs`、`btn_touch`、`btn_tool`、`tbtn_switch_mode` hard-button 进入 `GMOCAPY_NATIVE_PAGE` 诊断,不伪装为已实现页面。
|
||||
|
||||
### 2026-06-27 R3
|
||||
|
||||
接续复核命令:
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run smoke:node
|
||||
```
|
||||
|
||||
结果:通过。关键输出包含:
|
||||
|
||||
- `gmoccapy_xyzab_profile_smoke=ok`
|
||||
- `gmoccapy_communication_model_smoke=ok`
|
||||
- `gmoccapy_hal_model_smoke=ok`
|
||||
- `gmoccapy_xyzab_gates_smoke=ok`
|
||||
- `linear_unit_conversion_smoke=ok`
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run build
|
||||
```
|
||||
|
||||
结果:通过,输出 `gmoccapy_static_build=ok`。
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams/web-rtcp-5axis-sim-plan/app
|
||||
npm run smoke
|
||||
```
|
||||
|
||||
结果:通过,输出:
|
||||
|
||||
- `gmoccapy_shell_smoke=ok`
|
||||
- `gmoccapy_dist_smoke=ok`
|
||||
|
||||
```bash
|
||||
cd /home/meswork/cnc_wams
|
||||
git diff --check -- web-rtcp-5axis-sim-plan work/working6
|
||||
```
|
||||
|
||||
结果:通过,无输出。
|
||||
|
||||
复核结论:
|
||||
|
||||
- W6 任务矩阵已全部完成,无需新增代码补丁。
|
||||
- profile/model/store/UI/tests 的实际差异与 W6 文档目标一致。
|
||||
- 本轮未生成截图、PDF、job_id 或 report_id。
|
||||
|
||||
## 页面/截图/report/job 记录
|
||||
|
||||
本轮未生成截图、PDF、job_id 或 report_id。浏览器页面证据由 headless Chromium smoke 脚本验证,关键 DOM 为 `data-gmoccapy-page="file"`、`data-gmoccapy-page="macros"`、`data-gmoccapy-page="tool-editor"`、`data-gmoccapy-page="matrix"`。
|
||||
127
work/working6/06-决策记录.md
Normal file
127
work/working6/06-决策记录.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# 06-决策记录
|
||||
|
||||
## DR-W6-001:working6 作为 working5 后续深化,不作为未完成补丁
|
||||
|
||||
日期:2026-06-27
|
||||
|
||||
决策:
|
||||
|
||||
- `working6` 不是修补 working5 未完成项,而是承接 working5 台账中“可选深化方向”。
|
||||
- 本轮主线聚焦 gmoccapy 文件/宏页面、tool editor 页面、native GTK 未实现页面诊断边界。
|
||||
- working5 中已完成的 HAL 输入、hard-button、状态机门控、换刀回环和低频 HAL pin 行为不得在 working6 中回退。
|
||||
|
||||
原因:
|
||||
|
||||
- `working5` 任务矩阵 W5-001 到 W5-900 已全部完成,并有 EV-W5-900 最终复核证据。
|
||||
- 文件/宏/tool editor/native GTK 页面属于页面级能力和诊断边界深化,风险面和验收口径不同于 working5 的 HAL pin 细化。
|
||||
|
||||
影响:
|
||||
|
||||
- `working6` 需要独立任务矩阵、验收证据和决策记录。
|
||||
- 后续提交或验收应区分 W5 已闭环行为与 W6 新增页面级诊断行为。
|
||||
|
||||
## DR-W6-002:未实现 native GTK 页面必须诊断化,不伪装成已实现
|
||||
|
||||
日期:2026-06-27
|
||||
|
||||
决策:
|
||||
|
||||
- 对 gmoccapy 原生存在但 Web 尚未完整实现的页面,先建立 implementation matrix。
|
||||
- Web UI 可以显示 diagnostic-only 状态、源码对应关系、未实现原因和未来补齐入口。
|
||||
- 未实现页面按钮和 hard-button pin 不得触发假的成功状态。
|
||||
|
||||
原因:
|
||||
|
||||
- gmoccapy 原生 GTK 页面和 Web shell 的布局、运行环境、文件系统权限、HAL 交互能力不同。
|
||||
- 若直接把未实现页面显示为可操作,会误导验收,掩盖仿真边界。
|
||||
|
||||
影响:
|
||||
|
||||
- UI 和 tests 必须验证 diagnostic-only/unsupported/not configured 等边界文案或结构化状态。
|
||||
- store 中未实现 action 应返回明确 operator message。
|
||||
|
||||
## DR-W6-003:文件/宏/tool editor 先按 XYZAB 配置边界建模
|
||||
|
||||
日期:2026-06-27
|
||||
|
||||
决策:
|
||||
|
||||
- 文件页面、宏页面和 tool editor 页面优先按 `gmoccapy_XYZAB.ini` 当前配置和 Web 仿真能力建模。
|
||||
- 配置未启用的能力显示为 no config 或 diagnostic-only。
|
||||
- 真实文件写入、外部 LinuxCNC 进程联动和持久化 tool table 修改不作为初始实现默认目标。
|
||||
|
||||
原因:
|
||||
|
||||
- 当前 Web 项目是 LinuxCNC/gmoccapy 行为仿真,不是完整桌面 gmoccapy 进程。
|
||||
- XYZAB 配置的宏、tool sensor、user message 等能力存在明确启用边界。
|
||||
- 先把边界表达清楚,后续才能安全决定哪些功能升级为可执行。
|
||||
|
||||
影响:
|
||||
|
||||
- W6-100、W6-110、W6-120 的验收重点是“能力、gate、边界和诊断是否正确”,不是盲目补齐所有 GTK 行为。
|
||||
- 若后续要启用真实写文件或外部进程,需要新增决策记录和验收任务。
|
||||
|
||||
## DR-W6-004:XYZAB 宏页按已配置 5 个 `[MACROS]` 建模
|
||||
|
||||
日期:2026-06-27
|
||||
|
||||
决策:
|
||||
|
||||
- `gmoccapy_XYZAB.ini` 的 `[MACROS]` 中 5 个宏必须建模为已配置能力:
|
||||
- `i_am_lost`
|
||||
- `halo_world`
|
||||
- `jog_around`
|
||||
- `increment xinc yinc`
|
||||
- `go_to_position X-pos Y-pos Z-pos`
|
||||
- Web 通过 `GMOCAPY_RUN_MACRO` 模拟 `_on_btn_macro_pressed()`,生成 `O<name> call [args]` MDI 命令。
|
||||
- 宏执行必须复用 `RUN_MDI` gate;未上电、未回零、非 MDI-capable 或解释器忙时拦截。
|
||||
|
||||
原因:
|
||||
|
||||
- 初始文档把“未配置宏时显示边界”列为需要处理的通用场景,但实际 XYZAB INI 明确配置了 5 个宏。
|
||||
- gmoccapy 原生 `_make_macro_button()` 从 INI 读取宏,`_on_btn_macro_pressed()` 将宏转为 O-word MDI 调用。
|
||||
|
||||
影响:
|
||||
|
||||
- profile、HAL model、communication model、store、Node/browser tests 均断言 XYZAB 宏 count 为 5。
|
||||
- Web 不创建 native entry dialog;参数由 dispatch/test 传入,后续如需 UI 参数输入需要单独任务。
|
||||
|
||||
## DR-W6-005:tool editor 本轮只做诊断和 gate,不写 `tool.tbl`
|
||||
|
||||
日期:2026-06-27
|
||||
|
||||
决策:
|
||||
|
||||
- Web 记录 `tooledit1`、`tool.tbl`、17 把刀、可见 XYZAB 轴和 M6/M61 工具动作边界。
|
||||
- `GMOCAPY_TOOL_EDITOR_ACTION` 对 `save`、`add`、`delete`、`touch-off` 等写操作返回 diagnostic-only/operator message,不修改本地 `tool.tbl`。
|
||||
- 工具换刀继续沿用 working5 的 `iocontrol-loopback`,不重新启用手动 gmoccapy toolchange GUI pins。
|
||||
|
||||
原因:
|
||||
|
||||
- 原生 gmoccapy tool editor 可以直接写配置目录中的 `tool.tbl`,但浏览器 Web 仿真没有等价的 LinuxCNC 配置写回权限和进程同步语义。
|
||||
- 未经单独设计直接写文件会混淆“诊断仿真”和“真实机床配置修改”的边界。
|
||||
|
||||
影响:
|
||||
|
||||
- 本轮验收关注 tool table 来源、数量、只读边界和换刀语义一致性。
|
||||
- 后续若要实现真实写回,需要新增持久化设计、备份策略、并发保护和验收任务。
|
||||
|
||||
## DR-W6-006:hard-button 对 native-only/diagnostic-only 页面使用结构化页面诊断
|
||||
|
||||
日期:2026-06-27
|
||||
|
||||
决策:
|
||||
|
||||
- `tbtn_user_tabs`、`tbtn_setup`、`btn_touch`、`btn_tool`、`tbtn_switch_mode` 不再作为普通 Web action 或模式切换伪装执行。
|
||||
- 这些按钮通过 `GMOCAPY_NATIVE_PAGE` 更新 `gmoccapyGui.activeNativePage`、`nativePageMode` 和 operator message。
|
||||
- UI 通过 `data-gmoccapy-page="matrix"` 展示 native GTK 页面实现矩阵。
|
||||
|
||||
原因:
|
||||
|
||||
- gmoccapy 原生 `_button_pin_changed()` 会触发当前可见且敏感的 GTK 按钮,但 Web shell 尚未实现完整 setup/user tabs/touch/tool/switchkins 页面。
|
||||
- 直接把这些按钮映射成其他 Web action 会误表达 native 行为。
|
||||
|
||||
影响:
|
||||
|
||||
- hard-button 模型仍保留 pin 到 native widget 的源码映射。
|
||||
- Web 验收明确区分 implemented、partial、diagnostic-only、native-only 页面,避免后续重复争论“未实现页面是否可点击成功”。
|
||||
33
work/working6/README.md
Normal file
33
work/working6/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# working6 README 索引
|
||||
|
||||
本目录用于推进 `/home/meswork/cnc_wams/web-rtcp-5axis-sim-plan` 中 gmoccapy 文件/宏页面、tool editor 页面、native GTK 未实现页面诊断边界的实现、验证和验收。
|
||||
|
||||
前置工作:
|
||||
|
||||
- `/home/meswork/cnc_wams/work/working5`
|
||||
- `/home/meswork/cnc_wams/work/working3/gmoccapy_XYZAB_execution_analysis.md`
|
||||
|
||||
对标基准:
|
||||
|
||||
- `/home/meswork/cnc_wams/linuxcnc/configs/sim/gmoccapy/gmoccapy_XYZAB.ini`
|
||||
- `/home/meswork/cnc_wams/linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.py`
|
||||
- `/home/meswork/cnc_wams/linuxcnc/src/emc/usr_intf/gmoccapy/gmoccapy.glade`
|
||||
- `/home/meswork/cnc_wams/linuxcnc/src/emc/usr_intf/gmoccapy/dialogs.py`
|
||||
- `/home/meswork/cnc_wams/linuxcnc/configs/sim/gmoccapy/*.hal`
|
||||
|
||||
工作文件:
|
||||
|
||||
1. [01-项目功能内容.md](01-项目功能内容.md)
|
||||
2. [02-项目程序开发详细步骤.md](02-项目程序开发详细步骤.md)
|
||||
3. [03-推进台账.md](03-推进台账.md)
|
||||
4. [04-任务矩阵.md](04-任务矩阵.md)
|
||||
5. [05-验收证据.md](05-验收证据.md)
|
||||
6. [06-决策记录.md](06-决策记录.md)
|
||||
|
||||
推进规则:
|
||||
|
||||
- 先按 `04-任务矩阵.md` 选择任务,避免重复做同一项。
|
||||
- 每轮结束更新 `03-推进台账.md`,记录做了什么、改了哪些文件、验证了什么、下一步是什么。
|
||||
- 所有命令、页面、report、job_id、PDF、截图、测试输出摘要写入 `05-验收证据.md`。
|
||||
- 影响架构、兼容性、验收口径或 LinuxCNC/gmoccapy 对标边界的判断写入 `06-决策记录.md`。
|
||||
- 本轮是 working5 的后续深化,不回退 working5 已完成的 HAL 输入和按钮门控行为。
|
||||
Reference in New Issue
Block a user