functions/public/Invoke-KlippyHome.ps1

function Invoke-KlippyHome {
    <#
    .SYNOPSIS
        Homes one or more axes on a Klipper printer.

    .DESCRIPTION
        Sends homing commands to the printer. Can home specific axes or all axes.

    .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 Axes
        The axes to home. Valid values: X, Y, Z, or combinations.
        If not specified, homes all axes (G28).

    .PARAMETER Wait
        Wait for the homing operation to complete before returning.

    .EXAMPLE
        Invoke-KlippyHome
        Homes all axes on the default printer.

    .EXAMPLE
        Invoke-KlippyHome -PrinterName "voronv2" -Axes X, Y
        Homes X and Y axes on the specified printer.

    .EXAMPLE
        Invoke-KlippyHome -Axes Z -Wait
        Homes Z axis and waits for completion.

    .OUTPUTS
        None or PSCustomObject if -Wait is specified.
    #>

    [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Default')]
    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()]
        [ValidateSet('X', 'Y', 'Z')]
        [string[]]$Axes,

        [Parameter()]
        [switch]$Wait
    )

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

        $printer = Resolve-KlippyPrinterTarget @resolveParams

        # Build G28 command
        $gcode = "G28"
        if ($Axes -and $Axes.Count -gt 0) {
            $gcode = "G28 $($Axes -join ' ')"
        }

        $axesDescription = if ($Axes) { $Axes -join ', ' } else { "all" }

        if ($PSCmdlet.ShouldProcess($printer.PrinterName, "Home axes: $axesDescription")) {
            Write-Verbose "[$($printer.PrinterName)] Sending: $gcode"

            try {
                # Send the gcode command
                $endpoint = "printer/gcode/script?script=$([System.Uri]::EscapeDataString($gcode))"
                $null = Invoke-KlippyJsonRpc -Printer $printer -Method $endpoint

                Write-Verbose "[$($printer.PrinterName)] Homing command sent"

                if ($Wait) {
                    Write-Verbose "[$($printer.PrinterName)] Waiting for homing to complete..."

                    # Wait for homing to complete by monitoring toolhead.homed_axes
                    $expectedAxes = if ($Axes) {
                        ($Axes | ForEach-Object { $_.ToLower() }) -join ''
                    } else {
                        "xyz"
                    }

                    $timeout = 120  # 2 minutes max for homing
                    $startTime = [datetime]::UtcNow

                    while (([datetime]::UtcNow - $startTime).TotalSeconds -lt $timeout) {
                        Start-Sleep -Milliseconds 500

                        $status = Get-KlippyObject -PrinterName $printer.PrinterName -ObjectName "toolhead" -Attributes "homed_axes"
                        $homedAxes = $status.HomedAxes

                        Write-Verbose "Homed axes: $homedAxes"

                        # Check if all requested axes are homed
                        $allHomed = $true
                        foreach ($axis in $expectedAxes.ToCharArray()) {
                            if ($homedAxes -notmatch $axis) {
                                $allHomed = $false
                                break
                            }
                        }

                        if ($allHomed) {
                            Write-Verbose "[$($printer.PrinterName)] Homing complete"

                            return [PSCustomObject]@{
                                PSTypeName  = 'KlippyCLI.HomeResult'
                                PrinterId   = $printer.Id
                                PrinterName = $printer.PrinterName
                                Axes        = $axesDescription
                                HomedAxes   = $homedAxes
                                Duration    = [datetime]::UtcNow - $startTime
                                Success     = $true
                            }
                        }
                    }

                    Write-Warning "[$($printer.PrinterName)] Homing timed out after $timeout seconds"
                    return [PSCustomObject]@{
                        PSTypeName  = 'KlippyCLI.HomeResult'
                        PrinterId   = $printer.Id
                        PrinterName = $printer.PrinterName
                        Axes        = $axesDescription
                        HomedAxes   = $homedAxes
                        Duration    = [datetime]::UtcNow - $startTime
                        Success     = $false
                    }
                }
            }
            catch {
                Write-Error "Failed to home '$($printer.PrinterName)': $_"
            }
        }
    }
}