Skip to content
24 changes: 19 additions & 5 deletions homeassistant/components/battery/condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,33 @@

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,
),
}

Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/battery/conditions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
entity:
- domain: binary_sensor
device_class: battery
primary_entities_only: false
fields:
behavior: &condition_behavior
required: true
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -60,6 +63,7 @@ is_level:
entity:
- domain: sensor
device_class: battery
primary_entities_only: false
fields:
behavior: *condition_behavior
threshold:
Expand Down
15 changes: 14 additions & 1 deletion homeassistant/helpers/condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from typing import (
TYPE_CHECKING,
Any,
ClassVar,
Final,
Literal,
Never,
Expand Down Expand Up @@ -448,6 +449,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
Expand Down Expand Up @@ -554,6 +558,7 @@ def _on_entities_update(added: set[str], removed: set[str]) -> None:
_state_change_listener,
self.entity_filter,
_on_entities_update,
primary_entities_only=self._primary_entities_only,
)
self._on_unload.append(unsub)

Expand Down Expand Up @@ -615,7 +620,10 @@ def _check_all_match_state(self, states: list[State]) -> bool:
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,
Comment on lines 622 to +626
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass the same primary_entities_only flag to the target state-change tracker so duration-based conditions track the same expanded entity set that _async_check evaluates.

Copilot uses AI. Check for mistakes.
)
referenced_entity_ids = targeted_entities.referenced.union(
targeted_entities.indirectly_referenced
Expand Down Expand Up @@ -663,6 +671,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).

Expand All @@ -686,6 +695,7 @@ class CustomCondition(EntityStateConditionBase):
else ENTITY_STATE_CONDITION_SCHEMA_ANY_ALL
)
_states = states_set
_primary_entities_only = primary_entities_only

return CustomCondition

Expand Down Expand Up @@ -793,6 +803,8 @@ def is_valid_state(self, entity_state: State) -> bool:
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)
Expand All @@ -802,6 +814,7 @@ class CustomCondition(EntityNumericalConditionBase):

_domain_specs = specs
_valid_unit = valid_unit
_primary_entities_only = primary_entities_only

return CustomCondition

Expand Down
9 changes: 7 additions & 2 deletions tests/components/battery/test_condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ATTR_UNIT_OF_MEASUREMENT,
STATE_OFF,
STATE_ON,
EntityCategory,
)
from homeassistant.core import HomeAssistant

Expand All @@ -32,13 +33,17 @@
@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(
Expand Down
Loading
Loading