Add a trigger for a user gcode file after print header is read
-
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.
-
@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.:
I see feature request as two fold:
- Add another field to be parsed.
- 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.
-
@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
-
@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.
-
@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=ValidNameor 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.
-
@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=ValidNameor 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
-
@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.
-
@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
-
@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.
-
@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
-
@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.
-
@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.
-
@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.
-
@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