New MACRO parameter for SAVE_VARIABLE command

Hi everyone!

I’m planning on PRing a new [MACRO=<name>] parameter to the SAVE_VARIABLE command of [save_variables].
The new functionality would update the macro variable, create a new section [gcode_macro <macroname>] in the variable config and save it, so gcode macro variables can persist across restarts (by reading the config file on startup and setting the gcode macro variable).
The point here is for a spool_id to be set on a toolchanger macro to allow easy spoolman spool selections in multi-tool setups - having to set every tools associated spool every time Klipper restarts will get annoying quickly.

First time contributing to Klipper, so not sure what’s valid code-wise and what isn’t.
I’ve published a first PoC under https://github.com/matmen/klipper/tree/feat/persistent-macro-variables, but I’m not sure about the following things:

  • Is it valid to modify gcode macro variables from outside of the gcode_macro module?
  • I’m concerned about automatically overriding the variable default values defined in the printer.cfg with ones saved in the save_variables config file. I feel like this could lead to confusion when troubleshooting.

I’ve considered simply issuing a SAVE_VARIABLE VARIABLE=<macro name>_<variable name> VALUE=<value> command, but this could create ambiguities:
A macro with name SET_SPOOL with variable ID would generate a SAVE_VARIABLE VARIABLE=SET_SPOOL_ID ..., but so would a macro with name SET and variable SPOOL_ID.
Also, it looks like gcode_macro variables don’t support a Jinja2 template as default value, so I’m not sure if loading the value on startup would be possible without issuing another set of commands.

Please let me know if you have any comments, questions or concerns.

I think I’ve found a solution for this without any code changes. Using a delayed_gcode in combination with save_variables fulfills almost all of the needs, except for the variable naming ambiguities.

FWIW, this is the delayed_gcode macro I came up with:

[delayed_gcode LOAD_TOOLCHANGER_SPOOL_INFO]
initial_duration: 0.1
gcode:
  {% set svv = printer.save_variables.variables %}
  {% for macro in ['T0', 'T1'] %}
    {% set var = (macro + '_SPOOL_ID')|lower %}
    {% if svv[var] is defined %}
      SET_GCODE_VARIABLE MACRO={macro} VARIABLE=spool_id VALUE={svv[var]}
    {% endif %}
  {% endfor %}