diff --git a/homeassistant/components/battery/condition.py b/homeassistant/components/battery/condition.py index 7004d9f00fbf..c89e9bd73216 100644 --- a/homeassistant/components/battery/condition.py +++ b/homeassistant/components/battery/condition.py @@ -30,19 +30,33 @@ BATTERY_PERCENTAGE_DOMAIN_SPECS = { CONDITIONS: dict[str, type[Condition]] = { "is_low": make_entity_state_condition( - BATTERY_DOMAIN_SPECS, STATE_ON, support_duration=True + BATTERY_DOMAIN_SPECS, + STATE_ON, + support_duration=True, + primary_entities_only=False, ), "is_not_low": make_entity_state_condition( - BATTERY_DOMAIN_SPECS, STATE_OFF, support_duration=True + BATTERY_DOMAIN_SPECS, + STATE_OFF, + support_duration=True, + primary_entities_only=False, ), "is_charging": make_entity_state_condition( - BATTERY_CHARGING_DOMAIN_SPECS, STATE_ON, support_duration=True + BATTERY_CHARGING_DOMAIN_SPECS, + STATE_ON, + support_duration=True, + primary_entities_only=False, ), "is_not_charging": make_entity_state_condition( - BATTERY_CHARGING_DOMAIN_SPECS, STATE_OFF, support_duration=True + BATTERY_CHARGING_DOMAIN_SPECS, + STATE_OFF, + support_duration=True, + primary_entities_only=False, ), "is_level": make_entity_numerical_condition( - BATTERY_PERCENTAGE_DOMAIN_SPECS, PERCENTAGE + BATTERY_PERCENTAGE_DOMAIN_SPECS, + PERCENTAGE, + primary_entities_only=False, ), } diff --git a/homeassistant/components/battery/conditions.yaml b/homeassistant/components/battery/conditions.yaml index b03f9516bd94..39ffc09109f2 100644 --- a/homeassistant/components/battery/conditions.yaml +++ b/homeassistant/components/battery/conditions.yaml @@ -3,6 +3,7 @@ entity: - domain: binary_sensor device_class: battery + primary_entities_only: false fields: behavior: &condition_behavior required: true @@ -42,6 +43,7 @@ is_charging: entity: - domain: binary_sensor device_class: battery_charging + primary_entities_only: false fields: behavior: *condition_behavior for: *condition_for @@ -51,6 +53,7 @@ is_not_charging: entity: - domain: binary_sensor device_class: battery_charging + primary_entities_only: false fields: behavior: *condition_behavior for: *condition_for @@ -60,6 +63,7 @@ is_level: entity: - domain: sensor device_class: battery + primary_entities_only: false fields: behavior: *condition_behavior threshold: diff --git a/homeassistant/helpers/condition.py b/homeassistant/helpers/condition.py index 6d53f674188b..41ca3536c79c 100644 --- a/homeassistant/helpers/condition.py +++ b/homeassistant/helpers/condition.py @@ -16,6 +16,7 @@ import sys from typing import ( TYPE_CHECKING, Any, + ClassVar, Final, Literal, Never, @@ -443,6 +444,9 @@ class EntityConditionBase(Condition): _domain_specs: Mapping[str, DomainSpec] _schema: vol.Schema = ENTITY_STATE_CONDITION_SCHEMA_ANY_ALL + # When True, indirect target expansion (via device/area/floor) skips + # entities with an entity_category. + _primary_entities_only: ClassVar[bool] = True @override @classmethod @@ -506,7 +510,10 @@ class EntityConditionBase(Condition): def _async_check(self, **kwargs: Unpack[ConditionCheckParams]) -> bool: """Test state condition.""" targeted_entities = async_extract_referenced_entity_ids( - self._hass, self._target_selection, expand_group=False + self._hass, + self._target_selection, + expand_group=False, + primary_entities_only=self._primary_entities_only, ) referenced_entity_ids = targeted_entities.referenced.union( targeted_entities.indirectly_referenced @@ -545,6 +552,7 @@ def make_entity_state_condition( states: str | bool | set[str | bool], *, support_duration: bool = False, + primary_entities_only: bool = True, ) -> type[EntityStateConditionBase]: """Create a condition for entity state changes to specific state(s). @@ -568,6 +576,7 @@ def make_entity_state_condition( else ENTITY_STATE_CONDITION_SCHEMA_ANY_ALL ) _states = states_set + _primary_entities_only = primary_entities_only return CustomCondition @@ -675,6 +684,8 @@ class EntityNumericalConditionBase(EntityConditionBase): def make_entity_numerical_condition( domain_specs: Mapping[str, DomainSpec] | str, valid_unit: str | None | UndefinedType = UNDEFINED, + *, + primary_entities_only: bool = True, ) -> type[EntityNumericalConditionBase]: """Create a condition for numerical state comparisons.""" specs = _normalize_domain_specs(domain_specs) @@ -684,6 +695,7 @@ def make_entity_numerical_condition( _domain_specs = specs _valid_unit = valid_unit + _primary_entities_only = primary_entities_only return CustomCondition diff --git a/tests/components/battery/test_condition.py b/tests/components/battery/test_condition.py index 8c828c0add8c..5e011431f209 100644 --- a/tests/components/battery/test_condition.py +++ b/tests/components/battery/test_condition.py @@ -9,6 +9,7 @@ from homeassistant.const import ( ATTR_UNIT_OF_MEASUREMENT, STATE_OFF, STATE_ON, + EntityCategory, ) from homeassistant.core import HomeAssistant @@ -31,13 +32,17 @@ _BATTERY_UNIT_ATTRS = {ATTR_UNIT_OF_MEASUREMENT: "%"} @pytest.fixture async def target_binary_sensors(hass: HomeAssistant) -> dict[str, list[str]]: """Create multiple binary sensor entities associated with different targets.""" - return await target_entities(hass, "binary_sensor") + return await target_entities( + hass, "binary_sensor", entity_category=EntityCategory.DIAGNOSTIC + ) @pytest.fixture async def target_sensors(hass: HomeAssistant) -> dict[str, list[str]]: """Create multiple sensor entities associated with different targets.""" - return await target_entities(hass, "sensor") + return await target_entities( + hass, "sensor", entity_category=EntityCategory.DIAGNOSTIC + ) @pytest.mark.parametrize(