diff --git a/homeassistant/components/unifi/entity.py b/homeassistant/components/unifi/entity.py index db7b414b3b0..7d9373d1188 100644 --- a/homeassistant/components/unifi/entity.py +++ b/homeassistant/components/unifi/entity.py @@ -44,6 +44,13 @@ def async_device_available_fn(controller: UniFiController, obj_id: str) -> bool: return controller.available and not device.disabled +@callback +def async_wlan_available_fn(controller: UniFiController, obj_id: str) -> bool: + """Check if WLAN is available.""" + wlan = controller.api.wlans[obj_id] + return controller.available and wlan.enabled + + @callback def async_device_device_info_fn(api: aiounifi.Controller, obj_id: str) -> DeviceInfo: """Create device registry entry for device.""" diff --git a/homeassistant/components/unifi/image.py b/homeassistant/components/unifi/image.py index c3969c21bc4..3ff893838c9 100644 --- a/homeassistant/components/unifi/image.py +++ b/homeassistant/components/unifi/image.py @@ -26,6 +26,7 @@ from .entity import ( HandlerT, UnifiEntity, UnifiEntityDescription, + async_wlan_available_fn, async_wlan_device_info_fn, ) @@ -61,11 +62,11 @@ ENTITY_DESCRIPTIONS: tuple[UnifiImageEntityDescription, ...] = ( entity_registry_enabled_default=False, allowed_fn=lambda controller, obj_id: True, api_handler_fn=lambda api: api.wlans, - available_fn=lambda controller, _: controller.available, + available_fn=async_wlan_available_fn, device_info_fn=async_wlan_device_info_fn, event_is_on=None, event_to_subscribe=None, - name_fn=lambda _: "QR Code", + name_fn=lambda wlan: "QR Code", object_fn=lambda api, obj_id: api.wlans[obj_id], should_poll=False, supported_fn=lambda controller, obj_id: True, diff --git a/homeassistant/components/unifi/sensor.py b/homeassistant/components/unifi/sensor.py index bb9365d486b..23cc8724c2c 100644 --- a/homeassistant/components/unifi/sensor.py +++ b/homeassistant/components/unifi/sensor.py @@ -39,6 +39,7 @@ from .entity import ( async_client_device_info_fn, async_device_available_fn, async_device_device_info_fn, + async_wlan_available_fn, async_wlan_device_info_fn, ) @@ -179,16 +180,16 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = ( key="WLAN clients", entity_category=EntityCategory.DIAGNOSTIC, has_entity_name=True, - allowed_fn=lambda controller, _: True, + allowed_fn=lambda controller, obj_id: True, api_handler_fn=lambda api: api.wlans, - available_fn=lambda controller, obj_id: controller.available, + available_fn=async_wlan_available_fn, device_info_fn=async_wlan_device_info_fn, event_is_on=None, event_to_subscribe=None, - name_fn=lambda client: None, + name_fn=lambda wlan: None, object_fn=lambda api, obj_id: api.wlans[obj_id], should_poll=True, - supported_fn=lambda controller, _: True, + supported_fn=lambda controller, obj_id: True, unique_id_fn=lambda controller, obj_id: f"wlan_clients-{obj_id}", value_fn=async_wlan_client_value_fn, ), diff --git a/tests/components/unifi/test_image.py b/tests/components/unifi/test_image.py index 564fd7598d8..afefee9fd02 100644 --- a/tests/components/unifi/test_image.py +++ b/tests/components/unifi/test_image.py @@ -5,13 +5,12 @@ from datetime import timedelta from http import HTTPStatus from aiounifi.models.message import MessageKey +from aiounifi.websocket import WebsocketState from syrupy.assertion import SnapshotAssertion from homeassistant.components.image import DOMAIN as IMAGE_DOMAIN from homeassistant.config_entries import RELOAD_AFTER_UPDATE_DELAY -from homeassistant.const import ( - EntityCategory, -) +from homeassistant.const import STATE_UNAVAILABLE, EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from homeassistant.helpers.entity_registry import RegistryEntryDisabler @@ -106,7 +105,7 @@ async def test_wlan_qr_code( image_state_2 = hass.states.get("image.ssid_1_qr_code") assert image_state_1.state == image_state_2.state - # Update state object - changeed password - new state + # Update state object - changed password - new state data = deepcopy(WLAN) data["x_passphrase"] = "new password" mock_unifi_websocket(message=MessageKey.WLAN_CONF_UPDATED, data=data) @@ -120,3 +119,28 @@ async def test_wlan_qr_code( assert resp.status == HTTPStatus.OK body = await resp.read() assert body == snapshot + + # Availability signalling + + # Controller disconnects + mock_unifi_websocket(state=WebsocketState.DISCONNECTED) + await hass.async_block_till_done() + assert hass.states.get("image.ssid_1_qr_code").state == STATE_UNAVAILABLE + + # Controller reconnects + mock_unifi_websocket(state=WebsocketState.RUNNING) + await hass.async_block_till_done() + assert hass.states.get("image.ssid_1_qr_code").state != STATE_UNAVAILABLE + + # WLAN gets disabled + wlan_1 = deepcopy(WLAN) + wlan_1["enabled"] = False + mock_unifi_websocket(message=MessageKey.WLAN_CONF_UPDATED, data=wlan_1) + await hass.async_block_till_done() + assert hass.states.get("image.ssid_1_qr_code").state == STATE_UNAVAILABLE + + # WLAN gets re-enabled + wlan_1["enabled"] = True + mock_unifi_websocket(message=MessageKey.WLAN_CONF_UPDATED, data=wlan_1) + await hass.async_block_till_done() + assert hass.states.get("image.ssid_1_qr_code").state != STATE_UNAVAILABLE diff --git a/tests/components/unifi/test_sensor.py b/tests/components/unifi/test_sensor.py index 3d50df8ada9..9670ecb43d0 100644 --- a/tests/components/unifi/test_sensor.py +++ b/tests/components/unifi/test_sensor.py @@ -558,3 +558,16 @@ async def test_wlan_client_sensors( mock_unifi_websocket(state=WebsocketState.RUNNING) await hass.async_block_till_done() assert hass.states.get("sensor.ssid_1").state == "0" + + # WLAN gets disabled + wlan_1 = deepcopy(WLAN) + wlan_1["enabled"] = False + mock_unifi_websocket(message=MessageKey.WLAN_CONF_UPDATED, data=wlan_1) + await hass.async_block_till_done() + assert hass.states.get("sensor.ssid_1").state == STATE_UNAVAILABLE + + # WLAN gets re-enabled + wlan_1["enabled"] = True + mock_unifi_websocket(message=MessageKey.WLAN_CONF_UPDATED, data=wlan_1) + await hass.async_block_till_done() + assert hass.states.get("sensor.ssid_1").state == "0"