functions/public/Get-KlippyHeater.ps1

function Get-KlippyHeater {
    <#
    .SYNOPSIS
        Gets heater status from a Klipper printer.

    .DESCRIPTION
        Retrieves the status of all heaters configured on the printer,
        including extruder heaters, bed heater, and generic heaters.

    .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 Name
        Filter by specific heater name. Supports wildcards.

    .PARAMETER Type
        Filter by heater type (Extruder, Bed, Generic).

    .EXAMPLE
        Get-KlippyHeater
        Gets all heaters from the default printer.

    .EXAMPLE
        Get-KlippyHeater -PrinterName "voronv2" -Type Bed
        Gets the bed heater from the specified printer.

    .EXAMPLE
        Get-KlippyHeater -Name "extruder*"
        Gets all extruder heaters.

    .OUTPUTS
        KlippyCLI.Heater objects.
    #>

    [CmdletBinding(DefaultParameterSetName = 'Default')]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(ParameterSetName = 'ById')]
        [ValidateNotNullOrEmpty()]
        [string]$Id,

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

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

        [Parameter()]
        [string]$Name,

        [Parameter()]
        [ValidateSet('Extruder', 'Bed', 'Generic')]
        [string]$Type
    )

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

        $printer = Resolve-KlippyPrinterTarget @resolveParams

        try {
            # Get list of available objects
            $allObjects = Invoke-KlippyJsonRpc -Printer $printer -Method "printer/objects/list"

            # Find heater objects
            $heaterObjects = foreach ($obj in $allObjects.Objects) {
                if ($obj -match '^extruder\d*$') {
                    [PSCustomObject]@{
                        ObjectName = $obj
                        HeaterType = 'Extruder'
                        HeaterName = $obj
                    }
                }
                elseif ($obj -eq 'heater_bed') {
                    [PSCustomObject]@{
                        ObjectName = $obj
                        HeaterType = 'Bed'
                        HeaterName = 'heater_bed'
                    }
                }
                elseif ($obj.StartsWith('heater_generic ')) {
                    [PSCustomObject]@{
                        ObjectName = $obj
                        HeaterType = 'Generic'
                        HeaterName = ($obj -split ' ', 2)[1]
                    }
                }
            }

            # Apply type filter
            if ($Type) {
                $heaterObjects = $heaterObjects | Where-Object { $_.HeaterType -eq $Type }
            }

            # Apply name filter
            if ($Name) {
                $heaterObjects = $heaterObjects | Where-Object { $_.HeaterName -like $Name }
            }

            if (-not $heaterObjects) {
                Write-Verbose "No heaters found matching the specified criteria."
                return
            }

            # Build query string
            $queryParts = $heaterObjects | ForEach-Object { [System.Uri]::EscapeDataString($_.ObjectName) }
            $endpoint = "printer/objects/query?" + ($queryParts -join '&')

            $response = Invoke-KlippyJsonRpc -Printer $printer -Method $endpoint -NoNormalize

            # Process results
            foreach ($heater in $heaterObjects) {
                $data = $response.status.($heater.ObjectName)
                if ($data) {
                    [PSCustomObject]@{
                        PSTypeName  = 'KlippyCLI.Heater'
                        PrinterId   = $printer.Id
                        PrinterName = $printer.PrinterName
                        Name        = $heater.HeaterName
                        Type        = $heater.HeaterType
                        Temperature = [math]::Round($data.temperature, 1)
                        Target      = $data.target
                        Power       = if ($null -ne $data.power) { [math]::Round($data.power * 100, 1) } else { $null }
                    }
                }
            }
        }
        catch {
            Write-Error "Failed to get heaters from '$($printer.PrinterName)': $_"
        }
    }
}