Jinja Parsing Order Prevents Overriding RatOS Variables?

Hey guys, I have written a variable heat soak macro to allow setting the
[gcode_macro RatOS]
variable_bed_heat_soak_time:
variable_hotend_heat_soak_time:
[gcode_macro RatOS]
variable_bed_heat_soak_time:
variable_hotend_heat_soak_time:
values dynamically based on certain print stats. However I am having an issue with trying to integrate this into the RatOS START_PRINT routine using the _USER_HOOK macros, and I believe it may be because of how Klipper parses Jinja statements before gcode? I can see the RatOS START_PRINT macro fetches the bed_heat_soak_time and hotend_heat_soak_time using Jinja set statements right at the top of the routine, and I had thought if I use the _USER_START_PRINT hook then that should update the variables defined in [gcode_macro RatOS] and allow me to reference them through the START_PRINT macro. However this doesn't seem to be the case, despite my _START_VARIABLE_HEATSOAK macro correctly calculating and setting the variables the machine still falls back to the default values defined in [gcode_macro RatOS]. I have somewhat proved this theory by changing the Machine Start Gcode in my slicer to:
_START_VARIABLE_HEATSOAK EXTRUDER_TEMP={first_layer_temperature[0]},{first_layer_temperature[1]} BED_TEMP={bed_temperature_initial_layer_single} X0={adaptive_bed_mesh_min[0]} Y0={adaptive_bed_mesh_min[1]} X1={adaptive_bed_mesh_max[0]} Y1={adaptive_bed_mesh_max[1]}

START_PRINT EXTRUDER_TEMP={first_layer_temperature[0]},{first_layer_temperature[1]} EXTRUDER_OTHER_LAYER_TEMP={nozzle_temperature[0]},{nozzle_temperature[1]} BED_TEMP={bed_temperature_initial_layer_single} CHAMBER_TEMP={overall_chamber_temperature} INITIAL_TOOL={initial_tool} TOTAL_LAYER_COUNT={total_layer_count} X0={adaptive_bed_mesh_min[0]} Y0={adaptive_bed_mesh_min[1]} X1={adaptive_bed_mesh_max[0]} Y1={adaptive_bed_mesh_max[1]}
_START_VARIABLE_HEATSOAK EXTRUDER_TEMP={first_layer_temperature[0]},{first_layer_temperature[1]} BED_TEMP={bed_temperature_initial_layer_single} X0={adaptive_bed_mesh_min[0]} Y0={adaptive_bed_mesh_min[1]} X1={adaptive_bed_mesh_max[0]} Y1={adaptive_bed_mesh_max[1]}

START_PRINT EXTRUDER_TEMP={first_layer_temperature[0]},{first_layer_temperature[1]} EXTRUDER_OTHER_LAYER_TEMP={nozzle_temperature[0]},{nozzle_temperature[1]} BED_TEMP={bed_temperature_initial_layer_single} CHAMBER_TEMP={overall_chamber_temperature} INITIAL_TOOL={initial_tool} TOTAL_LAYER_COUNT={total_layer_count} X0={adaptive_bed_mesh_min[0]} Y0={adaptive_bed_mesh_min[1]} X1={adaptive_bed_mesh_max[0]} Y1={adaptive_bed_mesh_max[1]}
And this runs correctly using the dynamically set heatsoak variables from my macro. Is there another way around this? This solution makes the slicer start gcode feel messy and I don't love it.
2 Replies
Martin Hanbury
Martin HanburyOP2mo ago
@tg73 apologies for the ping, but I thought you might know the answer to this one. Am I correct in my understanding of how Klipper parses the gcode being the cause of the problem? Do you know of a neater way I could achieve integrating this into the START_PRINT macro without needing to use the slicer?
tg73
tg732mo ago
You are correct re macro template parsing. There are two phases: rendering and execution. The only commands executed during rendering are the handful of actions like { action_respond_info('blah') }. Gcode is not executed during rendering. The result of rendering is plain gcode with no jinja stuff left (no loops, no conditions, etc). This plain gcode is then executed. Klipper provides a further layer of state consistency assurance during rendering (per-render-op caching of deep copies of printer object get_status() results), but this is fine detail which has a far more subtle effect than the fundamental render/execute split.

Did you find this page helpful?