From 805ef3f90b24279b634f48a33366c4c4852aed65 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 18 Jun 2021 12:03:13 -0700 Subject: [PATCH] Allow fetching multiple statistics (#51996) --- homeassistant/components/history/__init__.py | 6 +-- .../components/recorder/statistics.py | 14 +++---- tests/components/history/test_init.py | 38 ++++++++----------- tests/components/recorder/test_statistics.py | 31 +++++++-------- 4 files changed, 42 insertions(+), 47 deletions(-) diff --git a/homeassistant/components/history/__init__.py b/homeassistant/components/history/__init__.py index ac8a13e69ad..2b30936d9ed 100644 --- a/homeassistant/components/history/__init__.py +++ b/homeassistant/components/history/__init__.py @@ -119,7 +119,7 @@ class LazyState(history_models.LazyState): vol.Required("type"): "history/statistics_during_period", vol.Required("start_time"): str, vol.Optional("end_time"): str, - vol.Optional("statistic_id"): str, + vol.Optional("statistic_ids"): [str], } ) @websocket_api.async_response @@ -152,9 +152,9 @@ async def ws_get_statistics_during_period( hass, start_time, end_time, - msg.get("statistic_id"), + msg.get("statistic_ids"), ) - connection.send_result(msg["id"], {"statistics": statistics}) + connection.send_result(msg["id"], statistics) class HistoryPeriodView(HomeAssistantView): diff --git a/homeassistant/components/recorder/statistics.py b/homeassistant/components/recorder/statistics.py index ee733039d43..1e7f37f9f47 100644 --- a/homeassistant/components/recorder/statistics.py +++ b/homeassistant/components/recorder/statistics.py @@ -74,7 +74,7 @@ def compile_statistics(instance: Recorder, start: datetime.datetime) -> bool: return True -def statistics_during_period(hass, start_time, end_time=None, statistic_id=None): +def statistics_during_period(hass, start_time, end_time=None, statistic_ids=None): """Return states changes during UTC period start_time - end_time.""" with session_scope(hass=hass) as session: baked_query = hass.data[STATISTICS_BAKERY]( @@ -86,20 +86,20 @@ def statistics_during_period(hass, start_time, end_time=None, statistic_id=None) if end_time is not None: baked_query += lambda q: q.filter(Statistics.start < bindparam("end_time")) - if statistic_id is not None: - baked_query += lambda q: q.filter_by(statistic_id=bindparam("statistic_id")) - statistic_id = statistic_id.lower() + if statistic_ids is not None: + baked_query += lambda q: q.filter( + Statistics.statistic_id.in_(bindparam("statistic_ids")) + ) + statistic_ids = [statistic_id.lower() for statistic_id in statistic_ids] baked_query += lambda q: q.order_by(Statistics.statistic_id, Statistics.start) stats = execute( baked_query(session).params( - start_time=start_time, end_time=end_time, statistic_id=statistic_id + start_time=start_time, end_time=end_time, statistic_ids=statistic_ids ) ) - statistic_ids = [statistic_id] if statistic_id is not None else None - return _sorted_statistics_to_dict(stats, statistic_ids) diff --git a/tests/components/history/test_init.py b/tests/components/history/test_init.py index bf8d34e6ffe..d47d3d80393 100644 --- a/tests/components/history/test_init.py +++ b/tests/components/history/test_init.py @@ -834,11 +834,7 @@ async def test_statistics_during_period(hass, hass_ws_client): now = dt_util.utcnow() await hass.async_add_executor_job(init_recorder_component, hass) - await async_setup_component( - hass, - "history", - {"history": {}}, - ) + await async_setup_component(hass, "history", {}) await async_setup_component(hass, "sensor", {}) await hass.async_add_executor_job(hass.data[recorder.DATA_INSTANCE].block_till_done) hass.states.async_set( @@ -861,12 +857,12 @@ async def test_statistics_during_period(hass, hass_ws_client): "type": "history/statistics_during_period", "start_time": now.isoformat(), "end_time": now.isoformat(), - "statistic_id": "sensor.test", + "statistic_ids": ["sensor.test"], } ) response = await client.receive_json() assert response["success"] - assert response["result"] == {"statistics": {}} + assert response["result"] == {} client = await hass_ws_client() await client.send_json( @@ -874,26 +870,24 @@ async def test_statistics_during_period(hass, hass_ws_client): "id": 1, "type": "history/statistics_during_period", "start_time": now.isoformat(), - "statistic_id": "sensor.test", + "statistic_ids": ["sensor.test"], } ) response = await client.receive_json() assert response["success"] assert response["result"] == { - "statistics": { - "sensor.test": [ - { - "statistic_id": "sensor.test", - "start": now.isoformat(), - "mean": approx(10.0), - "min": approx(10.0), - "max": approx(10.0), - "last_reset": None, - "state": None, - "sum": None, - } - ] - } + "sensor.test": [ + { + "statistic_id": "sensor.test", + "start": now.isoformat(), + "mean": approx(10.0), + "min": approx(10.0), + "max": approx(10.0), + "last_reset": None, + "state": None, + "sum": None, + } + ] } diff --git a/tests/components/recorder/test_statistics.py b/tests/components/recorder/test_statistics.py index 1ec0f2284b4..679ef7597c2 100644 --- a/tests/components/recorder/test_statistics.py +++ b/tests/components/recorder/test_statistics.py @@ -26,21 +26,22 @@ def test_compile_hourly_statistics(hass_recorder): recorder.do_adhoc_statistics(period="hourly", start=zero) wait_recording_done(hass) - stats = statistics_during_period(hass, zero) - assert stats == { - "sensor.test1": [ - { - "statistic_id": "sensor.test1", - "start": process_timestamp_to_utc_isoformat(zero), - "mean": approx(14.915254237288135), - "min": approx(10.0), - "max": approx(20.0), - "last_reset": None, - "state": None, - "sum": None, - } - ] - } + for kwargs in ({}, {"statistic_ids": ["sensor.test1"]}): + stats = statistics_during_period(hass, zero, **kwargs) + assert stats == { + "sensor.test1": [ + { + "statistic_id": "sensor.test1", + "start": process_timestamp_to_utc_isoformat(zero), + "mean": approx(14.915254237288135), + "min": approx(10.0), + "max": approx(20.0), + "last_reset": None, + "state": None, + "sum": None, + } + ] + } def record_states(hass):