diff --git a/homeassistant/components/unifi/sensor.py b/homeassistant/components/unifi/sensor.py index ebbc75d7432e..aa58061f5e34 100644 --- a/homeassistant/components/unifi/sensor.py +++ b/homeassistant/components/unifi/sensor.py @@ -67,6 +67,9 @@ from .hub import UnifiHub PARALLEL_UPDATES = 0 +# UniFi names the first WAN "WAN", not "WAN1". +type WanName = Literal["WAN", "WAN2", "WAN3"] + @callback def async_bandwidth_sensor_allowed_fn(hub: UnifiHub, obj_id: str) -> bool: @@ -256,7 +259,7 @@ def async_device_state_value_fn(hub: UnifiHub, device: Device) -> str | None: @callback def async_device_wan_latency_supported_fn( - wan: Literal["WAN", "WAN2"], + wan: WanName, monitor_target: str, hub: UnifiHub, obj_id: str, @@ -269,7 +272,7 @@ def async_device_wan_latency_supported_fn( @callback def async_device_wan_latency_value_fn( - wan: Literal["WAN", "WAN2"], + wan: WanName, monitor_target: str, hub: UnifiHub, device: Device, @@ -286,7 +289,7 @@ def async_device_wan_latency_value_fn( @callback def _device_wan_latency_monitor( - wan: Literal["WAN", "WAN2"], monitor_target: str, device: Device + wan: WanName, monitor_target: str, device: Device ) -> TypedDeviceUptimeStatsWanMonitor | None: """Return the target of the WAN latency monitor.""" if device.uptime_stats and (uptime_stats_wan := device.uptime_stats.get(wan)): @@ -300,7 +303,7 @@ def make_wan_latency_sensors() -> tuple[UnifiSensorEntityDescription, ...]: """Create WAN latency sensors from WAN monitor data.""" def make_wan_latency_entity_description( - wan: Literal["WAN", "WAN2"], name: str, monitor_target: str + wan: WanName, name: str, monitor_target: str ) -> UnifiSensorEntityDescription: name_wan = f"{name} {wan}" return UnifiSensorEntityDescription[Devices, Device]( @@ -323,7 +326,7 @@ def make_wan_latency_sensors() -> tuple[UnifiSensorEntityDescription, ...]: value_fn=partial(async_device_wan_latency_value_fn, wan, monitor_target), ) - wans: tuple[Literal["WAN"], Literal["WAN2"]] = ("WAN", "WAN2") + wans: tuple[WanName, ...] = ("WAN", "WAN2", "WAN3") return tuple( make_wan_latency_entity_description(wan, name, target) for wan in wans diff --git a/tests/components/unifi/snapshots/test_sensor.ambr b/tests/components/unifi/snapshots/test_sensor.ambr index 441bdf86b1c4..05690d6b13e9 100644 --- a/tests/components/unifi/snapshots/test_sensor.ambr +++ b/tests/components/unifi/snapshots/test_sensor.ambr @@ -818,6 +818,64 @@ 'state': 'unknown', }) # --- +# name: test_entity_and_device_data[wlan_payload0-device_payload0-client_payload0-config_entry_options0][sensor.mock_name_cloudflare_wan3_latency-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + : , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.mock_name_cloudflare_wan3_latency', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Cloudflare WAN3 latency', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Cloudflare WAN3 latency', + 'platform': 'unifi', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'wan_latency', + 'unique_id': 'cloudflare_wan3_latency-10:00:00:00:01:01', + 'unit_of_measurement': , + }) +# --- +# name: test_entity_and_device_data[wlan_payload0-device_payload0-client_payload0-config_entry_options0][sensor.mock_name_cloudflare_wan3_latency-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'duration', + : 'mock-name Cloudflare WAN3 latency', + : , + : , + }), + 'context': , + 'entity_id': 'sensor.mock_name_cloudflare_wan3_latency', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '16', + }) +# --- # name: test_entity_and_device_data[wlan_payload0-device_payload0-client_payload0-config_entry_options0][sensor.mock_name_cloudflare_wan_latency-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ @@ -934,6 +992,64 @@ 'state': 'unknown', }) # --- +# name: test_entity_and_device_data[wlan_payload0-device_payload0-client_payload0-config_entry_options0][sensor.mock_name_google_wan3_latency-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + : , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.mock_name_google_wan3_latency', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Google WAN3 latency', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Google WAN3 latency', + 'platform': 'unifi', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'wan_latency', + 'unique_id': 'google_wan3_latency-10:00:00:00:01:01', + 'unit_of_measurement': , + }) +# --- +# name: test_entity_and_device_data[wlan_payload0-device_payload0-client_payload0-config_entry_options0][sensor.mock_name_google_wan3_latency-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'duration', + : 'mock-name Google WAN3 latency', + : , + : , + }), + 'context': , + 'entity_id': 'sensor.mock_name_google_wan3_latency', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '32', + }) +# --- # name: test_entity_and_device_data[wlan_payload0-device_payload0-client_payload0-config_entry_options0][sensor.mock_name_google_wan_latency-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ @@ -1050,6 +1166,64 @@ 'state': 'unknown', }) # --- +# name: test_entity_and_device_data[wlan_payload0-device_payload0-client_payload0-config_entry_options0][sensor.mock_name_microsoft_wan3_latency-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + : , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.mock_name_microsoft_wan3_latency', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Microsoft WAN3 latency', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Microsoft WAN3 latency', + 'platform': 'unifi', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'wan_latency', + 'unique_id': 'microsoft_wan3_latency-10:00:00:00:01:01', + 'unit_of_measurement': , + }) +# --- +# name: test_entity_and_device_data[wlan_payload0-device_payload0-client_payload0-config_entry_options0][sensor.mock_name_microsoft_wan3_latency-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'duration', + : 'mock-name Microsoft WAN3 latency', + : , + : , + }), + 'context': , + 'entity_id': 'sensor.mock_name_microsoft_wan3_latency', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '41', + }) +# --- # name: test_entity_and_device_data[wlan_payload0-device_payload0-client_payload0-config_entry_options0][sensor.mock_name_microsoft_wan_latency-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ diff --git a/tests/components/unifi/test_sensor.py b/tests/components/unifi/test_sensor.py index 158bce8f455e..933ba6bfdd3c 100644 --- a/tests/components/unifi/test_sensor.py +++ b/tests/components/unifi/test_sensor.py @@ -528,6 +528,28 @@ UPS_DEVICE_2["vbms_table"]["battpool"]["device_bypass_voltage"] = 121.7 {"availability": 0.0, "target": "1.1.1.1", "type": "icmp"}, ], }, + "WAN3": { + "monitors": [ + { + "availability": 100.0, + "latency_average": 41, + "target": "www.microsoft.com", + "type": "icmp", + }, + { + "availability": 100.0, + "latency_average": 32, + "target": "google.com", + "type": "icmp", + }, + { + "availability": 100.0, + "latency_average": 16, + "target": "1.1.1.1", + "type": "icmp", + }, + ], + }, }, "state": 1, "type": "usw", @@ -1819,6 +1841,28 @@ async def test_device_uptime( {"availability": 0.0, "target": "1.1.1.1", "type": "icmp"}, ], }, + "WAN3": { + "monitors": [ + { + "availability": 100.0, + "latency_average": 41, + "target": "www.microsoft.com", + "type": "icmp", + }, + { + "availability": 100.0, + "latency_average": 32, + "target": "google.com", + "type": "icmp", + }, + { + "availability": 100.0, + "latency_average": 16, + "target": "1.1.1.1", + "type": "icmp", + }, + ], + }, }, "state": 1, "type": "usw", @@ -1828,21 +1872,92 @@ async def test_device_uptime( ], ) @pytest.mark.parametrize( - ("monitor_id", "state", "index_to_update", "monitor_update", "updated_state"), + ( + "wan", + "monitor_id", + "state", + "index_to_update", + "monitor_update", + "updated_state", + ), [ pytest.param( - "microsoft_wan", "56", 0, {"latency_average": 20}, "20", id="microsoft" - ), - pytest.param("google_wan", "53", 1, {"latency_average": 90}, "90", id="google"), - pytest.param( - "cloudflare_wan", "30", 2, {"latency_average": 80}, "80", id="cloudflare" + "WAN", + "microsoft_wan", + "56", + 0, + {"latency_average": 20}, + "20", + id="microsoft", ), pytest.param( - "microsoft_wan", "56", 0, {}, STATE_UNKNOWN, id="microsoft_no_response" + "WAN", "google_wan", "53", 1, {"latency_average": 90}, "90", id="google" ), - pytest.param("google_wan", "53", 1, {}, STATE_UNKNOWN, id="google_no_response"), pytest.param( - "cloudflare_wan", "30", 2, {}, STATE_UNKNOWN, id="cloudflare_no_response" + "WAN", + "cloudflare_wan", + "30", + 2, + {"latency_average": 80}, + "80", + id="cloudflare", + ), + pytest.param( + "WAN", + "microsoft_wan", + "56", + 0, + {}, + STATE_UNKNOWN, + id="microsoft_no_response", + ), + pytest.param( + "WAN", "google_wan", "53", 1, {}, STATE_UNKNOWN, id="google_no_response" + ), + pytest.param( + "WAN", + "cloudflare_wan", + "30", + 2, + {}, + STATE_UNKNOWN, + id="cloudflare_no_response", + ), + pytest.param( + "WAN3", + "microsoft_wan3", + "41", + 0, + {"latency_average": 25}, + "25", + id="microsoft_wan3", + ), + pytest.param( + "WAN3", + "google_wan3", + "32", + 1, + {"latency_average": 60}, + "60", + id="google_wan3", + ), + pytest.param( + "WAN3", + "cloudflare_wan3", + "16", + 2, + {"latency_average": 70}, + "70", + id="cloudflare_wan3", + ), + pytest.param( + "WAN3", + "cloudflare_wan3", + "16", + 2, + {}, + STATE_UNKNOWN, + id="cloudflare_wan3_no_response", ), ], ) @@ -1852,6 +1967,7 @@ async def test_wan_monitor_latency( entity_registry: er.EntityRegistry, mock_websocket_message: WebsocketMessageMock, device_payload: list[dict[str, Any]], + wan: str, monitor_id: str, state: str, index_to_update: int, @@ -1886,7 +2002,7 @@ async def test_wan_monitor_latency( # Update state device = deepcopy(device_payload[0]) - monitor = device["uptime_stats"]["WAN"]["monitors"][index_to_update] + monitor = device["uptime_stats"][wan]["monitors"][index_to_update] monitor.pop("latency_average") monitor.update(monitor_update) mock_websocket_message(message=MessageKey.DEVICE, data=device)