Adjust sensor group behavior (#152167)

This commit is contained in:
Erik Montnemery
2026-01-14 08:23:34 +01:00
committed by GitHub
parent d43102de1b
commit 56f02a41ca
2 changed files with 33 additions and 23 deletions
+7 -3
View File
@@ -374,7 +374,7 @@ class SensorGroup(GroupEntity, SensorEntity):
def async_update_group_state(self) -> None:
"""Query all members and determine the sensor group state."""
self.calculate_state_attributes(self._get_valid_entities())
states: list[str] = []
states: list[str | None] = []
valid_units = self._valid_units
valid_states: list[bool] = []
sensor_values: list[tuple[str, float, State]] = []
@@ -435,9 +435,12 @@ class SensorGroup(GroupEntity, SensorEntity):
state.attributes.get("unit_of_measurement"),
self.entity_id,
)
else:
states.append(None)
valid_states.append(False)
# Set group as unavailable if all members do not have numeric values
self._attr_available = any(numeric_state for numeric_state in valid_states)
# Set group as unavailable if all members are unavailable or missing
self._attr_available = not all(s in (STATE_UNAVAILABLE, None) for s in states)
valid_state = self.mode(
state not in (STATE_UNKNOWN, STATE_UNAVAILABLE) for state in states
@@ -446,6 +449,7 @@ class SensorGroup(GroupEntity, SensorEntity):
if not valid_state or not valid_state_numeric:
self._attr_native_value = None
self._extra_state_attribute = {}
return
# Calculate values
+26 -20
View File
@@ -206,7 +206,7 @@ async def test_not_enough_sensor_value(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
state = hass.states.get("sensor.test_max")
assert state.state == STATE_UNAVAILABLE
assert state.state == STATE_UNKNOWN
assert state.attributes.get("min_entity_id") is None
assert state.attributes.get("max_entity_id") is None
@@ -228,7 +228,7 @@ async def test_not_enough_sensor_value(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
state = hass.states.get("sensor.test_max")
assert state.state == STATE_UNAVAILABLE
assert state.state == STATE_UNKNOWN
assert state.attributes.get("min_entity_id") is None
assert state.attributes.get("max_entity_id") is None
@@ -281,14 +281,14 @@ async def test_reload(hass: HomeAssistant) -> None:
(STATES_ONE_MISSING, "17.0"),
(STATES_ONE_UNKNOWN, "17.0"),
(STATES_ONE_UNAVAILABLE, "17.0"),
(STATES_ALL_ERROR, STATE_UNAVAILABLE),
(STATES_ALL_ERROR, STATE_UNKNOWN),
(STATES_ALL_MISSING, STATE_UNAVAILABLE),
(STATES_ALL_UNKNOWN, STATE_UNAVAILABLE),
(STATES_ALL_UNKNOWN, STATE_UNKNOWN),
(STATES_ALL_UNAVAILABLE, STATE_UNAVAILABLE),
(STATES_MIX_MISSING_UNAVAILABLE, STATE_UNAVAILABLE),
(STATES_MIX_MISSING_UNKNOWN, STATE_UNAVAILABLE),
(STATES_MIX_UNAVAILABLE_UNKNOWN, STATE_UNAVAILABLE),
(STATES_MIX_MISSING_UNAVAILABLE_UNKNOWN, STATE_UNAVAILABLE),
(STATES_MIX_MISSING_UNKNOWN, STATE_UNKNOWN),
(STATES_MIX_UNAVAILABLE_UNKNOWN, STATE_UNKNOWN),
(STATES_MIX_MISSING_UNAVAILABLE_UNKNOWN, STATE_UNKNOWN),
],
)
async def test_sensor_incorrect_state_with_ignore_non_numeric(
@@ -339,17 +339,17 @@ async def test_sensor_incorrect_state_with_ignore_non_numeric(
("states_list", "expected_group_state", "error_count"),
[
(STATES_ONE_ERROR, STATE_UNKNOWN, 1),
(STATES_ONE_MISSING, "17.0", 0),
(STATES_ONE_MISSING, STATE_UNKNOWN, 0),
(STATES_ONE_UNKNOWN, STATE_UNKNOWN, 1),
(STATES_ONE_UNAVAILABLE, STATE_UNKNOWN, 1),
(STATES_ALL_ERROR, STATE_UNAVAILABLE, 3),
(STATES_ALL_ERROR, STATE_UNKNOWN, 3),
(STATES_ALL_MISSING, STATE_UNAVAILABLE, 0),
(STATES_ALL_UNKNOWN, STATE_UNAVAILABLE, 3),
(STATES_ALL_UNKNOWN, STATE_UNKNOWN, 3),
(STATES_ALL_UNAVAILABLE, STATE_UNAVAILABLE, 3),
(STATES_MIX_MISSING_UNKNOWN, STATE_UNAVAILABLE, 2),
(STATES_MIX_UNAVAILABLE_UNKNOWN, STATE_UNAVAILABLE, 3),
(STATES_MIX_MISSING_UNAVAILABLE, STATE_UNAVAILABLE, 2),
(STATES_MIX_MISSING_UNAVAILABLE_UNKNOWN, STATE_UNAVAILABLE, 2),
(STATES_MIX_MISSING_UNKNOWN, STATE_UNKNOWN, 2),
(STATES_MIX_UNAVAILABLE_UNKNOWN, STATE_UNKNOWN, 3),
(STATES_MIX_MISSING_UNAVAILABLE_UNKNOWN, STATE_UNKNOWN, 2),
],
)
async def test_sensor_incorrect_state_with_not_ignore_non_numeric(
@@ -402,17 +402,17 @@ async def test_sensor_incorrect_state_with_not_ignore_non_numeric(
("states_list", "expected_group_state"),
[
(STATES_ONE_ERROR, STATE_UNKNOWN),
(STATES_ONE_MISSING, "32.3"),
(STATES_ONE_MISSING, STATE_UNKNOWN),
(STATES_ONE_UNKNOWN, STATE_UNKNOWN),
(STATES_ONE_UNAVAILABLE, STATE_UNKNOWN),
(STATES_ALL_ERROR, STATE_UNAVAILABLE),
(STATES_ALL_ERROR, STATE_UNKNOWN),
(STATES_ALL_MISSING, STATE_UNAVAILABLE),
(STATES_ALL_UNKNOWN, STATE_UNAVAILABLE),
(STATES_ALL_UNKNOWN, STATE_UNKNOWN),
(STATES_ALL_UNAVAILABLE, STATE_UNAVAILABLE),
(STATES_MIX_MISSING_UNAVAILABLE, STATE_UNAVAILABLE),
(STATES_MIX_MISSING_UNKNOWN, STATE_UNAVAILABLE),
(STATES_MIX_UNAVAILABLE_UNKNOWN, STATE_UNAVAILABLE),
(STATES_MIX_MISSING_UNAVAILABLE_UNKNOWN, STATE_UNAVAILABLE),
(STATES_MIX_MISSING_UNKNOWN, STATE_UNKNOWN),
(STATES_MIX_UNAVAILABLE_UNKNOWN, STATE_UNKNOWN),
(STATES_MIX_MISSING_UNAVAILABLE_UNKNOWN, STATE_UNKNOWN),
],
)
async def test_sensor_require_all_states(
@@ -740,7 +740,7 @@ async def test_sensor_calculated_result_fails_on_uom(hass: HomeAssistant) -> Non
await hass.async_block_till_done()
state = hass.states.get("sensor.test_sum")
assert state.state == STATE_UNAVAILABLE
assert state.state == STATE_UNKNOWN
assert state.attributes.get("device_class") == "energy"
assert state.attributes.get("state_class") == "total"
assert state.attributes.get("unit_of_measurement") is None
@@ -847,6 +847,12 @@ async def test_last_sensor(hass: HomeAssistant) -> None:
entity_ids = config["sensor"]["entities"]
for entity_id in entity_ids[1:]:
hass.states.async_set(entity_id, "0.0")
await hass.async_block_till_done()
state = hass.states.get("sensor.test_last")
assert state.state == STATE_UNKNOWN
for entity_id, value in dict(zip(entity_ids, VALUES, strict=False)).items():
hass.states.async_set(entity_id, str(value))
await hass.async_block_till_done()