639 lines
52 KiB
PowerShell
639 lines
52 KiB
PowerShell
#region Get-OmadaInventory
|
|
Function Get-OmadaInventory
|
|
{
|
|
<#
|
|
.SYNOPSIS
|
|
Collects the layer two inventory from an Omada controller and returns a normalized model.
|
|
|
|
.DESCRIPTION
|
|
Collection prefers the controller interface and degrades to the Open API, which is arranged by Connect-OmadaController and
|
|
enforced per request by Invoke-OmadaRequest. The normalized model is identical either way; the controller interface simply
|
|
populates more of it.
|
|
|
|
Available from both transports.
|
|
|
|
Sites, device inventory, switch port lists, and wired and wireless client sessions.
|
|
|
|
Available only from the controller interface.
|
|
|
|
Switch uplinks including the peer port, which is what allows an inter switch cable to be drawn with both ends known.
|
|
Switch downlinks, which describe the same topology from the other direction.
|
|
Per port LLDP neighbour detail, VLAN membership, media type, and power over Ethernet state.
|
|
VLAN definitions with their gateway subnets.
|
|
The real SSID configuration, rather than SSID names inferred from whichever clients happen to be associated.
|
|
|
|
Enumerations observed on the controller interface and relied upon here.
|
|
|
|
Port type 1 is copper RJ45 and 3 is a fibre or direct attach cage.
|
|
Link speed 0 auto, 1 ten megabit, 2 one hundred megabit, 3 one gigabit, 4 two and a half gigabit, 5 ten gigabit.
|
|
Link status 1 is up.
|
|
Device status 0 is disconnected and 1 is connected.
|
|
|
|
.PARAMETER Context
|
|
The connection context produced by Connect-OmadaController.
|
|
|
|
.PARAMETER SiteName
|
|
Optionally restricts collection to one or more named sites.
|
|
|
|
.PARAMETER PageSize
|
|
The number of rows requested per page.
|
|
|
|
.EXAMPLE
|
|
$OmadaInventory = Get-OmadaInventory -Context $OmadaContext -SiteName 'Headquarters'
|
|
|
|
.NOTES
|
|
Author: Grace Solutions
|
|
Version: 2026.08.02.0000
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$True)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[PSObject]$Context,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[AllowNull()]
|
|
[String[]]$SiteName,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[ValidateRange(10, 1000)]
|
|
[Int]$PageSize = 100
|
|
)
|
|
|
|
Try
|
|
{
|
|
#region Define the paged retrieval logic, which differs only in the name of the page parameters
|
|
[ScriptBlock]$GetPagedResult = {
|
|
Param
|
|
(
|
|
[String]$ControllerPath,
|
|
[String]$OpenAPIPath
|
|
)
|
|
|
|
$AggregateList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
$CurrentPage = 1
|
|
$TotalRowCount = 0
|
|
|
|
:PageLoop Do
|
|
{
|
|
$ControllerQuery = "currentPage=$($CurrentPage)¤tPageSize=$($PageSize)"
|
|
$OpenAPIQuery = "page=$($CurrentPage)&pageSize=$($PageSize)"
|
|
|
|
#region The two transports name their page parameters differently, so each attempt carries its own
|
|
$PageResult = Invoke-OmadaRequest -Context ($Context) -ControllerPath ($ControllerPath) -QueryString ($ControllerQuery)
|
|
|
|
#region Some controller routes reject paging parameters outright while others require them
|
|
# A route such as the device list answers a bare request and rejects one that carries paging, whereas a route
|
|
# such as the network list does the opposite. Rather than maintaining a list of which is which, a rejected
|
|
# first page is retried without paging and the answer is then treated as complete.
|
|
Switch (($PageResult.IsSuccess -eq $False) -and ($CurrentPage -eq 1) -and ([String]::IsNullOrWhiteSpace($ControllerPath) -eq $False))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$PageResult = Invoke-OmadaRequest -Context ($Context) -ControllerPath ($ControllerPath)
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
Switch ((($PageResult.IsSuccess -eq $False) -or ($PageResult.Transport -ieq 'OpenAPI')) -and ([String]::IsNullOrWhiteSpace($OpenAPIPath) -eq $False))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$PageResult = Invoke-OmadaRequest -Context ($Context) -OpenAPIPath ($OpenAPIPath) -QueryString ($OpenAPIQuery)
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
Switch ($PageResult.IsSuccess)
|
|
{
|
|
{($_ -eq $False)}
|
|
{
|
|
Break PageLoop
|
|
}
|
|
}
|
|
|
|
#region A collection arrives either as a bare array or as a data array alongside a total
|
|
# The envelope test has to be exact. Asking a bare array for a data property does not return null, because
|
|
# PowerShell enumerates the members of the array and hands back an empty array, which would otherwise be
|
|
# mistaken for an envelope carrying no rows and would silently discard the entire collection.
|
|
$PageRowList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
$ResultIsEnvelope = ($PageResult.Result -isnot [System.Array]) -and ($PageResult.Result -isnot [System.Collections.IList]) -and ($Null -ine $PageResult.Result.PSObject.Properties['data'])
|
|
|
|
Switch ($ResultIsEnvelope)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$TotalRowCount = [Int]"0$($PageResult.Result.totalRows)"
|
|
|
|
ForEach ($PageRow In @($PageResult.Result.data)) {$PageRowList.Add($PageRow)}
|
|
}
|
|
|
|
{($_ -eq $False)}
|
|
{
|
|
ForEach ($PageRow In @($PageResult.Result)) {$PageRowList.Add($PageRow)}
|
|
|
|
$TotalRowCount = $PageRowList.Count
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
ForEach ($PageRow In $PageRowList)
|
|
{
|
|
Switch ($Null -ine $PageRow)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$AggregateList.Add($PageRow)
|
|
}
|
|
}
|
|
}
|
|
|
|
Switch ($PageRowList.Count -eq 0)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
Break PageLoop
|
|
}
|
|
}
|
|
|
|
$CurrentPage++
|
|
}
|
|
While ($AggregateList.Count -lt $TotalRowCount)
|
|
|
|
Write-Output -InputObject (,$AggregateList)
|
|
}
|
|
#endregion
|
|
|
|
#region Define the link speed translation
|
|
$LinkSpeedTable = New-Object -TypeName 'System.Collections.Generic.Dictionary[[System.String], [System.String]]'
|
|
$LinkSpeedTable.Add('0', '')
|
|
$LinkSpeedTable.Add('1', '10M')
|
|
$LinkSpeedTable.Add('2', '100M')
|
|
$LinkSpeedTable.Add('3', '1G')
|
|
$LinkSpeedTable.Add('4', '2.5G')
|
|
$LinkSpeedTable.Add('5', '10G')
|
|
|
|
[ScriptBlock]$ConvertToLinkSpeed = {
|
|
Param
|
|
(
|
|
[System.Object]$SpeedValue
|
|
)
|
|
|
|
$SpeedName = ''
|
|
|
|
Switch ($LinkSpeedTable.ContainsKey("$($SpeedValue)"))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SpeedName = "$($LinkSpeedTable["$($SpeedValue)"])"
|
|
}
|
|
}
|
|
|
|
Write-Output -InputObject ("$($SpeedName)")
|
|
}
|
|
#endregion
|
|
|
|
#region Define the device status translation
|
|
[ScriptBlock]$ConvertToDeviceStatus = {
|
|
Param
|
|
(
|
|
[System.Object]$StatusValue
|
|
)
|
|
|
|
$DeviceStatus = 'unknown'
|
|
|
|
Switch ("$($StatusValue)")
|
|
{
|
|
{($_ -ieq '0')}
|
|
{
|
|
$DeviceStatus = 'offline'
|
|
}
|
|
|
|
{($_ -iin @('1', '4', '11'))}
|
|
{
|
|
$DeviceStatus = 'online'
|
|
}
|
|
|
|
{($_ -iin @('2', '3', '5', '6'))}
|
|
{
|
|
$DeviceStatus = 'warning'
|
|
}
|
|
}
|
|
|
|
Write-Output -InputObject ("$($DeviceStatus)")
|
|
}
|
|
#endregion
|
|
|
|
#region Enumerate sites
|
|
$SiteObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
$DiscoveredSiteList = $GetPagedResult.InvokeReturnAsIs('sites', 'sites')
|
|
|
|
Write-Verbose -Message "[$([System.DateTime]::UtcNow.ToString('yyyy/MM/dd HH:mm:ss.FFF'))] - [INFO] - $($DiscoveredSiteList.Count) Omada site(s) were discovered."
|
|
|
|
For ($DiscoveredSiteIndex = 0; $DiscoveredSiteIndex -lt $DiscoveredSiteList.Count; $DiscoveredSiteIndex++)
|
|
{
|
|
$DiscoveredSite = $DiscoveredSiteList[$DiscoveredSiteIndex]
|
|
|
|
#region The two transports name the site identifier differently
|
|
$SiteID = "$($DiscoveredSite.siteId)$($DiscoveredSite.id)"
|
|
|
|
Switch ([String]::IsNullOrWhiteSpace("$($DiscoveredSite.siteId)") -eq $False)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SiteID = "$($DiscoveredSite.siteId)"
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
$SiteIsRequested = $True
|
|
|
|
Switch (($Null -ine $SiteName) -and ($SiteName.Count -gt 0))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SiteIsRequested = "$($DiscoveredSite.name)" -iin $SiteName
|
|
}
|
|
}
|
|
|
|
Switch ($SiteIsRequested)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$WriteProgressParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$WriteProgressParameters.Activity = 'Collecting the Omada inventory'
|
|
$WriteProgressParameters.Status = "Processing site `"$($DiscoveredSite.name)`" ($($DiscoveredSiteIndex + 1) of $($DiscoveredSiteList.Count))"
|
|
$WriteProgressParameters.PercentComplete = [System.Math]::Round((($DiscoveredSiteIndex + 1) / $DiscoveredSiteList.Count) * 100, 2)
|
|
$WriteProgressParameters.Id = 20
|
|
|
|
$Null = Write-Progress @WriteProgressParameters
|
|
|
|
#region VLAN definitions, which only the controller interface exposes
|
|
$VLANObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
$NetworkIdentifierTable = New-Object -TypeName 'System.Collections.Generic.Dictionary[[System.String], [System.Int32]]'
|
|
|
|
ForEach ($DiscoveredNetwork In $GetPagedResult.InvokeReturnAsIs("sites/$($SiteID)/setting/lan/networks", ''))
|
|
{
|
|
$NetworkVLANID = [Int]"0$($DiscoveredNetwork.vlan)"
|
|
|
|
Switch ($NetworkVLANID -gt 0)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$NetworkIdentifierTable["$($DiscoveredNetwork.id)"] = $NetworkVLANID
|
|
|
|
$VLANProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$VLANProperties.VLANID = $NetworkVLANID
|
|
$VLANProperties.Name = "$($DiscoveredNetwork.name)"
|
|
$VLANProperties.Purpose = "$($DiscoveredNetwork.purpose)"
|
|
$VLANProperties.GatewaySubnet = "$($DiscoveredNetwork.gatewaySubnet)"
|
|
$VLANProperties.NetworkID = "$($DiscoveredNetwork.id)"
|
|
|
|
$VLANObjectList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($VLANProperties)))
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region SSID configuration, which only the controller interface exposes
|
|
$SSIDObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
$SecurityTable = New-Object -TypeName 'System.Collections.Generic.Dictionary[[System.String], [System.String]]'
|
|
$SecurityTable.Add('0', 'Open')
|
|
$SecurityTable.Add('1', 'WEP')
|
|
$SecurityTable.Add('2', 'WPA Personal')
|
|
$SecurityTable.Add('3', 'WPA Enterprise')
|
|
$SecurityTable.Add('4', 'WPA2/WPA3 Personal')
|
|
$SecurityTable.Add('5', 'WPA2/WPA3 Enterprise')
|
|
|
|
ForEach ($DiscoveredWLAN In $GetPagedResult.InvokeReturnAsIs("sites/$($SiteID)/setting/wlans", ''))
|
|
{
|
|
ForEach ($DiscoveredSSID In $GetPagedResult.InvokeReturnAsIs("sites/$($SiteID)/setting/wlans/$($DiscoveredWLAN.id)/ssids", ''))
|
|
{
|
|
$SSIDVLANID = ''
|
|
|
|
Switch (("$($DiscoveredSSID.vlanEnable)" -ieq 'True') -and ([Int]"0$($DiscoveredSSID.vlanId)" -gt 0))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SSIDVLANID = "$($DiscoveredSSID.vlanId)"
|
|
}
|
|
}
|
|
|
|
$SSIDProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$SSIDProperties.Name = "$($DiscoveredSSID.name)"
|
|
$SSIDProperties.Security = Switch ($SecurityTable.ContainsKey("$($DiscoveredSSID.security)")) {{($_ -eq $True)} {"$($SecurityTable["$($DiscoveredSSID.security)"])"} Default {''}}
|
|
$SSIDProperties.IsHidden = ("$($DiscoveredSSID.broadcast)" -ieq 'False')
|
|
$SSIDProperties.IsGuest = ("$($DiscoveredSSID.guestNetEnable)" -ieq 'True')
|
|
$SSIDProperties.VLANID = "$($SSIDVLANID)"
|
|
$SSIDProperties.WLANGroupName = "$($DiscoveredWLAN.name)"
|
|
|
|
$SSIDObjectList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($SSIDProperties)))
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Devices
|
|
$DeviceObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
$DiscoveredDeviceList = $GetPagedResult.InvokeReturnAsIs("sites/$($SiteID)/devices", "sites/$($SiteID)/devices")
|
|
|
|
For ($DiscoveredDeviceIndex = 0; $DiscoveredDeviceIndex -lt $DiscoveredDeviceList.Count; $DiscoveredDeviceIndex++)
|
|
{
|
|
$DiscoveredDevice = $DiscoveredDeviceList[$DiscoveredDeviceIndex]
|
|
|
|
$DeviceMACAddress = "$($DiscoveredDevice.mac)".ToUpperInvariant()
|
|
|
|
#region Per device detail, which carries the port list and the topology
|
|
$DetailSegment = Switch ("$($DiscoveredDevice.type)")
|
|
{
|
|
{($_ -ieq 'switch')}
|
|
{
|
|
'switches'
|
|
}
|
|
|
|
{($_ -ieq 'ap')}
|
|
{
|
|
'eaps'
|
|
}
|
|
|
|
{($_ -ieq 'gateway')}
|
|
{
|
|
'gateways'
|
|
}
|
|
|
|
Default
|
|
{
|
|
''
|
|
}
|
|
}
|
|
|
|
$DeviceDetail = $Null
|
|
|
|
Switch ([String]::IsNullOrWhiteSpace($DetailSegment) -eq $False)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$DetailResult = Invoke-OmadaRequest -Context ($Context) -ControllerPath "sites/$($SiteID)/$($DetailSegment)/$($DeviceMACAddress)" -OpenAPIPath "sites/$($SiteID)/$(Switch ($DetailSegment) {{($_ -ieq 'eaps')} {'aps'} Default {$DetailSegment}})/$($DeviceMACAddress)"
|
|
|
|
Switch ($DetailResult.IsSuccess)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$DeviceDetail = $DetailResult.Result
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Ports, taken from the controller port list when present and from the Open API port list otherwise
|
|
$DevicePortList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
$RawPortList = @($DeviceDetail.ports) + @($DeviceDetail.portList)
|
|
|
|
ForEach ($DiscoveredPort In $RawPortList)
|
|
{
|
|
Switch ($Null -ine $DiscoveredPort)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$PortStatus = $DiscoveredPort.portStatus
|
|
|
|
#region Media is inferred from the cage type reported by the controller, falling back to the model heuristic elsewhere
|
|
$PortKind = ''
|
|
|
|
Switch ("$($DiscoveredPort.type)")
|
|
{
|
|
{($_ -ieq '1')}
|
|
{
|
|
$PortKind = 'rj45'
|
|
}
|
|
|
|
{($_ -ieq '3')}
|
|
{
|
|
$PortKind = 'sfp_plus'
|
|
}
|
|
}
|
|
|
|
$PortSpeed = $ConvertToLinkSpeed.InvokeReturnAsIs($DiscoveredPort.maxSpeed)
|
|
|
|
Switch (("$($PortKind)" -ieq 'sfp_plus') -and ("$($PortSpeed)" -ieq '1G'))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$PortKind = 'sfp'
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region VLAN membership, where a native network identifier resolves to a VLAN number
|
|
$PortVLANID = ''
|
|
|
|
Switch ($NetworkIdentifierTable.ContainsKey("$($DiscoveredPort.nativeNetworkId)"))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$PortVLANID = "$($NetworkIdentifierTable["$($DiscoveredPort.nativeNetworkId)"])"
|
|
}
|
|
}
|
|
|
|
$PortMode = Switch (@($DiscoveredPort.tagNetworkIds).Count -gt 0) {{($_ -eq $True)} {'trunk'} Default {'access'}}
|
|
|
|
Switch ("$($DiscoveredPort.profileName)" -ieq 'All')
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$PortMode = 'trunk'
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
$PortProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$PortProperties.Number = [Int]"$($DiscoveredPort.port)"
|
|
$PortProperties.Name = "$($DiscoveredPort.name)"
|
|
$PortProperties.ProfileName = "$($DiscoveredPort.profileName)"
|
|
$PortProperties.Kind = "$($PortKind)"
|
|
$PortProperties.Speed = "$($PortSpeed)"
|
|
$PortProperties.Mode = "$($PortMode)"
|
|
$PortProperties.VLANID = "$($PortVLANID)"
|
|
$PortProperties.IsDisabled = ("$($DiscoveredPort.disable)" -ieq 'True')
|
|
$PortProperties.IsPoweredOverEthernet = ("$($PortStatus.poe)" -ieq 'True')
|
|
$PortProperties.IsLinkAggregationMember = ("$($DiscoveredPort.lagPort)" -ieq 'True')
|
|
$PortProperties.NeighbourChassisID = "$($PortStatus.chassisId)".ToUpperInvariant()
|
|
$PortProperties.NeighbourPortID = "$($PortStatus.portId)"
|
|
|
|
#region Link state arrives as a status object from the controller and as a bare status from the Open API
|
|
$LinkStateValue = Switch ($Null -ine $PortStatus) {{($_ -eq $True)} {"$($PortStatus.linkStatus)"} Default {"$($DiscoveredPort.status)"}}
|
|
|
|
$PortProperties.LinkState = Switch ("$($LinkStateValue)")
|
|
{
|
|
{($_ -ieq '1')}
|
|
{
|
|
'up'
|
|
}
|
|
|
|
{($_ -ieq '0')}
|
|
{
|
|
'down'
|
|
}
|
|
|
|
Default
|
|
{
|
|
'unknown'
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
$DevicePortList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($PortProperties)))
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Uplink and downlinks, which describe the same topology from either end
|
|
$UplinkObject = $Null
|
|
|
|
Switch ($Null -ine $DeviceDetail.uplink)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$UplinkProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$UplinkProperties.LocalPortNumber = "$($DeviceDetail.uplink.port)"
|
|
$UplinkProperties.UpstreamMACAddress = "$($DeviceDetail.uplink.mac)".ToUpperInvariant()
|
|
$UplinkProperties.UpstreamDeviceName = "$($DeviceDetail.uplink.name)"
|
|
$UplinkProperties.UpstreamPortNumber = "$($DeviceDetail.uplink.linkPeerPortInfo.port)"
|
|
$UplinkProperties.Speed = $ConvertToLinkSpeed.InvokeReturnAsIs($DeviceDetail.uplink.linkSpeed)
|
|
|
|
$UplinkObject = New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($UplinkProperties)
|
|
}
|
|
}
|
|
|
|
$DownlinkObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
ForEach ($DiscoveredDownlink In @($DeviceDetail.downlinkList))
|
|
{
|
|
Switch ($Null -ine $DiscoveredDownlink)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$DownlinkProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$DownlinkProperties.LocalPortNumber = "$($DiscoveredDownlink.port)"
|
|
$DownlinkProperties.PeerMACAddress = "$($DiscoveredDownlink.mac)".ToUpperInvariant()
|
|
$DownlinkProperties.PeerDeviceName = "$($DiscoveredDownlink.name)"
|
|
$DownlinkProperties.PeerPortNumber = "$($DiscoveredDownlink.linkPeerPortInfo.port)"
|
|
$DownlinkProperties.Speed = $ConvertToLinkSpeed.InvokeReturnAsIs($DiscoveredDownlink.linkSpeed)
|
|
|
|
$DownlinkObjectList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($DownlinkProperties)))
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
$DeviceTagList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
|
|
|
ForEach ($DeviceTag In "$($DiscoveredDevice.tagName)".Split(',', [System.StringSplitOptions]::RemoveEmptyEntries))
|
|
{
|
|
$DeviceTagList.Add("$($DeviceTag)".Trim())
|
|
}
|
|
|
|
$DeviceProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$DeviceProperties.MACAddress = "$($DeviceMACAddress)"
|
|
$DeviceProperties.Name = "$($DiscoveredDevice.name)"
|
|
$DeviceProperties.Type = "$($DiscoveredDevice.type)"
|
|
$DeviceProperties.Model = "$($DiscoveredDevice.model)"
|
|
$DeviceProperties.ModelName = Switch ([String]::IsNullOrWhiteSpace("$($DiscoveredDevice.showModel)")) {{($_ -eq $False)} {"$($DiscoveredDevice.showModel)"} Default {"$($DiscoveredDevice.modelName)"}}
|
|
$DeviceProperties.IPAddress = "$($DiscoveredDevice.ip)"
|
|
$DeviceProperties.SerialNumber = "$($DiscoveredDevice.sn)"
|
|
$DeviceProperties.FirmwareVersion = "$($DiscoveredDevice.firmwareVersion)"
|
|
$DeviceProperties.Status = $ConvertToDeviceStatus.InvokeReturnAsIs($DiscoveredDevice.status)
|
|
$DeviceProperties.Uptime = "$($DiscoveredDevice.uptime)"
|
|
$DeviceProperties.Location = "$($DiscoveredDevice.location)"
|
|
$DeviceProperties.TagList = $DeviceTagList
|
|
$DeviceProperties.LastSeen = Try {[System.DateTimeOffset]::FromUnixTimeMilliseconds([Int64]"$($DiscoveredDevice.lastSeen)").UtcDateTime} Catch {$Null}
|
|
$DeviceProperties.PortList = $DevicePortList
|
|
$DeviceProperties.Uplink = $UplinkObject
|
|
$DeviceProperties.DownlinkList = $DownlinkObjectList
|
|
$DeviceProperties.SiteID = "$($SiteID)"
|
|
$DeviceProperties.SiteName = "$($DiscoveredSite.name)"
|
|
|
|
$DeviceObjectList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($DeviceProperties)))
|
|
}
|
|
#endregion
|
|
|
|
#region Clients, which use identical field names on both transports
|
|
$ClientObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
ForEach ($DiscoveredClient In $GetPagedResult.InvokeReturnAsIs("sites/$($SiteID)/clients", "sites/$($SiteID)/clients"))
|
|
{
|
|
$ClientProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$ClientProperties.MACAddress = "$($DiscoveredClient.mac)".ToUpperInvariant()
|
|
$ClientProperties.Name = "$($DiscoveredClient.name)"
|
|
$ClientProperties.IPAddress = "$($DiscoveredClient.ip)"
|
|
$ClientProperties.Vendor = "$($DiscoveredClient.vendor)"
|
|
$ClientProperties.DeviceCategory = "$($DiscoveredClient.deviceCategory)"
|
|
$ClientProperties.IsWireless = ("$($DiscoveredClient.wireless)" -ieq 'True')
|
|
$ClientProperties.VLANID = "$($DiscoveredClient.vid)"
|
|
$ClientProperties.NetworkName = "$($DiscoveredClient.networkName)"
|
|
$ClientProperties.SwitchMACAddress = "$($DiscoveredClient.switchMac)".ToUpperInvariant()
|
|
$ClientProperties.SwitchName = "$($DiscoveredClient.switchName)"
|
|
$ClientProperties.SwitchPort = "$($DiscoveredClient.port)"
|
|
$ClientProperties.SSID = "$($DiscoveredClient.ssid)"
|
|
$ClientProperties.AccessPointMACAddress = "$($DiscoveredClient.apMac)".ToUpperInvariant()
|
|
$ClientProperties.AccessPointName = "$($DiscoveredClient.apName)"
|
|
$ClientProperties.RadioID = "$($DiscoveredClient.radioId)"
|
|
$ClientProperties.Channel = "$($DiscoveredClient.channel)"
|
|
$ClientProperties.SignalDbm = Switch ($Null -ine $DiscoveredClient.rssi) {{($_ -eq $True)} {[Int]"$($DiscoveredClient.rssi)"} Default {$Null}}
|
|
$ClientProperties.LastSeen = Try {[System.DateTimeOffset]::FromUnixTimeMilliseconds([Int64]"$($DiscoveredClient.lastSeen)").UtcDateTime} Catch {$Null}
|
|
$ClientProperties.SiteID = "$($SiteID)"
|
|
$ClientProperties.SiteName = "$($DiscoveredSite.name)"
|
|
|
|
$ClientObjectList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($ClientProperties)))
|
|
}
|
|
#endregion
|
|
|
|
$SiteProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$SiteProperties.SiteID = "$($SiteID)"
|
|
$SiteProperties.Name = "$($DiscoveredSite.name)"
|
|
$SiteProperties.Region = "$($DiscoveredSite.region)"
|
|
$SiteProperties.TimeZone = "$($DiscoveredSite.timeZone)"
|
|
$SiteProperties.DeviceList = $DeviceObjectList
|
|
$SiteProperties.ClientList = $ClientObjectList
|
|
$SiteProperties.VLANList = $VLANObjectList
|
|
$SiteProperties.SSIDList = $SSIDObjectList
|
|
|
|
$SiteObjectList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($SiteProperties)))
|
|
|
|
Write-Verbose -Message "[$([System.DateTime]::UtcNow.ToString('yyyy/MM/dd HH:mm:ss.FFF'))] - [INFO] - Collected $($DeviceObjectList.Count) device(s), $($ClientObjectList.Count) client(s), $($VLANObjectList.Count) VLAN(s), and $($SSIDObjectList.Count) SSID(s) from Omada site `"$($DiscoveredSite.name)`"."
|
|
}
|
|
}
|
|
}
|
|
|
|
$Null = Write-Progress -Activity 'Collecting the Omada inventory' -Id 20 -Completed
|
|
#endregion
|
|
|
|
$InventoryProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$InventoryProperties.SourceType = 'Omada'
|
|
$InventoryProperties.Vendor = 'TP-Link'
|
|
$InventoryProperties.ControllerName = 'Omada Controller'
|
|
$InventoryProperties.BaseURL = [System.URI]"$($Context.BaseAddress)"
|
|
$InventoryProperties.OmadacID = "$($Context.OmadacID)"
|
|
$InventoryProperties.ControllerVersion = "$($Context.ControllerVersion)"
|
|
$InventoryProperties.CollectionMode = "$($Context.Mode)"
|
|
$InventoryProperties.RetrievedAt = [System.DateTime]::UtcNow
|
|
$InventoryProperties.SiteList = $SiteObjectList
|
|
|
|
Write-Output -InputObject (New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($InventoryProperties))
|
|
}
|
|
Catch
|
|
{
|
|
Throw
|
|
}
|
|
}
|
|
#endregion
|