mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 19:27:45 +00:00
Support for multiple states in history_stats (#43416)
Co-authored-by: Indu Prakash <6459774+InduPrakash@users.noreply.github.com>
This commit is contained in:
parent
f22f568169
commit
7213d5f31b
@ -62,7 +62,7 @@ PLATFORM_SCHEMA = vol.All(
|
|||||||
PLATFORM_SCHEMA.extend(
|
PLATFORM_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
||||||
vol.Required(CONF_STATE): cv.string,
|
vol.Required(CONF_STATE): vol.All(cv.ensure_list, [cv.string]),
|
||||||
vol.Optional(CONF_START): cv.template,
|
vol.Optional(CONF_START): cv.template,
|
||||||
vol.Optional(CONF_END): cv.template,
|
vol.Optional(CONF_END): cv.template,
|
||||||
vol.Optional(CONF_DURATION): cv.time_period,
|
vol.Optional(CONF_DURATION): cv.time_period,
|
||||||
@ -77,11 +77,10 @@ PLATFORM_SCHEMA = vol.All(
|
|||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the History Stats sensor."""
|
"""Set up the History Stats sensor."""
|
||||||
|
|
||||||
setup_reload_service(hass, DOMAIN, PLATFORMS)
|
setup_reload_service(hass, DOMAIN, PLATFORMS)
|
||||||
|
|
||||||
entity_id = config.get(CONF_ENTITY_ID)
|
entity_id = config.get(CONF_ENTITY_ID)
|
||||||
entity_state = config.get(CONF_STATE)
|
entity_states = config.get(CONF_STATE)
|
||||||
start = config.get(CONF_START)
|
start = config.get(CONF_START)
|
||||||
end = config.get(CONF_END)
|
end = config.get(CONF_END)
|
||||||
duration = config.get(CONF_DURATION)
|
duration = config.get(CONF_DURATION)
|
||||||
@ -95,7 +94,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
add_entities(
|
add_entities(
|
||||||
[
|
[
|
||||||
HistoryStatsSensor(
|
HistoryStatsSensor(
|
||||||
hass, entity_id, entity_state, start, end, duration, sensor_type, name
|
hass, entity_id, entity_states, start, end, duration, sensor_type, name
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -107,11 +106,11 @@ class HistoryStatsSensor(Entity):
|
|||||||
"""Representation of a HistoryStats sensor."""
|
"""Representation of a HistoryStats sensor."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, hass, entity_id, entity_state, start, end, duration, sensor_type, name
|
self, hass, entity_id, entity_states, start, end, duration, sensor_type, name
|
||||||
):
|
):
|
||||||
"""Initialize the HistoryStats sensor."""
|
"""Initialize the HistoryStats sensor."""
|
||||||
self._entity_id = entity_id
|
self._entity_id = entity_id
|
||||||
self._entity_state = entity_state
|
self._entity_states = entity_states
|
||||||
self._duration = duration
|
self._duration = duration
|
||||||
self._start = start
|
self._start = start
|
||||||
self._end = end
|
self._end = end
|
||||||
@ -230,14 +229,14 @@ class HistoryStatsSensor(Entity):
|
|||||||
|
|
||||||
# Get the first state
|
# Get the first state
|
||||||
last_state = history.get_state(self.hass, start, self._entity_id)
|
last_state = history.get_state(self.hass, start, self._entity_id)
|
||||||
last_state = last_state is not None and last_state == self._entity_state
|
last_state = last_state is not None and last_state in self._entity_states
|
||||||
last_time = start_timestamp
|
last_time = start_timestamp
|
||||||
elapsed = 0
|
elapsed = 0
|
||||||
count = 0
|
count = 0
|
||||||
|
|
||||||
# Make calculations
|
# Make calculations
|
||||||
for item in history_list.get(self._entity_id):
|
for item in history_list.get(self._entity_id):
|
||||||
current_state = item.state == self._entity_state
|
current_state = item.state in self._entity_states
|
||||||
current_time = item.last_changed.timestamp()
|
current_time = item.last_changed.timestamp()
|
||||||
|
|
||||||
if last_state:
|
if last_state:
|
||||||
|
@ -50,6 +50,28 @@ class TestHistoryStatsSensor(unittest.TestCase):
|
|||||||
state = self.hass.states.get("sensor.test")
|
state = self.hass.states.get("sensor.test")
|
||||||
assert state.state == STATE_UNKNOWN
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
def test_setup_multiple_states(self):
|
||||||
|
"""Test the history statistics sensor setup for multiple states."""
|
||||||
|
self.init_recorder()
|
||||||
|
config = {
|
||||||
|
"history": {},
|
||||||
|
"sensor": {
|
||||||
|
"platform": "history_stats",
|
||||||
|
"entity_id": "binary_sensor.test_id",
|
||||||
|
"state": ["on", "true"],
|
||||||
|
"start": "{{ now().replace(hour=0)"
|
||||||
|
".replace(minute=0).replace(second=0) }}",
|
||||||
|
"duration": "02:00",
|
||||||
|
"name": "Test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert setup_component(self.hass, "sensor", config)
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
state = self.hass.states.get("sensor.test")
|
||||||
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
@patch(
|
@patch(
|
||||||
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
|
"homeassistant.helpers.template.TemplateEnvironment.is_safe_callable",
|
||||||
return_value=True,
|
return_value=True,
|
||||||
@ -152,6 +174,90 @@ class TestHistoryStatsSensor(unittest.TestCase):
|
|||||||
assert sensor3.state == 2
|
assert sensor3.state == 2
|
||||||
assert sensor4.state == 50
|
assert sensor4.state == 50
|
||||||
|
|
||||||
|
def test_measure_multiple(self):
|
||||||
|
"""Test the history statistics sensor measure for multiple states."""
|
||||||
|
t0 = dt_util.utcnow() - timedelta(minutes=40)
|
||||||
|
t1 = t0 + timedelta(minutes=20)
|
||||||
|
t2 = dt_util.utcnow() - timedelta(minutes=10)
|
||||||
|
|
||||||
|
# Start t0 t1 t2 End
|
||||||
|
# |--20min--|--20min--|--10min--|--10min--|
|
||||||
|
# |---------|--orange-|-default-|---blue--|
|
||||||
|
|
||||||
|
fake_states = {
|
||||||
|
"input_select.test_id": [
|
||||||
|
ha.State("input_select.test_id", "orange", last_changed=t0),
|
||||||
|
ha.State("input_select.test_id", "default", last_changed=t1),
|
||||||
|
ha.State("input_select.test_id", "blue", last_changed=t2),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
start = Template("{{ as_timestamp(now()) - 3600 }}", self.hass)
|
||||||
|
end = Template("{{ now() }}", self.hass)
|
||||||
|
|
||||||
|
sensor1 = HistoryStatsSensor(
|
||||||
|
self.hass,
|
||||||
|
"input_select.test_id",
|
||||||
|
["orange", "blue"],
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
None,
|
||||||
|
"time",
|
||||||
|
"Test",
|
||||||
|
)
|
||||||
|
|
||||||
|
sensor2 = HistoryStatsSensor(
|
||||||
|
self.hass,
|
||||||
|
"unknown.id",
|
||||||
|
["orange", "blue"],
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
None,
|
||||||
|
"time",
|
||||||
|
"Test",
|
||||||
|
)
|
||||||
|
|
||||||
|
sensor3 = HistoryStatsSensor(
|
||||||
|
self.hass,
|
||||||
|
"input_select.test_id",
|
||||||
|
["orange", "blue"],
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
None,
|
||||||
|
"count",
|
||||||
|
"test",
|
||||||
|
)
|
||||||
|
|
||||||
|
sensor4 = HistoryStatsSensor(
|
||||||
|
self.hass,
|
||||||
|
"input_select.test_id",
|
||||||
|
["orange", "blue"],
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
None,
|
||||||
|
"ratio",
|
||||||
|
"test",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert sensor1._type == "time"
|
||||||
|
assert sensor3._type == "count"
|
||||||
|
assert sensor4._type == "ratio"
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.history.state_changes_during_period",
|
||||||
|
return_value=fake_states,
|
||||||
|
):
|
||||||
|
with patch("homeassistant.components.history.get_state", return_value=None):
|
||||||
|
sensor1.update()
|
||||||
|
sensor2.update()
|
||||||
|
sensor3.update()
|
||||||
|
sensor4.update()
|
||||||
|
|
||||||
|
assert sensor1.state == 0.5
|
||||||
|
assert sensor2.state is None
|
||||||
|
assert sensor3.state == 2
|
||||||
|
assert sensor4.state == 50
|
||||||
|
|
||||||
def test_wrong_date(self):
|
def test_wrong_date(self):
|
||||||
"""Test when start or end value is not a timestamp or a date."""
|
"""Test when start or end value is not a timestamp or a date."""
|
||||||
good = Template("{{ now() }}", self.hass)
|
good = Template("{{ now() }}", self.hass)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user