functions/Get-WUGDeviceAttribute.ps1

    <#
    .SYNOPSIS
    Retrieves device attributes from the WhatsUp Gold API.
 
    .DESCRIPTION
    Fetches attributes for specified devices, with options to filter by names, name contains, value contains, or attribute IDs.
    Supports fetching specific attributes using AttributeId.
    Handles paging and error handling efficiently.
 
    .PARAMETER DeviceId
    The ID(s) of the device(s) to retrieve attributes from.
 
    .PARAMETER Names
    An array of attribute names to filter the results.
 
    .PARAMETER NameContains
    A string to match attribute names that contain this value.
 
    .PARAMETER ValueContains
    A string to match attribute values that contain this value.
 
    .PARAMETER AttributeId
    The ID(s) of specific attributes to retrieve.
 
    .PARAMETER Limit
    The maximum number of attributes to retrieve per device (default is 250).
 
    .EXAMPLE
    Get-WUGDeviceAttribute -DeviceId 2367 -Names "TestAttribute"
 
    Retrieves the attribute named "TestAttribute" for device 2367.
 
    .EXAMPLE
    Get-WUGDeviceAttribute -DeviceId 2367 -AttributeId 28852, 28853
 
    Retrieves the attributes with IDs 28852 and 28853 for device 2367.
 
    .NOTES
    When specifying -AttributeId, you can only specify one DeviceId.
    #>

    function Get-WUGDeviceAttribute {
        [CmdletBinding(DefaultParameterSetName = 'Default')]
        param(
            [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'Default', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
            [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'ByNames', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
            [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'ByNameContains', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
            [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'ByValueContains', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
            [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'ByAttributeId', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
            [Alias('id')]
            [int[]]$DeviceId,
    
            [Parameter(Mandatory = $true, ParameterSetName = 'ByNames')]
            [string[]]$Names,
    
            [Parameter(Mandatory = $true, ParameterSetName = 'ByNameContains')]
            [string]$NameContains,
    
            [Parameter(Mandatory = $true, ParameterSetName = 'ByValueContains')]
            [string]$ValueContains,
    
            [Parameter(Mandatory = $true, ParameterSetName = 'ByAttributeId')]
            [int[]]$AttributeId,
    
            [Parameter(ParameterSetName = 'ByNames')]
            [Parameter(ParameterSetName = 'ByNameContains')]
            [Parameter(ParameterSetName = 'ByValueContains')]
            [Parameter(ParameterSetName = 'Default')]
            [ValidateRange(1, 250)]
            [int]$Limit = 250
        )
    
        begin {
            Write-Debug "Initializing Get-WUGDeviceAttribute function."
            Write-Debug "ParameterSetName: $($PSCmdlet.ParameterSetName)"
            Write-Debug "DeviceId: $DeviceId"
            Write-Debug "Names: $Names"
            Write-Debug "NameContains: $NameContains"
            Write-Debug "ValueContains: $ValueContains"
            Write-Debug "AttributeId: $AttributeId"
            Write-Debug "Limit: $Limit"
    
            # Enforce that when -AttributeId is specified, only one DeviceId can be specified
            if ($PSCmdlet.ParameterSetName -eq 'ByAttributeId' -and $DeviceId.Count -gt 1) {
                throw "When specifying -AttributeId, you can only specify one DeviceId."
            }
    
            # Initialize the pipeline flag
            $bpipeline = $false
    
            # Initialize collections
            $finalOutput = @()
            $collectedDeviceInfo = @()
        }
    
        process {
            # Process input objects
            if ($null -ne $_ -and $_.PSObject.Properties.Match('id').Count -gt 0) {
                # Input is a device object
                $inputObject = $_
                $deviceId = $inputObject.id
                $deviceName = $inputObject.name
                $networkAddress = $inputObject.networkAddress
                $hostName = $inputObject.hostName
    
                $collectedDeviceInfo += @{
                    DeviceId       = $deviceId
                    DeviceName     = $deviceName
                    NetworkAddress = $networkAddress
                    HostName       = $hostName
                }
                $bpipeline = $true
                Write-Debug "Pipeline input detected. DeviceId: $deviceId"
            }
            else {
                # Input is an array of Device IDs
                foreach ($id in $DeviceId) {
                    $collectedDeviceInfo += @{
                        DeviceId = $id
                    }
                    Write-Debug "Added DeviceId: $id to collectedDeviceInfo"
                }
            }
        }
    
        end {
            Write-Debug "Processing collected device information."
    
            $totalDevices = $collectedDeviceInfo.Count
            $currentDeviceIndex = 0
    
            foreach ($device in $collectedDeviceInfo) {
                $deviceId = $device.DeviceId
                $deviceName = $device.DeviceName
                $networkAddress = $device.NetworkAddress
                $hostName = $device.HostName
    
                $currentDeviceIndex++
                $devicePercentComplete = [Math]::Round(($currentDeviceIndex / $totalDevices) * 100, 2)
                Write-Progress -Id 1 -Activity "Fetching Attributes" -Status "Processing Device $currentDeviceIndex of $totalDevices (DeviceID: $deviceId)" -PercentComplete $devicePercentComplete
    
                if ($PSCmdlet.ParameterSetName -eq 'ByAttributeId') {
                    # Fetch specific attributes for a single device
                    foreach ($attrId in $AttributeId) {
                        $attributesUri = "$($global:WhatsUpServerBaseURI)/api/v1/devices/$deviceId/attributes/$attrId"
    
                        Write-Verbose "Requesting URI: $attributesUri"
    
                        try {
                            # Make the API call and retrieve the response
                            $result = Get-WUGAPIResponse -Uri $attributesUri -Method GET
    
                            if ($result.data) {
                                $attribute = $result.data
    
                                # Add additional device properties if available
                                if ($bpipeline) {
                                    if ($deviceName) {
                                        $attribute | Add-Member -NotePropertyName "DeviceName" -NotePropertyValue $deviceName -Force
                                    }
                                    if ($networkAddress) {
                                        $attribute | Add-Member -NotePropertyName "NetworkAddress" -NotePropertyValue $networkAddress -Force
                                    }
                                    if ($hostName) {
                                        $attribute | Add-Member -NotePropertyName "HostName" -NotePropertyValue $hostName -Force
                                    }
                                }
    
                                $finalOutput += $attribute
                            }
    
                        }
                        catch {
                            Write-Error "Error fetching attribute ID $attrId for DeviceID ${deviceId}: $($_.Exception.Message)"
                        }
                    }
                }
                else {
                    # Build the query string if filters are specified
                    $queryString = ""
                    if ($PSBoundParameters.ContainsKey('Names') -and $Names -and $Names.Count -gt 0) {
                        foreach ($name in $Names) {
                            if (![string]::IsNullOrWhiteSpace($name)) {
                                $queryString += "names=$([System.Web.HttpUtility]::UrlEncode($name))&"
                            }
                        }
                    }
                    if ($PSBoundParameters.ContainsKey('NameContains') -and ![string]::IsNullOrWhiteSpace($NameContains)) {
                        $queryString += "nameContains=$([System.Web.HttpUtility]::UrlEncode($NameContains))&"
                    }
                    if ($PSBoundParameters.ContainsKey('ValueContains') -and ![string]::IsNullOrWhiteSpace($ValueContains)) {
                        $queryString += "valueContains=$([System.Web.HttpUtility]::UrlEncode($ValueContains))&"
                    }
                    if ($PSBoundParameters.ContainsKey('Limit') -and $Limit -gt 0) {
                        $queryString += "limit=$Limit&"
                    }
                    # Trim the trailing "&" if it exists
                    $queryString = $queryString.TrimEnd('&')
    
                    # Construct the URI for fetching attributes
                    $attributesUri = "$($global:WhatsUpServerBaseURI)/api/v1/devices/$deviceId/attributes/-"
                    if (-not [string]::IsNullOrWhiteSpace($queryString)) {
                        $attributesUri += "?$queryString"
                        Write-Debug "Query String: $queryString"
                    }
    
                    $currentPageId = $null
                    $pageCount = 0
    
                    do {
                        if ($currentPageId) {
                            $uri = "$attributesUri&pageId=$currentPageId"
                        }
                        else {
                            $uri = $attributesUri
                        }
    
                        Write-Verbose "Requesting URI: $uri"
    
                        try {
                            # Make the API call and retrieve the response
                            $result = Get-WUGAPIResponse -Uri $uri -Method GET
    
                            if ($result.data) {
                                foreach ($attribute in $result.data) {
                                    # Add additional device properties if available
                                    if ($bpipeline) {
                                        if ($deviceName) {
                                            $attribute | Add-Member -NotePropertyName "DeviceName" -NotePropertyValue $deviceName -Force
                                        }
                                        if ($networkAddress) {
                                            $attribute | Add-Member -NotePropertyName "NetworkAddress" -NotePropertyValue $networkAddress -Force
                                        }
                                        if ($hostName) {
                                            $attribute | Add-Member -NotePropertyName "HostName" -NotePropertyValue $hostName -Force
                                        }
                                    }
    
                                    $finalOutput += $attribute
                                }
                            }
    
                            $currentPageId = $result.paging.nextPageId
                            $pageCount++
    
                            # Update paging progress
                            if ($result.paging.totalPages) {
                                $percentCompletePages = ($pageCount / $result.paging.totalPages) * 100
                                Write-Progress -Id 2 -Activity "Fetching Attributes for DeviceID: $deviceId" -Status "Page $pageCount of $($result.paging.totalPages)" -PercentComplete $percentCompletePages
                            } else {
                                Write-Progress -Id 2 -Activity "Fetching Attributes for DeviceID: ${deviceId}" -Status "Processing page $pageCount" -PercentComplete 0
                            }
    
                        }
                        catch {
                            Write-Error "Error fetching attributes for DeviceID ${deviceId}: $($_.Exception.Message)"
                            $currentPageId = $null
                        }
    
                    } while ($null -ne $currentPageId)
    
                    # Clear the paging progress for the current device after all pages are processed
                    Write-Progress -Id 2 -Activity "Fetching Attributes for DeviceID: $deviceId" -Status "Completed" -Completed
                }
            }
    
            # Clear the main device progress after all devices are processed
            Write-Progress -Id 1 -Activity "Fetching Attributes" -Status "All devices processed" -Completed
            Write-Debug "Get-WUGDeviceAttribute function completed."
    
            # Output the final data
            return $finalOutput
        }
    }
    
    


# SIG # Begin signature block
# MIIVvgYJKoZIhvcNAQcCoIIVrzCCFasCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBKcabOnI0Hf40w
# UHKKIJiwJrCFj4ilHutx7M4WptaSX6CCEfkwggVvMIIEV6ADAgECAhBI/JO0YFWU
# jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI
# DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM
# EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy
# dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG
# EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv
# IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA
# A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s
# hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD
# J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7
# P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme
# me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz
# T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q
# RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz
# mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc
# QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T
# OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/
# AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID
# AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD
# VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV
# HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE
# VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v
# ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE
# KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI
# hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF
# OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC
# J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ
# pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl
# d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH
# +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggYaMIIEAqADAgECAhBiHW0M
# UgGeO5B5FSCJIRwKMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYD
# VQQKEw9TZWN0aWdvIExpbWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENv
# ZGUgU2lnbmluZyBSb290IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5
# NTlaMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzAp
# BgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0G
# CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxjI
# ztNsfvxYB5UXeWUzCxEeAEZGbEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NV
# DgFigOMYzB2OKhdqfWGVoYW3haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/3
# 6F09fy1tsB8je/RV0mIk8XL/tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05Zw
# mRmTnAO5/arnY83jeNzhP06ShdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm
# +qxp4VqpB3MV/h53yl41aHU5pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUe
# dyz8rNyfQJy/aOs5b4s+ac7IH60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz4
# 4MPZ1f9+YEQIQty/NQd/2yGgW+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBM
# dlyh2n5HirY4jKnFH/9gRvd+QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQY
# MBaAFDLrkpr/NZZILyhAQnAgNpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritU
# pimqF6TNDDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNV
# HSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsG
# A1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1
# YmxpY0NvZGVTaWduaW5nUm9vdFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsG
# AQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2Rl
# U2lnbmluZ1Jvb3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0
# aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURh
# w1aVcdGRP4Wh60BAscjW4HL9hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0Zd
# OaWTsyNyBBsMLHqafvIhrCymlaS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajj
# cw5+w/KeFvPYfLF/ldYpmlG+vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNc
# WbWDRF/3sBp6fWXhz7DcML4iTAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalO
# hOfCipnx8CaLZeVme5yELg09Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJs
# zkyeiaerlphwoKx1uHRzNyE6bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z7
# 6mKnzAfZxCl/3dq3dUNw4rg3sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5J
# KdGvspbOrTfOXyXvmPL6E52z1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHH
# j95Ejza63zdrEcxWLDX6xWls/GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2
# Bev6SivBBOHY+uqiirZtg0y9ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/
# L9Uo2bC5a4CH2RwwggZkMIIEzKADAgECAhEA6IUbK/8zRw2NKvPg4jKHsTANBgkq
# hkiG9w0BAQwFADBUMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1p
# dGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2
# MB4XDTIzMDQxOTAwMDAwMFoXDTI2MDcxODIzNTk1OVowVTELMAkGA1UEBhMCVVMx
# FDASBgNVBAgMC0Nvbm5lY3RpY3V0MRcwFQYDVQQKDA5KYXNvbiBBbGJlcmlubzEX
# MBUGA1UEAwwOSmFzb24gQWxiZXJpbm8wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
# ggIKAoICAQC2JA01BehqpO3INejKVsKScaS9sd0Hjoz1tceFig6Yyu2glTKimH9n
# r9l5438Cjpc1x+n42gMfnS5Cza4tZUWr1usOq3d0TljKFOOSW8Uve1J+PC0f/Hxp
# DbI8hE38ICDmgv8EozBOgo4lPm/rDHVTHgiRZvy1H8gPTuE13ck2sevVslku2E2F
# 8wst5Kb12OqngF96RXptEeM0iTipPhfNinWCa8e58+mbt1dHCbX46593DRd3yQv+
# rvPkIh9QkMGmumfjV5lv1S3iqf/Vg6XP9R3lTPMWNO2IEzIjk12t817rU3xYyf2Q
# 4dlA/i1bRpFfjEVcxQiZJdQKnQlqd3hOk0tr8bxTI3RZxgOLRgC8mA9hgcnJmreM
# WP4CwXZUKKX13pMqzrX/qiSUsB+Mvcn7LHGEo9pJIBgMItZW4zn4uPzGbf53EQUW
# nPfUOSBdgkRAdkb/c7Lkhhc1HNPWlUqzS/tdopI7+TzNsYr7qEckXpumBlUSONoJ
# n2V1zukFbgsBq0mRWSZf+ut3OVGo7zSYopsMXSIPFEaBcxNuvcZQXv6YdXEsDpvG
# mysbgVa/7uP3KwH9h79WeFU/TiGEISH5B59qTg26+GMRqhyZoYHj7wI36omwSNja
# tUo5cYz4AEYTO58gceMcztNO45BynLwPbZwZ0bxPN2wL1ruIYd+ewQIDAQABo4IB
# rjCCAaowHwYDVR0jBBgwFoAUDyrLIIcouOxvSK4rVKYpqhekzQwwHQYDVR0OBBYE
# FJHuVIzRubayI0tfw82Q7Q/47iu9MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8E
# AjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMEoGA1UdIARDMEEwNQYMKwYBBAGyMQEC
# AQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAgGBmeB
# DAEEATBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLnNlY3RpZ28uY29tL1Nl
# Y3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBUjM2LmNybDB5BggrBgEFBQcBAQRtMGsw
# RAYIKwYBBQUHMAKGOGh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1B1Ymxp
# Y0NvZGVTaWduaW5nQ0FSMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5z
# ZWN0aWdvLmNvbTAjBgNVHREEHDAagRhqYXNvbi5hbGJlcmlub0BnbWFpbC5jb20w
# DQYJKoZIhvcNAQEMBQADggGBAET0EFH0r+hqoQWr4Ha9UDuEv28rTgV2aao1nFRg
# GZ/5owM7x9lxappLUbgQFfeIzzAsp3gwTKMYf47njUjvOBZD9zV/3I/vaLmY2enm
# MXZ48Om9GW4pNmnvsef2Ub1/+dRzgs8UFX5wBJcfy4OWP3t0OaKJkn+ZltgFF1cu
# L/RPiWSRcZuhh7dIWgoPQrVx8BtC8pkh4F5ECxogQnlaDNBzGYf1UYNfEQOFec31
# UK8oENwWx5/EaKFrSi9Y4tu6rkpH0idmYds/1fvqApGxujhvCO4Se8Atfc98icX4
# DWkc1QILREHiVinmoO3smmjB5wumgP45p9OVJXhI0D0gUFQfOSappa5eO2lbnNVG
# 90rCsADmVpDDmNt2qPG01luBbX6VtWMP2thjP5/CWvUy6+xfrhlqvwZyZt3SKtuf
# FWkqnNWMnmgtBNSmBF5+q8w5SJW+24qrncKJWSIim/nRtC11XnoI9SXlaucS3Nlb
# crQVicXOtbhksEqMTn52i8NOfzGCAxswggMXAgEBMGkwVDELMAkGA1UEBhMCR0Ix
# GDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UEAxMiU2VjdGlnbyBQdWJs
# aWMgQ29kZSBTaWduaW5nIENBIFIzNgIRAOiFGyv/M0cNjSrz4OIyh7EwDQYJYIZI
# AWUDBAIBBQCggYQwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0B
# CQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAv
# BgkqhkiG9w0BCQQxIgQgaT3tdq7ugi//XkMoHhGjE5ciXdSNc5l+PBDc23Vs8sAw
# DQYJKoZIhvcNAQEBBQAEggIAl8+cpkt0idewCg3quf9NielqcUiPkDYobe000wX7
# GMLiYHj2bQybM8nrkIXeGE8EVpnIYrKfSjkz3e0dPkAby4We4k/byumFtIVsyAei
# 1b6IRCIgY1lMOYaVe2+lOLfvDJzrFfBoI4mGdKV9XykdZ9NKUbXMYAm80DBE0VEG
# DzVP3D0lQxGnVuAYURNwOWr1C7BFlWQPdfjZwcTl9F6yLPljEkuJUFBPJ12x37vk
# UNpAghkevTjmyvL/JketM+Kxq3z8XClcJBWYbWx5IfqdXXyJKga/6RYIzvwd1mS7
# RX6gZuLVX+TSmhOJaPzzTITwTtIgEPrBwzcAQpMsBD/Irt/NTZf2OGZoUDucxnxx
# i7aMtj0g8wD6oPlGi7199DbdudnFvE4R5jzhrL5li8xrWXqzIdsPbULeIL7esz5I
# elJc20fB34s56hAGe3bjO3DM7IkjqG3mb2rtb3BwWpUOcnyi3smeGAwRtdtUNij/
# rcFRlzTugPjmuRFVg8NmMT7rJwa+MGO9C0onJbMjrEjE0JQ+QIQMJ1rF5WQ01Xtc
# OXt+UzV5TAfmlCXmazBtHQtVvYV8TBm0UAfnAewC1emBqn8SiA8oULSLIkHZB9yP
# n8nUuaQt6UDPVwJBPpnnYB+MZ5YAduM5Zxbobw9KgbixmCiRcCmAvCDdBIfEVQH1
# WLk=
# SIG # End signature block