Light significant changes + sensor tweaks (#45583)
This commit is contained in:
parent
74efe78d0a
commit
352d0870e3
6 changed files with 179 additions and 15 deletions
71
homeassistant/components/light/significant_change.py
Normal file
71
homeassistant/components/light/significant_change.py
Normal file
|
@ -0,0 +1,71 @@
|
|||
"""Helper to test significant Light state changes."""
|
||||
from typing import Any, Optional
|
||||
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.significant_change import (
|
||||
check_numeric_changed,
|
||||
either_one_none,
|
||||
)
|
||||
|
||||
from . import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_TEMP,
|
||||
ATTR_EFFECT,
|
||||
ATTR_HS_COLOR,
|
||||
ATTR_WHITE_VALUE,
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def async_check_significant_change(
|
||||
hass: HomeAssistant,
|
||||
old_state: str,
|
||||
old_attrs: dict,
|
||||
new_state: str,
|
||||
new_attrs: dict,
|
||||
**kwargs: Any,
|
||||
) -> Optional[bool]:
|
||||
"""Test if state significantly changed."""
|
||||
if old_state != new_state:
|
||||
return True
|
||||
|
||||
if old_attrs.get(ATTR_EFFECT) != new_attrs.get(ATTR_EFFECT):
|
||||
return True
|
||||
|
||||
old_color = old_attrs.get(ATTR_HS_COLOR)
|
||||
new_color = new_attrs.get(ATTR_HS_COLOR)
|
||||
|
||||
if either_one_none(old_color, new_color):
|
||||
return True
|
||||
|
||||
if old_color and new_color:
|
||||
# Range 0..360
|
||||
if check_numeric_changed(old_color[0], new_color[0], 5):
|
||||
return True
|
||||
|
||||
# Range 0..100
|
||||
if check_numeric_changed(old_color[1], new_color[1], 3):
|
||||
return True
|
||||
|
||||
if check_numeric_changed(
|
||||
old_attrs.get(ATTR_BRIGHTNESS), new_attrs.get(ATTR_BRIGHTNESS), 3
|
||||
):
|
||||
return True
|
||||
|
||||
if check_numeric_changed(
|
||||
# Default range 153..500
|
||||
old_attrs.get(ATTR_COLOR_TEMP),
|
||||
new_attrs.get(ATTR_COLOR_TEMP),
|
||||
5,
|
||||
):
|
||||
return True
|
||||
|
||||
if check_numeric_changed(
|
||||
# Range 0..255
|
||||
old_attrs.get(ATTR_WHITE_VALUE),
|
||||
new_attrs.get(ATTR_WHITE_VALUE),
|
||||
5,
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
|
@ -1,5 +1,5 @@
|
|||
"""Helper to test significant sensor state changes."""
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
|
@ -28,18 +28,18 @@ def async_check_significant_change(
|
|||
|
||||
if device_class == DEVICE_CLASS_TEMPERATURE:
|
||||
if new_attrs.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_FAHRENHEIT:
|
||||
change = 0.03
|
||||
change: Union[float, int] = 1
|
||||
else:
|
||||
change = 0.05
|
||||
change = 0.5
|
||||
|
||||
old_value = float(old_state)
|
||||
new_value = float(new_state)
|
||||
return abs(1 - old_value / new_value) > change
|
||||
return abs(old_value - new_value) >= change
|
||||
|
||||
if device_class in (DEVICE_CLASS_BATTERY, DEVICE_CLASS_HUMIDITY):
|
||||
old_value = float(old_state)
|
||||
new_value = float(new_state)
|
||||
|
||||
return abs(old_value - new_value) > 2
|
||||
return abs(old_value - new_value) >= 1
|
||||
|
||||
return None
|
||||
|
|
|
@ -73,6 +73,32 @@ async def _initialize(hass: HomeAssistant) -> None:
|
|||
await async_process_integration_platforms(hass, PLATFORM, process_platform)
|
||||
|
||||
|
||||
def either_one_none(val1: Optional[Any], val2: Optional[Any]) -> bool:
|
||||
"""Test if exactly one value is None."""
|
||||
return (val1 is None and val2 is not None) or (val1 is not None and val2 is None)
|
||||
|
||||
|
||||
def check_numeric_changed(
|
||||
val1: Optional[Union[int, float]],
|
||||
val2: Optional[Union[int, float]],
|
||||
change: Union[int, float],
|
||||
) -> bool:
|
||||
"""Check if two numeric values have changed."""
|
||||
if val1 is None and val2 is None:
|
||||
return False
|
||||
|
||||
if either_one_none(val1, val2):
|
||||
return True
|
||||
|
||||
assert val1 is not None
|
||||
assert val2 is not None
|
||||
|
||||
if abs(val1 - val2) >= change:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class SignificantlyChangedChecker:
|
||||
"""Class to keep track of entities to see if they have significantly changed.
|
||||
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
"""Test the sensor significant change platform."""
|
||||
"""Test the NEW_NAME significant change platform."""
|
||||
from homeassistant.components.NEW_DOMAIN.significant_change import (
|
||||
async_check_significant_change,
|
||||
)
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS
|
||||
|
||||
|
||||
async def test_significant_change():
|
||||
"""Detect NEW_NAME significant change."""
|
||||
attrs = {ATTR_DEVICE_CLASS: "some_device_class"}
|
||||
|
||||
"""Detect NEW_NAME significant changes."""
|
||||
attrs = {}
|
||||
assert not async_check_significant_change(None, "on", attrs, "on", attrs)
|
||||
|
||||
assert async_check_significant_change(None, "on", attrs, "off", attrs)
|
||||
|
|
70
tests/components/light/test_significant_change.py
Normal file
70
tests/components/light/test_significant_change.py
Normal file
|
@ -0,0 +1,70 @@
|
|||
"""Test the Light significant change platform."""
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_TEMP,
|
||||
ATTR_EFFECT,
|
||||
ATTR_HS_COLOR,
|
||||
ATTR_WHITE_VALUE,
|
||||
)
|
||||
from homeassistant.components.light.significant_change import (
|
||||
async_check_significant_change,
|
||||
)
|
||||
|
||||
|
||||
async def test_significant_change():
|
||||
"""Detect Light significant changes."""
|
||||
assert not async_check_significant_change(None, "on", {}, "on", {})
|
||||
assert async_check_significant_change(None, "on", {}, "off", {})
|
||||
|
||||
# Brightness
|
||||
assert not async_check_significant_change(
|
||||
None, "on", {ATTR_BRIGHTNESS: 60}, "on", {ATTR_BRIGHTNESS: 61}
|
||||
)
|
||||
assert async_check_significant_change(
|
||||
None, "on", {ATTR_BRIGHTNESS: 60}, "on", {ATTR_BRIGHTNESS: 63}
|
||||
)
|
||||
|
||||
# Color temp
|
||||
assert not async_check_significant_change(
|
||||
None, "on", {ATTR_COLOR_TEMP: 60}, "on", {ATTR_COLOR_TEMP: 64}
|
||||
)
|
||||
assert async_check_significant_change(
|
||||
None, "on", {ATTR_COLOR_TEMP: 60}, "on", {ATTR_COLOR_TEMP: 65}
|
||||
)
|
||||
|
||||
# White value
|
||||
assert not async_check_significant_change(
|
||||
None, "on", {ATTR_WHITE_VALUE: 60}, "on", {ATTR_WHITE_VALUE: 64}
|
||||
)
|
||||
assert async_check_significant_change(
|
||||
None, "on", {ATTR_WHITE_VALUE: 60}, "on", {ATTR_WHITE_VALUE: 65}
|
||||
)
|
||||
|
||||
# Effect
|
||||
for eff1, eff2, expected in (
|
||||
(None, None, False),
|
||||
(None, "colorloop", True),
|
||||
("colorloop", None, True),
|
||||
("colorloop", "jump", True),
|
||||
("colorloop", "colorloop", False),
|
||||
):
|
||||
result = async_check_significant_change(
|
||||
None, "on", {ATTR_EFFECT: eff1}, "on", {ATTR_EFFECT: eff2}
|
||||
)
|
||||
assert result is expected
|
||||
|
||||
# Hue
|
||||
assert not async_check_significant_change(
|
||||
None, "on", {ATTR_HS_COLOR: [120, 20]}, "on", {ATTR_HS_COLOR: [124, 20]}
|
||||
)
|
||||
assert async_check_significant_change(
|
||||
None, "on", {ATTR_HS_COLOR: [120, 20]}, "on", {ATTR_HS_COLOR: [125, 20]}
|
||||
)
|
||||
|
||||
# Satursation
|
||||
assert not async_check_significant_change(
|
||||
None, "on", {ATTR_HS_COLOR: [120, 20]}, "on", {ATTR_HS_COLOR: [120, 22]}
|
||||
)
|
||||
assert async_check_significant_change(
|
||||
None, "on", {ATTR_HS_COLOR: [120, 20]}, "on", {ATTR_HS_COLOR: [120, 23]}
|
||||
)
|
|
@ -34,10 +34,10 @@ async def test_significant_change_temperature():
|
|||
ATTR_UNIT_OF_MEASUREMENT: TEMP_FAHRENHEIT,
|
||||
}
|
||||
assert async_check_significant_change(
|
||||
None, "70", freedom_attrs, "74", freedom_attrs
|
||||
None, "70", freedom_attrs, "71", freedom_attrs
|
||||
)
|
||||
assert not async_check_significant_change(
|
||||
None, "70", freedom_attrs, "71", freedom_attrs
|
||||
None, "70", freedom_attrs, "70.5", freedom_attrs
|
||||
)
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ async def test_significant_change_battery():
|
|||
ATTR_DEVICE_CLASS: DEVICE_CLASS_BATTERY,
|
||||
}
|
||||
assert not async_check_significant_change(None, "100", attrs, "100", attrs)
|
||||
assert async_check_significant_change(None, "100", attrs, "97", attrs)
|
||||
assert async_check_significant_change(None, "100", attrs, "99", attrs)
|
||||
|
||||
|
||||
async def test_significant_change_humidity():
|
||||
|
@ -56,4 +56,4 @@ async def test_significant_change_humidity():
|
|||
ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY,
|
||||
}
|
||||
assert not async_check_significant_change(None, "100", attrs, "100", attrs)
|
||||
assert async_check_significant_change(None, "100", attrs, "97", attrs)
|
||||
assert async_check_significant_change(None, "100", attrs, "99", attrs)
|
||||
|
|
Loading…
Add table
Reference in a new issue