Functions/Public/EPCOther.ps1

Function Get-EPCTestPlan {
    <#
        .SYNOPSIS
        Return a list of EPC test plans
         
        .DESCRIPTION
        Return a list of EPC test plans
         
        .EXAMPLE
        Get-EPCTestPlan
 
        .NOTES
        Version 1.0
    #>

    
    [cmdletbinding()]
    Param (
        [switch]$UseXML
    )
    
    Begin {
        Connect-EPCController

        If ($Global:EPC_UseWSDL -And $UseXML -eq $False) {
            $EPCCred = New-Object -TypeName EPC.ActiveCtrl.CredentialsType
            $EPCCred.username = $Global:EPControllerCred.UserName
            $EPCCred.password = $Global:EPControllerCred.GetNetworkCredential().Password
        }
        Else {
            $ProgressPreference = 'SilentlyContinue'
        }
    }
    Process {
        If ($Global:EPC_UseWSDL -And $UseXML -eq $False) {
            $EPCListTestPlansParams = New-Object -TypeName EPC.ActiveCtrl.ListTestPlansParametersType
            $EPCListTestPlansParams.credentials = $EPCCred

            $TestPlanResults = $Global:EPCWSDL_ActiveCtrl.listTestPlans($EPCListTestPlansParams)
            
            Write-Verbose $TestPlanResults.result
            
            If ($TestPlanResults.result -eq 'success') {
                Return $TestPlanResults.TestPlanList
            }
            Else {
                Throw $TestPlanResults.result
            }
        }
        Else {
            Write-Verbose 'Using XML to pull test plan list'
            $PwdEscaped = [System.Security.SecurityElement]::Escape($Global:EPControllerCred.GetNetworkCredential().Password)
            [xml]$SOAPReq = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'
                xmlns:urn='urn:telchemyActiveCtrl'>
                 <soapenv:Header/>
                 <soapenv:Body>
                 <urn:listTestPlansParameters>
                <credentials>
                <username>$($Global:EPControllerCred.UserName)</username>
                <password>$PwdEscaped</password>
                </credentials>
                 </urn:listTestPlansParameters>
                 </soapenv:Body>
                </soapenv:Envelope>"


            $SOAPFQDN = "https://$Global:EPControllerFQDN/telchemywebservices/services/telchemyActiveCtrlService"
            Write-Verbose $SOAPFQDN
            Write-Verbose $SOAPReq.OuterXML

            If ($Global:EPC_UseSOAPHeader) {
                $Headers = @{'SOAPAction' = 'urn:telchemyActiveCtrl/listTestPlansParameters'}
            } Else {
                $Headers = @{}
            }

            
            [xml]$XMLResponse = (Invoke-WebRequest -UseBasicParsing -Method POST -URI $SOAPFQDN -Headers $Headers -Body $SOAPReq -ContentType 'text/xml').Content
            $TestPlanResults = $XMLResponse.Envelope.Body.listTestPlansResults
            
            If ($TestPlanResults.result -eq 'success') {
                [psobject]$TestPlans = $TestPlanResults.TestPlanList.testplan | ConvertFrom-XMLElement
                Return $TestPlans
            }
            Else {
                Throw $TestPlanResults.result
            }
        }
    }
}



#################################################################################################################################################
# #
# EPC Service Functions #
# #
#################################################################################################################################################

Function Get-EPCService {
    <#
        .SYNOPSIS
        Return list of EPC services
          
        .DESCRIPTION
        Return list of EPC services
          
        .PARAMETER ServiceClass
        Limit results to only a specific service class
          
        .EXAMPLE
        Get-EPCService -ServiceClass VOIP
        Returns service information about all VOIP services
  
        .NOTES
        Version 1.0
    #>

    
    [cmdletbinding()]
    Param (
        [Parameter(Mandatory=$False)]
        [ValidateSet('Composite','Interface','IPSec','IPTV','NetApp','NetSVC','NetTrans','Network','Other','System','TCP','VidConf','VOIP', IgnoreCase=$True)]
        [string]$ServiceClass
    )
    
    Begin {
        Connect-EPCController
        
        $EPCCred = New-Object -TypeName EPC.SvcMgmt.CredentialsType
        $EPCCred.username = $Global:EPControllerCred.UserName
        $EPCCred.password = $Global:EPControllerCred.GetNetworkCredential().Password
    }
    Process {
        $EPCListServicesParams = New-Object -TypeName EPC.SvcMgmt.ListServicesParametersType
        $EPCListServicesParams.credentials = $EPCCred
        
        If ($ServiceClass) {
            $EPCListServicesParams.serviceClass = $ServiceClass
            $EPCListServicesParams.serviceClassSpecified = $True
        }
        
        $ServiceResults = $Global:EPCWSDL_SvcMgmt.listServices($EPCListServicesParams)
        Write-Verbose $ServiceResults.result
        
        If ($ServiceResults.result -eq 'success') {
            Return $ServiceResults.ServiceList
        }
        Else {
            Throw $ServiceResults.result
        }            
    }
}


#################################################################################################################################################
# #
# EPC Resource Group Functions #
# #
#################################################################################################################################################

