Create stats for all sensors that have % unit and are measurement (#53576)

This commit is contained in:
Paulus Schoutsen 2021-07-27 12:56:34 -07:00 committed by GitHub
parent 3488053648
commit f71980a634
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 20 deletions

View file

@ -23,6 +23,7 @@ from homeassistant.const import (
DEVICE_CLASS_POWER,
ENERGY_KILO_WATT_HOUR,
ENERGY_WATT_HOUR,
PERCENTAGE,
POWER_KILO_WATT,
POWER_WATT,
PRESSURE_BAR,
@ -44,7 +45,7 @@ from . import ATTR_LAST_RESET, DOMAIN
_LOGGER = logging.getLogger(__name__)
DEVICE_CLASS_STATISTICS = {
DEVICE_CLASS_OR_UNIT_STATISTICS = {
DEVICE_CLASS_BATTERY: {"mean", "min", "max"},
DEVICE_CLASS_ENERGY: {"sum"},
DEVICE_CLASS_HUMIDITY: {"mean", "min", "max"},
@ -52,6 +53,7 @@ DEVICE_CLASS_STATISTICS = {
DEVICE_CLASS_POWER: {"mean", "min", "max"},
DEVICE_CLASS_PRESSURE: {"mean", "min", "max"},
DEVICE_CLASS_TEMPERATURE: {"mean", "min", "max"},
PERCENTAGE: {"mean", "min", "max"},
}
# Normalized units which will be stored in the statistics table
@ -102,13 +104,19 @@ def _get_entities(hass: HomeAssistant) -> list[tuple[str, str]]:
entity_ids = []
for state in all_sensors:
device_class = state.attributes.get(ATTR_DEVICE_CLASS)
state_class = state.attributes.get(ATTR_STATE_CLASS)
if not state_class or state_class != STATE_CLASS_MEASUREMENT:
if state.attributes.get(ATTR_STATE_CLASS) != STATE_CLASS_MEASUREMENT:
continue
if not device_class or device_class not in DEVICE_CLASS_STATISTICS:
continue
entity_ids.append((state.entity_id, device_class))
if (
key := state.attributes.get(ATTR_DEVICE_CLASS)
) in DEVICE_CLASS_OR_UNIT_STATISTICS:
entity_ids.append((state.entity_id, key))
if (
key := state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
) in DEVICE_CLASS_OR_UNIT_STATISTICS:
entity_ids.append((state.entity_id, key))
return entity_ids
@ -158,12 +166,12 @@ def _time_weighted_average(
def _normalize_states(
entity_history: list[State], device_class: str, entity_id: str
entity_history: list[State], key: str, entity_id: str
) -> tuple[str | None, list[tuple[float, State]]]:
"""Normalize units."""
unit = None
if device_class not in UNIT_CONVERSIONS:
if key not in UNIT_CONVERSIONS:
# We're not normalizing this device class, return the state as they are
fstates = [
(float(el.state), el) for el in entity_history if _is_number(el.state)
@ -182,15 +190,15 @@ def _normalize_states(
fstate = float(state.state)
unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
# Exclude unsupported units from statistics
if unit not in UNIT_CONVERSIONS[device_class]:
if unit not in UNIT_CONVERSIONS[key]:
if entity_id not in WARN_UNSUPPORTED_UNIT:
WARN_UNSUPPORTED_UNIT.add(entity_id)
_LOGGER.warning("%s has unknown unit %s", entity_id, unit)
continue
fstates.append((UNIT_CONVERSIONS[device_class][unit](fstate), state))
fstates.append((UNIT_CONVERSIONS[key][unit](fstate), state))
return DEVICE_CLASS_UNITS[device_class], fstates
return DEVICE_CLASS_UNITS[key], fstates
def compile_statistics(
@ -209,14 +217,14 @@ def compile_statistics(
hass, start - datetime.timedelta.resolution, end, [i[0] for i in entities]
)
for entity_id, device_class in entities:
wanted_statistics = DEVICE_CLASS_STATISTICS[device_class]
for entity_id, key in entities:
wanted_statistics = DEVICE_CLASS_OR_UNIT_STATISTICS[key]
if entity_id not in history_list:
continue
entity_history = history_list[entity_id]
unit, fstates = _normalize_states(entity_history, device_class, entity_id)
unit, fstates = _normalize_states(entity_history, key, entity_id)
if not fstates:
continue
@ -288,8 +296,8 @@ def list_statistic_ids(hass: HomeAssistant, statistic_type: str | None = None) -
statistic_ids = {}
for entity_id, device_class in entities:
provided_statistics = DEVICE_CLASS_STATISTICS[device_class]
for entity_id, key in entities:
provided_statistics = DEVICE_CLASS_OR_UNIT_STATISTICS[key]
if statistic_type is not None and statistic_type not in provided_statistics:
continue
@ -302,14 +310,14 @@ def list_statistic_ids(hass: HomeAssistant, statistic_type: str | None = None) -
native_unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
if device_class not in UNIT_CONVERSIONS:
if key not in UNIT_CONVERSIONS:
statistic_ids[entity_id] = native_unit
continue
if native_unit not in UNIT_CONVERSIONS[device_class]:
if native_unit not in UNIT_CONVERSIONS[key]:
continue
statistics_unit = DEVICE_CLASS_UNITS[device_class]
statistics_unit = DEVICE_CLASS_UNITS[key]
statistic_ids[entity_id] = statistics_unit
return statistic_ids