Home Assistant Unofficial Reference 2024.12.1
significant_change.py
Go to the documentation of this file.
1 """Helper to test significant Climate state changes."""
2 
3 from __future__ import annotations
4 
5 from typing import Any
6 
7 from homeassistant.const import UnitOfTemperature
8 from homeassistant.core import HomeAssistant, callback
10  check_absolute_change,
11  check_valid_float,
12 )
13 
14 from . import (
15  ATTR_AUX_HEAT,
16  ATTR_CURRENT_HUMIDITY,
17  ATTR_CURRENT_TEMPERATURE,
18  ATTR_FAN_MODE,
19  ATTR_HUMIDITY,
20  ATTR_HVAC_ACTION,
21  ATTR_PRESET_MODE,
22  ATTR_SWING_HORIZONTAL_MODE,
23  ATTR_SWING_MODE,
24  ATTR_TARGET_TEMP_HIGH,
25  ATTR_TARGET_TEMP_LOW,
26  ATTR_TEMPERATURE,
27 )
28 
29 SIGNIFICANT_ATTRIBUTES: set[str] = {
30  ATTR_AUX_HEAT,
31  ATTR_CURRENT_HUMIDITY,
32  ATTR_CURRENT_TEMPERATURE,
33  ATTR_FAN_MODE,
34  ATTR_HUMIDITY,
35  ATTR_HVAC_ACTION,
36  ATTR_PRESET_MODE,
37  ATTR_SWING_MODE,
38  ATTR_SWING_HORIZONTAL_MODE,
39  ATTR_TARGET_TEMP_HIGH,
40  ATTR_TARGET_TEMP_LOW,
41  ATTR_TEMPERATURE,
42 }
43 
44 
45 @callback
47  hass: HomeAssistant,
48  old_state: str,
49  old_attrs: dict,
50  new_state: str,
51  new_attrs: dict,
52  **kwargs: Any,
53 ) -> bool | None:
54  """Test if state significantly changed."""
55  if old_state != new_state:
56  return True
57 
58  old_attrs_s = set(
59  {k: v for k, v in old_attrs.items() if k in SIGNIFICANT_ATTRIBUTES}.items()
60  )
61  new_attrs_s = set(
62  {k: v for k, v in new_attrs.items() if k in SIGNIFICANT_ATTRIBUTES}.items()
63  )
64 
65  changed_attrs: set[str] = {item[0] for item in old_attrs_s ^ new_attrs_s}
66  ha_unit = hass.config.units.temperature_unit
67 
68  for attr_name in changed_attrs:
69  if attr_name in [
70  ATTR_AUX_HEAT,
71  ATTR_FAN_MODE,
72  ATTR_HVAC_ACTION,
73  ATTR_PRESET_MODE,
74  ATTR_SWING_MODE,
75  ATTR_SWING_HORIZONTAL_MODE,
76  ]:
77  return True
78 
79  old_attr_value = old_attrs.get(attr_name)
80  new_attr_value = new_attrs.get(attr_name)
81  if new_attr_value is None or not check_valid_float(new_attr_value):
82  # New attribute value is invalid, ignore it
83  continue
84 
85  if old_attr_value is None or not check_valid_float(old_attr_value):
86  # Old attribute value was invalid, we should report again
87  return True
88 
89  absolute_change: float | None = None
90  if attr_name in [
91  ATTR_CURRENT_TEMPERATURE,
92  ATTR_TARGET_TEMP_HIGH,
93  ATTR_TARGET_TEMP_LOW,
94  ATTR_TEMPERATURE,
95  ]:
96  if ha_unit == UnitOfTemperature.FAHRENHEIT:
97  absolute_change = 1.0
98  else:
99  absolute_change = 0.5
100 
101  if attr_name in [ATTR_CURRENT_HUMIDITY, ATTR_HUMIDITY]:
102  absolute_change = 1.0
103 
104  if absolute_change and check_absolute_change(
105  old_attr_value, new_attr_value, absolute_change
106  ):
107  return True
108 
109  # no significant attribute change detected
110  return False
bool|None async_check_significant_change(HomeAssistant hass, str old_state, dict old_attrs, str new_state, dict new_attrs, **Any kwargs)
bool check_absolute_change(float|None val1, float|None val2, float change)