This commit is contained in:
Bas Nijholt 2020-10-04 23:15:12 +02:00
commit c245298512
4 changed files with 44 additions and 23 deletions

View file

@ -14,6 +14,7 @@ from .const import ( # pylint: disable=unused-import
NONE_STR,
VALIDATION_TUPLES,
)
from .switch import _supported_features
_LOGGER = logging.getLogger(__name__)
@ -89,10 +90,12 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
if not errors:
return self.async_create_entry(title="", data=user_input)
all_lights = sorted(self.hass.states.async_entity_ids("light"))
to_replace = {
CONF_LIGHTS: cv.multi_select(all_lights),
}
all_lights = [
light
for light in self.hass.states.async_entity_ids("light")
if _supported_features(self.hass, light)
]
to_replace = {CONF_LIGHTS: cv.multi_select(sorted(all_lights))}
options_schema = {}
for name, default, validation in VALIDATION_TUPLES:

View file

@ -38,8 +38,8 @@
"sunrise_time": "sunrise_time, in 'HH:MM:SS' format",
"sunset_offset": "sunset_offset, in +/- seconds",
"sunset_time": "sunset_time, in 'HH:MM:SS' format",
"take_over_control": "take_over_control, if manually adjusting the lights when they are already on",
"detect_non_ha_changes": "detect_non_ha_changes, detect changes to lights made outside of HA (calls 'homeassistant.update_entity'!)",
"take_over_control": "take_over_control, if anything but Adaptive Lighting calls 'light.turn_on' when a light is already on, stop adapting that light until it (or the switch) toggles off -> on.",
"detect_non_ha_changes": "detect_non_ha_changes, detects all >5% changes made to the lights (also outside of HA), requires 'take_over_control' to be enabled (calls 'homeassistant.update_entity' every 'interval'!)",
"transition": "transition, in seconds"
}
}

View file

