functions/public/Wait-KlippyHeaterTemperature.ps1
|
function Wait-KlippyHeaterTemperature { <# .SYNOPSIS Waits for a heater to reach a target temperature. .DESCRIPTION Monitors heater temperature via WebSocket and waits until the temperature reaches the target within the specified tolerance. .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 Heater The heater to monitor. Common values: "extruder", "heater_bed", "extruder1". Default is "extruder". .PARAMETER Temperature The target temperature to wait for. If not specified, waits for the heater's current target temperature. .PARAMETER Tolerance Temperature tolerance in degrees. Default is 2. .PARAMETER Timeout Maximum time to wait in seconds. Default is 600 (10 minutes). .PARAMETER Quiet Suppress progress messages. .EXAMPLE Wait-KlippyHeaterTemperature -Heater "extruder" -Temperature 200 Waits for extruder to reach 200C. .EXAMPLE Wait-KlippyHeaterTemperature -Heater "heater_bed" Waits for bed to reach its current target temperature. .EXAMPLE Invoke-KlippyGcode "M104 S200" | Wait-KlippyHeaterTemperature -Heater "extruder" Sets extruder temp and waits for it to heat up. .OUTPUTS PSCustomObject with temperature state 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()] [ValidateNotNullOrEmpty()] [string]$Heater = 'extruder', [Parameter()] [ValidateRange(0, 500)] [double]$Temperature, [Parameter()] [ValidateRange(0.1, 20)] [double]$Tolerance = 2, [Parameter()] [ValidateRange(1, 3600)] [int]$Timeout = 600, [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 # Get current heater state and target $targetTemp = $Temperature try { $heaterState = Get-KlippyObject -PrinterName $printer.PrinterName -ObjectName $Heater -Attributes "temperature", "target" if (-not $PSBoundParameters.ContainsKey('Temperature')) { $targetTemp = $heaterState.Target if ($targetTemp -eq 0) { Write-Warning "[$($printer.PrinterName)] Heater '$Heater' has no target temperature set." return [PSCustomObject]@{ PSTypeName = 'KlippyCLI.WaitResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName Heater = $Heater Temperature = $heaterState.Temperature Target = 0 WaitTime = [TimeSpan]::Zero Success = $false Error = "No target temperature set" } } } # Check if already at temperature $currentTemp = $heaterState.Temperature if ([Math]::Abs($currentTemp - $targetTemp) -le $Tolerance) { if (-not $Quiet) { Write-Host "[$($printer.PrinterName)] $Heater already at temperature: $([Math]::Round($currentTemp, 1))C (target: $targetTemp`C)" } return [PSCustomObject]@{ PSTypeName = 'KlippyCLI.WaitResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName Heater = $Heater Temperature = $currentTemp Target = $targetTemp WaitTime = [TimeSpan]::Zero Success = $true } } } catch { Write-Error "[$($printer.PrinterName)] Failed to get heater state for '$Heater': $_" return } if (-not $Quiet) { Write-Host "[$($printer.PrinterName)] Waiting for $Heater to reach $targetTemp`C..." -NoNewline } $startTime = [datetime]::UtcNow $ws = $null $lastTemp = 0 try { $ws = New-KlippyWebSocketClient -Printer $printer # Subscribe to the heater $subscribeObj = @{} $subscribeObj[$Heater] = @('temperature', 'target') $null = $ws.Subscribe($subscribeObj) $deadline = [datetime]::UtcNow.AddSeconds($Timeout) $lastProgressTime = [datetime]::MinValue while ([datetime]::UtcNow -lt $deadline) { $message = $ws.Receive(1000) if ($null -ne $message -and $message.method -eq 'notify_status_update' -and $message.params) { $status = $message.params[0] $heaterData = $status.$Heater if ($heaterData.temperature) { $lastTemp = $heaterData.temperature # Check if at target if ([Math]::Abs($lastTemp - $targetTemp) -le $Tolerance) { if (-not $Quiet) { Write-Host " Done! ($([Math]::Round($lastTemp, 1))C)" } return [PSCustomObject]@{ PSTypeName = 'KlippyCLI.WaitResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName Heater = $Heater Temperature = $lastTemp Target = $targetTemp WaitTime = [datetime]::UtcNow - $startTime Success = $true } } # Progress update every 5 seconds if (-not $Quiet -and ([datetime]::UtcNow - $lastProgressTime).TotalSeconds -ge 5) { Write-Host " $([Math]::Round($lastTemp, 1))C" -NoNewline $lastProgressTime = [datetime]::UtcNow } } } } # Timeout if (-not $Quiet) { Write-Host " Timeout!" } Write-Warning "[$($printer.PrinterName)] Timeout waiting for $Heater to reach $targetTemp`C. Current: $([Math]::Round($lastTemp, 1))C" return [PSCustomObject]@{ PSTypeName = 'KlippyCLI.WaitResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName Heater = $Heater Temperature = $lastTemp Target = $targetTemp WaitTime = [datetime]::UtcNow - $startTime Success = $false } } catch { if (-not $Quiet) { Write-Host " Error!" } Write-Error "[$($printer.PrinterName)] Error waiting for temperature: $_" return [PSCustomObject]@{ PSTypeName = 'KlippyCLI.WaitResult' PrinterId = $printer.Id PrinterName = $printer.PrinterName Heater = $Heater Temperature = $lastTemp Target = $targetTemp WaitTime = [datetime]::UtcNow - $startTime Success = $false Error = $_.Exception.Message } } finally { if ($ws) { $ws.Close() } } } } |