Automatically generate more service tables in the README (#509)

* Automatically sync more data

* Automatically generate apply table

* Generate manual control

* Add manual control docs

* Update README.md

* Move docs functions to separate file

* Update code

* simple

* no path

* link paths

* Fix link

* missed

* cd core

* Update README.md

* Allow alternative docs

* update readme

* More special

* Fx

* Update README.md

* Remove common descriptions

* Update README.md

* Update README.md

* Rephrase

* Update README.md

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Bas Nijholt 2023-04-03 00:58:39 -07:00 committed by GitHub
commit 19fcb1d6b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 333 additions and 211 deletions

View file

@ -31,8 +31,8 @@ jobs:
echo "::notice::### 4. ERROR:homeassistant.setup:Setup failed for 'component': Unable to import component: No module named ''module'' ###"
echo "::notice::### 5. add 'component'.'module' (without the '') from the above log into the 'required' list inside of 'test_dependencies.py' ###"
echo "::notice::### 6. Try again! If more issues persist they should be easily solvable by reading the verbose logs now. ###"
- name: Run pytest
timeout-minutes: 60
- name: Link custom_components/adaptive_lighting
run: |
cd core
@ -46,6 +46,10 @@ jobs:
ln -fs ../../../tests adaptive_lighting
cd -
- name: Run pytest
timeout-minutes: 60
run: |
cd core
python3 -X dev -m pytest \
-qq \
--timeout=9 \

View file

@ -22,10 +22,15 @@ jobs:
with:
python_version: "3.10"
- name: Install pandas and tabulate
- name: Install markdown-code-runner and README code dependencies
run: |
pip install markdown-code-runner pandas tabulate
- name: Link custom_components/adaptive_lighting
run: |
cd core/homeassistant/components
ln -fs ../../../custom_components/adaptive_lighting adaptive_lighting
- name: Run markdown-code-runner
run: markdown-code-runner --debug README.md

View file

@ -82,11 +82,8 @@ All of the configuration options are listed below, along with their default valu
The YAML and frontend configuration methods support all of the options listed below.
<!-- START_CODE -->
<!-- import os, sys -->
<!-- sys.path.append(os.path.abspath(".")) -->
<!-- from custom_components.adaptive_lighting import const -->
<!-- markdown_table = const.generate_markdown_table() -->
<!-- print(markdown_table) -->
<!-- from homeassistant.components.adaptive_lighting import _docs_helpers -->
<!-- print(_docs_helpers.generate_config_markdown_table()) -->
<!-- END_CODE -->
<!-- START_OUTPUT -->
@ -94,27 +91,27 @@ The YAML and frontend configuration methods support all of the options listed be
| Variable name | Description | Default | Type |
|:-------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------|:-------------------------------------|
| `lights` | List of light entities to be controlled by Adaptive Lighting (may be empty). 🌟 | `[]` | list of `entity_id`s |
| `prefer_rgb_color` | Use RGB color adjustment instead of native light color temperature. 🌈 | `False` | `bool` |
| `prefer_rgb_color` | Whether to prefer RGB color adjustment over light color temperature when possible. 🌈 | `False` | `bool` |
| `include_config_in_attributes` | Show all options as attributes on the switch in Home Assistant when set to `true`. 📝 | `False` | `bool` |
| `adapt_until_sleep` | When `true`, Adaptive Lighting will use the sleep settings as the minimum, and transition to these values past the sunset | `False` | `bool` |
| `initial_transition` | Duration of the first transition when lights turn from `off` to `on`. ⏲️ | `1` | `float` 0-6553 |
| `sleep_transition` | Duration of transition when 'sleep mode' is toggled. 😴 | `1` | `float` 0-6553 |
| `initial_transition` | Duration of the first transition when lights turn from `off` to `on` in seconds. ⏲️ | `1` | `float` 0-6553 |
| `sleep_transition` | Duration of transition when 'sleep mode' is toggled in seconds. 😴 | `1` | `float` 0-6553 |
| `transition` | Duration of transition when lights change, in seconds. 🕑 | `45` | `float` 0-6553 |
| `transition_until_sleep` | When enabled, Adaptive Lighting will treat sleep settings as the minimum, transitioning to these values after sunset. 🌙 | `False` | `bool` |
| `interval` | Frequency to adapt the lights, in seconds. 🔄 | `90` | `int > 0` |
| `min_brightness` | Minimum brightness percentage. 💡 | `1` | `int` 1-100 |
| `max_brightness` | Maximum brightness percentage. 💡 | `100` | `int` 1-100 |
| `min_color_temp` | Warmest color temperature in Kelvin. 🔥 | `2000` | `int` 1000-10000 |
| `max_color_temp` | Coldest color temperature in Kelvin. ❄️ | `5500` | `int` 1000-10000 |
| `sleep_brightness` | Brightness of lights in sleep mode. 😴 | `1` | `int` 1-100 |
| `sleep_brightness` | Brightness percentage of lights in sleep mode. 😴 | `1` | `int` 1-100 |
| `sleep_rgb_or_color_temp` | Use either `'rgb_color'` or `'color_temp'` in sleep mode. 🌙 | `color_temp` | one of `['color_temp', 'rgb_color']` |
| `sleep_color_temp` | Color temperature in sleep mode (used when `sleep_rgb_or_color_temp` is `color_temp`). 😴 | `1000` | `int` 1000-10000 |
| `sleep_color_temp` | Color temperature in sleep mode (used when `sleep_rgb_or_color_temp` is `color_temp`) in Kelvin. 😴 | `1000` | `int` 1000-10000 |
| `sleep_rgb_color` | RGB color in sleep mode (used when `sleep_rgb_or_color_temp` is 'rgb_color'). 🌈 | `[255, 56, 0]` | RGB color |
| `sunrise_time` | Set a fixed time for sunrise. 🌅 | `None` | `str` |
| `max_sunrise_time` | Set the latest virtual sunrise time, allowing for earlier real sunrises. 🌅 | `None` | `str` |
| `sunrise_offset` | Adjust sunrise time with a positive or negative offset. ⏰ | `0` | `int` |
| `sunset_time` | Set a fixed time for sunset. 🌇 | `None` | `str` |
| `min_sunset_time` | Set the earliest virtual sunset time, allowing for later real sunsets. 🌇 | `None` | `str` |
| `sunset_offset` | Adjust sunset time with a positive or negative offset. ⏰ | `0` | `int` |
| `sunrise_time` | Set a fixed time (HH:MM:SS) for sunrise. 🌅 | `None` | `str` |
| `max_sunrise_time` | Set the latest virtual sunrise time (HH:MM:SS), allowing for earlier real sunrises. 🌅 | `None` | `str` |
| `sunrise_offset` | Adjust sunrise time with a positive or negative offset in seconds. ⏰ | `0` | `int` |
| `sunset_time` | Set a fixed time (HH:MM:SS) for sunset. 🌇 | `None` | `str` |
| `min_sunset_time` | Set the earliest virtual sunset time (HH:MM:SS), allowing for later real sunsets. 🌇 | `None` | `str` |
| `sunset_offset` | Adjust sunset time with a positive or negative offset in seconds. ⏰ | `0` | `int` |
| `only_once` | Adapt lights only when they are turned on (`true`) or keep adapting them (`false`). 🔄 | `False` | `bool` |
| `take_over_control` | Disable Adaptive Lighting if another source calls `light.turn_on` while lights are on and being adapted. Note that this calls `homeassistant.update_entity` every `interval`! 🔒 | `True` | `bool` |
| `detect_non_ha_changes` | Detect non-`light.turn_on` state changes and stop adapting lights. Requires `take_over_control`. 🕵️ | `False` | `bool` |
@ -158,26 +155,42 @@ adaptive_lighting:
`adaptive_lighting.apply` applies Adaptive Lighting settings to lights on demand.
| Service data attribute | Required | Description |
| ---------------------- | -------- | -------------------------------------------------------------------------------------------- |
| `entity_id` | ✅ | The `entity_id` of the switch with the settings to apply. |
| `lights` | ❌ | A light (or list of lights) to apply the settings to. |
| `transition` | ❌ | The number of seconds for the transition. |
| `adapt_brightness` | ❌ | Whether to change the brightness of the light or not. |
| `adapt_color` | ❌ | Whether to adapt the color on supporting lights. |
| `prefer_rgb_color` | ❌ | Whether to prefer RGB color adjustment over of native light color temperature when possible. |
| `turn_on_lights` | ❌ | Whether to turn on lights that are currently off. |
<!-- START_CODE -->
<!-- from homeassistant.components.adaptive_lighting import _docs_helpers -->
<!-- print(_docs_helpers.generate_apply_markdown_table()) -->
<!-- END_CODE -->
<!-- START_OUTPUT -->
<!-- THIS CONTENT IS AUTOMATICALLY GENERATED -->
| Service data attribute | Description | Required | Type |
|:-------------------------|:-------------------------------------------------------------------------------------|:-----------|:---------------------|
| `entity_id` | The `entity_id` of the switch with the settings to apply. 📝 | ✅ | list of `entity_id`s |
| `lights` | A light (or list of lights) to apply the settings to. 💡 | ❌ | list of `entity_id`s |
| `transition` | Duration of transition when lights change, in seconds. 🕑 | ❌ | `float` 0-6553 |
| `adapt_brightness` | Whether to adapt the brightness of the light. 🌞 | ❌ | bool |
| `adapt_color` | Whether to adapt the color on supporting lights. 🌈 | ❌ | bool |
| `prefer_rgb_color` | Whether to prefer RGB color adjustment over light color temperature when possible. 🌈 | ❌ | bool |
| `turn_on_lights` | Whether to turn on lights that are currently off. 🔆 | ❌ | bool |
<!-- END_OUTPUT -->
#### `adaptive_lighting.set_manual_control`
`adaptive_lighting.set_manual_control` can mark (or unmark) whether a light is "manually controlled", meaning that when a light has `manual_control`, the light is not adapted.
| Service data attribute | Required | Description |
| ---------------------- | -------- | --------------------------------------------------------------------------------------------------- |
| `entity_id` | ✅ | The `entity_id` of the switch in which to (un)mark the light as being "manually controlled". |
| `lights` | ❌ | entity_id(s) of lights, if not specified, all lights in the switch are selected. |
| `manual_control` | ❌ | Whether to add ('true') or remove ('false') the light from the 'manual_control' list, default: true |
<!-- START_CODE -->
<!-- from homeassistant.components.adaptive_lighting import _docs_helpers -->
<!-- print(_docs_helpers.generate_set_manual_control_markdown_table()) -->
<!-- END_CODE -->
<!-- START_OUTPUT -->
<!-- THIS CONTENT IS AUTOMATICALLY GENERATED -->
| Service data attribute | Description | Required | Type |
|:-------------------------|:-----------------------------------------------------------------------------------------------|:-----------|:---------------------|
| `entity_id` | The `entity_id` of the switch in which to (un)mark the light as being `manually controlled`. 📝 | ✅ | list of `entity_id`s |
| `lights` | entity_id(s) of lights, if not specified, all lights in the switch are selected. 💡 | ❌ | list of `entity_id`s |
| `manual_control` | Whether to add ('true') or remove ('false') the light from the 'manual_control' list. 🔒 | ❌ | bool |
<!-- END_OUTPUT -->
#### `adaptive_lighting.change_switch_settings`
`adaptive_lighting.change_switch_settings` (new in 1.7.0) Change any of the above configuration options of Adaptive Lighting (such as `sunrise_time` or `prefer_rgb_color`) with a service call directly from your script/automation.

View file

@ -0,0 +1,116 @@
from typing import Any
from homeassistant.helpers import selector
import homeassistant.helpers.config_validation as cv
import pandas as pd
import voluptuous as vol
from .const import (
DOCS,
DOCS_APPLY,
DOCS_MANUAL_CONTROL,
SET_MANUAL_CONTROL_SCHEMA,
VALIDATION_TUPLES,
apply_service_schema,
)
def _format_voluptuous_instance(instance):
coerce_type = None
min_val = None
max_val = None
for validator in instance.validators:
if isinstance(validator, vol.Coerce):
coerce_type = validator.type.__name__
elif isinstance(validator, (vol.Clamp, vol.Range)):
min_val = validator.min
max_val = validator.max
if min_val is not None and max_val is not None:
return f"`{coerce_type}` {min_val}-{max_val}"
elif min_val is not None:
return f"`{coerce_type} > {min_val}`"
elif max_val is not None:
return f"`{coerce_type} < {max_val}`"
else:
return f"`{coerce_type}`"
def _type_to_str(type_: Any) -> str:
"""Convert a (voluptuous) type to a string."""
if type_ == cv.entity_ids:
return "list of `entity_id`s"
elif type_ in (bool, int, float, str):
return f"`{type_.__name__}`"
elif type_ == cv.boolean:
return "bool"
elif isinstance(type_, vol.All):
return _format_voluptuous_instance(type_)
elif isinstance(type_, vol.In):
return f"one of `{type_.container}`"
elif isinstance(type_, selector.SelectSelector):
return f"one of `{type_.config['options']}`"
elif isinstance(type_, selector.ColorRGBSelector):
return "RGB color"
else:
raise ValueError(f"Unknown type: {type_}")
def generate_config_markdown_table():
import pandas as pd
rows = []
for k, default, type_ in VALIDATION_TUPLES:
description = DOCS[k]
row = {
"Variable name": f"`{k}`",
"Description": description,
"Default": f"`{default}`",
"Type": _type_to_str(type_),
}
rows.append(row)
df = pd.DataFrame(rows)
return df.to_markdown(index=False)
def _schema_to_dict(schema: vol.Schema) -> dict[str, tuple[Any, Any]]:
result = {}
for key, value in schema.schema.items():
if isinstance(key, vol.Optional):
default_value = key.default
result[key.schema] = (default_value, value)
return result
def _generate_service_markdown_table(
schema: dict[str, tuple[Any, Any]], alternative_docs: dict[str, str] = None
):
schema = _schema_to_dict(schema)
rows = []
for k, (default, type_) in schema.items():
if alternative_docs is not None and k in alternative_docs:
description = alternative_docs[k]
else:
description = DOCS[k]
row = {
"Service data attribute": f"`{k}`",
"Description": description,
"Required": "" if default == vol.UNDEFINED else "",
"Type": _type_to_str(type_),
}
rows.append(row)
df = pd.DataFrame(rows)
return df.to_markdown(index=False)
def generate_apply_markdown_table():
return _generate_service_markdown_table(apply_service_schema(), DOCS_APPLY)
def generate_set_manual_control_markdown_table():
return _generate_service_markdown_table(
SET_MANUAL_CONTROL_SCHEMA, DOCS_MANUAL_CONTROL
)

View file

@ -1,6 +1,7 @@
"""Constants for the Adaptive Lighting integration."""
from homeassistant.components.light import VALID_TRANSITION
from homeassistant.const import CONF_ENTITY_ID
from homeassistant.helpers import selector
import homeassistant.helpers.config_validation as cv
import voluptuous as vol
@ -14,7 +15,7 @@ DOMAIN = "adaptive_lighting"
SUN_EVENT_NOON = "solar_noon"
SUN_EVENT_MIDNIGHT = "solar_midnight"
DOCS = {}
DOCS = {CONF_ENTITY_ID: "Entity ID of the switch. 📝"}
CONF_NAME, DEFAULT_NAME = "name", "default"
@ -45,11 +46,14 @@ DOCS[CONF_INCLUDE_CONFIG_IN_ATTRIBUTES] = (
CONF_INITIAL_TRANSITION, DEFAULT_INITIAL_TRANSITION = "initial_transition", 1
DOCS[CONF_INITIAL_TRANSITION] = (
"Duration of the first transition when lights turn " "from `off` to `on`. ⏲️"
"Duration of the first transition when lights turn "
"from `off` to `on` in seconds. ⏲️"
)
CONF_SLEEP_TRANSITION, DEFAULT_SLEEP_TRANSITION = "sleep_transition", 1
DOCS[CONF_SLEEP_TRANSITION] = "Duration of transition when 'sleep mode' is toggled. 😴"
DOCS[CONF_SLEEP_TRANSITION] = (
"Duration of transition when 'sleep mode' is toggled " "in seconds. 😴"
)
CONF_INTERVAL, DEFAULT_INTERVAL = "interval", 90
DOCS[CONF_INTERVAL] = "Frequency to adapt the lights, in seconds. 🔄"
@ -73,9 +77,10 @@ DOCS[CONF_ONLY_ONCE] = (
)
CONF_PREFER_RGB_COLOR, DEFAULT_PREFER_RGB_COLOR = "prefer_rgb_color", False
DOCS[
CONF_PREFER_RGB_COLOR
] = "Use RGB color adjustment instead of native light color temperature. 🌈"
DOCS[CONF_PREFER_RGB_COLOR] = (
"Whether to prefer RGB color adjustment over "
"light color temperature when possible. 🌈"
)
CONF_SEPARATE_TURN_ON_COMMANDS, DEFAULT_SEPARATE_TURN_ON_COMMANDS = (
"separate_turn_on_commands",
@ -87,12 +92,12 @@ DOCS[CONF_SEPARATE_TURN_ON_COMMANDS] = (
)
CONF_SLEEP_BRIGHTNESS, DEFAULT_SLEEP_BRIGHTNESS = "sleep_brightness", 1
DOCS[CONF_SLEEP_BRIGHTNESS] = "Brightness of lights in sleep mode. 😴"
DOCS[CONF_SLEEP_BRIGHTNESS] = "Brightness percentage of lights in sleep mode. 😴"
CONF_SLEEP_COLOR_TEMP, DEFAULT_SLEEP_COLOR_TEMP = "sleep_color_temp", 1000
DOCS[CONF_SLEEP_COLOR_TEMP] = (
"Color temperature in sleep mode (used when `sleep_rgb_or_color_temp` is "
"`color_temp`). 😴"
"`color_temp`) in Kelvin. 😴"
)
CONF_SLEEP_RGB_COLOR, DEFAULT_SLEEP_RGB_COLOR = "sleep_rgb_color", [255, 56, 0]
@ -104,30 +109,36 @@ CONF_SLEEP_RGB_OR_COLOR_TEMP, DEFAULT_SLEEP_RGB_OR_COLOR_TEMP = (
"sleep_rgb_or_color_temp",
"color_temp",
)
DOCS[
CONF_SLEEP_RGB_OR_COLOR_TEMP
] = "Use either `'rgb_color'` or `'color_temp'` in sleep mode. 🌙"
DOCS[CONF_SLEEP_RGB_OR_COLOR_TEMP] = (
"Use either `'rgb_color'` or `'color_temp'` " "in sleep mode. 🌙"
)
CONF_SUNRISE_OFFSET, DEFAULT_SUNRISE_OFFSET = "sunrise_offset", 0
DOCS[CONF_SUNRISE_OFFSET] = "Adjust sunrise time with a positive or negative offset. ⏰"
DOCS[CONF_SUNRISE_OFFSET] = (
"Adjust sunrise time with a positive or negative offset " "in seconds. ⏰"
)
CONF_SUNRISE_TIME = "sunrise_time"
DOCS[CONF_SUNRISE_TIME] = "Set a fixed time for sunrise. 🌅"
DOCS[CONF_SUNRISE_TIME] = "Set a fixed time (HH:MM:SS) for sunrise. 🌅"
CONF_MAX_SUNRISE_TIME = "max_sunrise_time"
DOCS[CONF_MAX_SUNRISE_TIME] = (
"Set the latest virtual sunrise time, allowing" " for earlier real sunrises. 🌅"
"Set the latest virtual sunrise time (HH:MM:SS), allowing"
" for earlier real sunrises. 🌅"
)
CONF_SUNSET_OFFSET, DEFAULT_SUNSET_OFFSET = "sunset_offset", 0
DOCS[CONF_SUNSET_OFFSET] = "Adjust sunset time with a positive or negative offset. ⏰"
DOCS[
CONF_SUNSET_OFFSET
] = "Adjust sunset time with a positive or negative offset in seconds. ⏰"
CONF_SUNSET_TIME = "sunset_time"
DOCS[CONF_SUNSET_TIME] = "Set a fixed time for sunset. 🌇"
DOCS[CONF_SUNSET_TIME] = "Set a fixed time (HH:MM:SS) for sunset. 🌇"
CONF_MIN_SUNSET_TIME = "min_sunset_time"
DOCS[CONF_MIN_SUNSET_TIME] = (
"Set the earliest virtual sunset time, allowing" " for later real sunsets. 🌇"
"Set the earliest virtual sunset time (HH:MM:SS), allowing"
" for later real sunsets. 🌇"
)
CONF_TAKE_OVER_CONTROL, DEFAULT_TAKE_OVER_CONTROL = "take_over_control", True
@ -145,8 +156,8 @@ CONF_ADAPT_UNTIL_SLEEP, DEFAULT_ADAPT_UNTIL_SLEEP = (
False,
)
DOCS[CONF_ADAPT_UNTIL_SLEEP] = (
"When checked, Adaptive Lighting will use the sleep settings as the minimum,"
" and transition to these values past the sunset"
"When enabled, Adaptive Lighting will treat sleep settings as the minimum, "
"transitioning to these values after sunset. 🌙"
)
CONF_ADAPT_DELAY, DEFAULT_ADAPT_DELAY = "adapt_delay", 0
@ -174,18 +185,36 @@ ATTR_TURN_ON_OFF_LISTENER = "turn_on_off_listener"
UNDO_UPDATE_LISTENER = "undo_update_listener"
NONE_STR = "None"
ATTR_ADAPT_COLOR = "adapt_color"
DOCS[ATTR_ADAPT_COLOR] = "Whether to adapt the color on supporting lights. 🌈"
ATTR_ADAPT_BRIGHTNESS = "adapt_brightness"
DOCS[ATTR_ADAPT_BRIGHTNESS] = "Whether to adapt the brightness of the light. 🌞"
SERVICE_SET_MANUAL_CONTROL = "set_manual_control"
CONF_MANUAL_CONTROL = "manual_control"
DOCS[CONF_MANUAL_CONTROL] = "Whether to manually control the lights. 🔒"
SERVICE_APPLY = "apply"
CONF_TURN_ON_LIGHTS = "turn_on_lights"
DOCS[CONF_TURN_ON_LIGHTS] = "Whether to turn on lights that are currently off. 🔆"
SERVICE_CHANGE_SWITCH_SETTINGS = "change_switch_settings"
CONF_USE_DEFAULTS = "use_defaults"
DOCS[CONF_USE_DEFAULTS] = "Whether to use default settings for the switches. ⚙️"
TURNING_OFF_DELAY = 5
DOCS_MANUAL_CONTROL = {
CONF_ENTITY_ID: "The `entity_id` of the switch in which to (un)mark the "
"light as being `manually controlled`. 📝",
CONF_LIGHTS: "entity_id(s) of lights, if not specified, all lights in the "
"switch are selected. 💡",
CONF_MANUAL_CONTROL: "Whether to add ('true') or remove ('false') the "
"light from the 'manual_control' list. 🔒",
}
DOCS_APPLY = {
CONF_ENTITY_ID: "The `entity_id` of the switch with the settings to apply. 📝",
CONF_LIGHTS: "A light (or list of lights) to apply the settings to. 💡",
}
def int_between(min_int, max_int):
"""Return an integer between 'min_int' and 'max_int'."""
@ -290,55 +319,28 @@ _DOMAIN_SCHEMA = vol.Schema(
)
def _format_voluptuous_instance(instance):
coerce_type = None
min_val = None
max_val = None
for validator in instance.validators:
if isinstance(validator, vol.Coerce):
coerce_type = validator.type.__name__
elif isinstance(validator, (vol.Clamp, vol.Range)):
min_val = validator.min
max_val = validator.max
if min_val is not None and max_val is not None:
return f"`{coerce_type}` {min_val}-{max_val}"
elif min_val is not None:
return f"`{coerce_type} > {min_val}`"
elif max_val is not None:
return f"`{coerce_type} < {max_val}`"
else:
return f"`{coerce_type}`"
def generate_markdown_table():
import pandas as pd
rows = []
for k, default, type_ in VALIDATION_TUPLES:
description = DOCS[k]
if type_ == cv.entity_ids:
type_ = "list of `entity_id`s"
elif type_ in (bool, int, float, str):
type_ = f"`{type_.__name__}`"
elif isinstance(type_, vol.All):
type_ = _format_voluptuous_instance(type_)
elif isinstance(type_, vol.In):
type_ = f"one of `{type_.container}`"
elif isinstance(type_, selector.SelectSelector):
type_ = f"one of `{type_.config['options']}`"
elif isinstance(type_, selector.ColorRGBSelector):
type_ = "RGB color"
else:
raise ValueError(f"Unknown type: {type_}")
row = {
"Variable name": f"`{k}`",
"Description": description,
"Default": f"`{default}`",
"Type": type_,
def apply_service_schema(initial_transition: int = 1):
"""Return the schema for the apply service."""
return vol.Schema(
{
vol.Optional(CONF_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_LIGHTS, default=[]): cv.entity_ids,
vol.Optional(
CONF_TRANSITION,
default=initial_transition,
): VALID_TRANSITION,
vol.Optional(ATTR_ADAPT_BRIGHTNESS, default=True): cv.boolean,
vol.Optional(ATTR_ADAPT_COLOR, default=True): cv.boolean,
vol.Optional(CONF_PREFER_RGB_COLOR, default=False): cv.boolean,
vol.Optional(CONF_TURN_ON_LIGHTS, default=False): cv.boolean,
}
rows.append(row)
)
df = pd.DataFrame(rows)
return df.to_markdown(index=False)
SET_MANUAL_CONTROL_SCHEMA = vol.Schema(
{
vol.Optional(CONF_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_LIGHTS, default=[]): cv.entity_ids,
vol.Optional(CONF_MANUAL_CONTROL, default=True): cv.boolean,
}
)

View file

@ -2,7 +2,7 @@ apply:
description: Applies the current Adaptive Lighting settings to lights.
fields:
entity_id:
description: entity_id of the Adaptive Lighting switch. If not specified, the current Adaptive Lighting switch will be used.
description: "Entity ID of the switch. \U0001F4DD"
example: switch.adaptive_lighting_default
selector:
entity:
@ -10,43 +10,42 @@ apply:
domain: switch
multiple: false
lights:
description: entity_id(s) of lights, if not specified, all lights in the switch are selected.
description: "List of light entities to be controlled by Adaptive Lighting (may be empty). \U0001F31F"
example: light.bedroom_ceiling
selector:
entity:
domain: light
multiple: true
transition:
description: Transition of the lights.
description: "Duration of transition when lights change, in seconds. \U0001F551"
example: 10
selector:
text:
text: null
adapt_brightness:
description: "Adapt the 'brightness', default: true"
description: "Whether to adapt the brightness of the light. \U0001F31E"
example: true
selector:
boolean:
boolean: null
adapt_color:
description: "Adapt the color_temp/color_rgb, default: true"
description: "Whether to adapt the color of the light. \U0001F308"
example: true
selector:
boolean:
boolean: null
prefer_rgb_color:
description: "Prefer to use color_rgb over color_temp if possible, default: false"
description: "Use RGB color adjustment instead of native light color temperature. \U0001F308"
example: false
selector:
boolean:
boolean: null
turn_on_lights:
description: "Turn on the lights that are off, default: false"
description: "Whether to turn on lights if they are off. \U0001F506"
example: false
selector:
boolean:
boolean: null
set_manual_control:
description: Mark whether a light is 'manually controlled'.
fields:
entity_id:
description: entity_id of the Adaptive Lighting switch. If not specified, the current Adaptive Lighting switch will be used.
description: "Entity ID of the switch. \U0001F4DD"
example: switch.adaptive_lighting_default
selector:
entity:
@ -54,138 +53,137 @@ set_manual_control:
domain: switch
multiple: false
lights:
description: entity_id(s) of lights, if not specified, all lights in the switch are selected.
description: "List of light entities to be controlled by Adaptive Lighting (may be empty). \U0001F31F"
example: light.bedroom_ceiling
selector:
entity:
domain: light
multiple: true
manual_control:
description: "Whether to add ('true') or remove ('false') the light from the 'manual_control' list, default: true"
description: "Whether to manually control the lights. \U0001F512"
example: true
default: true
selector:
boolean:
boolean: null
change_switch_settings:
description: "Change any settings you'd like in the switch. All options here are the same as in the config flow."
description: Change any settings you'd like in the switch. All options here are the same as in the config flow.
fields:
entity_id:
description: "entity_id of the Adaptive Lighting switch."
description: "Entity ID of the switch. \U0001F4DD"
required: true
selector:
entity:
domain: switch
use_defaults:
description: "(default: 'current' for current settings) You can set this to 'factory', 'configuration', or 'current' to reset the variables not being set with this service call. 'current' leaves them as is, 'configuration' resets to whatever already initializes at startup, 'factory' resets to the default values listed in the documentation."
example: "current"
description: "Whether to use default settings for the switches. \u2699\uFE0F"
example: current
required: false
default: "current"
default: current
selector:
select:
options:
- "current"
- "configuration"
- "factory"
- current
- configuration
- factory
include_config_in_attributes:
description: "include_config_in_attributes: All config options will be listed as attributes under the adaptive-lighting switch this integration creates. (default: false)"
description: "Show all options as attributes on the switch in Home Assistant when set to `true`. \U0001F4DD"
required: false
selector:
boolean:
boolean: null
turn_on_lights:
description: "Turn on the lights that are off, default: false"
description: "Whether to turn on lights if they are off. \U0001F506"
example: false
required: false
selector:
boolean:
boolean: null
initial_transition:
description: "initial_transition: When lights turn 'off' to 'on'. (seconds)"
description: "Duration of the first transition when lights turn from `off` to `on` in seconds. \u23F2\uFE0F"
example: 1
required: false
selector:
text:
text: null
sleep_transition:
description: "sleep_transition: When 'sleep_state' changes. (seconds)"
description: "Duration of transition when 'sleep mode' is toggled in seconds. \U0001F634"
example: 1
required: false
selector:
text:
text: null
max_brightness:
description: "max_brightness: Highest brightness of lights during a cycle. (%)"
description: "Maximum brightness percentage. \U0001F4A1"
required: false
example: 100
selector:
text:
text: null
max_color_temp:
description: "max_color_temp: Coldest hue of the color temperature cycle. (Kelvin)"
description: "Coldest color temperature in Kelvin. \u2744\uFE0F"
required: false
example: 5500
selector:
text:
text: null
min_brightness:
description: "min_brightness: Lowest brightness of lights during a cycle. (%)"
description: "Minimum brightness percentage. \U0001F4A1"
required: false
example: 1
selector:
text:
text: null
min_color_temp:
description: "min_color_temp, Warmest hue of the color temperature cycle. (Kelvin)"
description: "Warmest color temperature in Kelvin. \U0001F525"
required: false
example: 2000
selector:
text:
text: null
only_once:
description: "only_once: Only adapt the lights when turning them on."
description: "Adapt lights only when they are turned on (`true`) or keep adapting them (`false`). \U0001F504"
example: false
required: false
selector:
boolean:
boolean: null
prefer_rgb_color:
description: "prefer_rgb_color: Use 'rgb_color' rather than 'color_temp' when possible."
description: "Use RGB color adjustment instead of native light color temperature. \U0001F308"
required: false
example: false
selector:
boolean:
boolean: null
separate_turn_on_commands:
description: "separate_turn_on_commands: Separate the commands for each attribute (color, brightness, etc.) in 'light.turn_on' (required for some lights)."
description: "Use separate `light.turn_on` calls for color and brightness, needed for some light types. \U0001F500"
required: false
example: false
selector:
boolean:
boolean: null
send_split_delay:
description: "send_split_delay: wait between commands (milliseconds), when separate_turn_on_commands is used. May ensure that both commands are handled by the bulb correctly."
description: "Wait time (milliseconds) between commands when using `separate_turn_on_commands`. Helps ensure correct handling. \u23F2\uFE0F"
required: false
example: 0
selector:
boolean:
boolean: null
sleep_brightness:
description: "sleep_brightness, Brightness setting for Sleep Mode. (%)"
description: "Brightness percentage of lights in sleep mode. \U0001F634"
required: false
example: 1
selector:
text:
text: null
sleep_rgb_or_color_temp:
description: "sleep_rgb_or_color_temp, use 'rgb_color' or 'color_temp'"
description: "Use either `'rgb_color'` or `'color_temp'` in sleep mode. \U0001F319"
required: false
example: "color_temp"
example: color_temp
selector:
select:
options:
- "rgb_color"
- "color_temp"
- rgb_color
- color_temp
sleep_rgb_color:
description: "sleep_rgb_color, in RGB"
description: "RGB color in sleep mode (used when `sleep_rgb_or_color_temp` is 'rgb_color'). \U0001F308"
required: false
selector:
color_rgb:
color_rgb: null
sleep_color_temp:
description: "sleep_color_temp: Color temperature setting for Sleep Mode. (Kelvin)"
description: "Color temperature in sleep mode (used when `sleep_rgb_or_color_temp` is `color_temp`) in Kelvin. \U0001F634"
required: false
example: 1000
selector:
text:
text: null
sunrise_offset:
description: sunrise_offset, in +/- seconds (integer)
description: "Adjust sunrise time with a positive or negative offset in seconds. \u23F0"
required: false
example: 0
selector:
@ -193,64 +191,64 @@ change_switch_settings:
min: 0
max: 86300
sunrise_time:
description: sunrise_time, in 'HH:MM:SS' format (if 'None', it uses the actual sunrise time at your location)
description: "Set a fixed time (HH:MM:SS) for sunrise. \U0001F305"
required: false
example: ""
example: ''
selector:
time:
time: null
sunset_offset:
description: sunset_offset, in +/- seconds (integer)
description: "Adjust sunset time with a positive or negative offset in seconds. \u23F0"
required: false
example: ""
example: ''
selector:
number:
min: 0
max: 86300
sunset_time:
description: sunset_time, in 'HH:MM:SS' format (if 'None', it uses the actual sunset time at your location)
example: ""
description: "Set a fixed time (HH:MM:SS) for sunset. \U0001F307"
example: ''
required: false
selector:
time:
time: null
max_sunrise_time:
description: "max_sunrise_time: Manual override of the maximum sunrise time, if 'None', it uses the actual sunrise time at your location (HH:MM:SS)"
example: ""
description: "Set the latest virtual sunrise time (HH:MM:SS), allowing for earlier real sunrises. \U0001F305"
example: ''
required: false
selector:
time:
time: null
min_sunset_time:
description: "min_sunset_time: Manual override of the minimum sunset time, if 'None', it uses the actual sunset time at your location (HH:MM:SS)"
example: ""
description: "Set the earliest virtual sunset time (HH:MM:SS), allowing for later real sunsets. \U0001F307"
example: ''
required: false
selector:
time:
time: null
take_over_control:
description: "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."
description: "Disable Adaptive Lighting if another source calls `light.turn_on` while lights are on and being adapted. Note that this calls `homeassistant.update_entity` every `interval`! \U0001F512"
required: false
example: true
selector:
boolean:
boolean: null
detect_non_ha_changes:
description: "detect_non_ha_changes: detects all >10% changes made to the lights (also outside of HA), requires 'take_over_control' to be enabled (calls 'homeassistant.update_entity' every 'interval'!)"
description: "Detect non-`light.turn_on` state changes and stop adapting lights. Requires `take_over_control`. \U0001F575\uFE0F"
required: false
example: false
selector:
boolean:
boolean: null
transition:
description: "Transition time when applying a change to the lights (seconds)"
description: "Duration of transition when lights change, in seconds. \U0001F551"
required: false
example: 45
selector:
text:
text: null
adapt_delay:
description: "adapt_delay: wait time between light turn on (seconds), and Adaptive Lights applying changes to the light state. May avoid flickering."
description: "Wait time (seconds) between light turn on and Adaptive Lighting applying changes. Helps avoid flickering. \u23F2\uFE0F"
required: false
example: 0
selector:
text:
text: null
autoreset_control_seconds:
description: "autoreset_control_seconds: wait time (seconds) before Adaptive Lighting resets `manual_control` status of any light (default: 0)"
description: "Automatically reset the manual control after a number of seconds. Set to 0 to disable. \u23F2\uFE0F"
required: false
example: 0
selector:
text:
text: null

View file

@ -39,7 +39,6 @@ from homeassistant.components.light import (
SUPPORT_COLOR,
SUPPORT_COLOR_TEMP,
SUPPORT_TRANSITION,
VALID_TRANSITION,
is_on,
)
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
@ -137,11 +136,13 @@ from .const import (
SERVICE_APPLY,
SERVICE_CHANGE_SWITCH_SETTINGS,
SERVICE_SET_MANUAL_CONTROL,
SET_MANUAL_CONTROL_SCHEMA,
SLEEP_MODE_SWITCH,
SUN_EVENT_MIDNIGHT,
SUN_EVENT_NOON,
TURNING_OFF_DELAY,
VALIDATION_TUPLES,
apply_service_schema,
replace_none_str,
)
@ -495,20 +496,9 @@ async def async_setup_entry(
domain=DOMAIN,
service=SERVICE_APPLY,
service_func=handle_apply,
schema=vol.Schema(
{
vol.Optional("entity_id"): cv.entity_ids,
vol.Optional(CONF_LIGHTS, default=[]): cv.entity_ids,
vol.Optional(
CONF_TRANSITION,
default=switch._initial_transition, # pylint: disable=protected-access
): VALID_TRANSITION,
vol.Optional(ATTR_ADAPT_BRIGHTNESS, default=True): cv.boolean,
vol.Optional(ATTR_ADAPT_COLOR, default=True): cv.boolean,
vol.Optional(CONF_PREFER_RGB_COLOR, default=False): cv.boolean,
vol.Optional(CONF_TURN_ON_LIGHTS, default=False): cv.boolean,
}
),
schema=apply_service_schema(
switch._initial_transition
), # pylint: disable=protected-access
)
# Register `set_manual_control` service
@ -516,13 +506,7 @@ async def async_setup_entry(
domain=DOMAIN,
service=SERVICE_SET_MANUAL_CONTROL,
service_func=handle_set_manual_control,
schema=vol.Schema(
{
vol.Optional("entity_id"): cv.entity_ids,
vol.Optional(CONF_LIGHTS, default=[]): cv.entity_ids,
vol.Optional(CONF_MANUAL_CONTROL, default=True): cv.boolean,
}
),
schema=SET_MANUAL_CONTROL_SCHEMA,
)
args = {vol.Optional(CONF_USE_DEFAULTS, default="current"): cv.string}