def async_check_significant_change( hass: HomeAssistant, old_state: str, old_attrs: dict, new_state: str, new_attrs: dict, **kwargs: Any, ) -> bool | None: """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 old_color and new_color: # Range 0..360 if check_absolute_change(old_color[0], new_color[0], 5): return True # Range 0..100 if check_absolute_change(old_color[1], new_color[1], 3): return True if check_absolute_change(old_attrs.get(ATTR_BRIGHTNESS), new_attrs.get(ATTR_BRIGHTNESS), 3): return True if check_absolute_change( # Default range 153..500 old_attrs.get(ATTR_COLOR_TEMP), new_attrs.get(ATTR_COLOR_TEMP), 5, ): return True if check_absolute_change( # Range 0..255 old_attrs.get(ATTR_WHITE_VALUE), new_attrs.get(ATTR_WHITE_VALUE), 5, ): return True return False
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)
def async_check_significant_change( hass: HomeAssistant, old_state: str, old_attrs: dict, new_state: str, new_attrs: dict, **kwargs: Any, ) -> bool | None: """Test if state significantly changed.""" device_class = new_attrs.get(ATTR_DEVICE_CLASS) if device_class is None: return None absolute_change: float | None = None percentage_change: float | None = None if device_class == DEVICE_CLASS_TEMPERATURE: if new_attrs.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_FAHRENHEIT: absolute_change = 1.0 else: absolute_change = 0.5 if device_class in (DEVICE_CLASS_BATTERY, DEVICE_CLASS_HUMIDITY): absolute_change = 1.0 if device_class in ( DEVICE_CLASS_AQI, DEVICE_CLASS_CO, DEVICE_CLASS_CO2, DEVICE_CLASS_PM25, DEVICE_CLASS_PM10, DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS, ): absolute_change = 1.0 percentage_change = 2.0 if absolute_change is not None and percentage_change is not None: return _absolute_and_relative_change(float(old_state), float(new_state), absolute_change, percentage_change) if absolute_change is not None: return check_absolute_change(float(old_state), float(new_state), absolute_change) return None
if device_class == SensorDeviceClass.TEMPERATURE: if new_attrs.get(ATTR_UNIT_OF_MEASUREMENT) == TEMP_FAHRENHEIT: absolute_change = 1.0 else: absolute_change = 0.5 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 if absolute_change is not None and percentage_change is not None: return _absolute_and_relative_change( float(old_state), float(new_state), absolute_change, percentage_change ) if absolute_change is not None: return check_absolute_change( float(old_state), float(new_state), absolute_change ) return None
SensorDeviceClass.AQI, SensorDeviceClass.CO, SensorDeviceClass.CO2, SensorDeviceClass.PM25, SensorDeviceClass.PM10, SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS, ): absolute_change = 1.0 percentage_change = 2.0 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) return None