Add display unit to WS recorder/get_statistics_metadata (#82870)

pull/82773/head
Erik Montnemery 2022-11-28 19:46:57 +01:00 committed by GitHub
parent 3a65537c5e
commit a038314d8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 207 additions and 2 deletions

View File

@ -147,6 +147,30 @@ def _get_unit_class(unit: str | None) -> str | None:
return None
def get_display_unit(
hass: HomeAssistant,
statistic_id: str,
statistic_unit: str | None,
) -> str | None:
"""Return the unit which the statistic will be displayed in."""
if statistic_unit is None:
return None
if (converter := STATISTIC_UNIT_TO_UNIT_CONVERTER.get(statistic_unit)) is None:
return statistic_unit
state_unit: str | None = statistic_unit
if state := hass.states.get(statistic_id):
state_unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
if state_unit == statistic_unit or state_unit not in converter.VALID_UNITS:
# Guard against invalid state unit in the DB
return statistic_unit
return state_unit
def _get_statistic_to_display_unit_converter(
statistic_unit: str | None,
state_unit: str | None,
@ -902,6 +926,9 @@ def list_statistic_ids(
result = {
meta["statistic_id"]: {
"display_unit_of_measurement": get_display_unit(
hass, meta["statistic_id"], meta["unit_of_measurement"]
),
"has_mean": meta["has_mean"],
"has_sum": meta["has_sum"],
"name": meta["name"],
@ -924,6 +951,7 @@ def list_statistic_ids(
if key in result:
continue
result[key] = {
"display_unit_of_measurement": meta["unit_of_measurement"],
"has_mean": meta["has_mean"],
"has_sum": meta["has_sum"],
"name": meta["name"],
@ -936,6 +964,7 @@ def list_statistic_ids(
return [
{
"statistic_id": _id,
"display_unit_of_measurement": info["display_unit_of_measurement"],
"has_mean": info["has_mean"],
"has_sum": info["has_sum"],
"name": info.get("name"),

View File

@ -63,6 +63,7 @@ async def test_demo_statistics(recorder_mock, mock_history, hass):
list_statistic_ids, hass
)
assert {
"display_unit_of_measurement": "°C",
"has_mean": True,
"has_sum": False,
"name": "Outdoor temperature",
@ -72,6 +73,7 @@ async def test_demo_statistics(recorder_mock, mock_history, hass):
"unit_class": "temperature",
} in statistic_ids
assert {
"display_unit_of_measurement": "kWh",
"has_mean": False,
"has_sum": True,
"name": "Energy consumption 1",

View File

@ -554,6 +554,7 @@ async def test_import_statistics(
statistic_ids = list_statistic_ids(hass)
assert statistic_ids == [
{
"display_unit_of_measurement": "kWh",
"has_mean": False,
"has_sum": True,
"statistic_id": statistic_id,
@ -650,6 +651,7 @@ async def test_import_statistics(
statistic_ids = list_statistic_ids(hass)
assert statistic_ids == [
{
"display_unit_of_measurement": "kWh",
"has_mean": False,
"has_sum": True,
"statistic_id": statistic_id,

View File

@ -1350,6 +1350,7 @@ async def test_list_statistic_ids(
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": display_unit,
"has_mean": has_mean,
"has_sum": has_sum,
"name": None,
@ -1371,6 +1372,7 @@ async def test_list_statistic_ids(
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": display_unit,
"has_mean": has_mean,
"has_sum": has_sum,
"name": None,
@ -1395,6 +1397,7 @@ async def test_list_statistic_ids(
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": display_unit,
"has_mean": has_mean,
"has_sum": has_sum,
"name": None,
@ -1415,6 +1418,7 @@ async def test_list_statistic_ids(
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": display_unit,
"has_mean": has_mean,
"has_sum": has_sum,
"name": None,
@ -1427,6 +1431,121 @@ async def test_list_statistic_ids(
assert response["result"] == []
@pytest.mark.parametrize(
"attributes, attributes2, display_unit, statistics_unit, unit_class",
[
(
DISTANCE_SENSOR_M_ATTRIBUTES,
DISTANCE_SENSOR_FT_ATTRIBUTES,
"ft",
"m",
"distance",
),
(
ENERGY_SENSOR_WH_ATTRIBUTES,
ENERGY_SENSOR_KWH_ATTRIBUTES,
"kWh",
"Wh",
"energy",
),
(GAS_SENSOR_FT3_ATTRIBUTES, GAS_SENSOR_M3_ATTRIBUTES, "", "ft³", "volume"),
(POWER_SENSOR_KW_ATTRIBUTES, POWER_SENSOR_W_ATTRIBUTES, "W", "kW", "power"),
(
PRESSURE_SENSOR_HPA_ATTRIBUTES,
PRESSURE_SENSOR_PA_ATTRIBUTES,
"Pa",
"hPa",
"pressure",
),
(
SPEED_SENSOR_KPH_ATTRIBUTES,
SPEED_SENSOR_MPH_ATTRIBUTES,
"mph",
"km/h",
"speed",
),
(
TEMPERATURE_SENSOR_C_ATTRIBUTES,
TEMPERATURE_SENSOR_F_ATTRIBUTES,
"°F",
"°C",
"temperature",
),
(
VOLUME_SENSOR_FT3_ATTRIBUTES,
VOLUME_SENSOR_M3_ATTRIBUTES,
"",
"ft³",
"volume",
),
],
)
async def test_list_statistic_ids_unit_change(
recorder_mock,
hass,
hass_ws_client,
attributes,
attributes2,
display_unit,
statistics_unit,
unit_class,
):
"""Test list_statistic_ids."""
now = dt_util.utcnow()
has_mean = attributes["state_class"] == "measurement"
has_sum = not has_mean
await async_setup_component(hass, "sensor", {})
await async_recorder_block_till_done(hass)
client = await hass_ws_client()
await client.send_json({"id": 1, "type": "recorder/list_statistic_ids"})
response = await client.receive_json()
assert response["success"]
assert response["result"] == []
hass.states.async_set("sensor.test", 10, attributes=attributes)
await async_wait_recording_done(hass)
do_adhoc_statistics(hass, start=now)
await async_recorder_block_till_done(hass)
await client.send_json({"id": 2, "type": "recorder/list_statistic_ids"})
response = await client.receive_json()
assert response["success"]
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": statistics_unit,
"has_mean": has_mean,
"has_sum": has_sum,
"name": None,
"source": "recorder",
"statistics_unit_of_measurement": statistics_unit,
"unit_class": unit_class,
}
]
# Change the state unit
hass.states.async_set("sensor.test", 10, attributes=attributes2)
await client.send_json({"id": 3, "type": "recorder/list_statistic_ids"})
response = await client.receive_json()
assert response["success"]
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": display_unit,
"has_mean": has_mean,
"has_sum": has_sum,
"name": None,
"source": "recorder",
"statistics_unit_of_measurement": statistics_unit,
"unit_class": unit_class,
}
]
async def test_validate_statistics(recorder_mock, hass, hass_ws_client):
"""Test validate_statistics can be called."""
id = 1
@ -1570,10 +1689,11 @@ async def test_clear_statistics(recorder_mock, hass, hass_ws_client):
@pytest.mark.parametrize(
"new_unit, new_unit_class", [("dogs", None), (None, None), ("W", "power")]
"new_unit, new_unit_class, new_display_unit",
[("dogs", None, "dogs"), (None, None, None), ("W", "power", "kW")],
)
async def test_update_statistics_metadata(
recorder_mock, hass, hass_ws_client, new_unit, new_unit_class
recorder_mock, hass, hass_ws_client, new_unit, new_unit_class, new_display_unit
):
"""Test removing statistics."""
now = dt_util.utcnow()
@ -1599,6 +1719,7 @@ async def test_update_statistics_metadata(
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": "kW",
"has_mean": True,
"has_sum": False,
"name": None,
@ -1626,6 +1747,7 @@ async def test_update_statistics_metadata(
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": new_display_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -1688,6 +1810,7 @@ async def test_change_statistics_unit(recorder_mock, hass, hass_ws_client):
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": "kW",
"has_mean": True,
"has_sum": False,
"name": None,
@ -1742,6 +1865,7 @@ async def test_change_statistics_unit(recorder_mock, hass, hass_ws_client):
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": "kW",
"has_mean": True,
"has_sum": False,
"name": None,
@ -1793,6 +1917,7 @@ async def test_change_statistics_unit_errors(
expected_statistic_ids = [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": "kW",
"has_mean": True,
"has_sum": False,
"name": None,
@ -2177,6 +2302,7 @@ async def test_get_statistics_metadata(
assert response["result"] == [
{
"statistic_id": "test:total_gas",
"display_unit_of_measurement": unit,
"has_mean": has_mean,
"has_sum": has_sum,
"name": "Total imported energy",
@ -2204,6 +2330,7 @@ async def test_get_statistics_metadata(
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": attributes["unit_of_measurement"],
"has_mean": has_mean,
"has_sum": has_sum,
"name": None,
@ -2231,6 +2358,7 @@ async def test_get_statistics_metadata(
assert response["result"] == [
{
"statistic_id": "sensor.test",
"display_unit_of_measurement": attributes["unit_of_measurement"],
"has_mean": has_mean,
"has_sum": has_sum,
"name": None,
@ -2324,6 +2452,7 @@ async def test_import_statistics(
statistic_ids = list_statistic_ids(hass) # TODO
assert statistic_ids == [
{
"display_unit_of_measurement": "kWh",
"has_mean": False,
"has_sum": True,
"statistic_id": statistic_id,
@ -2550,6 +2679,7 @@ async def test_adjust_sum_statistics_energy(
statistic_ids = list_statistic_ids(hass) # TODO
assert statistic_ids == [
{
"display_unit_of_measurement": "kWh",
"has_mean": False,
"has_sum": True,
"statistic_id": statistic_id,
@ -2740,6 +2870,7 @@ async def test_adjust_sum_statistics_gas(
statistic_ids = list_statistic_ids(hass) # TODO
assert statistic_ids == [
{
"display_unit_of_measurement": "",
"has_mean": False,
"has_sum": True,
"statistic_id": statistic_id,
@ -2946,6 +3077,7 @@ async def test_adjust_sum_statistics_errors(
statistic_ids = list_statistic_ids(hass)
assert statistic_ids == [
{
"display_unit_of_measurement": state_unit,
"has_mean": False,
"has_sum": True,
"statistic_id": statistic_id,

View File

@ -141,6 +141,7 @@ def test_compile_hourly_statistics(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -214,6 +215,7 @@ def test_compile_hourly_statistics_purged_state_changes(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -282,6 +284,7 @@ def test_compile_hourly_statistics_wrong_unit(hass_recorder, caplog, attributes)
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": "°C",
"has_mean": True,
"has_sum": False,
"name": None,
@ -290,6 +293,7 @@ def test_compile_hourly_statistics_wrong_unit(hass_recorder, caplog, attributes)
"unit_class": "temperature",
},
{
"display_unit_of_measurement": "invalid",
"has_mean": True,
"has_sum": False,
"name": None,
@ -299,6 +303,7 @@ def test_compile_hourly_statistics_wrong_unit(hass_recorder, caplog, attributes)
"unit_class": None,
},
{
"display_unit_of_measurement": None,
"has_mean": True,
"has_sum": False,
"name": None,
@ -309,6 +314,7 @@ def test_compile_hourly_statistics_wrong_unit(hass_recorder, caplog, attributes)
},
{
"statistic_id": "sensor.test6",
"display_unit_of_measurement": "°C",
"has_mean": True,
"has_sum": False,
"name": None,
@ -318,6 +324,7 @@ def test_compile_hourly_statistics_wrong_unit(hass_recorder, caplog, attributes)
},
{
"statistic_id": "sensor.test7",
"display_unit_of_measurement": "°C",
"has_mean": True,
"has_sum": False,
"name": None,
@ -473,6 +480,7 @@ async def test_compile_hourly_sum_statistics_amount(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": statistics_unit,
"has_mean": False,
"has_sum": True,
"name": None,
@ -662,6 +670,7 @@ def test_compile_hourly_sum_statistics_amount_reset_every_state_change(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": False,
"has_sum": True,
"name": None,
@ -758,6 +767,7 @@ def test_compile_hourly_sum_statistics_amount_invalid_last_reset(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": False,
"has_sum": True,
"name": None,
@ -841,6 +851,7 @@ def test_compile_hourly_sum_statistics_nan_inf_state(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": False,
"has_sum": True,
"name": None,
@ -965,6 +976,7 @@ def test_compile_hourly_sum_statistics_negative_state(
wait_recording_done(hass)
statistic_ids = list_statistic_ids(hass)
assert {
"display_unit_of_measurement": display_unit,
"has_mean": False,
"has_sum": True,
"name": None,
@ -1052,6 +1064,7 @@ def test_compile_hourly_sum_statistics_total_no_reset(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": False,
"has_sum": True,
"name": None,
@ -1151,6 +1164,7 @@ def test_compile_hourly_sum_statistics_total_increasing(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": False,
"has_sum": True,
"name": None,
@ -1261,6 +1275,7 @@ def test_compile_hourly_sum_statistics_total_increasing_small_dip(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": False,
"has_sum": True,
"name": None,
@ -1352,6 +1367,7 @@ def test_compile_hourly_energy_statistics_unsupported(hass_recorder, caplog):
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": "kWh",
"has_mean": False,
"has_sum": True,
"name": None,
@ -1441,6 +1457,7 @@ def test_compile_hourly_energy_statistics_multiple(hass_recorder, caplog):
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": "kWh",
"has_mean": False,
"has_sum": True,
"name": None,
@ -1450,6 +1467,7 @@ def test_compile_hourly_energy_statistics_multiple(hass_recorder, caplog):
},
{
"statistic_id": "sensor.test2",
"display_unit_of_measurement": "kWh",
"has_mean": False,
"has_sum": True,
"name": None,
@ -1459,6 +1477,7 @@ def test_compile_hourly_energy_statistics_multiple(hass_recorder, caplog):
},
{
"statistic_id": "sensor.test3",
"display_unit_of_measurement": "Wh",
"has_mean": False,
"has_sum": True,
"name": None,
@ -1814,6 +1833,7 @@ def test_list_statistic_ids(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": statistic_type == "mean",
"has_sum": statistic_type == "sum",
"name": None,
@ -1828,6 +1848,7 @@ def test_list_statistic_ids(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": statistic_type == "mean",
"has_sum": statistic_type == "sum",
"name": None,
@ -1921,6 +1942,7 @@ def test_compile_hourly_statistics_changing_units_1(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": state_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -1955,6 +1977,7 @@ def test_compile_hourly_statistics_changing_units_1(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": state_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2029,6 +2052,7 @@ def test_compile_hourly_statistics_changing_units_2(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": "cats",
"has_mean": True,
"has_sum": False,
"name": None,
@ -2094,6 +2118,7 @@ def test_compile_hourly_statistics_changing_units_3(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2128,6 +2153,7 @@ def test_compile_hourly_statistics_changing_units_3(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2206,6 +2232,7 @@ def test_compile_hourly_statistics_equivalent_units_1(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": state_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2236,6 +2263,7 @@ def test_compile_hourly_statistics_equivalent_units_1(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": state_unit2,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2319,6 +2347,7 @@ def test_compile_hourly_statistics_equivalent_units_2(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": state_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2384,6 +2413,7 @@ def test_compile_hourly_statistics_changing_device_class_1(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": state_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2428,6 +2458,7 @@ def test_compile_hourly_statistics_changing_device_class_1(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": state_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2482,6 +2513,7 @@ def test_compile_hourly_statistics_changing_device_class_1(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": state_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2568,6 +2600,7 @@ def test_compile_hourly_statistics_changing_device_class_2(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2612,6 +2645,7 @@ def test_compile_hourly_statistics_changing_device_class_2(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": display_unit,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2690,6 +2724,7 @@ def test_compile_hourly_statistics_changing_statistics(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": None,
"has_mean": True,
"has_sum": False,
"name": None,
@ -2725,6 +2760,7 @@ def test_compile_hourly_statistics_changing_statistics(
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": None,
"has_mean": False,
"has_sum": True,
"name": None,
@ -2916,6 +2952,7 @@ def test_compile_statistics_hourly_daily_monthly_summary(hass_recorder, caplog):
assert statistic_ids == [
{
"statistic_id": "sensor.test1",
"display_unit_of_measurement": "%",
"has_mean": True,
"has_sum": False,
"name": None,
@ -2925,6 +2962,7 @@ def test_compile_statistics_hourly_daily_monthly_summary(hass_recorder, caplog):
},
{
"statistic_id": "sensor.test2",
"display_unit_of_measurement": "%",
"has_mean": True,
"has_sum": False,
"name": None,
@ -2934,6 +2972,7 @@ def test_compile_statistics_hourly_daily_monthly_summary(hass_recorder, caplog):
},
{
"statistic_id": "sensor.test3",
"display_unit_of_measurement": "%",
"has_mean": True,
"has_sum": False,
"name": None,
@ -2943,6 +2982,7 @@ def test_compile_statistics_hourly_daily_monthly_summary(hass_recorder, caplog):
},
{
"statistic_id": "sensor.test4",
"display_unit_of_measurement": "EUR",
"has_mean": False,
"has_sum": True,
"name": None,