From 340df38bd00a6d5ae1dab962015b6c0c548bd624 Mon Sep 17 00:00:00 2001 From: Tucker Kern Date: Wed, 31 Jan 2024 12:02:21 -0700 Subject: [PATCH] Suppress log warnings when a sensor group has non numeric members (#102828) --- homeassistant/components/group/sensor.py | 14 ++++-- tests/components/group/test_sensor.py | 61 +++++++++++++++++++----- 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/group/sensor.py b/homeassistant/components/group/sensor.py index 84827ef89fa..402a8242af7 100644 --- a/homeassistant/components/group/sensor.py +++ b/homeassistant/components/group/sensor.py @@ -299,7 +299,7 @@ class SensorGroup(GroupEntity, SensorEntity): unique_id: str | None, name: str, entity_ids: list[str], - mode: bool, + ignore_non_numeric: bool, sensor_type: str, unit_of_measurement: str | None, state_class: SensorStateClass | None, @@ -318,7 +318,8 @@ class SensorGroup(GroupEntity, SensorEntity): self._attr_name = f"{DEFAULT_NAME} {sensor_type}".capitalize() self._attr_extra_state_attributes = {ATTR_ENTITY_ID: entity_ids} self._attr_unique_id = unique_id - self.mode = all if mode is False else any + self._ignore_non_numeric = ignore_non_numeric + self.mode = all if ignore_non_numeric is False else any self._state_calc: Callable[ [list[tuple[str, float, State]]], tuple[dict[str, str | None], float | None], @@ -358,9 +359,14 @@ class SensorGroup(GroupEntity, SensorEntity): sensor_values.append((entity_id, numeric_state, state)) if entity_id in self._state_incorrect: self._state_incorrect.remove(entity_id) + valid_states.append(True) except ValueError: valid_states.append(False) - if entity_id not in self._state_incorrect: + # Log invalid states unless ignoring non numeric values + if ( + not self._ignore_non_numeric + and entity_id not in self._state_incorrect + ): self._state_incorrect.add(entity_id) _LOGGER.warning( "Unable to use state. Only numerical states are supported," @@ -388,8 +394,6 @@ class SensorGroup(GroupEntity, SensorEntity): state.attributes.get("unit_of_measurement"), self.entity_id, ) - continue - valid_states.append(True) # Set group as unavailable if all members do not have numeric values self._attr_available = any(numeric_state for numeric_state in valid_states) diff --git a/tests/components/group/test_sensor.py b/tests/components/group/test_sensor.py index 12bb8d0f7de..aa4901e689c 100644 --- a/tests/components/group/test_sensor.py +++ b/tests/components/group/test_sensor.py @@ -245,15 +245,15 @@ async def test_reload(hass: HomeAssistant) -> None: assert hass.states.get("sensor.second_test") -async def test_sensor_incorrect_state( +async def test_sensor_incorrect_state_with_ignore_non_numeric( hass: HomeAssistant, caplog: pytest.LogCaptureFixture ) -> None: - """Test the min sensor.""" + """Test that non numeric values are ignored in a group.""" config = { SENSOR_DOMAIN: { "platform": GROUP_DOMAIN, - "name": "test_failure", - "type": "min", + "name": "test_ignore_non_numeric", + "type": "max", "ignore_non_numeric": True, "entities": ["sensor.test_1", "sensor.test_2", "sensor.test_3"], "unique_id": "very_unique_id", @@ -266,24 +266,63 @@ async def test_sensor_incorrect_state( entity_ids = config["sensor"]["entities"] + # Check that the final sensor value ignores the non numeric input + for entity_id, value in dict(zip(entity_ids, VALUES_ERROR)).items(): + hass.states.async_set(entity_id, value) + await hass.async_block_till_done() + + state = hass.states.get("sensor.test_ignore_non_numeric") + assert state.state == "17.0" + assert ( + "Unable to use state. Only numerical states are supported," not in caplog.text + ) + + # Check that the final sensor value with all numeric inputs + for entity_id, value in dict(zip(entity_ids, VALUES)).items(): + hass.states.async_set(entity_id, value) + await hass.async_block_till_done() + + state = hass.states.get("sensor.test_ignore_non_numeric") + assert state.state == "20.0" + + +async def test_sensor_incorrect_state_with_not_ignore_non_numeric( + hass: HomeAssistant, caplog: pytest.LogCaptureFixture +) -> None: + """Test that non numeric values cause a group to be unknown.""" + config = { + SENSOR_DOMAIN: { + "platform": GROUP_DOMAIN, + "name": "test_failure", + "type": "max", + "ignore_non_numeric": False, + "entities": ["sensor.test_1", "sensor.test_2", "sensor.test_3"], + "unique_id": "very_unique_id", + "state_class": SensorStateClass.MEASUREMENT, + } + } + + assert await async_setup_component(hass, "sensor", config) + await hass.async_block_till_done() + + entity_ids = config["sensor"]["entities"] + + # Check that the final sensor value is unavailable if a non numeric input exists for entity_id, value in dict(zip(entity_ids, VALUES_ERROR)).items(): hass.states.async_set(entity_id, value) await hass.async_block_till_done() state = hass.states.get("sensor.test_failure") + assert state.state == "unknown" + assert "Unable to use state. Only numerical states are supported" in caplog.text - assert state.state == "15.3" - assert ( - "Unable to use state. Only numerical states are supported, entity sensor.test_2 with value string excluded from calculation" - in caplog.text - ) - + # Check that the final sensor value is correct with all numeric inputs for entity_id, value in dict(zip(entity_ids, VALUES)).items(): hass.states.async_set(entity_id, value) await hass.async_block_till_done() state = hass.states.get("sensor.test_failure") - assert state.state == "15.3" + assert state.state == "20.0" async def test_sensor_require_all_states(hass: HomeAssistant) -> None: