mirror of
https://github.com/home-assistant/core.git
synced 2025-08-02 10:08:23 +00:00
Add diagnostics to UISP AirOS (#149631)
This commit is contained in:
parent
8b53b26333
commit
22e054f4cd
33
homeassistant/components/airos/diagnostics.py
Normal file
33
homeassistant/components/airos/diagnostics.py
Normal file
@ -0,0 +1,33 @@
|
||||
"""Diagnostics support for airOS."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.const import CONF_HOST, CONF_PASSWORD
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .coordinator import AirOSConfigEntry
|
||||
|
||||
IP_REDACT = ["addr", "ipaddr", "ip6addr", "lastip"] # IP related
|
||||
HW_REDACT = ["apmac", "hwaddr", "mac"] # MAC address
|
||||
TO_REDACT_HA = [CONF_HOST, CONF_PASSWORD]
|
||||
TO_REDACT_AIROS = [
|
||||
"hostname", # Prevent leaking device naming
|
||||
"essid", # Network SSID
|
||||
"lat", # GPS latitude to prevent exposing location data.
|
||||
"lon", # GPS longitude to prevent exposing location data.
|
||||
*HW_REDACT,
|
||||
*IP_REDACT,
|
||||
]
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant, entry: AirOSConfigEntry
|
||||
) -> dict[str, Any]:
|
||||
"""Return diagnostics for a config entry."""
|
||||
return {
|
||||
"entry_data": async_redact_data(entry.data, TO_REDACT_HA),
|
||||
"data": async_redact_data(entry.runtime_data.data.to_dict(), TO_REDACT_AIROS),
|
||||
}
|
@ -41,7 +41,7 @@ rules:
|
||||
|
||||
# Gold
|
||||
devices: done
|
||||
diagnostics: todo
|
||||
diagnostics: done
|
||||
discovery-update-info: todo
|
||||
discovery: todo
|
||||
docs-data-update: done
|
||||
|
623
tests/components/airos/snapshots/test_diagnostics.ambr
Normal file
623
tests/components/airos/snapshots/test_diagnostics.ambr
Normal file
@ -0,0 +1,623 @@
|
||||
# serializer version: 1
|
||||
# name: test_diagnostics
|
||||
dict({
|
||||
'data': dict({
|
||||
'chain_names': list([
|
||||
dict({
|
||||
'name': 'Chain 0',
|
||||
'number': 1,
|
||||
}),
|
||||
dict({
|
||||
'name': 'Chain 1',
|
||||
'number': 2,
|
||||
}),
|
||||
]),
|
||||
'derived': dict({
|
||||
'mac': '**REDACTED**',
|
||||
'mac_interface': 'br0',
|
||||
}),
|
||||
'firewall': dict({
|
||||
'eb6tables': False,
|
||||
'ebtables': False,
|
||||
'ip6tables': False,
|
||||
'iptables': False,
|
||||
}),
|
||||
'genuine': '/images/genuine.png',
|
||||
'gps': dict({
|
||||
'fix': 0,
|
||||
'lat': '**REDACTED**',
|
||||
'lon': '**REDACTED**',
|
||||
}),
|
||||
'host': dict({
|
||||
'cpuload': 10.10101,
|
||||
'device_id': '03aa0d0b40fed0a47088293584ef5432',
|
||||
'devmodel': 'NanoStation 5AC loco',
|
||||
'freeram': 16564224,
|
||||
'fwversion': 'v8.7.17',
|
||||
'height': 3,
|
||||
'hostname': '**REDACTED**',
|
||||
'loadavg': 0.412598,
|
||||
'netrole': 'bridge',
|
||||
'power_time': 268683,
|
||||
'temperature': 0,
|
||||
'time': '2025-06-23 23:06:42',
|
||||
'timestamp': 2668313184,
|
||||
'totalram': 63447040,
|
||||
'uptime': 264888,
|
||||
}),
|
||||
'interfaces': list([
|
||||
dict({
|
||||
'enabled': True,
|
||||
'hwaddr': '**REDACTED**',
|
||||
'ifname': 'eth0',
|
||||
'mtu': 1500,
|
||||
'status': dict({
|
||||
'cable_len': 18,
|
||||
'duplex': True,
|
||||
'ip6addr': None,
|
||||
'ipaddr': '**REDACTED**',
|
||||
'plugged': True,
|
||||
'rx_bytes': 3984971949,
|
||||
'rx_dropped': 0,
|
||||
'rx_errors': 4,
|
||||
'rx_packets': 73564835,
|
||||
'snr': list([
|
||||
30,
|
||||
30,
|
||||
30,
|
||||
30,
|
||||
]),
|
||||
'speed': 1000,
|
||||
'tx_bytes': 209900085624,
|
||||
'tx_dropped': 10,
|
||||
'tx_errors': 0,
|
||||
'tx_packets': 185866883,
|
||||
}),
|
||||
}),
|
||||
dict({
|
||||
'enabled': True,
|
||||
'hwaddr': '**REDACTED**',
|
||||
'ifname': 'ath0',
|
||||
'mtu': 1500,
|
||||
'status': dict({
|
||||
'cable_len': None,
|
||||
'duplex': False,
|
||||
'ip6addr': None,
|
||||
'ipaddr': '**REDACTED**',
|
||||
'plugged': False,
|
||||
'rx_bytes': 206938324766,
|
||||
'rx_dropped': 0,
|
||||
'rx_errors': 0,
|
||||
'rx_packets': 149767200,
|
||||
'snr': None,
|
||||
'speed': 0,
|
||||
'tx_bytes': 5265602738,
|
||||
'tx_dropped': 2005,
|
||||
'tx_errors': 0,
|
||||
'tx_packets': 52980390,
|
||||
}),
|
||||
}),
|
||||
dict({
|
||||
'enabled': True,
|
||||
'hwaddr': '**REDACTED**',
|
||||
'ifname': 'br0',
|
||||
'mtu': 1500,
|
||||
'status': dict({
|
||||
'cable_len': None,
|
||||
'duplex': False,
|
||||
'ip6addr': '**REDACTED**',
|
||||
'ipaddr': '**REDACTED**',
|
||||
'plugged': True,
|
||||
'rx_bytes': 204802727,
|
||||
'rx_dropped': 0,
|
||||
'rx_errors': 0,
|
||||
'rx_packets': 1791592,
|
||||
'snr': None,
|
||||
'speed': 0,
|
||||
'tx_bytes': 236295176,
|
||||
'tx_dropped': 0,
|
||||
'tx_errors': 0,
|
||||
'tx_packets': 298119,
|
||||
}),
|
||||
}),
|
||||
]),
|
||||
'ntpclient': dict({
|
||||
}),
|
||||
'portfw': False,
|
||||
'provmode': dict({
|
||||
}),
|
||||
'services': dict({
|
||||
'airview': 2,
|
||||
'dhcp6d_stateful': False,
|
||||
'dhcpc': False,
|
||||
'dhcpd': False,
|
||||
'pppoe': False,
|
||||
}),
|
||||
'unms': dict({
|
||||
'status': 0,
|
||||
'timestamp': None,
|
||||
}),
|
||||
'wireless': dict({
|
||||
'antenna_gain': 13,
|
||||
'apmac': '**REDACTED**',
|
||||
'aprepeater': False,
|
||||
'band': 2,
|
||||
'cac_state': 0,
|
||||
'cac_timeout': 0,
|
||||
'center1_freq': 5530,
|
||||
'chanbw': 80,
|
||||
'compat_11n': 0,
|
||||
'count': 1,
|
||||
'dfs': 1,
|
||||
'distance': 0,
|
||||
'essid': '**REDACTED**',
|
||||
'frequency': 5500,
|
||||
'hide_essid': 0,
|
||||
'ieeemode': '11ACVHT80',
|
||||
'mode': 'ap-ptp',
|
||||
'noisef': -89,
|
||||
'nol_state': 0,
|
||||
'nol_timeout': 0,
|
||||
'polling': dict({
|
||||
'atpc_status': 2,
|
||||
'cb_capacity': 593970,
|
||||
'dl_capacity': 647400,
|
||||
'ff_cap_rep': False,
|
||||
'fixed_frame': False,
|
||||
'gps_sync': False,
|
||||
'rx_use': 42,
|
||||
'tx_use': 6,
|
||||
'ul_capacity': 540540,
|
||||
'use': 48,
|
||||
}),
|
||||
'rstatus': 5,
|
||||
'rx_chainmask': 3,
|
||||
'rx_idx': 8,
|
||||
'rx_nss': 2,
|
||||
'security': 'WPA2',
|
||||
'service': dict({
|
||||
'link': 266003,
|
||||
'time': 267181,
|
||||
}),
|
||||
'sta': list([
|
||||
dict({
|
||||
'airmax': dict({
|
||||
'actual_priority': 0,
|
||||
'atpc_status': 2,
|
||||
'beam': 0,
|
||||
'cb_capacity': 593970,
|
||||
'desired_priority': 0,
|
||||
'dl_capacity': 647400,
|
||||
'rx': dict({
|
||||
'cinr': 31,
|
||||
'evm': list([
|
||||
list([
|
||||
31,
|
||||
28,
|
||||
33,
|
||||
32,
|
||||
32,
|
||||
32,
|
||||
31,
|
||||
31,
|
||||
31,
|
||||
29,
|
||||
30,
|
||||
32,
|
||||
30,
|
||||
27,
|
||||
34,
|
||||
31,
|
||||
31,
|
||||
30,
|
||||
32,
|
||||
29,
|
||||
31,
|
||||
29,
|
||||
31,
|
||||
33,
|
||||
31,
|
||||
31,
|
||||
32,
|
||||
30,
|
||||
31,
|
||||
34,
|
||||
33,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
31,
|
||||
32,
|
||||
31,
|
||||
30,
|
||||
33,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
27,
|
||||
31,
|
||||
30,
|
||||
30,
|
||||
30,
|
||||
30,
|
||||
30,
|
||||
29,
|
||||
32,
|
||||
34,
|
||||
31,
|
||||
30,
|
||||
28,
|
||||
30,
|
||||
29,
|
||||
35,
|
||||
31,
|
||||
33,
|
||||
32,
|
||||
29,
|
||||
]),
|
||||
list([
|
||||
34,
|
||||
34,
|
||||
35,
|
||||
34,
|
||||
35,
|
||||
35,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
35,
|
||||
35,
|
||||
34,
|
||||
34,
|
||||
35,
|
||||
34,
|
||||
33,
|
||||
33,
|
||||
35,
|
||||
34,
|
||||
34,
|
||||
35,
|
||||
34,
|
||||
35,
|
||||
34,
|
||||
34,
|
||||
35,
|
||||
34,
|
||||
34,
|
||||
33,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
35,
|
||||
35,
|
||||
35,
|
||||
34,
|
||||
35,
|
||||
33,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
35,
|
||||
35,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
34,
|
||||
35,
|
||||
35,
|
||||
]),
|
||||
]),
|
||||
'usage': 42,
|
||||
}),
|
||||
'tx': dict({
|
||||
'cinr': 31,
|
||||
'evm': list([
|
||||
list([
|
||||
32,
|
||||
34,
|
||||
28,
|
||||
33,
|
||||
35,
|
||||
30,
|
||||
31,
|
||||
33,
|
||||
30,
|
||||
30,
|
||||
32,
|
||||
30,
|
||||
29,
|
||||
33,
|
||||
31,
|
||||
29,
|
||||
33,
|
||||
31,
|
||||
31,
|
||||
30,
|
||||
33,
|
||||
34,
|
||||
33,
|
||||
31,
|
||||
33,
|
||||
32,
|
||||
32,
|
||||
31,
|
||||
29,
|
||||
31,
|
||||
30,
|
||||
32,
|
||||
31,
|
||||
30,
|
||||
29,
|
||||
32,
|
||||
31,
|
||||
32,
|
||||
31,
|
||||
31,
|
||||
32,
|
||||
29,
|
||||
31,
|
||||
29,
|
||||
30,
|
||||
32,
|
||||
32,
|
||||
31,
|
||||
32,
|
||||
32,
|
||||
33,
|
||||
31,
|
||||
28,
|
||||
29,
|
||||
31,
|
||||
31,
|
||||
33,
|
||||
32,
|
||||
33,
|
||||
32,
|
||||
32,
|
||||
32,
|
||||
31,
|
||||
33,
|
||||
]),
|
||||
list([
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
38,
|
||||
38,
|
||||
37,
|
||||
36,
|
||||
38,
|
||||
38,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
39,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
36,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
38,
|
||||
37,
|
||||
37,
|
||||
38,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
38,
|
||||
37,
|
||||
38,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
36,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
38,
|
||||
37,
|
||||
37,
|
||||
38,
|
||||
37,
|
||||
36,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
37,
|
||||
]),
|
||||
]),
|
||||
'usage': 6,
|
||||
}),
|
||||
'ul_capacity': 540540,
|
||||
}),
|
||||
'airos_connected': True,
|
||||
'cb_capacity_expect': 416000,
|
||||
'chainrssi': list([
|
||||
35,
|
||||
32,
|
||||
0,
|
||||
]),
|
||||
'distance': 1,
|
||||
'dl_avg_linkscore': 100,
|
||||
'dl_capacity_expect': 208000,
|
||||
'dl_linkscore': 100,
|
||||
'dl_rate_expect': 3,
|
||||
'dl_signal_expect': -80,
|
||||
'last_disc': 1,
|
||||
'lastip': '**REDACTED**',
|
||||
'mac': '**REDACTED**',
|
||||
'noisefloor': -89,
|
||||
'remote': dict({
|
||||
'age': 1,
|
||||
'airview': 2,
|
||||
'antenna_gain': 13,
|
||||
'cable_loss': 0,
|
||||
'chainrssi': list([
|
||||
33,
|
||||
37,
|
||||
0,
|
||||
]),
|
||||
'compat_11n': 0,
|
||||
'cpuload': 43.564301,
|
||||
'device_id': 'd4f4cdf82961e619328a8f72f8d7653b',
|
||||
'distance': 1,
|
||||
'ethlist': list([
|
||||
dict({
|
||||
'cable_len': 14,
|
||||
'duplex': True,
|
||||
'enabled': True,
|
||||
'ifname': 'eth0',
|
||||
'plugged': True,
|
||||
'snr': list([
|
||||
30,
|
||||
30,
|
||||
29,
|
||||
30,
|
||||
]),
|
||||
'speed': 1000,
|
||||
}),
|
||||
]),
|
||||
'freeram': 14290944,
|
||||
'gps': dict({
|
||||
'fix': 0,
|
||||
'lat': '**REDACTED**',
|
||||
'lon': '**REDACTED**',
|
||||
}),
|
||||
'height': 2,
|
||||
'hostname': '**REDACTED**',
|
||||
'ip6addr': '**REDACTED**',
|
||||
'ipaddr': '**REDACTED**',
|
||||
'mode': 'sta-ptp',
|
||||
'netrole': 'bridge',
|
||||
'noisefloor': -90,
|
||||
'oob': False,
|
||||
'platform': 'NanoStation 5AC loco',
|
||||
'power_time': 268512,
|
||||
'rssi': 38,
|
||||
'rx_bytes': 3624206478,
|
||||
'rx_chainmask': 3,
|
||||
'rx_throughput': 251,
|
||||
'service': dict({
|
||||
'link': 265996,
|
||||
'time': 267195,
|
||||
}),
|
||||
'signal': -58,
|
||||
'sys_id': '0xe7fa',
|
||||
'temperature': 0,
|
||||
'time': '2025-06-23 23:13:54',
|
||||
'totalram': 63447040,
|
||||
'tx_bytes': 212308148210,
|
||||
'tx_power': -4,
|
||||
'tx_ratedata': list([
|
||||
14,
|
||||
4,
|
||||
372,
|
||||
2223,
|
||||
4708,
|
||||
4037,
|
||||
8142,
|
||||
485763,
|
||||
29420892,
|
||||
24748154,
|
||||
]),
|
||||
'tx_throughput': 16023,
|
||||
'unms': dict({
|
||||
'status': 0,
|
||||
'timestamp': None,
|
||||
}),
|
||||
'uptime': 265320,
|
||||
'version': 'WA.ar934x.v8.7.17.48152.250620.2132',
|
||||
}),
|
||||
'rssi': 37,
|
||||
'rx_idx': 8,
|
||||
'rx_nss': 2,
|
||||
'signal': -59,
|
||||
'stats': dict({
|
||||
'rx_bytes': 206938324814,
|
||||
'rx_packets': 149767200,
|
||||
'rx_pps': 846,
|
||||
'tx_bytes': 5265602739,
|
||||
'tx_packets': 52980390,
|
||||
'tx_pps': 0,
|
||||
}),
|
||||
'tx_idx': 9,
|
||||
'tx_latency': 0,
|
||||
'tx_lretries': 0,
|
||||
'tx_nss': 2,
|
||||
'tx_packets': 0,
|
||||
'tx_ratedata': list([
|
||||
175,
|
||||
4,
|
||||
47,
|
||||
200,
|
||||
673,
|
||||
158,
|
||||
163,
|
||||
138,
|
||||
68895,
|
||||
19577430,
|
||||
]),
|
||||
'tx_sretries': 0,
|
||||
'ul_avg_linkscore': 88,
|
||||
'ul_capacity_expect': 624000,
|
||||
'ul_linkscore': 86,
|
||||
'ul_rate_expect': 8,
|
||||
'ul_signal_expect': -55,
|
||||
'uptime': 170281,
|
||||
}),
|
||||
]),
|
||||
'sta_disconnected': list([
|
||||
]),
|
||||
'throughput': dict({
|
||||
'rx': 9907,
|
||||
'tx': 222,
|
||||
}),
|
||||
'tx_chainmask': 3,
|
||||
'tx_idx': 9,
|
||||
'tx_nss': 2,
|
||||
'txpower': -3,
|
||||
}),
|
||||
}),
|
||||
'entry_data': dict({
|
||||
'host': '**REDACTED**',
|
||||
'password': '**REDACTED**',
|
||||
'username': 'ubnt',
|
||||
}),
|
||||
})
|
||||
# ---
|
32
tests/components/airos/test_diagnostics.py
Normal file
32
tests/components/airos/test_diagnostics.py
Normal file
@ -0,0 +1,32 @@
|
||||
"""Diagnostic tests for airOS."""
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.airos.coordinator import AirOSData
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
|
||||
async def test_diagnostics(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
mock_airos_client: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
ap_fixture: AirOSData,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test diagnostics."""
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert (
|
||||
await get_diagnostics_for_config_entry(hass, hass_client, mock_config_entry)
|
||||
== snapshot
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user