functions/public/Invoke-KlippyGcode.ps1
|
function Invoke-KlippyGcode { <# .SYNOPSIS Executes G-code commands on a Klipper printer. .DESCRIPTION Sends G-code commands to the printer for execution. Supports single commands, multiple commands, and script files. .PARAMETER Id The unique identifier of the printer. .PARAMETER PrinterName The friendly name of the printer. .PARAMETER InputObject A printer object from pipeline input. .PARAMETER Gcode The G-code command(s) to execute. Can be a single command, multiple commands separated by newlines, or an array. .PARAMETER Path Path to a G-code script file to execute. .EXAMPLE Invoke-KlippyGcode -Gcode "G28" Homes all axes on the default printer. .EXAMPLE Invoke-KlippyGcode -PrinterName "voronv2" -Gcode "M104 S200", "M140 S60" Sets extruder to 200C and bed to 60C. .EXAMPLE Invoke-KlippyGcode -Gcode @" G28 G1 X150 Y150 Z50 F3000 "@ Executes multiple G-code commands. .EXAMPLE "G28", "G1 Z10 F600" | Invoke-KlippyGcode -PrinterName "voronv2" Pipes G-code commands to the printer. .EXAMPLE Invoke-KlippyGcode -Path "/path/to/macro.gcode" -PrinterName "voronv2" Executes commands from a file. .OUTPUTS PSCustomObject with execution result. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter()] [ValidateNotNullOrEmpty()] [string]$Id, [Parameter()] [ValidateNotNullOrEmpty()] [string]$PrinterName, [Parameter()] [PSCustomObject]$InputObject, [Parameter(Position = 0, ValueFromPipeline = $true)] [string[]]$Gcode, [Parameter()] [Alias('Script')] [string]$Path ) begin { $allCommands = [System.Collections.Generic.List[string]]::new() # Resolve printer once at the start $resolveParams = @{} if ($Id) { $resolveParams['Id'] = $Id } elseif ($PrinterName) { $resolveParams['PrinterName'] = $PrinterName } elseif ($InputObject) { $resolveParams['InputObject'] = $InputObject } $printer = Resolve-KlippyPrinterTarget @resolveParams # Load from file if Path specified if ($Path) { if (-not (Test-Path -Path $Path -PathType Leaf)) { throw "Script file not found: $Path" } $scriptContent = Get-Content -Path $Path -Raw $lines = $scriptContent -split "`r?`n" | Where-Object { $line = $_.Trim() $line -and -not $line.StartsWith(';') -and -not $line.StartsWith('#') } foreach ($line in $lines) { $allCommands.Add($line.Trim()) } } } process { if (-not $Path -and $Gcode) { foreach ($cmd in $Gcode) { # Split multi-line strings $lines = $cmd -split "`r?`n" | Where-Object { $line = $_.Trim() $line -and -not $line.StartsWith(';') -and -not $line.StartsWith('#') } foreach ($line in $lines) { $allCommands.Add($line.Trim()) } } } } end { if ($allCommands.Count -eq 0) { Write-Warning "No G-code commands to execute. Provide -Gcode or -Path." return } # Join all commands with newline for batch execution $gcodeScript = $allCommands -join "`n" $commandPreview = if ($allCommands.Count -le 3) { $allCommands -join "; " } else { "$($allCommands[0]); $($allCommands[1]); ... ($($allCommands.Count) commands)" } if ($PSCmdlet.ShouldProcess($printer.PrinterName, "Execute G-code: $commandPreview")) { try { Write-Verbose "[$($printer.PrinterName)] Executing $($allCommands.Count) G-code command(s)" foreach ($cmd in $allCommands) { Write-Verbose " > $cmd" } # URL encode the script $encodedScript = [System.Uri]::EscapeDataString($gcodeScript) $endpoint = "printer/gcode/script?script=$encodedScript" $null = Invoke-KlippyJsonRpc -Printer $printer -Method $endpoint Write-Verbose "[$($printer.PrinterName)] G-code executed successfully" # Return result object [PSCustomObject]@{ PSTypeName = 'KlippyCLI.GcodeResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName CommandCount = $allCommands.Count Commands = $allCommands.ToArray() Success = $true } } catch { Write-Error "Failed to execute G-code on '$($printer.PrinterName)': $_" [PSCustomObject]@{ PSTypeName = 'KlippyCLI.GcodeResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName CommandCount = $allCommands.Count Commands = $allCommands.ToArray() Success = $false Error = $_.Exception.Message } } } } } |