Macro Creation Tutorial

something to add to the tutorial:

The SET_GCODE_VARIABLE and SAVE_VARIABLE commands in klipper require that you pass them Python literals. Simple strings and numbers are pretty easy but what about complex types like arrays or objects? This has been a stumbling block for more ambitious macros. If you have tried the tojson filter you have probably not had a lot of luck. Here is a way to do it using the pprint filter:

[gcode_macro TEST_STUFF]
variable_hello: None
gcode:
    {action_respond_info(printer['gcode_macro TEST_STUFF'].hello | pprint)}
    {% set my_array = [1, 2.0, "heater_bed", None, 3] %}
    {% set my_object = {"name": "Hello World it's \"Fred\" calling", "some_data": my_array} %}
    {action_respond_info("my_array: %s" % (my_array | pprint | replace("\n", "") | replace("\"", "\\\"")))}
    {action_respond_info("my_object: %s" % (my_object | pprint | replace("\n", "") | replace("\"", "\\\"")))}
    SET_GCODE_VARIABLE MACRO=TEST_STUFF VARIABLE=hello VALUE="{my_object | pprint | replace("\n", "") | replace("\"", "\\\"")}"

Output of 2 calls:

$ TEST_STUFF
// None
// my_array: [1, 2.0, 'heater_bed', None, 3]
// my_object: {'name': 'Hello World it\'s \"Fred\" calling', 'some_data': [1, 2.0, 'heater_bed', None, 3]}

$ TEST_STUFF
// {'name': 'Hello World it\'s "Fred" calling',
// 'some_data': [1, 2.0, 'heater_bed', None, 3]}
// my_array: [1, 2.0, 'heater_bed', None, 3]
// my_object: {'name': 'Hello World it\'s \"Fred\" calling', 'some_data': [1, 2.0, 'heater_bed', None, 3]}
  • pprint converts Python objects to their Python Literal format but it adds newlines when the object is too large to comfortably read.
  • replace("\n", "") deletes the newlines
  • replace("\"", "\\\"") escapes double quotes in the string so it can be passed to a klipper command wrapped in double quotes.

The end result is a valid Python literal that you can pass to the macros:

SET_GCODE_VARIABLE MACRO=TEST_STUFF VARIABLE=hello VALUE="{my_object | pprint | replace("\n", "") | replace("\"", "\\\"")}"
SAVE_VARIABLE VARIABLE="my_saved_variable" VALUE="{my_object | pprint | replace("\n", "") | replace("\"", "\\\"")}"
4 Likes