functions/public/Restart-KlippyFirmware.ps1

function Restart-KlippyFirmware {
    <#
    .SYNOPSIS
        Restarts the Klipper firmware.

    .DESCRIPTION
        Restarts the Klipper firmware without rebooting the host.
        This is equivalent to FIRMWARE_RESTART in Klipper.
        Use this to recover from an emergency stop or to apply config changes.

    .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 Wait
        Wait for the printer to become ready after restart.

    .PARAMETER Timeout
        Timeout in seconds when using -Wait. Default is 60.

    .EXAMPLE
        Restart-KlippyFirmware
        Restarts the firmware on the default printer.

    .EXAMPLE
        Restart-KlippyFirmware -PrinterName "voronv2" -Wait
        Restarts firmware and waits for ready state.

    .OUTPUTS
        None, or printer status if -Wait is specified.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(ParameterSetName = 'ById')]
        [ValidateNotNullOrEmpty()]
        [string]$Id,

        [Parameter(ParameterSetName = 'ByName', Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]$PrinterName,

        [Parameter(ParameterSetName = 'ByObject', ValueFromPipeline = $true)]
        [PSCustomObject]$InputObject,

        [Parameter()]
        [switch]$Wait,

        [Parameter()]
        [ValidateRange(10, 300)]
        [int]$Timeout = 60
    )

    process {
        # Resolve printer
        $resolveParams = @{}
        switch ($PSCmdlet.ParameterSetName) {
            'ById' { $resolveParams['Id'] = $Id }
            'ByName' { $resolveParams['PrinterName'] = $PrinterName }
            'ByObject' { $resolveParams['InputObject'] = $InputObject }
        }

        $printer = Resolve-KlippyPrinterTarget @resolveParams

        if ($PSCmdlet.ShouldProcess($printer.PrinterName, "Firmware Restart")) {
            try {
                Write-Verbose "[$($printer.PrinterName)] Restarting firmware..."
                $null = Invoke-KlippyJsonRpc -Printer $printer -Method "printer/firmware_restart"
                Write-Host "Firmware restart initiated on '$($printer.PrinterName)'." -ForegroundColor Green

                if ($Wait) {
                    Write-Host "Waiting for printer to become ready..." -ForegroundColor Yellow
                    Start-Sleep -Seconds 3  # Give it a moment to start restarting

                    $deadline = [datetime]::UtcNow.AddSeconds($Timeout)
                    $ready = $false

                    while ([datetime]::UtcNow -lt $deadline) {
                        Start-Sleep -Seconds 2
                        try {
                            $status = Get-KlippyStatus -Id $printer.Id -ErrorAction SilentlyContinue
                            if ($status -and $status.State -eq 'ready') {
                                $ready = $true
                                break
                            }
                            elseif ($status) {
                                Write-Verbose "Current state: $($status.State)"
                            }
                        }
                        catch {
                            Write-Verbose "Waiting for Klipper to respond..."
                        }
                    }

                    if ($ready) {
                        Write-Host "Printer '$($printer.PrinterName)' is ready." -ForegroundColor Green
                        return $status
                    }
                    else {
                        Write-Warning "Timeout waiting for printer to become ready."
                    }
                }
            }
            catch {
                Write-Error "Failed to restart firmware on '$($printer.PrinterName)': $_"
            }
        }
    }
}