Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UniFi WLAN Password sensor #114419

Merged
merged 13 commits into from
Mar 30, 2024
Merged
13 changes: 13 additions & 0 deletions homeassistant/components/unifi/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,19 @@ class UnifiSensorEntityDescription(
value_fn=async_device_state_value_fn,
options=list(DEVICE_STATES.values()),
),
UnifiSensorEntityDescription[Wlans, Wlan](
brunohenriquy marked this conversation as resolved.
Show resolved Hide resolved
key="WLAN password",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
api_handler_fn=lambda api: api.wlans,
available_fn=async_wlan_available_fn,
device_info_fn=async_wlan_device_info_fn,
name_fn=lambda wlan: "Password",
object_fn=lambda api, obj_id: api.wlans[obj_id],
supported_fn=lambda hub, obj_id: hub.api.wlans[obj_id].x_passphrase is not None,
unique_id_fn=lambda hub, obj_id: f"password-{obj_id}",
value_fn=lambda hub, obj: obj.x_passphrase,
),
)


Expand Down
71 changes: 71 additions & 0 deletions tests/components/unifi/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -998,3 +998,74 @@ async def test_device_state(
device["state"] = i
mock_unifi_websocket(message=MessageKey.DEVICE, data=device)
assert hass.states.get("sensor.device_state").state == DEVICE_STATES[i]


async def test_wlan_password(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
aioclient_mock: AiohttpClientMocker,
mock_unifi_websocket,
websocket_mock,
) -> None:
"""Test the WLAN password sensor behavior."""
await setup_unifi_integration(hass, aioclient_mock, wlans_response=[WLAN])

sensor_password = "sensor.ssid_1_password"
password = "password"
new_password = "new_password"

ent_reg_entry = entity_registry.async_get(sensor_password)
assert ent_reg_entry.unique_id == "password-012345678910111213141516"
assert ent_reg_entry.disabled_by == RegistryEntryDisabler.INTEGRATION
assert ent_reg_entry.entity_category is EntityCategory.DIAGNOSTIC

# Enable entity
entity_registry.async_update_entity(entity_id=sensor_password, disabled_by=None)
await hass.async_block_till_done()

async_fire_time_changed(
hass,
dt_util.utcnow() + timedelta(seconds=RELOAD_AFTER_UPDATE_DELAY + 1),
)
await hass.async_block_till_done()

# Validate state object
wlan_password_sensor_1 = hass.states.get(sensor_password)
assert wlan_password_sensor_1.state == password

# Update state object - same password - no change to state
mock_unifi_websocket(message=MessageKey.WLAN_CONF_UPDATED, data=WLAN)
await hass.async_block_till_done()
wlan_password_sensor_2 = hass.states.get(sensor_password)
assert wlan_password_sensor_1.state == wlan_password_sensor_2.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)
await hass.async_block_till_done()
wlan_password_sensor_3 = hass.states.get(sensor_password)
assert wlan_password_sensor_1.state != wlan_password_sensor_3.state

# Availability signaling

# Controller disconnects
await websocket_mock.disconnect()
assert hass.states.get(sensor_password).state == STATE_UNAVAILABLE

# Controller reconnects
await websocket_mock.reconnect()
assert hass.states.get(sensor_password).state == new_password

# 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_password).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_password).state == password