Function Get-EPCResourceGroup {
    <#
        .SYNOPSIS
        Return list of EPC resource groups
         
        .DESCRIPTION
        Return list of EPC resource groups
         
        .PARAMETER ParentRGID
        Limit results to only a specific resource group
         
        .EXAMPLE
        Get-EPCResourceGroup
 
        .NOTES
        Version 1.0
    #>

    
    [cmdletbinding()]
    Param (
        [Parameter(Mandatory=$False)]
        [int]$ParentRGID,
        [Parameter(Mandatory=$False)]
        [int]$ResultSize = 1000,
        [switch]$UseXML
    )
    Begin {
        Connect-EPCController
        
        If ($Global:EPC_UseWSDL -And $UseXML -eq $False) {
            $EPCCred = New-Object -TypeName EPC.ResGrpMgmt.CredentialsType
            $EPCCred.username = $Global:EPControllerCred.UserName
            $EPCCred.password = $Global:EPControllerCred.GetNetworkCredential().Password
        }
        Else {
            $ProgressPreference = 'SilentlyContinue'
        }
    }
    Process {
        If ($Global:EPC_UseWSDL -And $UseXML -eq $False) {
            $EPCListResourceGroupParams = New-Object -TypeName EPC.ResGrpMgmt.ListResourceGroupParametersType
            $EPCListResourceGroupParams.credentials = $EPCCred
            $EPCListResourceGroupParams.maxNumber = $ResultSize
            
            If ($ParentRGID) {
                $RGRelation = New-Object -TypeName EPC.ResGrpMgmt.ResourceGroupRelationshipMapType
                $RGRelation.RGID = $ParentRGID
                $FilterType = New-Object -TypeName EPC.ResGrpMgmt.ResourceGroupFilterType
                $FilterType.ItemElementName = 'RGrelation'
                $FilterType.Item = $RGRelation
                $EPCListResourceGroupParams.filter = $FilterType
            }
            
    
            $ResourceGroupResults = $Global:EPCWSDL_ResGrpMgmt.listResourceGroups($EPCListResourceGroupParams)
            Write-Verbose $ResourceGroupResults.result
            
            If ($ResourceGroupResults.result -eq 'success') {
                Return $ResourceGroupResults.ResourceGroupList
            }
            Else {
                Throw $ResourceGroupResults.result
            }
        }
        Else {
            Write-Verbose 'Using XML to pull resource group list'
            $PwdEscaped = [System.Security.SecurityElement]::Escape($Global:EPControllerCred.GetNetworkCredential().Password)
            [xml]$SOAPReq = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'
                xmlns:urn='urn:telchemyRsrcGroupMgmt'>
                 <soapenv:Header/>
                 <soapenv:Body>
                 <urn:listResourceGroupParameters>
                <credentials>
                <username>$($Global:EPControllerCred.UserName)</username>
                <password>$PwdEscaped</password>
                </credentials>
                 </urn:listResourceGroupParameters>
                 </soapenv:Body>
                </soapenv:Envelope>"

            
            # Add filter options if entered
            If ($ParentRGID) {
                $FilterXMLElement = $SOAPReq.Envelope.Body.listResourceGroupParameters.AppendChild($SOAPReq.CreateElement('filter'))
                $RGRelationXMLElement = $FilterXMLElement.AppendChild($SOAPReq.CreateElement('RGrelation'))
                $RGRelationshipXMLElement = $RGRelationXMLElement.AppendChild($SOAPReq.CreateElement('relationship'))
                $NULL = $RGRelationshipXMLElement.AppendChild($SOAPReq.CreateTextNode('all-children'))
                $RGIDXMLElement = $RGRelationXMLElement.AppendChild($SOAPReq.CreateElement('RGID'))
                $NULL = $RGIDXMLElement.AppendChild($SOAPReq.CreateTextNode($ParentRGID))
            }

            $SOAPFQDN = "https://$Global:EPControllerFQDN/telchemywebservices/services/telchemyRsrcGroupMgmtService"
            Write-Verbose $SOAPFQDN
            Write-Verbose $SOAPReq.OuterXML

            If ($Global:EPC_UseSOAPHeader) {
                $Headers = @{'SOAPAction' = 'urn:telchemyRsrcGroupMgmt/listResourceGroupParameters'}
            } Else {
                $Headers = @{}
            }
            
            [xml]$XMLResponse = (Invoke-WebRequest -UseBasicParsing -Method POST -URI $SOAPFQDN -Headers $Headers -Body $SOAPReq -ContentType 'text/xml').Content
            $ResourceGroupResults = $XMLResponse.Envelope.Body.listResourceGroupResults

            If ($ResourceGroupResults.result -eq 'success') {
                [psobject]$ResourceGroups = $ResourceGroupResults.ResourceGroupList.RG | ConvertFrom-XMLElement
                Return $ResourceGroups
            }
            Else {
                Throw $ResourceGroupResults.result
            }
        }
    }
}



Function Get-EPCControllerUUID {
    [cmdletbinding()]
    Param (
        [switch]$UseXML
    )
    
    Begin {
        Get-EPCWebSessionCookie
        $ProgressPreference = 'SilentlyContinue'
    }
    Process {
        $FQDN = "https://$Global:EPControllerFQDN/components.do?action=4&type=3"
        $Result = Invoke-RestMethod -Method GET -Uri $FQDN -WebSession $Global:EPCSessionCookie
        
        $ControllerUUID = $Result.data.uuid
                
        If ($ControllerUUID) {
            Return $ControllerUUID
        }
        Else {
            Write-Error "Could not obtain controller UUID"
        }
    }
}



Function Get-EPCBulkExportJobs {
    <#
        .SYNOPSIS
        Return list of EPC bulk export jobs
         
        .DESCRIPTION
        Return list of EPC bulk export jobs
         
        .EXAMPLE
        Get-EPCBulkExportJobs
        Returns a list of all EPC bulk export jobs
 
        .NOTES
        Version 1.0
    #>

    
    [cmdletbinding()]
    Param (
        [switch]$UseXML
    )
    
    Begin {
        Connect-EPCController
        
        If ($Global:EPC_UseWSDL -And $UseXML -eq $False) {
            $EPCCred = New-Object -TypeName EPC.BulkExport.CredentialsType
            $EPCCred.username = $Global:EPControllerCred.UserName
            $EPCCred.password = $Global:EPControllerCred.GetNetworkCredential().Password
        }
        Else {
            #$ProgressPreference = 'SilentlyContinue'
        }
    }
    Process {
        If ($Global:EPC_UseWSDL -And $UseXML -eq $False) {
            $EPCListExportJobsParams = New-Object -TypeName EPC.BulkExport.ListExportJobsType
            $EPCListExportJobsParams.credentials = $EPCCred
            
            $ExportJobResults = $Global:EPCWSDL_BulkExport.listExportJobs($EPCListExportJobsParams)
            Write-Verbose $ExportJobResults.result
            
            If ($ExportJobResults.result -eq 'success') {
                Return $ExportJobResults.jobList
            }
            Else {
                Throw $ExportJobResults.result
            }            
        }
        Else {
            [xml]$SOAPReq = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'
                xmlns:urn='urn:telchemyBulkExport'>
                 <soapenv:Header/>
                 <soapenv:Body>
                 <urn:listExportJobsParameters>
                <credentials>
                <username>$($Global:EPControllerCred.UserName)</username>
                <password>$PwdEscaped</password>
                </credentials>
                 </urn:listExportJobsParameters>
                 </soapenv:Body>
                </soapenv:Envelope>"

            
            $SOAPFQDN = "https://$Global:EPControllerFQDN/telchemywebservices/services/telchemyBulkExportService"
            Write-Verbose $SOAPFQDN
            Write-Verbose $SOAPReq.OuterXML

            If ($Global:EPC_UseSOAPHeader) {
                $Headers = @{'SOAPAction' = 'urn:telchemyBulkExport/listExportJobsParameters'}
            } Else {
                $Headers = @{}
            }
            
            [xml]$XMLResponse = (Invoke-WebRequest -UseBasicParsing -Method POST -URI $SOAPFQDN -Headers $Headers -Body $SOAPReq -ContentType 'text/xml').Content
            $ExportJobResults = $XMLResponse.Envelope.Body.listExportJobsResults
            
            If ($ExportJobResults.result -eq 'success') {
                #[psobject]$JobList = $ExportJobResults.jobList.job | ConvertFrom-XMLElement
                Return $ExportJobResults.jobList.job
            }
            Else {
                Throw $ExportJobResults.result
            }    
        }
    }
}



