|
| 1 | +# Data Binding: `action` and `observes` |
| 2 | + |
| 3 | +The data binding system provides a mechanism to connect the state of your application (the machine interface) to the UI, and to receive events from the UI back into your application logic. It is based on a "Model-View-ViewModel" (MVVM) pattern that creates a clean separation of concerns: |
| 4 | + |
| 5 | +* **View:** The UI definition in your YAML file. |
| 6 | +* **Model:** The `machine_interface_t` struct, representing the CNC machine's state. |
| 7 | +* **ViewModel:** The `data_binding` library, which mediates between the Model and the View. |
| 8 | + |
| 9 | +This system is comprised of two main features, configured by the `action` and `observes` keys in your UI definition. |
| 10 | + |
| 11 | +## `action`: UI to Machine Communication |
| 12 | + |
| 13 | +The `action` key allows widgets to send commands to the machine. When a user interacts with a widget (e.g., clicks a button), a named action is dispatched to a handler that calls the corresponding function on the `machine_interface_t`. |
| 14 | + |
| 15 | +### Action Reference |
| 16 | + |
| 17 | +| Action Name | Description | Value Type | YAML Example | |
| 18 | +| :--- | :--- | :--- | :--- | |
| 19 | +| **Homing & Control** | |
| 20 | +| `home_machine` | Homes all axes (`G28`). | `trigger` | `{ home_machine: trigger }` | |
| 21 | +| `home_machine_x` | Homes the X axis (`G28 X`). | `trigger` | `{ home_machine_x: trigger }` | |
| 22 | +| `home_machine_y` | Homes the Y axis (`G28 Y`). | `trigger` | `{ home_machine_y: trigger }` | |
| 23 | +| `home_machine_z` | Homes the Z axis (`G28 Z`). | `trigger` | `{ home_machine_z: trigger }` | |
| 24 | +| `feed_hold` | Toggles feed hold (`!`) and resume (`~`). | `trigger` | `{ feed_hold: trigger }` | |
| 25 | +| `program_run` | Starts or resumes the current job (`M24`). | `trigger` | `{ program_run: trigger }` | |
| 26 | +| `program_stop` | Issues a soft reset (`Ctrl+X`). | `trigger` | `{ program_stop: trigger }` | |
| 27 | +| **Overrides** | |
| 28 | +| `set_feed_override` | Sets the feed rate override percentage. | `float` | `{ set_feed_override: 110.0 }` | |
| 29 | +| `set_speed_override` | Sets the spindle speed override percentage. | `float` | `{ set_speed_override: 95.0 }` | |
| 30 | +| **Movement & Jogging** | |
| 31 | +| `jog_continuous_start_x_plus` | Starts a continuous positive jog on the X axis. | `trigger` | `{ jog_continuous_start_x_plus: trigger }` | |
| 32 | +| `jog_continuous_start_x_minus` | Starts a continuous negative jog on the X axis. | `trigger` | `{ jog_continuous_start_x_minus: trigger }` | |
| 33 | +| ..._y_plus/minus | (Same for Y axis) | `trigger` | ... | |
| 34 | +| ..._z_plus/minus | (Same for Z axis) | `trigger` | ... | |
| 35 | +| `jog_continuous_stop` | Stops any continuous jog. | `trigger` | `{ jog_continuous_stop: trigger }` | |
| 36 | +| `jog_step_x_plus` | Steps the X axis by `jog_step` distance. | `trigger` | `{ jog_step_x_plus: trigger }` | |
| 37 | +| `jog_step_x_minus` | Steps the X axis by `-jog_step` distance. | `trigger` | `{ jog_step_x_minus: trigger }` | |
| 38 | +| ..._y_plus/minus | (Same for Y axis) | `trigger` | ... | |
| 39 | +| ..._z_plus/minus | (Same for Z axis) | `trigger` | ... | |
| 40 | +| `cycle_jog_step` | Cycles through predefined jog step distances. | `cycle` | `{ cycle_jog_step: [0.01, 0.1, 1.0, 10.0] }` | |
| 41 | +| `set_move_axis_x` | Sets the currently active axis for jogging to X. | `trigger` | `{ set_move_axis_x: trigger }` | |
| 42 | +| `set_move_axis_y` | Sets the currently active axis for jogging to Y. | `trigger` | `{ set_move_axis_y: trigger }` | |
| 43 | +| `set_move_axis_z` | Sets the currently active axis for jogging to Z. | `trigger` | `{ set_move_axis_z: trigger }` | |
| 44 | +| `set_move_axis_off` | Deactivates axis jogging selection. | `trigger` | `{ set_move_axis_off: trigger }` | |
| 45 | +| `cycle_move_axis` | Cycles the active jog axis (X -> Y -> Z -> OFF). | `trigger` | `{ cycle_move_axis: trigger }` | |
| 46 | +| **Coordinate Systems (WCS)** | |
| 47 | +| `set_wcs` | Sets the current Work Coordinate System. | `float` | `{ set_wcs: 2.0 }` (for G55) | |
| 48 | +| `cycle_wcs` | Cycles to the next WCS (e.g., G54 -> G55). | `trigger` | `{ cycle_wcs: trigger }` | |
| 49 | +| `zero_wcs_x` | Sets the current X position as the origin for the current WCS. | `trigger` | `{ zero_wcs_x: trigger }` | |
| 50 | +| `zero_wcs_y` | Sets the current Y position as the origin for the current WCS. | `trigger` | `{ zero_wcs_y: trigger }` | |
| 51 | +| `zero_wcs_z` | Sets the current Z position as the origin for the current WCS. | `trigger` | `{ zero_wcs_z: trigger }` | |
| 52 | +| **Files & Macros** | |
| 53 | +| `list_files` | Requests a file listing for a given path. | `string` | `{ list_files: "/gcodes" }` | |
| 54 | +| `run_macro` | Runs a macro file by name. | `string` | `{ run_macro: "probe.g" }` | |
| 55 | +| `start_job` | Starts a job file by name. | `string` | `{ start_job: "my_part.gcode" }` | |
| 56 | +| **Probing** | |
| 57 | +| `probe` | Executes a G-code probing routine. | `string` | `{ probe: "G38.2 Z-20 F100" }` | |
| 58 | +| **Dialogs / Modals** | |
| 59 | +| `dialog_ok` | Responds "OK" to the current modal dialog. | `trigger` | `{ dialog_ok: trigger }` | |
| 60 | +| `dialog_cancel` | Responds "Cancel" to the current modal dialog. | `trigger` | `{ dialog_cancel: trigger }` | |
| 61 | +| `dialog_choice` | Responds with a choice to a multi-choice dialog. | `float` | `{ dialog_choice: 1.0 }` (for 2nd choice) | |
| 62 | +| `dialog_input_int` | Submits an integer value from an input dialog. | `float` | `{ dialog_input_int: 123.0 }` | |
| 63 | +| `dialog_input_float`| Submits a float value from an input dialog. | `float` | `{ dialog_input_float: 45.6 }` | |
| 64 | +| `dialog_input_str` | Submits a string value from an input dialog. | `string` | `{ dialog_input_str: "my_value" }` | |
| 65 | +| **G-Code** | |
| 66 | +| `send_gcode` | Sends a raw G-code string to the machine. | `string` | `{ send_gcode: "M3 S10000" }` | |
| 67 | + |
| 68 | +## `observes`: Machine to UI Communication |
| 69 | + |
| 70 | +The `observes` key allows widgets to automatically update their appearance in response to changes in the machine's state. You simply notify the data binding system when a piece of your data changes, and it handles updating the UI. |
| 71 | + |
| 72 | +### Observable State Reference |
| 73 | + |
| 74 | +| State Name | Description | Value Type | YAML Example | |
| 75 | +| :--- | :--- | :--- | :--- | |
| 76 | +| **Machine Status** | |
| 77 | +| `is_connected` | `true` if a connection to the machine is active. | `bool` | `{ is_connected: { visible: { true: true, false: false } } }` | |
| 78 | +| `machine_mode`| The current high-level status (e.g., "IDLE", "AUTO", "PAUSED").| `string` | `{ machine_mode: { text: "%s" } }` | |
| 79 | +| `program_running` | `true` if a job is currently running. | `bool` | `{ program_running: { style: { true: '@style_active' } } }` | |
| 80 | +| `program_paused` | `true` if a job is currently paused. | `bool` | `{ program_paused: { visible: true } }` | |
| 81 | +| **Position** | |
| 82 | +| `pos_x` / `_y` / `_z` | Machine-space X, Y, or Z position. | `float` | `{ pos_x: { text: "X: %.3f" } }` | |
| 83 | +| `wcs_pos_x` / `_y` / `_z` | Work-space (WCS) X, Y, or Z position. | `float` | `{ wcs_pos_x: { text: "%.3f" } }` | |
| 84 | +| `target_pos_x` / `_y` / `_z` | The final target position for the current move. | `float` | `{ target_pos_x: { text: "Target: %.3f" } }` | |
| 85 | +| **Homing** | |
| 86 | +| `x_is_homed` | `true` if the X axis has been homed. | `bool` | `{ x_is_homed: { style: { true: '@style_homed' } } }` | |
| 87 | +| `y_is_homed` | `true` if the Y axis has been homed. | `bool` | `{ y_is_homed: { checked: { true: true, false: false } } }` | |
| 88 | +| `z_is_homed` | `true` if the Z axis has been homed. | `bool` | `{ z_is_homed: { disabled: { true: false, false: true } } }` | |
| 89 | +| **Coordinate Systems (WCS)** | |
| 90 | +| `wcs_name` | The name of the active WCS (e.g., "G54", "G55"). | `string` | `{ wcs_name: { text: "%s" } }` | |
| 91 | +| `wcs_number` | The number of the active WCS (1 for G54, etc.). | `float` | `{ wcs_number: { value: [LV_ANIM_OFF] } }` | |
| 92 | +| `z_offset` | The current Z-offset value. | `float` | `{ z_offset: { text: "Z-Off: %.3f" } }` | |
| 93 | +| **Feed & Speed** | |
| 94 | +| `feed` | The current actual feed rate. | `float` | `{ feed: { text: "Feed: %.0f" } }` | |
| 95 | +| `feed_requested` | The requested feed rate from G-code. | `float` | `{ feed_requested: { text: "Req: %.0f" } }` | |
| 96 | +| `feed_override` | The current feed override percentage (e.g., 100.0 for 100%). | `float` | `{ feed_override: { value: [LV_ANIM_ON] } }` | |
| 97 | +| **Spindle & Tool** | |
| 98 | +| `spindle_0_rpm` | RPM of the first spindle. | `float` | `{ spindle_0_rpm: { text: "RPM: %.0f" } }` | |
| 99 | +| `spindle_0_name` | Name of the first spindle. | `string` | `{ spindle_0_name: { text: "%s" } }` | |
| 100 | +| `spindle_0_on` | `true` if the first spindle is active. | `bool` | `{ spindle_0_on: { style: { true: '@style_active' } } }` | |
| 101 | +| `tool_name` | The name of the currently active tool. | `string` | `{ tool_name: { text: "Tool: %s" } }` | |
| 102 | +| **Jogging & UI State** | |
| 103 | +| `move_is_relative` | `true` if G-code moves are in relative mode (G91). | `bool` | `{ move_is_relative: { visible: true } }` | |
| 104 | +| `move_is_step` | `true` if jogging is in step mode. | `bool` | `{ move_is_step: { style: { true: '@style_active' } } }` | |
| 105 | +| `current_move_axis`| The currently selected jog axis ("X", "Y", "Z", or "OFF"). | `string` | `{ current_move_axis: { text: "Axis: %s" } }` | |
| 106 | +| `jog_step` | The current step distance for jogging. | `float` | `{ jog_step: { text: "%.2f" } }` | |
| 107 | +| **Sensors** | |
| 108 | +| `probe_0_value` | The value of the first probe. | `float` | `{ probe_0_value: { text: "%.3f" } }` | |
| 109 | +| `end_stop_0_triggered`| `true` if the first endstop is triggered. | `bool` | `{ end_stop_0_triggered: { visible: true } }` | |
| 110 | +| **Files** | |
| 111 | +| `filelist_gcodes`| A newline-separated list of g-code files. For `dropdown` widgets.| `string`| `{ filelist_gcodes: { text: "%s" } }`| |
| 112 | +| `filelist_macros`| A newline-separated list of macro files. For `dropdown` widgets.| `string`| `{ filelist_macros: { text: "%s" } }`| |
| 113 | +| **Dialogs / Modals** | |
| 114 | +| `dialog_active` | `true` if a modal dialog is currently active. | `bool` | `{ dialog_active: { visible: true } }` | |
| 115 | +| `dialog_title`| The title of the current dialog. | `string` | `{ dialog_title: { text: "%s" } }` | |
| 116 | +| `dialog_text` | The main text/message of the current dialog. | `string` | `{ dialog_text: { text: "%s" } }` | |
| 117 | +| `dialog_choices`| Newline-separated list of choices for a choice dialog. | `string` | `{ dialog_choices: { text: "%s" } }` | |
| 118 | +| `dialog_mode` | The type of dialog (see `message_box_mode_t`). | `float` | `{ dialog_mode: { visible: { 2.0: true } } }` | |
| 119 | + |
0 commit comments