functions/public/Wait-KlippyPrintFinished.ps1
|
function Wait-KlippyPrintFinished { <# .SYNOPSIS Waits for a print job to finish on a Klipper printer. .DESCRIPTION Monitors the print_stats state via WebSocket and waits until the print completes, is cancelled, or errors out. .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 Timeout Maximum time to wait in seconds. Default is 86400 (24 hours). .PARAMETER ShowProgress Display print progress updates. .PARAMETER Quiet Suppress all progress messages. .EXAMPLE Wait-KlippyPrintFinished -PrinterName "voronv2" -ShowProgress Waits for the current print to finish with progress updates. .EXAMPLE Start-KlippyPrint "test.gcode" | Wait-KlippyPrintFinished -Timeout 3600 Starts a print and waits up to 1 hour for it to finish. .OUTPUTS PSCustomObject with print completion information. #> [CmdletBinding(DefaultParameterSetName = 'Default')] [OutputType([PSCustomObject])] param( [Parameter(Mandatory = $true, ParameterSetName = 'ById')] [ValidateNotNullOrEmpty()] [string]$Id, [Parameter(Mandatory = $true, ParameterSetName = 'ByName', Position = 0)] [ValidateNotNullOrEmpty()] [string]$PrinterName, [Parameter(Mandatory = $true, ParameterSetName = 'ByObject', ValueFromPipeline = $true)] [PSCustomObject]$InputObject, [Parameter()] [ValidateRange(1, 604800)] # Up to 1 week [int]$Timeout = 86400, [Parameter()] [switch]$ShowProgress, [Parameter()] [switch]$Quiet ) process { # Resolve printer $resolveParams = @{} switch ($PSCmdlet.ParameterSetName) { 'ById' { $resolveParams['Id'] = $Id } 'ByName' { $resolveParams['PrinterName'] = $PrinterName } 'ByObject' { $resolveParams['InputObject'] = $InputObject } } $printer = Resolve-KlippyPrinterTarget @resolveParams # Terminal states $terminalStates = @('complete', 'cancelled', 'error', 'standby') # Check current state try { $printStats = Get-KlippyObject -PrinterName $printer.PrinterName -ObjectName "print_stats" if ($printStats.State -in $terminalStates) { if (-not $Quiet) { Write-Host "[$($printer.PrinterName)] Print already finished. State: $($printStats.State)" } return [PSCustomObject]@{ PSTypeName = 'KlippyCLI.WaitResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName State = $printStats.State Filename = $printStats.Filename PrintDuration = [TimeSpan]::FromSeconds($printStats.PrintDuration) FilamentUsed = [Math]::Round($printStats.FilamentUsed / 1000, 2) WaitTime = [TimeSpan]::Zero Success = ($printStats.State -eq 'complete') } } } catch { Write-Verbose "Could not get current print state: $_" } if (-not $Quiet) { Write-Host "[$($printer.PrinterName)] Waiting for print to finish..." } $startTime = [datetime]::UtcNow $ws = $null $lastState = 'unknown' $lastProgress = 0 $filename = '' $printDuration = 0 $filamentUsed = 0 try { $ws = New-KlippyWebSocketClient -Printer $printer $null = $ws.Subscribe(@{ print_stats = @('state', 'filename', 'print_duration', 'filament_used') display_status = @('progress') }) $deadline = [datetime]::UtcNow.AddSeconds($Timeout) $lastProgressUpdate = [datetime]::MinValue while ([datetime]::UtcNow -lt $deadline) { $message = $ws.Receive(5000) if ($null -ne $message -and $message.method -eq 'notify_status_update' -and $message.params) { $status = $message.params[0] # Update print stats if ($status.print_stats) { if ($status.print_stats.state) { $lastState = $status.print_stats.state } if ($status.print_stats.filename) { $filename = $status.print_stats.filename } if ($status.print_stats.print_duration) { $printDuration = $status.print_stats.print_duration } if ($status.print_stats.filament_used) { $filamentUsed = $status.print_stats.filament_used } # Check for terminal state if ($lastState -in $terminalStates) { $stateMessage = switch ($lastState) { 'complete' { "Complete!" } 'cancelled' { "Cancelled" } 'error' { "Error!" } 'standby' { "Stopped" } default { $lastState } } if (-not $Quiet) { Write-Host "[$($printer.PrinterName)] Print finished: $stateMessage" } return [PSCustomObject]@{ PSTypeName = 'KlippyCLI.WaitResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName State = $lastState Filename = $filename PrintDuration = [TimeSpan]::FromSeconds([int]$printDuration) FilamentUsed = [Math]::Round($filamentUsed / 1000, 2) WaitTime = [datetime]::UtcNow - $startTime Success = ($lastState -eq 'complete') } } } # Update progress if ($status.display_status.progress) { $lastProgress = [Math]::Round($status.display_status.progress * 100, 1) } # Show progress if enabled if ($ShowProgress -and -not $Quiet -and ([datetime]::UtcNow - $lastProgressUpdate).TotalSeconds -ge 30) { $duration = [TimeSpan]::FromSeconds([int]$printDuration) Write-Host " Progress: $lastProgress% | Duration: $($duration.ToString('hh\:mm\:ss')) | State: $lastState" $lastProgressUpdate = [datetime]::UtcNow } } } # Timeout if (-not $Quiet) { Write-Host "[$($printer.PrinterName)] Timeout!" } Write-Warning "[$($printer.PrinterName)] Timeout waiting for print to finish after $Timeout seconds" return [PSCustomObject]@{ PSTypeName = 'KlippyCLI.WaitResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName State = $lastState Filename = $filename Progress = $lastProgress PrintDuration = [TimeSpan]::FromSeconds([int]$printDuration) FilamentUsed = [Math]::Round($filamentUsed / 1000, 2) WaitTime = [datetime]::UtcNow - $startTime Success = $false } } catch { if (-not $Quiet) { Write-Host "[$($printer.PrinterName)] Error!" } Write-Error "[$($printer.PrinterName)] Error waiting for print to finish: $_" return [PSCustomObject]@{ PSTypeName = 'KlippyCLI.WaitResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName State = $lastState Filename = $filename WaitTime = [datetime]::UtcNow - $startTime Success = $false Error = $_.Exception.Message } } finally { if ($ws) { $ws.Close() } } } } |