Skip to content

Commit

Permalink
Implement call intercept for multiple lights (#679)
Browse files Browse the repository at this point in the history
* Implement call intercept for multiple lights

* remove comment

* skip if no eids

* add comment

* fix type

* Fix skipped

* indentation

* Add logging and fix error

* Fix for HA ≤2023.04

* simplify

* remove unused ignores

* Debug mode

* Add test

* Make test failing

* rename switch

* rename lights

* Fix tests

* Rename lights in tests

* Remove unused dependencies

* Improve tests

* More tests

* Remove the DEBUG_MODE

* Add doc-string

* Extra test

* assert

* extra test

* Comments

* fix

* fix

* expand light groups

* more logging

* sort

* Revert is_proactively_adapting checks
This reverts commit 39fd8f2.

* simplify the mapping

* Revert "Revert is_proactively_adapting checks"

This reverts commit 18803e8.

* test

* no light groups

* do not expand

* Do not expand_light_groups in intercept

* more logging

* Fix

* add comment

* Add multi_light_intercept config option

* Update README.md, strings.json, and services.yaml

* add light group

* fix platform

* add simple test

* turn off again

* Test without take over control

* improve test and fix it in one way

* Fixes

* add cleanup fixture

* format

* Update test_switch.py

* add __str__

* remove unneeded call

* simplify service_data construction

* Generalize is_our_context

* Fix multi_light_intercept: false

* add comments

* add docs

* Update README.md, strings.json, and services.yaml

* Add feature line

* move function

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
basnijholt and github-actions[bot] authored Aug 4, 2023
1 parent 4251cca commit 1ef7ed5
Show file tree
Hide file tree
Showing 8 changed files with 646 additions and 120 deletions.
2 changes: 1 addition & 1 deletion .ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ ignore = [
"FBT002", # Boolean default value in function definition
"FIX004", # Line contains HACK, consider resolving the issue
"PD901", # df is a bad variable name. Be kinder to your future self.
"PERF203",# `try`-`except` within a loop incurs performance overhead
"PERF203", # `try`-`except` within a loop incurs performance overhead
"PLR0913", # Too many arguments to function call (N > 5)
"PLR2004", # Magic value used in comparison, consider replacing X with a constant variable
"S101", # Use of assert detected
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ In addition to its regular mode, Adaptive Lighting also offers a "sleep mode"

## :bulb: Features

When initially turning on a light that is controlled by Adaptive Lighting, the `light.turn_on` service call is intercepted, and the light's brightness and color are automatically adjusted based on the sun's position.
After that, the light's brightness and color are automatically adjusted at a regular interval.

Adaptive Lighting provides four switches (using "living_room" as an example component name):

- `switch.adaptive_lighting_living_room`: Turn Adaptive Lighting on or off and view current light settings through its attributes.
Expand Down Expand Up @@ -124,7 +127,8 @@ The YAML and frontend configuration methods support all of the options listed be
| `send_split_delay` | Delay (ms) between `separate_turn_on_commands` for lights that don't support simultaneous brightness and color setting. ⏲️ | `0` | `int` 0-10000 |
| `adapt_delay` | Wait time (seconds) between light turn on and Adaptive Lighting applying changes. Might help to avoid flickering. ⏲️ | `0` | `float > 0` |
| `autoreset_control_seconds` | Automatically reset the manual control after a number of seconds. Set to 0 to disable. ⏲️ | `0` | `int` 0-31536000 |
| `skip_redundant_commands` | Skip sending adaptation commands whose target state already equals the light's known state. Minimizes network traffic and improves the adaptation responsivity in some situations. Disable if physical light states get out of sync with HA's recorded state. | `False` | `bool` |
| `skip_redundant_commands` | Skip sending adaptation commands whose target state already equals the light's known state. Minimizes network traffic and improves the adaptation responsivity in some situations. 📉Disable if physical light states get out of sync with HA's recorded state. | `False` | `bool` |
| `multi_light_intercept` | Intercept and adapt `light.turn_on` calls that target multiple lights. ➗⚠️ This might result in splitting up a single `light.turn_on` call into multiple calls, e.g., when lights are in different switches. | `True` | `bool` |

<!-- END_OUTPUT -->

Expand Down
14 changes: 14 additions & 0 deletions custom_components/adaptive_lighting/adaptation_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,20 @@ async def next_service_call_data(self) -> ServiceData | None:
"""Return data for the next service call, or none if no more data exists."""
return await anext(self.service_call_datas, None)

def __str__(self) -> str:
"""Return a string representation of the data."""
return (
f"{self.__class__.__name__}("
f"entity_id={self.entity_id}, "
f"context_id={self.context.id}, "
f"sleep_time={self.sleep_time}, "
f"force={self.force}, "
f"max_length={self.max_length}, "
f"which={self.which}, "
f"initial_sleep={self.initial_sleep}"
")"
)


class NoColorOrBrightnessInServiceDataError(Exception):
"""Exception raised when no color or brightness attributes are found in service data."""
Expand Down
13 changes: 12 additions & 1 deletion custom_components/adaptive_lighting/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,20 @@
DOCS[CONF_SKIP_REDUNDANT_COMMANDS] = (
"Skip sending adaptation commands whose target state already "
"equals the light's known state. Minimizes network traffic and improves the "
"adaptation responsivity in some situations. "
"adaptation responsivity in some situations. 📉"
"Disable if physical light states get out of sync with HA's recorded state."
)

CONF_MULTI_LIGHT_INTERCEPT, DEFAULT_MULTI_LIGHT_INTERCEPT = (
"multi_light_intercept",
True,
)
DOCS[CONF_MULTI_LIGHT_INTERCEPT] = (
"Intercept and adapt `light.turn_on` calls that target multiple lights. ➗"
"⚠️ This might result in splitting up a single `light.turn_on` call "
"into multiple calls, e.g., when lights are in different switches."
)

SLEEP_MODE_SWITCH = "sleep_mode_switch"
ADAPT_COLOR_SWITCH = "adapt_color_switch"
ADAPT_BRIGHTNESS_SWITCH = "adapt_brightness_switch"
Expand Down Expand Up @@ -290,6 +300,7 @@ def int_between(min_int, max_int):
DEFAULT_SKIP_REDUNDANT_COMMANDS,
bool,
),
(CONF_MULTI_LIGHT_INTERCEPT, DEFAULT_MULTI_LIGHT_INTERCEPT, bool),
]