@ -218,9 +218,12 @@ def _supported_features(hass, light: str):
return {key for key, value in _SUPPORT_OPTS.items() if supported_features & value}
def abs_rel_diff(a, b):
def abs_rel_diff(val_a, val_b):
"""Absolute relative difference in %."""
return abs((a - b) / b) * 100
if val_b == 0:
# To avoid ZeroDivisionError
val_b = 1e-6
return abs((val_a - val_b) / val_b) * 100
class AdaptiveSwitch(SwitchEntity, RestoreEntity):
@ -382,9 +385,6 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
return {key: None for key in self._settings}
return self._settings
def _reset_take_over_control(self):
self.turn_on_off_listener.reset(*self._lights)
async def async_turn_on( # pylint: disable=arguments-differ
self, adapt_lights: bool = True
) -> None:
@ -395,7 +395,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
if self.is_on:
return
self._state = True
self._reset_take_over_control()
self.turn_on_off_listener.reset(*self._lights)
await self._setup_listeners()
if adapt_lights:
await self._update_attrs_and_maybe_adapt_lights(
@ -408,7 +408,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
return
self._state = False
self._remove_listeners()
self._reset_take_over_control()
self.turn_on_off_listener.reset(*self._lights)
async def _async_update_at_interval(self, now=None) -> None:
await self._update_attrs_and_maybe_adapt_lights(force=False)
@ -467,6 +467,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
self._adapt_brightness,
self._adapt_color_temp,
self._adapt_rgb_color,
self.__context,
)
):
return
@ -534,7 +535,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
if not match_state_event(event, ("on", "off")):
return
_LOGGER.debug("%s: _sleep_state_event, event: '%s'", self._name, event)
self._reset_take_over_control()
self.turn_on_off_listener.reset(*self._lights)
await self._update_attrs_and_maybe_adapt_lights(
transition=self._initial_transition, force=True
)
@ -552,6 +553,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity):
_LOGGER.debug(
"%s: Detected an 'off''on' event for '%s'", self._name, entity_id
)
self.turn_on_off_listener.reset(entity_id)
# Tracks 'off' → 'on' state changes
self._off_to_on_event[entity_id] = event
lock = self._locks.get(entity_id)
@ -867,7 +869,13 @@ class TurnOnOffListener:
return manually_controlled
async def significant_change(
self, light, adapt_brightness, adapt_color_temp, adapt_rgb_color, threshold=5
self,
light,
adapt_brightness,
adapt_color_temp,
adapt_rgb_color,
context,
threshold=5,
):
"""Has the light made a significant change since last update.
@ -885,6 +893,7 @@ class TurnOnOffListener:
SERVICE_UPDATE_ENTITY,
{ATTR_ENTITY_ID: light},
blocking=True,
context=context,
)
attributes = self.hass.states.get(light).attributes
if (
@ -895,7 +904,12 @@ class TurnOnOffListener:
applied_brightness = round(255 * service_data[ATTR_BRIGHTNESS_PCT] / 100)
current_brightness = attributes["brightness"]
if abs_rel_diff(current_brightness, applied_brightness) > threshold:
_LOGGER.debug("Brightness of '%s' significantly changed", light)
_LOGGER.debug(
"Brightness of '%s' significantly changed from %s to %s",
light,
applied_brightness,
current_brightness,
)
changed = True
if (
@ -907,8 +921,10 @@ class TurnOnOffListener:
current_color_temp = attributes[ATTR_COLOR_TEMP]
if abs_rel_diff(current_color_temp, applied_color_temp) > threshold:
_LOGGER.debug(
"Color temperature of '%s' significantly changed",
"Color temperature of '%s' significantly changed from %s to %s",
light,
applied_color_temp,
current_color_temp,
)
changed = True
@ -922,8 +938,10 @@ class TurnOnOffListener:
for col_applied, col_current in zip(applied_rgb_color, current_rgb_color):
if abs_rel_diff(col_applied, col_current) > threshold:
_LOGGER.debug(
"color RGB of '%s' significantly changed",
"color RGB of '%s' significantly changed from %s to %s",
light,
applied_rgb_color,
current_rgb_color,
)
changed = True
break
@ -962,8 +980,7 @@ class TurnOnOffListener:
id_on_to_off = on_to_off_event.context.id
turn_off_event = self.turn_off_event.get(entity_id)
id_turn_off = turn_off_event.context.id
transition = turn_off_event.data[ATTR_SERVICE_DATA].get(ATTR_TRANSITION)
transition = turn_off_event.data.get(ATTR_SERVICE_DATA, {}).get(ATTR_TRANSITION)
turn_on_event = self.turn_on_event.get(entity_id)
id_turn_on = turn_on_event.context.id
@ -975,7 +992,8 @@ class TurnOnOffListener:
return False
if (
id_on_to_off == id_turn_off
turn_off_event is not None
and id_on_to_off == turn_off_event.context.id
and id_on_to_off is not None
and transition is not None # 'turn_off' is called with transition=...
):

View file

@ -38,8 +38,8 @@
"sunrise_time": "sunrise_time, in 'HH:MM:SS' format",
"sunset_offset": "sunset_offset, in +/- seconds",
"sunset_time": "sunset_time, in 'HH:MM:SS' format",
"take_over_control": "take_over_control, if manually adjusting the lights when they are already on",
"detect_non_ha_changes": "detect_non_ha_changes, detect changes to lights made outside of HA (calls 'homeassistant.update_entity'!)",
"take_over_control": "take_over_control, if anything but Adaptive Lighting calls 'light.turn_on' when a light is already on, stop adapting that light until it (or the switch) toggles off -> on.",
"detect_non_ha_changes": "detect_non_ha_changes, detects all >5% changes made to the lights (also outside of HA), requires 'take_over_control' to be enabled (calls 'homeassistant.update_entity' every 'interval'!)",
"transition": "transition, in seconds"
}
}