1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-02 00:20:30 +01:00

Fix KeyError for device temperature sensor in Unifi integration (#166410)

This commit is contained in:
Maciej Bieniek
2026-03-25 08:00:14 +01:00
committed by GitHub
parent a3add179a0
commit a2b91a9ac0
2 changed files with 91 additions and 8 deletions

View File

@@ -300,13 +300,22 @@ def make_wan_latency_sensors() -> tuple[UnifiSensorEntityDescription, ...]:
@callback
def async_device_temperatures_value_fn(
temperature_name: str, hub: UnifiHub, device: Device
) -> float:
) -> float | None:
"""Retrieve the temperature of the device."""
return_value: float = 0
if device.temperatures:
temperature = _device_temperature(temperature_name, device.temperatures)
return_value = temperature if temperature is not None else 0
return return_value
return _device_temperature(temperature_name, device.temperatures)
return None
@callback
def async_device_temperatures_available_fn(
temperature_name: str, hub: UnifiHub, obj_id: str
) -> bool:
"""Determine if a device temperature has a value."""
device = hub.api.devices[obj_id]
if not async_device_available_fn(hub, obj_id):
return False
return _device_temperature(temperature_name, device.temperatures or []) is not None
@callback
@@ -315,7 +324,11 @@ def async_device_temperatures_supported_fn(
) -> bool:
"""Determine if an device have a temperatures."""
if (device := hub.api.devices[obj_id]) and device.temperatures:
return _device_temperature(temperature_name, device.temperatures) is not None
return any(
temperature_name in temperature["name"]
for temperature in device.temperatures
)
return False
@@ -326,7 +339,8 @@ def _device_temperature(
"""Return the temperature of the device."""
for temperature in temperatures:
if temperature_name in temperature["name"]:
return temperature["value"]
if (value := temperature.get("value")) is not None:
return value
return None
@@ -344,7 +358,7 @@ def make_device_temperatur_sensors() -> tuple[UnifiSensorEntityDescription, ...]
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
entity_registry_enabled_default=False,
api_handler_fn=lambda api: api.devices,
available_fn=async_device_available_fn,
available_fn=partial(async_device_temperatures_available_fn, name),
device_info_fn=async_device_device_info_fn,
name_fn=lambda device: f"{device.name} {name} Temperature",
object_fn=lambda api, obj_id: api.devices[obj_id],

View File

@@ -1774,6 +1774,75 @@ async def test_device_temperatures(
assert hass.states.get(entity_id).state == updated_state
@pytest.mark.parametrize(
"device_payload",
[
[
{
"board_rev": 3,
"device_id": "mock-id",
"has_fan": True,
"fan_level": 0,
"ip": "10.0.1.1",
"last_seen": 1562600145,
"mac": "00:00:00:00:01:01",
"model": "US16P150",
"name": "Device",
"next_interval": 20,
"overheating": True,
"state": 1,
"type": "usw",
"upgradable": True,
"uptime": 60,
"version": "4.0.42.10433",
"temperatures": [
{"name": "CPU", "type": "cpu", "value": 66.0},
],
}
]
],
)
@pytest.mark.usefixtures("config_entry_setup")
async def test_device_temperature_with_missing_value(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
mock_websocket_message,
device_payload: list[dict[str, Any]],
) -> None:
"""Verify that device temperatures sensors are working as expected."""
entity_id = "sensor.device_device_cpu_temperature"
temperature_entity = entity_registry.async_get(entity_id)
assert temperature_entity.disabled_by == RegistryEntryDisabler.INTEGRATION
# Enable entity
entity_registry.async_update_entity(entity_id=entity_id, 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()
# Verify sensor state
assert hass.states.get(entity_id).state == "66.0"
# Remove temperature value from payload
device = deepcopy(device_payload[0])
device["temperatures"][0].pop("value")
mock_websocket_message(message=MessageKey.DEVICE, data=device)
assert hass.states.get(entity_id).state == STATE_UNAVAILABLE
# Send original payload again to verify sensor recovers
mock_websocket_message(message=MessageKey.DEVICE, data=device_payload[0])
assert hass.states.get(entity_id).state == "66.0"
@pytest.mark.parametrize(
"device_payload",
[