Is Better M73 Support Possible?

PrusaSlicer and SuperSlicer support a more robust version of M73 where they pass both the percentage remaining and the time remaining in minutes. Both values are supplied as integers. (I don’t know if other slicers like Cura do this differently?)

Anyway, the two values are meant to be “equivalent” but depending on the length of the print one value has more information in it than the other. For prints shorter than 100 minutes the percentage values has more info than the minutes values (1% represents less than 60 seconds). For prints longer than 100 minutes the minutes value tells you more than the % value (1% is a unit of time longer than 1 minute).

Klipper accepts the percentage value to M73 as a float, so it would be valid to say M73 P42.1234. Then the front end could work out what that amount of time remaining is. I thought I could whip up a quick macro to override M73 to:

  • Check if the print is longer than 100 minutes
    • If it is, compute the percentage as (minutes / total minutes)
    • else report the percentage as-is

But this can’t be done because I cant get the total print time in a macro:

  • Moonraker parses the metadata out of the gcode file and that’s how all of the front ends get the total print time. You cant really call Moonraker from a klipper macro.
  • In the slicer the print_time placeholder is only available in the file name, not in the G-Code, so I cant pass it to M73 that way.
  • If the print time is in the file name, I cant (easily) parse it from a macro because Jinja lacks any kind of Regex support. You could iterate through the string 1 character at a time and try to grab the relevant strings, but do I really want to do that?

So if anyone else has any ideas I’ll see if I cant implement it.

Well… Jinja will let you call Python methods on the string object… and it will let you use the string slicing syntax… so I guess its option #3?

[gcode_macro TEST_STRING_HACKS]
gcode:
    {% set filenames = ["First Layer Patches-15h20m", "First Layer Patches-15h20m.gcode", "First Layer Patches-20m.gcode", "First Layer Patches-15h.gcode", "First Layer Patches.gcode", "xxxxmxxxxh.gcode"] %}
    {% for filename in filenames %}
        {action_respond_info("Test Case: %s" % (filename)) }
        {% set hours = 0 %}
        {% set minutes = 0 %}
        # extract the time block
        {% set filetime_block = (filename.split("-"))[-1] %}
        {% set hours_index = filetime_block.find('h') %}
        {% set minutes_index = filetime_block.find('m') %}
        {% if hours_index != -1 %}
            {% set hours = filetime_block[0:hours_index] | int %}
        {% endif %}
        {% if minutes_index != -1 %}
            {% set hours_index = [0, (hours_index + 1)] | max %}
            {% set minutes = filetime_block[hours_index:minutes_index] | int %}
        {% endif %}
        # calculate the total print time in minutes
        {% set total_minutes = (hours * 60 + minutes) | float %}
        {action_respond_info("file time: %s, total minutes: %s" % (filetime_block, total_minutes)) }
    {% endfor %}

This generates this:

// Test Case: First Layer Patches-15h20m
// file time: 15h20m, total minutes: 920.0
// Test Case: First Layer Patches-15h20m.gcode
// file time: 15h20m.gcode, total minutes: 920.0
// Test Case: First Layer Patches-20m.gcode
// file time: 20m.gcode, total minutes: 20.0
// Test Case: First Layer Patches-15h.gcode
// file time: 15h.gcode, total minutes: 900.0
// Test Case: First Layer Patches.gcode
// file time: First Layer Patches.gcode, total minutes: 0.0
// Test Case: xxxxmxxxxh.gcode
// file time: xxxxmxxxxh.gcode, total minutes: 0.0

So as long as you end your gcode file names with the pattern -99h99m, which is the Prusa Slicer default, I can make this work. It seems to be robust against garbage inputs, coming up with a 0.0 which will get ignored in the final macro.

1 Like

Looks like they update the M73 calls to pass a float here: klipper_estimator/post_process.rs at 20de8303c5890f4c01993585b056784204a6f13c · Annex-Engineering/klipper_estimator · GitHub

I’ll have to try that out.

It doesn’t emit floats for M73 percentage. It does update the time estimate in the file metadata but not in the file name.

@ Creo2005 I got a change into the estimator to get us decimal percentages: Round M73 P to 3 decimal places (#29) · Annex-Engineering/klipper_estimator@a7d4407 · GitHub