545 lines
42 KiB
PowerShell
545 lines
42 KiB
PowerShell
#region Get-UnifiInventory
|
|
Function Get-UnifiInventory
|
|
{
|
|
<#
|
|
.SYNOPSIS
|
|
Collects the layer two inventory from a UniFi Network controller and returns the same normalized model that the Omada
|
|
collector returns.
|
|
|
|
.DESCRIPTION
|
|
The returned model is deliberately identical to the Omada one, so that everything downstream treats a UniFi estate and an
|
|
Omada estate the same way and no vendor specific branching leaks into the desired state graph.
|
|
|
|
Available from both transports.
|
|
|
|
Sites, device inventory, and client sessions.
|
|
|
|
Available only from the network interface.
|
|
|
|
Per port media, speed, and power over Ethernet state.
|
|
Per port LLDP neighbour detail.
|
|
Uplink relationships carrying the remote port, which is what allows an inter switch cable to be drawn with both ends known.
|
|
Network definitions with their subnets, which become VLANs and subnets.
|
|
The real wireless configuration, rather than SSID names inferred from whichever clients happen to be associated.
|
|
|
|
Enumerations relied upon here.
|
|
|
|
Device state 0 disconnected, 1 connected, 2 pending adoption, 4 upgrading, 5 provisioning, and anything else unknown.
|
|
Device type usw is a switch, uap is an access point, and ugw, udm, or uxg is a gateway.
|
|
Port media GE and FE are copper, SFP and SFP+ are a fibre or direct attach cage.
|
|
|
|
.PARAMETER Context
|
|
The connection context produced by Connect-UnifiController.
|
|
|
|
.PARAMETER SiteName
|
|
Optionally restricts collection to one or more sites, matched against the site description as shown in the user interface.
|
|
|
|
.EXAMPLE
|
|
$UnifiInventory = Get-UnifiInventory -Context $UnifiContext
|
|
|
|
.NOTES
|
|
Author: Grace Solutions
|
|
Version: 2026.08.02.0000
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$True)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[PSObject]$Context,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[AllowNull()]
|
|
[String[]]$SiteName
|
|
)
|
|
|
|
Try
|
|
{
|
|
#region Define the device status translation
|
|
[ScriptBlock]$ConvertToDeviceStatus = {
|
|
Param
|
|
(
|
|
[System.Object]$StateValue
|
|
)
|
|
|
|
$DeviceStatus = 'unknown'
|
|
|
|
Switch ("$($StateValue)")
|
|
{
|
|
{($_ -ieq '0')}
|
|
{
|
|
$DeviceStatus = 'offline'
|
|
}
|
|
|
|
{($_ -ieq '1')}
|
|
{
|
|
$DeviceStatus = 'online'
|
|
}
|
|
|
|
{($_ -iin @('2', '4', '5', '6'))}
|
|
{
|
|
$DeviceStatus = 'warning'
|
|
}
|
|
}
|
|
|
|
Write-Output -InputObject ("$($DeviceStatus)")
|
|
}
|
|
#endregion
|
|
|
|
#region Define the port media translation
|
|
[ScriptBlock]$ConvertToPortKind = {
|
|
Param
|
|
(
|
|
[String]$MediaValue,
|
|
[System.Object]$SpeedValue
|
|
)
|
|
|
|
$PortKind = 'rj45'
|
|
|
|
Switch ("$($MediaValue)")
|
|
{
|
|
{($_ -imatch '^(?i)SFP\+$')}
|
|
{
|
|
$PortKind = 'sfp_plus'
|
|
}
|
|
|
|
{($_ -imatch '^(?i)SFP$')}
|
|
{
|
|
$PortKind = 'sfp'
|
|
}
|
|
}
|
|
|
|
#region A cage reporting ten gigabit is a plus cage regardless of how it labelled itself
|
|
Switch (("$($PortKind)" -ieq 'sfp') -and ([Int]"0$($SpeedValue)" -ge 10000))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$PortKind = 'sfp_plus'
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
Write-Output -InputObject ("$($PortKind)")
|
|
}
|
|
#endregion
|
|
|
|
#region Define the link speed translation, which UniFi reports in megabits
|
|
[ScriptBlock]$ConvertToLinkSpeed = {
|
|
Param
|
|
(
|
|
[System.Object]$SpeedValue
|
|
)
|
|
|
|
$SpeedName = ''
|
|
|
|
Switch ([Int]"0$($SpeedValue)")
|
|
{
|
|
{($_ -ge 10000)}
|
|
{
|
|
$SpeedName = '10G'
|
|
}
|
|
|
|
{($_ -ge 2500) -and ($_ -lt 10000)}
|
|
{
|
|
$SpeedName = '2.5G'
|
|
}
|
|
|
|
{($_ -ge 1000) -and ($_ -lt 2500)}
|
|
{
|
|
$SpeedName = '1G'
|
|
}
|
|
|
|
{($_ -ge 100) -and ($_ -lt 1000)}
|
|
{
|
|
$SpeedName = '100M'
|
|
}
|
|
|
|
{($_ -gt 0) -and ($_ -lt 100)}
|
|
{
|
|
$SpeedName = '10M'
|
|
}
|
|
}
|
|
|
|
Write-Output -InputObject ("$($SpeedName)")
|
|
}
|
|
#endregion
|
|
|
|
#region Enumerate sites
|
|
$SiteObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
$SiteResult = Invoke-UnifiRequest -Context ($Context) -NetworkPath 'api/self/sites' -IntegrationPath 'v1/sites'
|
|
|
|
$DiscoveredSiteList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
ForEach ($DiscoveredSite In @($SiteResult.Result))
|
|
{
|
|
Switch ($Null -ine $DiscoveredSite)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$DiscoveredSiteList.Add($DiscoveredSite)
|
|
}
|
|
}
|
|
}
|
|
|
|
#region A controller that will not enumerate sites still has the default site, which is enough to proceed
|
|
Switch ($DiscoveredSiteList.Count -eq 0)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$DefaultSiteProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$DefaultSiteProperties.name = 'default'
|
|
$DefaultSiteProperties.desc = 'Default'
|
|
|
|
$DiscoveredSiteList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($DefaultSiteProperties)))
|
|
|
|
Write-Verbose -Message "[$([System.DateTime]::UtcNow.ToString('yyyy/MM/dd HH:mm:ss.FFF'))] - [WARNING] - The UniFi site list could not be retrieved, so the default site will be collected on its own. [$($SiteResult.ErrorMessage)]"
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
Write-Verbose -Message "[$([System.DateTime]::UtcNow.ToString('yyyy/MM/dd HH:mm:ss.FFF'))] - [INFO] - $($DiscoveredSiteList.Count) UniFi site(s) were discovered."
|
|
|
|
For ($DiscoveredSiteIndex = 0; $DiscoveredSiteIndex -lt $DiscoveredSiteList.Count; $DiscoveredSiteIndex++)
|
|
{
|
|
$DiscoveredSite = $DiscoveredSiteList[$DiscoveredSiteIndex]
|
|
|
|
#region The network interface addresses a site by its short name and the integration API by its identifier
|
|
$SiteKey = "$($DiscoveredSite.name)"
|
|
$SiteDisplayName = "$($DiscoveredSite.desc)"
|
|
|
|
Switch ([String]::IsNullOrWhiteSpace($SiteDisplayName))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SiteDisplayName = "$($DiscoveredSite.name)"
|
|
}
|
|
}
|
|
|
|
Switch ([String]::IsNullOrWhiteSpace($SiteKey))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SiteKey = "$($DiscoveredSite.id)"
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
$SiteIsRequested = $True
|
|
|
|
Switch (($Null -ine $SiteName) -and ($SiteName.Count -gt 0))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SiteIsRequested = ("$($SiteDisplayName)" -iin $SiteName) -or ("$($SiteKey)" -iin $SiteName)
|
|
}
|
|
}
|
|
|
|
Switch ($SiteIsRequested)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$WriteProgressParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$WriteProgressParameters.Activity = 'Collecting the UniFi inventory'
|
|
$WriteProgressParameters.Status = "Processing site `"$($SiteDisplayName)`" ($($DiscoveredSiteIndex + 1) of $($DiscoveredSiteList.Count))"
|
|
$WriteProgressParameters.PercentComplete = [System.Math]::Round((($DiscoveredSiteIndex + 1) / $DiscoveredSiteList.Count) * 100, 2)
|
|
$WriteProgressParameters.Id = 23
|
|
|
|
$Null = Write-Progress @WriteProgressParameters
|
|
|
|
#region Network definitions, which become VLANs and their subnets
|
|
$VLANObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
$NetworkIdentifierTable = New-Object -TypeName 'System.Collections.Generic.Dictionary[[System.String], [System.Int32]]'
|
|
|
|
$NetworkResult = Invoke-UnifiRequest -Context ($Context) -NetworkPath "api/s/$($SiteKey)/rest/networkconf"
|
|
|
|
ForEach ($DiscoveredNetwork In @($NetworkResult.Result))
|
|
{
|
|
$NetworkVLANID = [Int]"0$($DiscoveredNetwork.vlan)"
|
|
|
|
Switch (($NetworkVLANID -gt 0) -and ("$($DiscoveredNetwork.purpose)" -inotmatch '^(?i)wan'))
|
|
{
|
|
{($_ -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.ip_subnet)"
|
|
$VLANProperties.NetworkID = "$($DiscoveredNetwork._id)"
|
|
|
|
$VLANObjectList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($VLANProperties)))
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Wireless configuration
|
|
$SSIDObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
$SecurityTable = New-Object -TypeName 'System.Collections.Generic.Dictionary[[System.String], [System.String]]'
|
|
$SecurityTable.Add('open', 'Open')
|
|
$SecurityTable.Add('wep', 'WEP')
|
|
$SecurityTable.Add('wpapsk', 'WPA Personal')
|
|
$SecurityTable.Add('wpaeap', 'WPA Enterprise')
|
|
|
|
$WirelessResult = Invoke-UnifiRequest -Context ($Context) -NetworkPath "api/s/$($SiteKey)/rest/wlanconf"
|
|
|
|
ForEach ($DiscoveredSSID In @($WirelessResult.Result))
|
|
{
|
|
Switch ([String]::IsNullOrWhiteSpace("$($DiscoveredSSID.name)") -eq $False)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
#region The security mode is refined by the protected access generation when the controller reports one
|
|
$SecurityName = Switch ($SecurityTable.ContainsKey("$($DiscoveredSSID.security)".ToLowerInvariant())) {{($_ -eq $True)} {"$($SecurityTable["$($DiscoveredSSID.security)".ToLowerInvariant()])"} Default {"$($DiscoveredSSID.security)"}}
|
|
|
|
Switch ("$($DiscoveredSSID.wpa3_support)" -ieq 'True')
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SecurityName = Switch ("$($DiscoveredSSID.wpa3_transition)" -ieq 'True') {{($_ -eq $True)} {'WPA2/WPA3 Personal'} Default {'WPA3 Personal'}}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
$SSIDVLANID = ''
|
|
|
|
Switch ($NetworkIdentifierTable.ContainsKey("$($DiscoveredSSID.networkconf_id)"))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SSIDVLANID = "$($NetworkIdentifierTable["$($DiscoveredSSID.networkconf_id)"])"
|
|
}
|
|
}
|
|
|
|
$SSIDProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$SSIDProperties.Name = "$($DiscoveredSSID.name)"
|
|
$SSIDProperties.Security = "$($SecurityName)"
|
|
$SSIDProperties.IsHidden = ("$($DiscoveredSSID.hide_ssid)" -ieq 'True')
|
|
$SSIDProperties.IsGuest = ("$($DiscoveredSSID.is_guest)" -ieq 'True')
|
|
$SSIDProperties.VLANID = "$($SSIDVLANID)"
|
|
$SSIDProperties.WLANGroupName = "$($DiscoveredSSID.wlangroup_id)"
|
|
|
|
$SSIDObjectList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($SSIDProperties)))
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Devices
|
|
$DeviceObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
$DeviceResult = Invoke-UnifiRequest -Context ($Context) -NetworkPath "api/s/$($SiteKey)/stat/device" -IntegrationPath "v1/sites/$($DiscoveredSite.id)/devices"
|
|
|
|
ForEach ($DiscoveredDevice In @($DeviceResult.Result))
|
|
{
|
|
$DeviceMACAddress = "$($DiscoveredDevice.mac)".ToUpperInvariant()
|
|
|
|
$DeviceTypeName = Switch ("$($DiscoveredDevice.type)")
|
|
{
|
|
{($_ -ieq 'usw')}
|
|
{
|
|
'switch'
|
|
}
|
|
|
|
{($_ -ieq 'uap')}
|
|
{
|
|
'ap'
|
|
}
|
|
|
|
{($_ -iin @('ugw', 'udm', 'uxg'))}
|
|
{
|
|
'gateway'
|
|
}
|
|
|
|
Default
|
|
{
|
|
'other'
|
|
}
|
|
}
|
|
|
|
#region Ports
|
|
$DevicePortList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
ForEach ($DiscoveredPort In @($DiscoveredDevice.port_table))
|
|
{
|
|
Switch ($Null -ine $DiscoveredPort)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$PortVLANID = ''
|
|
|
|
Switch ($NetworkIdentifierTable.ContainsKey("$($DiscoveredPort.native_networkconf_id)"))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$PortVLANID = "$($NetworkIdentifierTable["$($DiscoveredPort.native_networkconf_id)"])"
|
|
}
|
|
}
|
|
|
|
$PortProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$PortProperties.Number = [Int]"0$($DiscoveredPort.port_idx)"
|
|
$PortProperties.Name = Switch ([String]::IsNullOrWhiteSpace("$($DiscoveredPort.name)")) {{($_ -eq $False)} {"$($DiscoveredPort.name)"} Default {"Port $($DiscoveredPort.port_idx)"}}
|
|
$PortProperties.ProfileName = "$($DiscoveredPort.portconf_id)"
|
|
$PortProperties.Kind = $ConvertToPortKind.InvokeReturnAsIs("$($DiscoveredPort.media)", $DiscoveredPort.speed)
|
|
$PortProperties.Speed = $ConvertToLinkSpeed.InvokeReturnAsIs($DiscoveredPort.speed)
|
|
$PortProperties.Mode = Switch ("$($DiscoveredPort.op_mode)" -ieq 'switch') {{($_ -eq $True)} {'trunk'} Default {'access'}}
|
|
$PortProperties.VLANID = "$($PortVLANID)"
|
|
$PortProperties.IsDisabled = ("$($DiscoveredPort.enable)" -ieq 'False')
|
|
$PortProperties.IsPoweredOverEthernet = ("$($DiscoveredPort.poe_enable)" -ieq 'True')
|
|
$PortProperties.IsLinkAggregationMember = ("$($DiscoveredPort.aggregated_by)" -ieq 'True')
|
|
$PortProperties.LinkState = Switch ("$($DiscoveredPort.up)" -ieq 'True') {{($_ -eq $True)} {'up'} Default {'down'}}
|
|
$PortProperties.NeighbourChassisID = "$($DiscoveredPort.lldp_table.lldp_chassis_id)".ToUpperInvariant()
|
|
$PortProperties.NeighbourPortID = "$($DiscoveredPort.lldp_table.lldp_port_id)"
|
|
|
|
$DevicePortList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($PortProperties)))
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Uplink, which carries the remote port and therefore describes both ends
|
|
$UplinkObject = $Null
|
|
|
|
Switch (($Null -ine $DiscoveredDevice.uplink) -and ([String]::IsNullOrWhiteSpace("$($DiscoveredDevice.uplink.uplink_mac)") -eq $False))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$UplinkProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$UplinkProperties.LocalPortNumber = "$($DiscoveredDevice.uplink.port_idx)"
|
|
$UplinkProperties.UpstreamMACAddress = "$($DiscoveredDevice.uplink.uplink_mac)".ToUpperInvariant()
|
|
$UplinkProperties.UpstreamDeviceName = "$($DiscoveredDevice.uplink.uplink_device_name)"
|
|
$UplinkProperties.UpstreamPortNumber = "$($DiscoveredDevice.uplink.uplink_remote_port)"
|
|
$UplinkProperties.Speed = $ConvertToLinkSpeed.InvokeReturnAsIs($DiscoveredDevice.uplink.speed)
|
|
|
|
$UplinkObject = New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($UplinkProperties)
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
$DeviceProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$DeviceProperties.MACAddress = "$($DeviceMACAddress)"
|
|
$DeviceProperties.Name = Switch ([String]::IsNullOrWhiteSpace("$($DiscoveredDevice.name)")) {{($_ -eq $False)} {"$($DiscoveredDevice.name)"} Default {"$($DeviceMACAddress)"}}
|
|
$DeviceProperties.Type = "$($DeviceTypeName)"
|
|
$DeviceProperties.Model = "$($DiscoveredDevice.model)"
|
|
$DeviceProperties.ModelName = Switch ([String]::IsNullOrWhiteSpace("$($DiscoveredDevice.model_in_lts)")) {{($_ -eq $False)} {"$($DiscoveredDevice.model)"} Default {"$($DiscoveredDevice.model)"}}
|
|
$DeviceProperties.IPAddress = "$($DiscoveredDevice.ip)"
|
|
$DeviceProperties.SerialNumber = "$($DiscoveredDevice.serial)"
|
|
$DeviceProperties.FirmwareVersion = "$($DiscoveredDevice.version)"
|
|
$DeviceProperties.Status = $ConvertToDeviceStatus.InvokeReturnAsIs($DiscoveredDevice.state)
|
|
$DeviceProperties.Uptime = "$($DiscoveredDevice.uptime)"
|
|
$DeviceProperties.Location = ''
|
|
$DeviceProperties.TagList = New-Object -TypeName 'System.Collections.Generic.List[String]'
|
|
$DeviceProperties.LastSeen = Try {[System.DateTimeOffset]::FromUnixTimeSeconds([Int64]"$($DiscoveredDevice.last_seen)").UtcDateTime} Catch {$Null}
|
|
$DeviceProperties.PortList = $DevicePortList
|
|
$DeviceProperties.Uplink = $UplinkObject
|
|
$DeviceProperties.DownlinkList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
$DeviceProperties.SiteID = "$($SiteKey)"
|
|
$DeviceProperties.SiteName = "$($SiteDisplayName)"
|
|
|
|
$DeviceObjectList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($DeviceProperties)))
|
|
}
|
|
#endregion
|
|
|
|
#region Clients
|
|
$ClientObjectList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
|
|
|
|
$ClientResult = Invoke-UnifiRequest -Context ($Context) -NetworkPath "api/s/$($SiteKey)/stat/sta" -IntegrationPath "v1/sites/$($DiscoveredSite.id)/clients"
|
|
|
|
ForEach ($DiscoveredClient In @($ClientResult.Result))
|
|
{
|
|
$ClientIsWired = ("$($DiscoveredClient.is_wired)" -ieq 'True')
|
|
|
|
$ClientProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$ClientProperties.MACAddress = "$($DiscoveredClient.mac)".ToUpperInvariant()
|
|
$ClientProperties.Name = Switch ([String]::IsNullOrWhiteSpace("$($DiscoveredClient.name)")) {{($_ -eq $False)} {"$($DiscoveredClient.name)"} Default {"$($DiscoveredClient.hostname)"}}
|
|
$ClientProperties.IPAddress = "$($DiscoveredClient.ip)"
|
|
$ClientProperties.Vendor = "$($DiscoveredClient.oui)"
|
|
$ClientProperties.DeviceCategory = ''
|
|
$ClientProperties.IsWireless = ($ClientIsWired -eq $False)
|
|
$ClientProperties.VLANID = "$($DiscoveredClient.vlan)"
|
|
$ClientProperties.NetworkName = "$($DiscoveredClient.network)"
|
|
$ClientProperties.SwitchMACAddress = "$($DiscoveredClient.sw_mac)".ToUpperInvariant()
|
|
$ClientProperties.SwitchName = ''
|
|
$ClientProperties.SwitchPort = "$($DiscoveredClient.sw_port)"
|
|
$ClientProperties.SSID = "$($DiscoveredClient.essid)"
|
|
$ClientProperties.AccessPointMACAddress = "$($DiscoveredClient.ap_mac)".ToUpperInvariant()
|
|
$ClientProperties.AccessPointName = ''
|
|
$ClientProperties.RadioID = Switch ("$($DiscoveredClient.radio)") {{($_ -ieq 'ng')} {'0'} {($_ -ieq 'na')} {'1'} {($_ -ieq '6e')} {'2'} Default {''}}
|
|
$ClientProperties.Channel = "$($DiscoveredClient.channel)"
|
|
$ClientProperties.SignalDbm = Switch ($Null -ine $DiscoveredClient.signal) {{($_ -eq $True)} {[Int]"$($DiscoveredClient.signal)"} Default {$Null}}
|
|
$ClientProperties.LastSeen = Try {[System.DateTimeOffset]::FromUnixTimeSeconds([Int64]"$($DiscoveredClient.last_seen)").UtcDateTime} Catch {$Null}
|
|
$ClientProperties.SiteID = "$($SiteKey)"
|
|
$ClientProperties.SiteName = "$($SiteDisplayName)"
|
|
|
|
$ClientObjectList.Add((New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($ClientProperties)))
|
|
}
|
|
|
|
#region The client record names its switch and access point by address only, so the names are filled in from the device inventory
|
|
ForEach ($ClientObject In $ClientObjectList)
|
|
{
|
|
ForEach ($DeviceObject In $DeviceObjectList)
|
|
{
|
|
Switch ("$($DeviceObject.MACAddress)" -ieq "$($ClientObject.SwitchMACAddress)")
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$ClientObject.SwitchName = "$($DeviceObject.Name)"
|
|
}
|
|
}
|
|
|
|
Switch ("$($DeviceObject.MACAddress)" -ieq "$($ClientObject.AccessPointMACAddress)")
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$ClientObject.AccessPointName = "$($DeviceObject.Name)"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
#endregion
|
|
|
|
$SiteProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$SiteProperties.SiteID = "$($SiteKey)"
|
|
$SiteProperties.Name = "$($SiteDisplayName)"
|
|
$SiteProperties.Region = ''
|
|
$SiteProperties.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 UniFi site `"$($SiteDisplayName)`"."
|
|
}
|
|
}
|
|
}
|
|
|
|
$Null = Write-Progress -Activity 'Collecting the UniFi inventory' -Id 23 -Completed
|
|
#endregion
|
|
|
|
$InventoryProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$InventoryProperties.SourceType = 'UniFi'
|
|
$InventoryProperties.Vendor = 'Ubiquiti'
|
|
$InventoryProperties.ControllerName = 'UniFi Network Controller'
|
|
$InventoryProperties.BaseURL = [System.URI]"$($Context.BaseAddress)"
|
|
$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
|