mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Fix filter sensor None state (#44439)
Co-authored-by: Franck Nijhof <frenck@frenck.dev>
This commit is contained in:
parent
6b743c3d16
commit
2d131823ce
@ -197,7 +197,15 @@ class SensorFilter(Entity):
|
|||||||
@callback
|
@callback
|
||||||
def _update_filter_sensor_state(self, new_state, update_ha=True):
|
def _update_filter_sensor_state(self, new_state, update_ha=True):
|
||||||
"""Process device state changes."""
|
"""Process device state changes."""
|
||||||
if new_state is None or new_state.state in [STATE_UNKNOWN, STATE_UNAVAILABLE]:
|
if new_state is None:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"While updating filter %s, the new_state is None", self._name
|
||||||
|
)
|
||||||
|
self._state = None
|
||||||
|
self.async_write_ha_state()
|
||||||
|
return
|
||||||
|
|
||||||
|
if new_state.state in [STATE_UNKNOWN, STATE_UNAVAILABLE]:
|
||||||
self._state = new_state.state
|
self._state = new_state.state
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
return
|
return
|
||||||
@ -218,7 +226,11 @@ class SensorFilter(Entity):
|
|||||||
return
|
return
|
||||||
temp_state = filtered_state
|
temp_state = filtered_state
|
||||||
except ValueError:
|
except ValueError:
|
||||||
_LOGGER.error("Could not convert state: %s to number", self._state)
|
_LOGGER.error(
|
||||||
|
"Could not convert state: %s (%s) to number",
|
||||||
|
new_state.state,
|
||||||
|
type(new_state.state),
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
self._state = temp_state.state
|
self._state = temp_state.state
|
||||||
@ -425,7 +437,7 @@ class Filter:
|
|||||||
"""Implement a common interface for filters."""
|
"""Implement a common interface for filters."""
|
||||||
fstate = FilterState(new_state)
|
fstate = FilterState(new_state)
|
||||||
if self._only_numbers and not isinstance(fstate.state, Number):
|
if self._only_numbers and not isinstance(fstate.state, Number):
|
||||||
raise ValueError
|
raise ValueError(f"State <{fstate.state}> is not a Number")
|
||||||
|
|
||||||
filtered = self._filter_state(fstate)
|
filtered = self._filter_state(fstate)
|
||||||
filtered.set_precision(self.precision)
|
filtered.set_precision(self.precision)
|
||||||
|
@ -15,7 +15,7 @@ from homeassistant.components.filter.sensor import (
|
|||||||
TimeThrottleFilter,
|
TimeThrottleFilter,
|
||||||
)
|
)
|
||||||
from homeassistant.components.sensor import DEVICE_CLASS_TEMPERATURE
|
from homeassistant.components.sensor import DEVICE_CLASS_TEMPERATURE
|
||||||
from homeassistant.const import SERVICE_RELOAD, STATE_UNAVAILABLE
|
from homeassistant.const import SERVICE_RELOAD, STATE_UNAVAILABLE, STATE_UNKNOWN
|
||||||
import homeassistant.core as ha
|
import homeassistant.core as ha
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
@ -136,6 +136,71 @@ async def test_chain_history(hass, values, missing=False):
|
|||||||
assert "17.05" == state.state
|
assert "17.05" == state.state
|
||||||
|
|
||||||
|
|
||||||
|
async def test_source_state_none(hass, values):
|
||||||
|
"""Test is source sensor state is null and sets state to STATE_UNKNOWN."""
|
||||||
|
await async_init_recorder_component(hass)
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"sensor": [
|
||||||
|
{
|
||||||
|
"platform": "template",
|
||||||
|
"sensors": {
|
||||||
|
"template_test": {
|
||||||
|
"value_template": "{{ states.sensor.test_state.state }}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"platform": "filter",
|
||||||
|
"name": "test",
|
||||||
|
"entity_id": "sensor.template_test",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filter": "time_simple_moving_average",
|
||||||
|
"window_size": "00:01",
|
||||||
|
"precision": "2",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
await async_setup_component(hass, "sensor", config)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
hass.states.async_set("sensor.test_state", 0)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("sensor.template_test")
|
||||||
|
assert state.state == "0"
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("sensor.test")
|
||||||
|
assert state.state == "0.0"
|
||||||
|
|
||||||
|
# Force Template Reload
|
||||||
|
yaml_path = path.join(
|
||||||
|
_get_fixtures_base_path(),
|
||||||
|
"fixtures",
|
||||||
|
"template/sensor_configuration.yaml",
|
||||||
|
)
|
||||||
|
with patch.object(hass_config, "YAML_CONFIG_FILE", yaml_path):
|
||||||
|
await hass.services.async_call(
|
||||||
|
"template",
|
||||||
|
SERVICE_RELOAD,
|
||||||
|
{},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# Template state gets to None
|
||||||
|
state = hass.states.get("sensor.template_test")
|
||||||
|
assert state is None
|
||||||
|
|
||||||
|
# Filter sensor ignores None state setting state to STATE_UNKNOWN
|
||||||
|
state = hass.states.get("sensor.test")
|
||||||
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
async def test_chain_history_missing(hass, values):
|
async def test_chain_history_missing(hass, values):
|
||||||
"""Test if filter chaining works when recorder is enabled but the source is not recorded."""
|
"""Test if filter chaining works when recorder is enabled but the source is not recorded."""
|
||||||
await test_chain_history(hass, values, missing=True)
|
await test_chain_history(hass, values, missing=True)
|
||||||
@ -239,6 +304,12 @@ async def test_invalid_state(hass):
|
|||||||
state = hass.states.get("sensor.test")
|
state = hass.states.get("sensor.test")
|
||||||
assert state.state == STATE_UNAVAILABLE
|
assert state.state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
hass.states.async_set("sensor.test_monitored", "invalid")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("sensor.test")
|
||||||
|
assert state.state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
|
||||||
async def test_outlier(values):
|
async def test_outlier(values):
|
||||||
"""Test if outlier filter works."""
|
"""Test if outlier filter works."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user