Expand Down
3 changes: 2 additions & 1 deletion custom_components/adaptive_lighting/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
"send_split_delay": "send_split_delay: Delay (ms) between `separate_turn_on_commands` for lights that don't support simultaneous brightness and color setting. ⏲️",
"adapt_delay": "adapt_delay: Wait time (seconds) between light turn on and Adaptive Lighting applying changes. Might help to avoid flickering. ⏲️",
"autoreset_control_seconds": "autoreset_control_seconds: Automatically reset the manual control after a number of seconds. Set to 0 to disable. ⏲️",
"skip_redundant_commands": "skip_redundant_commands: Skip sending adaptation commands whose target state already equals the light's known state. Minimizes network traffic and improves the adaptation responsivity in some situations. Disable if physical light states get out of sync with HA's recorded state."
"skip_redundant_commands": "skip_redundant_commands: Skip sending adaptation commands whose target state already equals the light's known state. Minimizes network traffic and improves the adaptation responsivity in some situations. 📉Disable if physical light states get out of sync with HA's recorded state.",
"multi_light_intercept": "multi_light_intercept: Intercept and adapt `light.turn_on` calls that target multiple lights. ➗⚠️ This might result in splitting up a single `light.turn_on` call into multiple calls, e.g., when lights are in different switches."
}
}
},
Expand Down
Loading

0 comments on commit 1ef7ed5

Please sign in to comment.