core/homeassistant/components/sensor/significant_change.py

86 lines
2.4 KiB
Python
Raw Normal View History

2021-01-26 13:13:27 +00:00
"""Helper to test significant sensor state changes."""
2021-03-18 13:31:38 +00:00
from __future__ import annotations
from typing import Any
2021-01-26 13:13:27 +00:00
from homeassistant.const import (
ATTR_DEVICE_CLASS,
ATTR_UNIT_OF_MEASUREMENT,
TEMP_FAHRENHEIT,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.significant_change import (
check_absolute_change,
check_percentage_change,
)
from . import SensorDeviceClass
2021-01-26 13:13:27 +00:00
def _absolute_and_relative_change(
old_state: int | float | None,
new_state: int | float | None,
absolute_change: int | float,
percentage_change: int | float,
) -> bool:
return check_absolute_change(
old_state, new_state, absolute_change
) and check_percentage_change(old_state, new_state, percentage_change)
2021-01-26 13:13:27 +00:00
@callback
def async_check_significant_change(
2021-01-26 13:13:27 +00:00
hass: HomeAssistant,
old_state: str,
old_attrs: dict,
new_state: str,
new_attrs: dict,
**kwargs: Any,
2021-03-18 13:31:38 +00:00
) -> bool | None:
2021-01-26 13:13:27 +00:00
"""Test if state significantly changed."""
2021-10-22 12:06:04 +00:00
if (device_class := new_attrs.get(ATTR_DEVICE_CLASS)) is None:
2021-01-26 13:13:27 +00:00
return None
absolute_change: float | None = None
percentage_change: float | None = None
if device_class == SensorDeviceClass.TEMPERATURE:
2021-01-26 13:13:27 +00:00
if new_attrs.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_FAHRENHEIT:
absolute_change = 1.0
2021-01-26 13:13:27 +00:00
else:
absolute_change = 0.5
2021-01-26 13:13:27 +00:00
if device_class in (SensorDeviceClass.BATTERY, SensorDeviceClass.HUMIDITY):
absolute_change = 1.0
if device_class in (
SensorDeviceClass.AQI,
SensorDeviceClass.CO,
SensorDeviceClass.CO2,
SensorDeviceClass.PM25,
SensorDeviceClass.PM10,
SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
):
absolute_change = 1.0
percentage_change = 2.0
2021-01-26 13:13:27 +00:00
try:
# New state is invalid, don't report it
new_state_f = float(new_state)
except ValueError:
return False
try:
# Old state was invalid, we should report again
old_state_f = float(old_state)
except ValueError:
return True
if absolute_change is not None and percentage_change is not None:
return _absolute_and_relative_change(
old_state_f, new_state_f, absolute_change, percentage_change
)
if absolute_change is not None:
return check_absolute_change(old_state_f, new_state_f, absolute_change)
2021-01-26 13:13:27 +00:00
return None