Duet3D Logo

    Duet3D

    • Register
    • Login
    • Search
    • Categories
    • Tags
    • Documentation
    • Order

    Add a trigger for a user gcode file after print header is read

    Firmware wishlist
    4
    20
    181
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • mikeabuilder
      mikeabuilder last edited by

      It would be useful to be able to have a user gcode macro executed after the header portion of a print file is read. Possibly a fixed name file like "post_print_header.g" that gets executed if it exists.

      This would let me write macros that interact with data I've automatically included in the header. One specific thing would be to stop the print if the slicer selected the wrong printer. I might also be able to log print start times, user stats, etc if I include the right data in a custom gcode header.

      One challenge I don't have a solution for is how to know when the header stops and print execution begins, but maybe there is some convention with print files.

      zapta 1 Reply Last reply Reply Quote 0
      • zapta
        zapta @mikeabuilder last edited by

        @mikeabuilder said in Add a trigger for a user gcode file after print header is read:

        This would let me write macros that interact with data I've automatically included in the header.

        How do you plan to do that?

        1 Reply Last reply Reply Quote 0
        • mikeabuilder
          mikeabuilder last edited by

          I would put a line in my custom gcode header for this printer defining a variable, say printer_type = "fred". Then, when this new piece of code is called, the printer type variable should be set to "fred" if it is not, then I assume the slicer did not add the line in it's header because the wrong printer was selected in the slicer, and I cancel the print, with a message to the user. And I have some code in start.g that sets printer_type to "none" so I clear the variable before each print.

          There is a longer discussion of this in this thread: https://forum.duet3d.com/topic/25763/implementing-a-slicer-checker

          fcwilt zapta 2 Replies Last reply Reply Quote 0
          • fcwilt
            fcwilt @mikeabuilder last edited by

            @mikeabuilder said in Add a trigger for a user gcode file after print header is read:

            I would put a line in my custom gcode header for this printer defining a variable, say printer_type = "fred". Then, when this new piece of code is called, the printer type variable should be set to "fred" if it is not, then I assume the slicer did not add the line in it's header because the wrong printer was selected in the slicer, and I cancel the print, with a message to the user. And I have some code in start.g that sets printer_type to "none" so I clear the variable before each print.

            There is a longer discussion of this in this thread: https://forum.duet3d.com/topic/25763/implementing-a-slicer-checker

            There is a big difference between extracting information from the head information generated by the slicer and generating you own data using the custom gcode feature of the slicer.

            I was under the impression that you wanted a solution that didn't rely on using slicer custom code?

            Frederick

            Printers: A FT-5 with the 713 upgrade bits. A custom MarkForged style. A small Utilmaker style and a CoreXY from kits. Various hotends. Using Duets (2 and 3) running 3.4.1

            zapta 1 Reply Last reply Reply Quote 0
            • zapta
              zapta @mikeabuilder last edited by

              @mikeabuilder said in Add a trigger for a user gcode file after print header is read:

              I would put a line in my custom gcode header for this printer defining a variable, say printer_type = "fred".

              I see, you may want to include this detail in the request here, such that the header parsing will include also custom headers you will add via the slicer's setting, rather than just the standard headers.

              1 Reply Last reply Reply Quote 0
              • zapta
                zapta @fcwilt last edited by

                @fcwilt said in Add a trigger for a user gcode file after print header is read:

                I was under the impression that you wanted a solution that didn't rely on using slicer custom code?

                I think that he wants the printer to verify that that file contains some evidence that it was generated with that printer in mind and generating the gocde with a printer specific header value may be that evidence.

                1 Reply Last reply Reply Quote 0
                • mikeabuilder
                  mikeabuilder last edited by

                  Thanks for the discussion. @zapata and @fcwilt - for my slicer-checker implementation, I expect that I will have the slicer include the setting of a global variable in the custom header code. But I do not plan to try to change the slicer software itself.

                  I've not suggested using information that would already be in a print file's gcode header because I don't know what that information might be. I'm completely ignorant in that area. I looked at one file that my PrusaSlicer generated and nothing looked like "header information" to me.

                  If there is a information that exists in the header, it might be nice for to be able to access it for other possible uses of this feature.

                  T3P3Tony fcwilt 2 Replies Last reply Reply Quote 0
                  • T3P3Tony
                    T3P3Tony administrators @mikeabuilder last edited by

                    @mikeabuilder different slicers add lots of varying information to headers &/footer comments. some of that is already parsed to work out e.g. what slicer was used, for display in DWC:
                    e.g.:
                    4fc52ebf-ff40-4443-ab06-bd9503181da5-image.png

                    I see feature request as two fold:

                    1. Add another field to be parsed.
                    2. Add a method you can optionally call to check and reject the files that do not have the correct vlaue in the field mentioned in point 1.

                    That could be on upload, or it could be on print. I assume on upload would be easier as thats when the file is parsed already.

                    That said @dc42 may have a much better way to achieve the same thing.

                    This is unlikely to get addressed immediately do in the sort/medium term I would use the deamon.g method I already mentioned and have your valid files set a global variable.

                    www.duet3d.com

                    mikeabuilder 1 Reply Last reply Reply Quote 0
                    • fcwilt
                      fcwilt @mikeabuilder last edited by

                      @mikeabuilder said in Add a trigger for a user gcode file after print header is read:

                      I expect that I will have the slicer include the setting of a global variable in the custom header code.

                      Given the way variables work and that you have access to the object model it would be simpler, I think, to have the custom slicer code check the printer name which you can access in the object model.

                      Something like:

                      if {network.name} != "expected_name" 
                        abort "Invalid Printer Name"
                      

                      I looked at one file that my PrusaSlicer generated and nothing looked like "header information" to me.

                      That's part of the problem - every slicer does things differently in this area. By default Prusa includes very little info and I don't know if it can be added to. By comparison look at the information Simplifi3D adds as "header information":

                      ; G-Code generated by Simplify3D(R) Version 4.1.2
                      ; Nov 2, 2021 at 7:09:49 PM
                      ; Settings Summary
                      ;   processName,FT5 90
                      ;   applyToModels,Cable Bracket for Frame v2
                      ;   profileName,FT-5 TBO=555 SPD=90 (modified)
                      ;   profileVersion,2021-10-14 21:59:01
                      ;   baseProfile,Folger Tech FT-5
                      ;   printMaterial,PLA
                      ;   printQuality,Medium
                      ;   printExtruders,
                      ;   extruderName,Primary Extruder
                      ;   extruderToolheadNumber,0
                      ;   extruderDiameter,0.4
                      ;   extruderAutoWidth,1
                      ;   extruderWidth,0.48
                      ;   extrusionMultiplier,0.9
                      ;   extruderUseRetract,1
                      ;   extruderRetractionDistance,0.8
                      ;   extruderExtraRestartDistance,0
                      ;   extruderRetractionZLift,0
                      ;   extruderRetractionSpeed,1800
                      ;   extruderUseCoasting,1
                      ;   extruderCoastingDistance,0.2
                      ;   extruderUseWipe,0
                      ;   extruderWipeDistance,5
                      ;   primaryExtruder,0
                      ;   layerHeight,0.2
                      ;   topSolidLayers,5
                      ;   bottomSolidLayers,5
                      ;   perimeterOutlines,5
                      ;   printPerimetersInsideOut,1
                      ;   startPointOption,2
                      ;   startPointOriginX,0
                      ;   startPointOriginY,150
                      ;   sequentialIslands,0
                      ;   spiralVaseMode,0
                      ;   firstLayerHeightPercentage,150
                      ;   firstLayerWidthPercentage,100
                      ;   firstLayerUnderspeed,0.1
                      ;   useRaft,0
                      ;   raftExtruder,0
                      ;   raftTopLayers,3
                      ;   raftBaseLayers,2
                      ;   raftOffset,3
                      ;   raftSeparationDistance,0.14
                      ;   raftTopInfill,100
                      ;   aboveRaftSpeedMultiplier,0.3
                      ;   useSkirt,1
                      ;   skirtExtruder,0
                      ;   skirtLayers,2
                      ;   skirtOutlines,2
                      ;   skirtOffset,3
                      ;   usePrimePillar,0
                      ;   primePillarExtruder,999
                      ;   primePillarWidth,12
                      ;   primePillarLocation,7
                      ;   primePillarSpeedMultiplier,1
                      ;   useOozeShield,0
                      ;   oozeShieldExtruder,999
                      ;   oozeShieldOffset,2
                      ;   oozeShieldOutlines,1
                      ;   oozeShieldSidewallShape,1
                      ;   oozeShieldSidewallAngle,30
                      ;   oozeShieldSpeedMultiplier,1
                      ;   infillExtruder,0
                      ;   internalInfillPattern,Grid
                      ;   externalInfillPattern,Rectilinear
                      ;   infillPercentage,20
                      ;   outlineOverlapPercentage,15
                      ;   infillExtrusionWidthPercentage,100
                      ;   minInfillLength,5
                      ;   infillLayerInterval,1
                      ;   internalInfillAngles,45,-45
                      ;   overlapInternalInfillAngles,1
                      ;   externalInfillAngles,-45,45
                      ;   generateSupport,0
                      ;   supportExtruder,0
                      ;   supportInfillPercentage,50
                      ;   supportExtraInflation,0
                      ;   supportBaseLayers,0
                      ;   denseSupportExtruder,0
                      ;   denseSupportLayers,0
                      ;   denseSupportInfillPercentage,70
                      ;   supportLayerInterval,1
                      ;   supportHorizontalPartOffset,0.3
                      ;   supportUpperSeparationLayers,1
                      ;   supportLowerSeparationLayers,1
                      ;   supportType,0
                      ;   supportGridSpacing,1
                      ;   maxOverhangAngle,45
                      ;   supportAngles,0
                      ;   temperatureName
                      ;   temperatureNumber
                      ;   temperatureSetpointCount
                      ;   temperatureSetpointLayers
                      ;   temperatureSetpointTemperatures
                      ;   temperatureStabilizeAtStartup
                      ;   temperatureHeatedBed
                      ;   fanLayers,1,2,3,4,5,6
                      ;   fanSpeeds,0,10,20,30,40,50
                      ;   blipFanToFullPower,0
                      ;   adjustSpeedForCooling,1
                      ;   minSpeedLayerTime,15
                      ;   minCoolingSpeedSlowdown,20
                      ;   increaseFanForCooling,0
                      ;   minFanLayerTime,45
                      ;   maxCoolingFanSpeed,100
                      ;   increaseFanForBridging,0
                      ;   bridgingFanSpeed,100
                      ;   use5D,1
                      ;   relativeEdistances,1
                      ;   allowEaxisZeroing,1
                      ;   independentExtruderAxes,0
                      ;   includeM10123,0
                      ;   stickySupport,1
                      ;   applyToolheadOffsets,0
                      ;   gcodeXoffset,0
                      ;   gcodeYoffset,0
                      ;   gcodeZoffset,0
                      ;   overrideMachineDefinition,1
                      ;   machineTypeOverride,0
                      ;   strokeXoverride,300
                      ;   strokeYoverride,300
                      ;   strokeZoverride,350
                      ;   originOffsetXoverride,150
                      ;   originOffsetYoverride,150
                      ;   originOffsetZoverride,0
                      ;   homeXdirOverride,1
                      ;   homeYdirOverride,1
                      ;   homeZdirOverride,-1
                      ;   flipXoverride,1
                      ;   flipYoverride,-1
                      ;   flipZoverride,1
                      ;   toolheadOffsets,0,0|0,0|0,0|0,0|0,0|0,0
                      ;   overrideFirmwareConfiguration,0
                      ;   firmwareTypeOverride,RepRap (Marlin/Repetier/Sprinter)
                      ;   GPXconfigOverride,r2
                      ;   baudRateOverride,250000
                      ;   overridePrinterModels,1
                      ;   printerModelsOverride
                      ;   startingGcode,M98 P"print_begin.g",,
                      ;   layerChangeGcode,M98 P"print_layer_change.g",
                      ;   retractionGcode,M98 P"print_retraction.g",
                      ;   toolChangeGcode,
                      ;   endingGcode,M98 P"print_end.g",,
                      ;   exportFileFormat,gcode
                      ;   celebration,0
                      ;   celebrationSong,Random Song
                      ;   postProcessing,
                      ;   defaultSpeed,5400
                      ;   outlineUnderspeed,0.5
                      ;   solidInfillUnderspeed,0.8
                      ;   supportUnderspeed,0.8
                      ;   rapidXYspeed,5400
                      ;   rapidZspeed,600
                      ;   minBridgingArea,50
                      ;   bridgingExtraInflation,0
                      ;   bridgingExtrusionMultiplier,1
                      ;   bridgingSpeedMultiplier,1
                      ;   useFixedBridgingAngle,0
                      ;   fixedBridgingAngle,0
                      ;   applyBridgingToPerimeters,0
                      ;   filamentDiameters,1.75|1.75|1.75|1.75|1.75|1.75
                      ;   filamentPricesPerKg,0|46|46|46|46|46
                      ;   filamentDensities,1.25|1.25|1.25|1.25|1.25|1.25
                      ;   useMinPrintHeight,0
                      ;   minPrintHeight,0
                      ;   useMaxPrintHeight,0
                      ;   maxPrintHeight,0
                      ;   useDiaphragm,0
                      ;   diaphragmLayerInterval,20
                      ;   robustSlicing,1
                      ;   mergeAllIntoSolid,0
                      ;   onlyRetractWhenCrossingOutline,1
                      ;   retractBetweenLayers,1
                      ;   useRetractionMinTravel,0
                      ;   retractionMinTravel,3
                      ;   retractWhileWiping,0
                      ;   onlyWipeOutlines,1
                      ;   avoidCrossingOutline,0
                      ;   maxMovementDetourFactor,3
                      ;   toolChangeRetractionDistance,12
                      ;   toolChangeExtraRestartDistance,-0.5
                      ;   toolChangeRetractionSpeed,600
                      ;   externalThinWallType,0
                      ;   internalThinWallType,1
                      ;   thinWallAllowedOverlapPercentage,10
                      ;   singleExtrusionMinLength,1
                      ;   singleExtrusionMinPrintingWidthPercentage,50
                      ;   singleExtrusionMaxPrintingWidthPercentage,200
                      ;   singleExtrusionEndpointExtension,0.2
                      ;   horizontalSizeCompensation,0
                      

                      Printers: A FT-5 with the 713 upgrade bits. A custom MarkForged style. A small Utilmaker style and a CoreXY from kits. Various hotends. Using Duets (2 and 3) running 3.4.1

                      T3P3Tony 1 Reply Last reply Reply Quote 0
                      • mikeabuilder
                        mikeabuilder @T3P3Tony last edited by

                        @t3p3tony - Thanks for the clarifications. I just read up on daemon.g and now that I understand it, I do think that will work for my purposes.

                        1 Reply Last reply Reply Quote 0
                        • T3P3Tony
                          T3P3Tony administrators @fcwilt last edited by

                          @fcwilt i think you miss the point that this must work to reject files that do not have something set in the print file.

                          so adding:
                          ;MYSPECIALMAGICNAME=ValidName

                          or whatever to the start gcode in the slicer would be parsed as long as was in the limits of whatever is parsed from a file, and the parsing element was extended to look for it.

                          www.duet3d.com

                          fcwilt 1 Reply Last reply Reply Quote 0
                          • fcwilt
                            fcwilt @T3P3Tony last edited by

                            @t3p3tony said in Add a trigger for a user gcode file after print header is read:

                            @fcwilt i think you miss the point that this must work to reject files that do not have something set in the print file.

                            so adding:
                            ;MYSPECIALMAGICNAME=ValidName

                            or whatever to the start gcode in the slicer would be parsed as long as was in the limits of whatever is parsed from a file, and the parsing element was extended to look for it.

                            The OP mentioned the situation where the slicer was setup for the wrong printer. So what difference does it make where the check is done, be it in the slicer custom code or in some macro invoked at the start of a print?

                            Frederick

                            Printers: A FT-5 with the 713 upgrade bits. A custom MarkForged style. A small Utilmaker style and a CoreXY from kits. Various hotends. Using Duets (2 and 3) running 3.4.1

                            T3P3Tony 1 Reply Last reply Reply Quote 0
                            • T3P3Tony
                              T3P3Tony administrators @fcwilt last edited by

                              @fcwilt because if a 3rd party slicer is used to generate the gcode - this check needs to work (and reject the gcode file). So a solution that works by assuming the slicer has the right check in its header does not cover that pert of the requirement.

                              www.duet3d.com

                              fcwilt 1 Reply Last reply Reply Quote 0
                              • fcwilt
                                fcwilt @T3P3Tony last edited by

                                @t3p3tony said in Add a trigger for a user gcode file after print header is read:

                                @fcwilt because if a 3rd party slicer is used to generate the gcode - this check needs to work (and reject the gcode file). So a solution that works by assuming the slicer has the right check in its header does not cover that pert of the requirement.

                                Understood but the OP mentioned setting a global variable in the slicer custom code. That approach also relies on an assumption - that the slicer set the variable - does it not?

                                Frederick

                                Printers: A FT-5 with the 713 upgrade bits. A custom MarkForged style. A small Utilmaker style and a CoreXY from kits. Various hotends. Using Duets (2 and 3) running 3.4.1

                                T3P3Tony 1 Reply Last reply Reply Quote 0
                                • T3P3Tony
                                  T3P3Tony administrators @fcwilt last edited by

                                  @fcwilt if the variable is not set (or comment flag in the header is not there) then the file will be rejected and not printed in the method we are proposing. If the check is in the start gcode then 3rd party files without a check will not be rejected. That's why two elements are needed. An identified of some sort in the file, and a process to check that identified, either when any file is uploaded, or printed.

                                  www.duet3d.com

                                  fcwilt 1 Reply Last reply Reply Quote 0
                                  • fcwilt
                                    fcwilt @T3P3Tony last edited by

                                    @t3p3tony said in Add a trigger for a user gcode file after print header is read:

                                    @fcwilt if the variable is not set (or comment flag in the header is not there) then the file will be rejected and not printed in the method we are proposing. If the check is in the start gcode then 3rd party files without a check will not be rejected. That's why two elements are needed. An identified of some sort in the file, and a process to check that identified, either when any file is uploaded, or printed.

                                    OK that much is clear.

                                    But without a way to protect the Duet code from modification there doesn't seem to be much to prevent bypassing the check.

                                    Well, as long as the OP is happy that is all that matters.

                                    Frederick

                                    Printers: A FT-5 with the 713 upgrade bits. A custom MarkForged style. A small Utilmaker style and a CoreXY from kits. Various hotends. Using Duets (2 and 3) running 3.4.1

                                    T3P3Tony 1 Reply Last reply Reply Quote 0
                                    • T3P3Tony
                                      T3P3Tony administrators @fcwilt last edited by

                                      @fcwilt yes this is not a high security measure but it would prevent naive users from printing their own sliced gcode on the wrong machines.

                                      www.duet3d.com

                                      mikeabuilder 1 Reply Last reply Reply Quote 0
                                      • mikeabuilder
                                        mikeabuilder @T3P3Tony last edited by mikeabuilder

                                        @t3p3tony has the gist of my objective. I think the initial implementation using daemon.g looks like this:

                                        in start.g:
                                        Set a variable called "stop_print = true"

                                        In daemon.g:
                                        Check the value of "stop_print". If true, abort the print, if not true, continue.

                                        In the slicer, I put a line in the custom gcode for this printer type (PrusaSlicer has this capability, I assume others do too):
                                        Set "stop_print = false"

                                        With this setup, any slicer that does not incorporate the "stop_print =false" line will result in a print aborted within one second.

                                        It will be possible for anyone to maliciously edit their gcode file, but I'm not worried about that user. I'm worried about the user that sliced for some other printer by accident.

                                        T3P3Tony 1 Reply Last reply Reply Quote 0
                                        • T3P3Tony
                                          T3P3Tony administrators @mikeabuilder last edited by

                                          @mikeabuilder that sounds like it should work. I would set a while loop up inside deamon.g to check stop print every (say) 2 seconds with a delay of G4 S2. You don't want deamon.g looping constantly.

                                          www.duet3d.com

                                          1 Reply Last reply Reply Quote 0
                                          • fcwilt
                                            fcwilt last edited by

                                            @mikeabuilder said in Add a trigger for a user gcode file after print header is read:

                                            @t3p3tony has the gist of my objective. I think the initial implementation using daemon.g looks like this:

                                            in start.g:
                                            Set a variable called "stop_print = true"

                                            In daemon.g:
                                            Check the value of "stop_print". If true, abort the print, if not true, continue.

                                            In the slicer, I put a line in the custom gcode for this printer type (PrusaSlicer has this capability, I assume others do too):
                                            Set "stop_print = false"

                                            With this setup, any slicer that does not incorporate the "stop_print =false" line will result in a print aborted within one second.

                                            It will be possible for anyone to maliciously edit their gcode file, but I'm not worried about that user. I'm worried about the user that sliced for some other printer by accident.

                                            Basically that will do what you seek.

                                            A couple of things:

                                            • I think the variable will have to be global
                                            • You will need to create the variable in config.g OR have code in start.g that creates or sets the variable as needed
                                            • The daemon.g file runs every 10 seconds - unless there has been a recent change I am not aware of

                                            Just FYI it is quite possible to run the same sliced code on different printers. It all depends on how much in the way of printer specific elements are included in the generated code. I use at different times Simplifi3D, Cura, Prusa or ideaMaker and generally I can run any of the sliced code on any of my printers.


                                            Best of luck!

                                            Frederick

                                            Printers: A FT-5 with the 713 upgrade bits. A custom MarkForged style. A small Utilmaker style and a CoreXY from kits. Various hotends. Using Duets (2 and 3) running 3.4.1

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Unless otherwise noted, all forum content is licensed under CC-BY-SA