mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Skip duplicated data when calculating fossil energy consumption (#60599)
This commit is contained in:
parent
dbe0a801c6
commit
159506262a
@ -274,14 +274,16 @@ async def ws_get_fossil_energy_consumption(
|
||||
) -> dict[datetime, float]:
|
||||
"""Combine multiple statistics, returns a dict indexed by start time."""
|
||||
result: defaultdict[datetime, float] = defaultdict(float)
|
||||
seen: defaultdict[datetime, set[str]] = defaultdict(set)
|
||||
|
||||
for statistics_id, stat in stats.items():
|
||||
if statistics_id not in statistic_ids:
|
||||
continue
|
||||
for period in stat:
|
||||
if period["sum"] is None:
|
||||
if period["sum"] is None or statistics_id in seen[period["start"]]:
|
||||
continue
|
||||
result[period["start"]] += period["sum"]
|
||||
seen[period["start"]].add(statistics_id)
|
||||
|
||||
return {key: result[key] for key in sorted(result)}
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
"""Test the Energy websocket API."""
|
||||
from unittest.mock import AsyncMock, Mock
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.energy import data, is_configured
|
||||
from homeassistant.components.recorder import statistics
|
||||
from homeassistant.components.recorder.statistics import async_add_external_statistics
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import dt as dt_util
|
||||
@ -963,6 +964,220 @@ async def test_fossil_energy_consumption(hass, hass_ws_client):
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.freeze_time("2021-08-01 00:00:00+00:00")
|
||||
async def test_fossil_energy_consumption_duplicate(hass, hass_ws_client):
|
||||
"""Test fossil_energy_consumption with co2 sensor data."""
|
||||
now = dt_util.utcnow()
|
||||
later = dt_util.as_utc(dt_util.parse_datetime("2022-09-01 00:00:00"))
|
||||
|
||||
await hass.async_add_executor_job(init_recorder_component, hass)
|
||||
await async_setup_component(hass, "history", {})
|
||||
await async_setup_component(hass, "sensor", {})
|
||||
|
||||
period1 = dt_util.as_utc(dt_util.parse_datetime("2021-09-01 00:00:00"))
|
||||
period2 = dt_util.as_utc(dt_util.parse_datetime("2021-09-30 23:00:00"))
|
||||
period2_day_start = dt_util.as_utc(dt_util.parse_datetime("2021-09-30 00:00:00"))
|
||||
period3 = dt_util.as_utc(dt_util.parse_datetime("2021-10-01 00:00:00"))
|
||||
period4 = dt_util.as_utc(dt_util.parse_datetime("2021-10-31 23:00:00"))
|
||||
period4_day_start = dt_util.as_utc(dt_util.parse_datetime("2021-10-31 00:00:00"))
|
||||
|
||||
external_energy_statistics_1 = (
|
||||
{
|
||||
"start": period1,
|
||||
"last_reset": None,
|
||||
"state": 0,
|
||||
"sum": 2,
|
||||
},
|
||||
{
|
||||
"start": period2,
|
||||
"last_reset": None,
|
||||
"state": 1,
|
||||
"sum": 3,
|
||||
},
|
||||
{
|
||||
"start": period3,
|
||||
"last_reset": None,
|
||||
"state": 2,
|
||||
"sum": 4,
|
||||
},
|
||||
{
|
||||
"start": period4,
|
||||
"last_reset": None,
|
||||
"state": 3,
|
||||
"sum": 5,
|
||||
},
|
||||
{
|
||||
"start": period4,
|
||||
"last_reset": None,
|
||||
"state": 3,
|
||||
"sum": 5,
|
||||
},
|
||||
)
|
||||
external_energy_metadata_1 = {
|
||||
"has_mean": False,
|
||||
"has_sum": True,
|
||||
"name": "Total imported energy",
|
||||
"source": "test",
|
||||
"statistic_id": "test:total_energy_import_tariff_1",
|
||||
"unit_of_measurement": "kWh",
|
||||
}
|
||||
external_energy_statistics_2 = (
|
||||
{
|
||||
"start": period1,
|
||||
"last_reset": None,
|
||||
"state": 0,
|
||||
"sum": 20,
|
||||
},
|
||||
{
|
||||
"start": period2,
|
||||
"last_reset": None,
|
||||
"state": 1,
|
||||
"sum": 30,
|
||||
},
|
||||
{
|
||||
"start": period3,
|
||||
"last_reset": None,
|
||||
"state": 2,
|
||||
"sum": 40,
|
||||
},
|
||||
{
|
||||
"start": period4,
|
||||
"last_reset": None,
|
||||
"state": 3,
|
||||
"sum": 50,
|
||||
},
|
||||
{
|
||||
"start": period4,
|
||||
"last_reset": None,
|
||||
"state": 3,
|
||||
"sum": 50,
|
||||
},
|
||||
)
|
||||
external_energy_metadata_2 = {
|
||||
"has_mean": False,
|
||||
"has_sum": True,
|
||||
"name": "Total imported energy",
|
||||
"source": "test",
|
||||
"statistic_id": "test:total_energy_import_tariff_2",
|
||||
"unit_of_measurement": "kWh",
|
||||
}
|
||||
external_co2_statistics = (
|
||||
{
|
||||
"start": period1,
|
||||
"last_reset": None,
|
||||
"mean": 10,
|
||||
},
|
||||
{
|
||||
"start": period2,
|
||||
"last_reset": None,
|
||||
"mean": 30,
|
||||
},
|
||||
{
|
||||
"start": period3,
|
||||
"last_reset": None,
|
||||
"mean": 60,
|
||||
},
|
||||
{
|
||||
"start": period4,
|
||||
"last_reset": None,
|
||||
"mean": 90,
|
||||
},
|
||||
)
|
||||
external_co2_metadata = {
|
||||
"has_mean": True,
|
||||
"has_sum": False,
|
||||
"name": "Fossil percentage",
|
||||
"source": "test",
|
||||
"statistic_id": "test:fossil_percentage",
|
||||
"unit_of_measurement": "%",
|
||||
}
|
||||
|
||||
with patch.object(
|
||||
statistics, "_statistics_exists", return_value=False
|
||||
), patch.object(
|
||||
statistics, "_insert_statistics", wraps=statistics._insert_statistics
|
||||
) as insert_statistics_mock:
|
||||
async_add_external_statistics(
|
||||
hass, external_energy_metadata_1, external_energy_statistics_1
|
||||
)
|
||||
async_add_external_statistics(
|
||||
hass, external_energy_metadata_2, external_energy_statistics_2
|
||||
)
|
||||
async_add_external_statistics(
|
||||
hass, external_co2_metadata, external_co2_statistics
|
||||
)
|
||||
await async_wait_recording_done_without_instance(hass)
|
||||
assert insert_statistics_mock.call_count == 14
|
||||
|
||||
client = await hass_ws_client()
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 1,
|
||||
"type": "energy/fossil_energy_consumption",
|
||||
"start_time": now.isoformat(),
|
||||
"end_time": later.isoformat(),
|
||||
"energy_statistic_ids": [
|
||||
"test:total_energy_import_tariff_1",
|
||||
"test:total_energy_import_tariff_2",
|
||||
],
|
||||
"co2_statistic_id": "test:fossil_percentage",
|
||||
"period": "hour",
|
||||
}
|
||||
)
|
||||
response = await client.receive_json()
|
||||
assert response["success"]
|
||||
assert response["result"] == {
|
||||
period2.isoformat(): pytest.approx((33.0 - 22.0) * 0.3),
|
||||
period3.isoformat(): pytest.approx((44.0 - 33.0) * 0.6),
|
||||
period4.isoformat(): pytest.approx((55.0 - 44.0) * 0.9),
|
||||
}
|
||||
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 2,
|
||||
"type": "energy/fossil_energy_consumption",
|
||||
"start_time": now.isoformat(),
|
||||
"end_time": later.isoformat(),
|
||||
"energy_statistic_ids": [
|
||||
"test:total_energy_import_tariff_1",
|
||||
"test:total_energy_import_tariff_2",
|
||||
],
|
||||
"co2_statistic_id": "test:fossil_percentage",
|
||||
"period": "day",
|
||||
}
|
||||
)
|
||||
response = await client.receive_json()
|
||||
assert response["success"]
|
||||
assert response["result"] == {
|
||||
period2_day_start.isoformat(): pytest.approx((33.0 - 22.0) * 0.3),
|
||||
period3.isoformat(): pytest.approx((44.0 - 33.0) * 0.6),
|
||||
period4_day_start.isoformat(): pytest.approx((55.0 - 44.0) * 0.9),
|
||||
}
|
||||
|
||||
await client.send_json(
|
||||
{
|
||||
"id": 3,
|
||||
"type": "energy/fossil_energy_consumption",
|
||||
"start_time": now.isoformat(),
|
||||
"end_time": later.isoformat(),
|
||||
"energy_statistic_ids": [
|
||||
"test:total_energy_import_tariff_1",
|
||||
"test:total_energy_import_tariff_2",
|
||||
],
|
||||
"co2_statistic_id": "test:fossil_percentage",
|
||||
"period": "month",
|
||||
}
|
||||
)
|
||||
response = await client.receive_json()
|
||||
assert response["success"]
|
||||
assert response["result"] == {
|
||||
period1.isoformat(): pytest.approx((33.0 - 22.0) * 0.3),
|
||||
period3.isoformat(): pytest.approx(
|
||||
((44.0 - 33.0) * 0.6) + ((55.0 - 44.0) * 0.9)
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
async def test_fossil_energy_consumption_checks(hass, hass_ws_client):
|
||||
"""Test fossil_energy_consumption parameter validation."""
|
||||
client = await hass_ws_client(hass)
|
||||
|
Loading…
x
Reference in New Issue
Block a user