Function Get-EPCBulkExportJobStatus {
    <#
        .SYNOPSIS
        Return the status of a given EPC bulk export job
         
        .DESCRIPTION
        Return the status of a given EPC bulk export job
         
        .PARAMETER JobID
        The JobID of the bulk export job to retrieve status
         
        .EXAMPLE
        Get-EPCBulkExportJobStatus -JobID 1
        Returns the export job status of bulk export job ID 1
 
        .NOTES
        Version 1.0
    #>

    
    [cmdletbinding()]
    Param (
        [Parameter(Mandatory=$True)]
        [int]$JobID,
        [switch]$UseXML
    )
    
    Begin {
        Connect-EPCController
        
        If ($Global:EPC_UseWSDL -And $UseXML -eq $False) {
            $EPCCred = New-Object -TypeName EPC.SvcMgmt.CredentialsType
            $EPCCred.username = $Global:EPControllerCred.UserName
            $EPCCred.password = $Global:EPControllerCred.GetNetworkCredential().Password
        }
        Else {
            $ProgressPreference = 'SilentlyContinue'
        }
    }
    Process {
        If ($Global:EPC_UseWSDL -And $UseXML -eq $False) {
            $EPCBulkExportStatusParams = New-Object -TypeName EPC.SvcMgmt.statusExportJobParameters>
            $EPCBulkExportStatusParams.credentials = $EPCCred
            
            $EPCBulkExportStatusParams.jobID = $JobID

            $ServiceResults = $Global:EPCWSDL_SvcMgmt.listServices($EPCListServicesParams)
            Write-Verbose $ServiceResults.result
            
            If ($ServiceResults.result -eq 'success') {
                Return $ServiceResults.ServiceList
            }
            Else {
                Throw $ServiceResults.result
            }            
        }
        Else {
            [xml]$SOAPReq = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'
                xmlns:urn='urn:telchemySvcMgmt'>
                 <soapenv:Header/>
                 <soapenv:Body>
                 <urn:listServicesParameters>
                <credentials>
                <username>$($Global:EPControllerCred.UserName)</username>
                <password>$PwdEscaped</password>
                </credentials>
                 </urn:listServicesParameters>
                 </soapenv:Body>
                </soapenv:Envelope>"

            
            # Add the testpoint ID to the search if entered
            If ($ServiceClass) {
                $NewXMLElement = $SOAPReq.Envelope.Body.listServicesParameters.AppendChild($SOAPReq.CreateElement('serviceClass'))
                $NULL = $NewXMLElement.AppendChild($SOAPReq.CreateTextNode($ServiceClass.ToLower()))    
            }

            $SOAPFQDN = "https://$Global:EPControllerFQDN/telchemywebservices/services/telchemySvcMgmtService"
            Write-Verbose $SOAPFQDN
            Write-Verbose $SOAPReq.OuterXML

            If ($Global:EPC_UseSOAPHeader) {
                $Headers = @{'SOAPAction' = 'urn:telchemySvcMgmt/listServicesParameters'}
            } Else {
                $Headers = @{}
            }
            
            [xml]$XMLResponse = (Invoke-WebRequest -UseBasicParsing -Method POST -URI $SOAPFQDN -Headers $Headers -Body $SOAPReq -ContentType 'text/xml').Content
            $ServiceResults = $XMLResponse.Envelope.Body.listServicesResults
            
            If ($ServiceResults.result -eq 'success') {
                [psobject]$Services = $ServiceResults.ServiceList.service | ConvertFrom-XMLElement
                Return $Services
            }
            Else {
                Throw $ServiceResults.result
            }    
        }
    }
}



Function Get-EPCControllerPerfData {
    <#
        .SYNOPSIS
        Returns a list of performance metrics for a given EPC controller
         
        .DESCRIPTION
        Returns a list of performance metrics for a given EPC controller
 
        .PARAMETER ResultSize
        The number of results to return. Defaults to 1000.
         
        .EXAMPLE
        Get-EPCControllerPerfData
 
        .NOTES
        Version 1.0
    #>

    
    [cmdletbinding()]
    Param (
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [Alias("testptID")]
        [string]$TestPointID,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$TestPointName,
        [Parameter(Mandatory=$False)]
        [ValidateSet('LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','TODAY','YESTERDAY','WEEK_TO_NOW','MONTH_TO_NOW','CUSTOM', IgnoreCase=$True)]
        [string]$TimePeriod = 'LAST_DAY',
        [Parameter(Mandatory=$False)]
        [Alias("StartDateFrom")]
        [datetimeoffset]$TimePeriodFrom,
        [Parameter(Mandatory=$False)]
        [Alias("StartDateTo")]
        [datetimeoffset]$TimePeriodTo,        
        [Parameter(Mandatory=$False)]
        [ValidateSet('Reporter','Controller','Agent', IgnoreCase=$True)]
        [string]$AppType,        
        [Parameter(Mandatory=$False)]
        [string]$SortColumn = 'evt_date',        
        [Parameter(Mandatory=$False)]
        [int]$ResultSize = 1000
    )
    
    Begin {
        Get-EPCWebSessionCookie
        $ProgressPreference = 'SilentlyContinue'
    }
    Process {
        # Get the time period to return stats for
        Switch ($TimePeriod) {
            'LAST_HOUR' { $TimePeriodFrom = [DateTimeOffset]::Now.AddHours(-1); $TimePeriodTo = [DateTimeOffset]::Now }
            'LAST_DAY' { $TimePeriodFrom = [DateTimeOffset]::Now.AddDays(-1); $TimePeriodTo = [DateTimeOffset]::Now }
            'LAST_WEEK' { $TimePeriodFrom = [DateTimeOffset]::Now.AddDays(-7); $TimePeriodTo = [DateTimeOffset]::Now }
            'LAST_MONTH' { $TimePeriodFrom = [DateTimeOffset]::Now.AddMonths(-1); $TimePeriodTo = [DateTimeOffset]::Now }
        }
        
        If (!$TimePeriodTo) { $TimePeriodTo = [DateTimeOffset]::Now }
        
        $Body.Add('beginsecs', $TimePeriodFrom.ToUnixTimeSeconds())
        $Body.Add('endsecs', $TimePeriodTo.ToUnixTimeSeconds())
        
        # If Testpoint name/id not provided, assume we're getting controller stats
        If (!$TestPointID -and !$TestPointName) {
            # Get the UUID of the controller
            $FQDN = "https://$Global:EPControllerFQDN/components.do?action=4&type=3"
            $Result = Invoke-RestMethod -Method GET -Uri $FQDN -WebSession $Global:EPCSessionCookie
            $ControllerUUID = $Result.data.uuid

            # Get the database response time
        }
    }
}




