1
0
mirror of https://github.com/home-assistant/core.git synced 2026-02-15 07:36:16 +00:00

Prefer explicit DeviceClass over hint in entity_id in homekit (#152507)

Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
This commit is contained in:
Björn Ebbinghaus
2026-01-14 00:00:58 +01:00
committed by GitHub
parent 1bcbebb00c
commit 3ebc08c5ec
2 changed files with 91 additions and 13 deletions

View File

@@ -220,31 +220,33 @@ def get_accessory( # noqa: C901
a_type = "TemperatureSensor"
elif device_class == SensorDeviceClass.HUMIDITY and unit == PERCENTAGE:
a_type = "HumiditySensor"
elif (
device_class == SensorDeviceClass.PM10
or SensorDeviceClass.PM10 in state.entity_id
):
elif device_class == SensorDeviceClass.PM10:
a_type = "PM10Sensor"
elif (
device_class == SensorDeviceClass.PM25
or SensorDeviceClass.PM25 in state.entity_id
):
elif device_class == SensorDeviceClass.PM25:
a_type = "PM25Sensor"
elif device_class == SensorDeviceClass.NITROGEN_DIOXIDE:
a_type = "NitrogenDioxideSensor"
elif device_class == SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS:
a_type = "VolatileOrganicCompoundsSensor"
elif (
device_class == SensorDeviceClass.GAS
or SensorDeviceClass.GAS in state.entity_id
):
elif device_class == SensorDeviceClass.GAS:
a_type = "AirQualitySensor"
elif device_class == SensorDeviceClass.CO:
a_type = "CarbonMonoxideSensor"
elif device_class == SensorDeviceClass.CO2 or "co2" in state.entity_id:
elif device_class == SensorDeviceClass.CO2:
a_type = "CarbonDioxideSensor"
elif device_class == SensorDeviceClass.ILLUMINANCE or unit == LIGHT_LUX:
a_type = "LightSensor"
# Fallbacks based on entity_id
elif SensorDeviceClass.PM10 in state.entity_id:
a_type = "PM10Sensor"
elif SensorDeviceClass.PM25 in state.entity_id:
a_type = "PM25Sensor"
elif SensorDeviceClass.GAS in state.entity_id:
a_type = "AirQualitySensor"
elif "co2" in state.entity_id:
a_type = "CarbonDioxideSensor"
else:
_LOGGER.debug(
"%s: Unsupported sensor type (device_class=%s) (unit=%s)",

View File

@@ -20,6 +20,13 @@ from homeassistant.components.homekit.const import (
TYPE_SWITCH,
TYPE_VALVE,
)
from homeassistant.components.homekit.type_sensors import (
AirQualitySensor,
CarbonDioxideSensor,
PM10Sensor,
PM25Sensor,
TemperatureSensor,
)
from homeassistant.components.media_player import (
MediaPlayerDeviceClass,
MediaPlayerEntityFeature,
@@ -42,6 +49,20 @@ from homeassistant.const import (
from homeassistant.core import State
def get_identified_type(entity_id, attrs, config=None):
"""Helper to return the accessory type name selected by get_accessory."""
def passthrough(type: type):
return lambda *args, **kwargs: type
# Patch TYPES so that get_accessory returns a type instead of an instance.
with patch.dict(
TYPES, {type_name: passthrough(v) for type_name, v in TYPES.items()}
):
entity_state = State(entity_id, "irrelevant", attrs)
return get_accessory(None, None, entity_state, 2, config or {})
def test_not_supported(caplog: pytest.LogCaptureFixture) -> None:
"""Test if none is returned if entity isn't supported."""
# not supported entity
@@ -425,3 +446,58 @@ def test_type_camera(type_name, entity_id, state, attrs) -> None:
entity_state = State(entity_id, state, attrs)
get_accessory(None, None, entity_state, 2, {})
assert mock_type.called
@pytest.mark.parametrize(
("expected_type", "entity_id", "attrs"),
[
(
PM10Sensor,
"sensor.air_quality_pm25",
{ATTR_DEVICE_CLASS: SensorDeviceClass.PM10},
),
(
PM25Sensor,
"sensor.air_quality_pm10",
{ATTR_DEVICE_CLASS: SensorDeviceClass.PM25},
),
(
AirQualitySensor,
"sensor.co2_sensor",
{ATTR_DEVICE_CLASS: SensorDeviceClass.GAS},
),
(
CarbonDioxideSensor,
"sensor.air_quality_gas",
{ATTR_DEVICE_CLASS: SensorDeviceClass.CO2},
),
(
TemperatureSensor,
"sensor.random_sensor",
{ATTR_DEVICE_CLASS: SensorDeviceClass.TEMPERATURE},
),
],
)
def test_explicit_device_class_takes_precedence(
expected_type, entity_id, attrs
) -> None:
"""Test that explicit device_class takes precedence over entity_id hints."""
identified_type = get_identified_type(entity_id, attrs=attrs)
assert identified_type == expected_type
@pytest.mark.parametrize(
("expected_type", "entity_id", "attrs"),
[
(PM10Sensor, "sensor.air_quality_pm10", {}),
(PM25Sensor, "sensor.air_quality_pm25", {}),
(AirQualitySensor, "sensor.air_quality_gas", {}),
(CarbonDioxideSensor, "sensor.airmeter_co2", {}),
],
)
def test_entity_id_fallback_when_no_device_class(
expected_type, entity_id, attrs
) -> None:
"""Test that entity_id is used as fallback when device_class is not set."""
identified_type = get_identified_type(entity_id, attrs=attrs)
assert identified_type == expected_type