Function Get-EPCLicense {
    <#
        .SYNOPSIS
        Returns a list of EPC licenses
         
        .DESCRIPTION
        Returns a list of EPC licenses
 
        .EXAMPLE
        Get-EPCLicense
 
        .NOTES
        Version 1.0
    #>

    
    [cmdletbinding()]
    Param (
        [switch]$UseXML
    )
    
    Begin {
        Get-EPCWebSessionCookie
        $Epoch = [datetime]"1970-01-01 00:00:00"
        $ProgressPreference = 'SilentlyContinue'
    }
    Process {
        $LicFQDN = "https://$Global:EPControllerFQDN/admin/licensecfg.do?action=12"
        $LicResult = Invoke-RestMethod -Method GET -Uri $LicFQDN -WebSession $Global:EPCSessionCookie

        $FormattedResults = $LicResult.pts | Select-Object `
                                            @{Name='Product';Expression={$_.product}},`
                                            @{Name='LicenseKey';Expression={$_.lk}},`
                                            @{Name='LastUpdate';Expression={$Epoch.AddSeconds($_.update).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")}},`
                                            @{Name='Expiry';Expression={If ($_.expiry -gt 0) { $Epoch.AddSeconds($_.expiry).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")}}},`
                                            status, host, id, `
                                            @{Name='AutoAssign';Expression={[regex]::Match($_.aV, 'autoAssign=(true|false)').captures.Groups[1].value }}
    }
    End {
        Return $FormattedResults
    }
}



Function Get-EPCLicenseDetails {
    <#
        .SYNOPSIS
        Returns details about a given EPC license
         
        .DESCRIPTION
        Returns details about a given EPC license. Accepts pipeline input from Get-EPCLicense
 
        .PARAMETER LicenseKey
        The license key of the license to retrieve
 
        .PARAMETER ID
        The id of the license to retrieve
         
        .EXAMPLE
        Get-EPCLicenseDetails -LicenseKey abcdef -ID 1
        Returns EPC license details about license key abcdef
 
        .EXAMPLE
        Get-EPCLicense | Where {$_.Product -like 'DVQ*'} | Get-EPCLicenseDetails
        Returns detailed license information about any license that starts with DVQ
 
        .NOTES
        Version 1.0
    #>

    
    [cmdletbinding()]
    Param (
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)]
        [string]$LicenseKey,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)]
        [string]$ID,
        [switch]$UseXML
    )
    
    Begin {
        Get-EPCWebSessionCookie
        $ProgressPreference = 'SilentlyContinue'
        [System.Collections.ArrayList]$LicMembers = @()
        
    }
    Process {
        Write-Verbose "LicenseKey: $LicenseKey"
        Write-Verbose "ID: $ID"
        $LicFQDN = "https://$Global:EPControllerFQDN/admin/viewlic.htm?licensekey=$LicenseKey&lkeyid=$ID"

        If ($PSItem.AutoAssign) { $LicFQDN = $LicFQDN + "&autoAssign=$($PSItem.AutoAssign)" } # For whatever reason, the value of the AutoAssign parameter is passed to the next page via the first page.

        Write-Verbose $LicFQDN
        $LicResult = Invoke-WebRequest -UseBasicParsing -Method GET -Uri $LicFQDN -WebSession $Global:EPCSessionCookie        
        $Item = [PSCustomObject][Ordered]@{}

        # Parse out tables and focus on the table which contains all the data we want
        If ($Global:EPC_UseWSDL -And $UseXML -eq $False) {
            Write-Verbose 'Using WSDL method'
            $Tables = $LicResult.ParsedHtml.body.getElementsByTagName('Table')
            $LicMemberRows = $Tables[0].rows | Select-Object InnerHTML # Get the row data innerHTML, which contains the data we want
        } Else { # PS v.6+ doesn't have ParsedHtml in Invoke-WebRequest, so we have to use different method
            $Tables = $LicResult.Content | ConvertFrom-Html
            $Tables = $Tables.SelectNodes("//table")
            $LicMemberRows = $Tables[0].SelectNodes("//tr")
        }

        $LicMemberRows = $LicMemberRows[1..($LicMemberRows.count - 2)] # Ignore the first row and the last 2 rows
        Write-Verbose "RowCount: $($LicMemberRows.Count)"
        
        # Parse each row and pull out the data which is in <TD></TD> blocks into a custom object
        ForEach ($Row in $LicMemberRows) {
            $RowData = $Row.InnerHTML
            $RowMatch = [regex]::Match($RowData, '^\s*<(TD|td) [\w=":;% ]+>([\w\ ]+)</(TD|td)>\s+<(TD|td)[\w=":;% ]*>([\w\s\-\.,<>:;&/]+)</(TD|td)>').captures
            $ItemName = $RowMatch.groups[2].value
            $ItemValue = $RowMatch.groups[5].value

            If ($ItemValue -eq ' ') { # If the item value is empty, it might be a date value provided via inline javascript. Try to get the value from there
                $RowMatchDate = [regex]::Match($RowData, 'var _(expire|update) = (\d+)').captures
                Try {
                    If ($NULL -ne $RowMatchDate) { 
                        $RowMatchDate = $RowMatchDate.groups[2].value
                        If ($RowMatchDate -gt 0) { 
                            $ItemValue = (([System.DateTimeOffset]::FromUnixTimeSeconds($RowMatchDate)).LocalDateTime).ToString("yyyy-MM-dd HH:mm:ss") 
                        } 
                    } 
                }
                Catch {
                    $ItemValue = ''
                }
            }

            $Item | Add-Member -NotePropertyName $ItemName -NotePropertyValue $ItemValue
        }
        $LicMembers += $Item
    }
    End {
        Return $LicMembers
    }
}




Function Get-EPCPoolKey {
    <#
        .SYNOPSIS
        Returns a list of EPC pool keys
         
        .DESCRIPTION
        Returns a list of EPC pool keys
 
        .PARAMETER PoolKeyType
        Return info about a certain type of pool key. Select from 'currentPoolKeys', 'newPoolKeys', 'retiredPoolKeys'. Defaults to 'currentPoolKeys'
 
        .EXAMPLE
        Get-EPCPoolKey
 
        .NOTES
        Version 1.0
    #>

    
    [cmdletbinding()]
    Param (
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [ValidateSet('currentPoolKeys', 'newPoolKeys', 'retiredPoolKeys', IgnoreCase=$False)]
        [string]$PoolKeyType = 'currentPoolKeys'
    )
    
    Begin {
        Get-EPCWebSessionCookie
        $ProgressPreference = 'SilentlyContinue'
        $Epoch = [datetime]"1970-01-01 00:00:00"
    }
    Process {
        $UnixTimeMS = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
        $FQDN = "https://$Global:EPControllerFQDN/poolKey.do?action=3&poolKeyType=$PoolKeyType&_=$UnixTimeMS"
        Write-Verbose $FQDN
        $Result = Invoke-RestMethod -Method GET -Uri $FQDN -WebSession $Global:EPCSessionCookie

        $FormattedResults = $Result.data | Select-Object `
                                            name,`
                                            @{Name='resourceGroup';Expression={$_.resoureGroup}},`
                                            roles, description, type, autoAssign,`
                                            @{Name='used';Expression={(($_.pkUsages -replace '<[^>]+>','') -split '\s*/\s*')[0]}},`
                                            @{Name='total';Expression={(($_.pkUsages -replace '<[^>]+>','') -split '\s*/\s*')[1]}},`
                                            @{Name='dateCreated';Expression={$Epoch.AddMilliseconds($_.dateCreated).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")}},`
                                            @{Name='dateExpired';Expression={If ($_.dateExpired -gt 0) {$Epoch.AddMilliseconds($_.dateExpired).ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")}}}
    }
    End {
        Return $FormattedResults
    }
}
# SIG # Begin signature block
# MIIfjAYJKoZIhvcNAQcCoIIffTCCH3kCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDqpQxTUhcrRKhp
# 8eRDmYTPTWV+WVPcwhevl7ekOYsPFaCCDRIwggZyMIIEWqADAgECAghkM1HTxzif
# CDANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
# EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8G
# A1UEAwwoU1NMLmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTAe
# Fw0xNjA2MjQyMDQ0MzBaFw0zMTA2MjQyMDQ0MzBaMHgxCzAJBgNVBAYTAlVTMQ4w
# DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENv
# cnAxNDAyBgNVBAMMK1NTTC5jb20gQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBD
# QSBSU0EgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCfgxNzqrDG
# bSHL24t6h3TQcdyOl3Ka5LuINLTdgAPGL0WkdJq/Hg9Q6p5tePOf+lEmqT2d0bKU
# Vz77OYkbkStW72fL5gvjDjmMxjX0jD3dJekBrBdCfVgWQNz51ShEHZVkMGE6ZPKX
# 13NMfXsjAm3zdetVPW+qLcSvvnSsXf5qtvzqXHnpD0OctVIFD+8+sbGP0EmtpuNC
# GVQ/8y8Ooct8/hP5IznaJRy4PgBKOm8yMDdkHseudQfYVdIYyQ6KvKNc8HwKp4WB
# wg6vj5lc02AlvINaaRwlE81y9eucgJvcLGfE3ckJmNVz68Qho+Uyjj4vUpjGYDdk
# jLJvSlRyGMwnh/rNdaJjIUy1PWT9K6abVa8mTGC0uVz+q0O9rdATZlAfC9KJpv/X
# gAbxwxECMzNhF/dWH44vO2jnFfF3VkopngPawismYTJboFblSSmNNqf1x1KiVgMg
# Lzh4gL32Bq5BNMuURb2bx4kYHwu6/6muakCZE93vUN8BuvIE1tAx3zQ4XldbyDge
# VtSsSKbt//m4wTvtwiS+RGCnd83VPZhZtEPqqmB9zcLlL/Hr9dQg1Zc0bl0EawUR
# 0tOSjAknRO1PNTFGfnQZBWLsiePqI3CY5NEv1IoTGEaTZeVYc9NMPSd6Ij/D+KNV
# t/nmh4LsRR7Fbjp8sU65q2j3m2PVkUG8qQIDAQABo4H7MIH4MA8GA1UdEwEB/wQF
# MAMBAf8wHwYDVR0jBBgwFoAU3QQJB6L1en1SUxKSle44gCUNplkwMAYIKwYBBQUH
# AQEEJDAiMCAGCCsGAQUFBzABhhRodHRwOi8vb2NzcHMuc3NsLmNvbTARBgNVHSAE
# CjAIMAYGBFUdIAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwOwYDVR0fBDQwMjAwoC6g
# LIYqaHR0cDovL2NybHMuc3NsLmNvbS9zc2wuY29tLXJzYS1Sb290Q0EuY3JsMB0G
# A1UdDgQWBBRUwv4QlQCTzWr158DX2bJLuI8M4zAOBgNVHQ8BAf8EBAMCAYYwDQYJ
# KoZIhvcNAQELBQADggIBAPUPJodwr5miyvXWyfCNZj05gtOII9iCv49UhCe204MH
# 154niU2EjlTRIO5gQ9tXQjzHsJX2vszqoz2OTwbGK1mGf+tzG8rlQCbgPW/M9r1x
# xs19DiBAOdYF0q+UCL9/wlG3K7V7gyHwY9rlnOFpLnUdTsthHvWlM98CnRXZ7WmT
# V7pGRS6AvGW+5xI+3kf/kJwQrfZWsqTU+tb8LryXIbN2g9KR+gZQ0bGAKID+260P
# Z+34fdzZcFt6umi1s0pmF4/n8OdX3Wn+vF7h1YyfE7uVmhX7eSuF1W0+Z0duGwdc
# +1RFDxYRLhHDsLy1bhwzV5Qe/kI0Ro4xUE7bM1eV+jjk5hLbq1guRbfZIsr0WkdJ
# LCjoT4xCPGRo6eZDrBmRqccTgl/8cQo3t51Qezxd96JSgjXktefTCm9r/o35pNfV
# HUvnfWII+NnXrJlJ27WEQRQu9i5gl1NLmv7xiHp0up516eDap8nMLDt7TAp4z5T3
# NmC2gzyKVMtODWgqlBF1JhTqIDfM63kXdlV4cW3iSTgzN9vkbFnHI2LmvM4uVEv9
# XgMqyN0eS3FE0HU+MWJliymm7STheh2ENH+kF3y0rH0/NVjLw78a3Z9UVm1F5VPz
# iIorMaPKPlDRADTsJwjDZ8Zc6Gi/zy4WZbg8Zv87spWrmo2dzJTw7XhQf+xkR6Od
# MIIGmDCCBICgAwIBAgIQIc+kRkn+AQupTThE+j58IjANBgkqhkiG9w0BAQsFADB4
# MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24x
# ETAPBgNVBAoMCFNTTCBDb3JwMTQwMgYDVQQDDCtTU0wuY29tIENvZGUgU2lnbmlu
# ZyBJbnRlcm1lZGlhdGUgQ0EgUlNBIFIxMB4XDTI1MDgwODIwMTMzNFoXDTI2MDgw
# ODIwMTMzNFowfzELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5ldyBZb3JrMRAwDgYD
# VQQHDAdKZXJpY2hvMR4wHAYDVQQKDBVOZWN0YXIgU2VydmljZXMgQ29ycC4xCzAJ
# BgNVBAsMAklUMR4wHAYDVQQDDBVOZWN0YXIgU2VydmljZXMgQ29ycC4wggGiMA0G
# CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCJXN3SkHk8zvqqnHkfyImA6vDVtGrO
# zTVO6nlzNe85eCoGRBk5ToZ+/uUwcFyjcxSV+jbR29y4O6azNBmwvEw96ukUVKUh
# J+0NIQoH2DJqtkp4v3EppsevtxxwarqC1fvMXMhz2NVBZS6moStIiFyeGTBgyR7P
# gdU+JRqiG1muq5QiSZWjCyBLN6DTDimz5YdX1nhc/64V/oT0g79tYmZm7UEw1rN8
# HZgk46Gezt3IIQGX22ng1nh/3vy1Q46T/8mCT3UANrd3l/jS0XUmYgW8Z91nYlrl
# iNH3nHbONGNFFN8WLPAakt3ITeGmqhZkHyyXmlxKlkLHiR8XewRHn7PpD/DT03x7
# ngKS5Ie0fUM1ZAdXDoghvQ6uNuQ5Q3TAjL2ukJs9u5VmvWyFL1l9ujuKCiNGfy1D
# cS7u1WlcCIXdrX4Hpe2lt/M7fZFkSMeS1TD2gM2+a/7xK5MWwmbV6qK27nKlRpbG
# Q6Yj0VmqJmcgekSrCKPFudNAsDyD6rUYxlUCAwEAAaOCAZUwggGRMAwGA1UdEwEB
# /wQCMAAwHwYDVR0jBBgwFoAUVML+EJUAk81q9efA19myS7iPDOMwegYIKwYBBQUH
# AQEEbjBsMEgGCCsGAQUFBzAChjxodHRwOi8vY2VydC5zc2wuY29tL1NTTGNvbS1T
# dWJDQS1Db2RlU2lnbmluZy1SU0EtNDA5Ni1SMS5jZXIwIAYIKwYBBQUHMAGGFGh0
# dHA6Ly9vY3Nwcy5zc2wuY29tMFEGA1UdIARKMEgwCAYGZ4EMAQQBMDwGDCsGAQQB
# gqkwAQMDATAsMCoGCCsGAQUFBwIBFh5odHRwczovL3d3dy5zc2wuY29tL3JlcG9z
# aXRvcnkwEwYDVR0lBAwwCgYIKwYBBQUHAwMwTQYDVR0fBEYwRDBCoECgPoY8aHR0
# cDovL2NybHMuc3NsLmNvbS9TU0xjb20tU3ViQ0EtQ29kZVNpZ25pbmctUlNBLTQw
# OTYtUjEuY3JsMB0GA1UdDgQWBBQoc8kxtmxEx1bpEE+bhb8JNyGrHTAOBgNVHQ8B
# Af8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBAD1Wlyoz/oOVnzXFQKuv29SQ9J6G
# lqSNMvPzF6204eydcEDLwKh5IpZ7iGo6Km5AoVGNzYwJWyWaTwZpaxOoh+M+NK+E
# /QIOH+mItAaHhKogn96pHL7ZG9oD23s+/EP9jqNpenOZ0HSBWNHc4PO0e7Ys5zyQ
# 0a63PF83kU6hqkny0hca7Mr4gZoFyt6ynEJvv/TIkNCE5tqo/cBW94EpjQBfXTd4
# ycDoQ5Be1gbLboBoEjyrnPl0n+5dQgXSCg25hgf37iTfg+sCXzw3SKeiFauf4s8o
# h3wyXvNGzW4q0ZoE+ZNInk/puRVGnGmGZUr6iKuplqey1vneOOAv5we2hryR8PaA
# eqo6OqxyEw6a+nmRwf3lsp9k6Aml6ary1bdGjRY+ysScAxbeCvC9yS/EzwtaU3Z8
# R+2qLqh7cX8gztflHxrsV7Ql0nE3MrM0ry2bAWYzthbdwYtIuoeGHibng/qxuHOI
# uRLSTzddpXDdLSmw+G116kaxxHCBM+wf6K0nvehm08pXNyzAolNIJrVjsll9YHDT
# wws15kpojCglZsMIDYAlrFzF9MI0dRdiaj7/ttGSdblKZJoDOdfPrWMuBlSmjamk
# 5VxgKKHPQ9mHTP1Q5baEuotRYqJLgTWV1ZzCF+MYH2vmmuyjm4sSEjVfetLaYwIk
# RYAx7I+e9wcfhciSMYIR0DCCEcwCAQEwgYwweDELMAkGA1UEBhMCVVMxDjAMBgNV
# BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMREwDwYDVQQKDAhTU0wgQ29ycDE0
# MDIGA1UEAwwrU1NMLmNvbSBDb2RlIFNpZ25pbmcgSW50ZXJtZWRpYXRlIENBIFJT
# QSBSMQIQIc+kRkn+AQupTThE+j58IjANBglghkgBZQMEAgEFAKB8MBAGCisGAQQB
# gjcCAQwxAjAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcC
# AQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCAJTqFLYH0sLYmklGTf
# SZrGVVkiBT9sfz7iyHyGzsibKTANBgkqhkiG9w0BAQEFAASCAYBv4RugdQR0AXAx
# RF475Vc9P0/3rSjTRNGsRJFznmTYIaWYsEpK+VDoRWttN0snCQvsMtS2W6UMbKfa
# 3kbUY0QzDAwtBlix+wIxoWaaVAUImf66VuCPcH3Kf9ynHCLOAKXQ3O0AEcWERU4v
# f4ahuNkX0F4FIV+eqtXfVVItpnHJSpHj0Fnq6VfI+rnkToZga6n7jx1Ya1Ga/Iqc
# nr6+ptkwMbuSR/0TB0AAWnrKBPky5rsmS8hjx1NCc1Cfungmm9lLSokxN0rjFLz9
# FTLhRy8ZnZqMjFvdyCU3t23x8sDmAk2UgKf6g7bSZ4lQxJPXfZBFnVlUJu0Fihf1
# GgXVkG1U9i2sTF9bu49C+f8yRTYTUCh/ejiwtWeLuXbdB23WvdYcduy8Lo8KjEEn
# XHfSGIohaqCTVkdgtQAKD76QLwYTXce7VaDF0TxAL79qOYddYlUoN3JMVVATZc4t
# fFIYQSdTLq1U3pj9iYxTgGe6Re/RXBiED+YqmCEL/xZ7dujiqlehgg8WMIIPEgYK
# KwYBBAGCNwMDATGCDwIwgg7+BgkqhkiG9w0BBwKggg7vMIIO6wIBAzENMAsGCWCG
# SAFlAwQCATB3BgsqhkiG9w0BCRABBKBoBGYwZAIBAQYMKwYBBAGCqTABAwYBMDEw
# DQYJYIZIAWUDBAIBBQAEIHR3QG3OrJYUYZL8fBwAoy9gAijCKwzaForRs0w1JTQN
# AghdINPi3ofj/BgPMjAyNjA0MDYxOTQzNDZaMAMCAQGgggwAMIIE/DCCAuSgAwIB
# AgIQH2sWYtIuG2xd8cDBoGAOODANBgkqhkiG9w0BAQsFADBzMQswCQYDVQQGEwJV
# UzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xETAPBgNVBAoMCFNT
# TCBDb3JwMS8wLQYDVQQDDCZTU0wuY29tIFRpbWVzdGFtcGluZyBJc3N1aW5nIFJT
# QSBDQSBSMTAeFw0yNTAyMTgxNjMyMDJaFw0zNDExMTIxODUwMDVaMG4xCzAJBgNV
# BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UE
# CgwIU1NMIENvcnAxKjAoBgNVBAMMIVNTTC5jb20gVGltZXN0YW1waW5nIFVuaXQg
# MjAyNSBFMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBv7UVHHb+ZVluxPXlfE
# 3M6tg0Xnq8dic+O3vPOCRpalUM1vO9A+GRzSVVjyygHhYrBw62XLFh1kv7e+yRd/
# aTajggFaMIIBVjAfBgNVHSMEGDAWgBQMnRAljpqnG5mHQ88IfuG9gZD0zzBRBggr
# BgEFBQcBAQRFMEMwQQYIKwYBBQUHMAKGNWh0dHA6Ly9jZXJ0LnNzbC5jb20vU1NM
# LmNvbS10aW1lU3RhbXBpbmctSS1SU0EtUjEuY2VyMFEGA1UdIARKMEgwPAYMKwYB
# BAGCqTABAwYBMCwwKgYIKwYBBQUHAgEWHmh0dHBzOi8vd3d3LnNzbC5jb20vcmVw
# b3NpdG9yeTAIBgZngQwBBAIwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwRgYDVR0f
# BD8wPTA7oDmgN4Y1aHR0cDovL2NybHMuc3NsLmNvbS9TU0wuY29tLXRpbWVTdGFt
# cGluZy1JLVJTQS1SMS5jcmwwHQYDVR0OBBYEFM582cAEgMUkEGoJ6hyrJT0R/ajS
# MA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAgEAgHN1JIW9ZlNip07F
# fY9r1LJwLKTl1h/y9r1BjDgHMEz7U7J7mAy32JxA1KLyjCCJqNkuRfhDHGFEfZtj
# TOru7AQMDSDiUDvCCc3jaz5py9jGvwIe5npkLbXqXhA+SqCzG719USigwhHkYr7v
# 8NiXoaY0Xu03p0BiZZreZlpngmGB9+86N94FqIFx2I5Z5iuu7d4j7aAOZBNxfU9j
# FDIIGDtWfWeCpF0Q8rLE/3DHDlzJKs5Il3i/VoOl7rTU938oSrxMwww6GDBlKX8r
# GHxvkjgIb9MXkVglJSDHsNAZDeCS/inaxKHA+ChuB8K4OxIxa6k1e+eHBypakAY3
# wuN7w7PlPmhN6k5IdqZn3HZHs2VjoR841Z9wmVPFdGDdkBZ7XOmb5OZUaKufsvtE
# R0VbY2DkzaqAaItt1kc+I+FUz7PiVz2PUzpegkftRRxvrPyIL08blJTnbMQ0XrqD
# N0rEfuTLv4XhhnKyJaXhxCUdjO/cRumMzZ35QTUMItBWy1xGp0iyoFVnAya2pPsV
# MuAI+sy1zxlOS9l5iSxvKJ8gpnpOgjqYTa7u1eyZo+4JlcGoiiR17LthMTrF1q62
# tO5xOpI8txUZ6gtKGtkJV6wdj+vZLcwKZ2M93GqVpOo6UBlGjx1sKsVZ7AIUzJZl
# i4NJ0M2KYcrfNnlebkYKpDnSqWwwggb8MIIE5KADAgECAhBtUhhwh+gjTYVgANCA
# j5NWMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhh
# czEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTEw
# LwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNB
# MB4XDTE5MTExMzE4NTAwNVoXDTM0MTExMjE4NTAwNVowczELMAkGA1UEBhMCVVMx
# DjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMREwDwYDVQQKDAhTU0wg
# Q29ycDEvMC0GA1UEAwwmU1NMLmNvbSBUaW1lc3RhbXBpbmcgSXNzdWluZyBSU0Eg
# Q0EgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCuURAT0vk8IKAg
# hd7JUBxkyeH9xek0/wp/MUjoclrFXqhh/fGH91Fc+7fm0MHCE7A+wmOiqBj9ODrJ
# AYGq3rm33jCnHSsCBNWAQYyoauLq8IjqsS1JlXL29qDNMMdwZ8UNzQS7vWZMDJ40
# JSGNphMGTIA2qn2bohGtgRc4p1395ESypUOaGvJ3t0FNL3BuKmb6YctMcQUF2sqo
# oMzd89h0E6ujdvBDo6ZwNnWoxj7YmfWjSXg33A5GuY9ym4QZM5OEVgo8ebz/B+gy
# hyCLNNhh4Mb/4xvCTCMVmNYrBviGgdPZYrym8Zb84TQCmSuX0JlLLa6WK1aO6qlw
# ISbb9bVGh866ekKblC/XRP20gAu1CjvcYciUgNTrGFg8f8AJgQPOCc1/CCdaJSYw
# hJpSdheKOnQgESgNmYZPhFOC6IKaMAUXk5U1tjTcFCgFvvArXtK4azAWUOO1Y3fd
# ldIBL6LjkzLUCYJNkFXqhsBVcPMuB0nUDWvLJfPimstjJ8lF4S6ECxWnlWi7OElV
# wTnt1GtRqeY9ydvvGLntU+FecK7DbqHDUd366UreMkSBtzevAc9aqoZPnjVMjvFq
# V1pYOjzmTiVHZtAc80bAfFe5LLfJzPI6DntNyqobpwTevQpHqPDN9qqNO83r3kaw
# 8A9j+HZiSw2AX5cGdQP0kG0vhzfgBwIDAQABo4IBgTCCAX0wEgYDVR0TAQH/BAgw
# BgEB/wIBADAfBgNVHSMEGDAWgBTdBAkHovV6fVJTEpKV7jiAJQ2mWTCBgwYIKwYB
# BQUHAQEEdzB1MFEGCCsGAQUFBzAChkVodHRwOi8vd3d3LnNzbC5jb20vcmVwb3Np
# dG9yeS9TU0xjb21Sb290Q2VydGlmaWNhdGlvbkF1dGhvcml0eVJTQS5jcnQwIAYI
# KwYBBQUHMAGGFGh0dHA6Ly9vY3Nwcy5zc2wuY29tMD8GA1UdIAQ4MDYwNAYEVR0g
# ADAsMCoGCCsGAQUFBwIBFh5odHRwczovL3d3dy5zc2wuY29tL3JlcG9zaXRvcnkw
# EwYDVR0lBAwwCgYIKwYBBQUHAwgwOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2Ny
# bHMuc3NsLmNvbS9zc2wuY29tLXJzYS1Sb290Q0EuY3JsMB0GA1UdDgQWBBQMnRAl
# jpqnG5mHQ88IfuG9gZD0zzAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD
# ggIBAJIZdQ2mWkLPGQfZ8vyU+sCb8BXpRJZaL3Ez3VDlE3uZk3cPxPtybVfLuqac
# i0W6SB22JTMttCiQMnIVOsXWnIuAbD/aFTcUkTLBI3xys+wEajzXaXJYWACDS47B
# RjDtYlDW14gLJxf8W6DQoH3jHDGGy8kGJFOlDKG7/YrK7UGfHtBAEDVe6lyZ+FtC
# srk7dD/IiL/+Q3Q6SFASJLQ2XI89ihFugdYL77CiDNXrI2MFspQGswXEAGpHuaQD
# THUp/LdR3TyrIsLlnzoLskUGswF/KF8+kpWUiKJNC4rPWtNrxlbXYRGgdEdx8SMj
# UTDClldcrknlFxbqHsVmr9xkT2QtFmG+dEq1v5fsIK0vHaHrWjMMmaJ9i+4qGJSD
# 0stYfQ6v0PddT7EpGxGd867Ada6FZyHwbuQSadMb0K0P0OC2r7rwqBUe0BaMqTa6
# LWzWItgBjGcObXeMxmbQqlEz2YtAcErkZvh0WABDDE4U8GyV/32FdaAvJgTfe9Mi
# L2nSBioYe/g5mHUSWAay/Ip1RQmQCvmF9sNfqlhJwkjy/1U1ibUkTIUBX3HgymyQ
# vqQTZLLys6pL2tCdWcjI9YuLw30rgZm8+K387L7ycUvqrmQ3ZJlujHl3r1hgV76s
# 3WwMPgKk1bAEFMj+rRXimSC+Ev30hXZdqyMdl/il5Ksd0vhGMYICWDCCAlQCAQEw
# gYcwczELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3Vz
# dG9uMREwDwYDVQQKDAhTU0wgQ29ycDEvMC0GA1UEAwwmU1NMLmNvbSBUaW1lc3Rh
# bXBpbmcgSXNzdWluZyBSU0EgQ0EgUjECEB9rFmLSLhtsXfHAwaBgDjgwCwYJYIZI
# AWUDBAIBoIIBYTAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcN
# AQkFMQ8XDTI2MDQwNjE5NDM0NlowKAYJKoZIhvcNAQk0MRswGTALBglghkgBZQME
# AgGhCgYIKoZIzj0EAwIwLwYJKoZIhvcNAQkEMSIEIP822hIT9NVz2LWhjdt9lS/d
# YcAZMncKHA1lCxwwh8klMIHJBgsqhkiG9w0BCRACLzGBuTCBtjCBszCBsAQgVCr5
# oWqNci5mEUl4iumUwYqaruWmXLNEolSa+Wx5x4swgYswd6R1MHMxCzAJBgNVBAYT
# AlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwI
# U1NMIENvcnAxLzAtBgNVBAMMJlNTTC5jb20gVGltZXN0YW1waW5nIElzc3Vpbmcg
# UlNBIENBIFIxAhAfaxZi0i4bbF3xwMGgYA44MAoGCCqGSM49BAMCBEcwRQIhAI/L
# cybbHJDTZdTVOnxE75mCrENairT+xbg+E+pIA2zyAiAwWPL+uud2QT85MuBK2xVC
# jww62oNgVXqYcjIJM/+PGQ==
# SIG # End signature block