adaptive-lighting/custom_components/adaptive_lighting/__init__.py

156 lines
5.2 KiB
Python
Raw Normal View History

Implement cdit-config-redesign groups 1-6 (30/53 tasks) const.py: - Drop 21 retired CONF_*/DEFAULT_* (sleep cluster, manual sun timing, brightness curve variants, take-over-control cluster). - Add CONF_SUNRISE_ENTITY / CONF_SUNSET_ENTITY (default sensor.sun_next_rising / _setting). - Add RAMP_HALF_WIDTH_SECONDS = 1800. - Add CONFIG_ENTRY_VERSION = 2 (gate for strict version-break). - Re-default DEFAULT_MIN_BRIGHTNESS 1→5, DEFAULT_MIN_COLOR_TEMP 2000→2200. - Update ICON_MAIN / _BRIGHTNESS / _COLOR_TEMP to the CDiT picks. manifest.json: bump to 2.0.0-cdit.1, pin homeassistant: 2025.1.0, re-point codeowners/documentation/issue_tracker to the CaseyRo fork. switch.py: - Drop sleep_mode_switch creation in async_setup_entry; integration now creates 3 switches per profile (master, adapt_color, adapt_brightness). - Strip sleep-mode state machine from AdaptiveSwitch (sleep_mode_switch attribute, sleep_transition, adapt_until_sleep, the state-change listener, the _sleep_mode_switch_state_event_action method). - Bridge-stub _take_over_control / _detect_non_ha_changes / _adapt_only_on_bare_turn_on / _only_once / _auto_reset_manual_control_time as class-level False/0 so Manager-side branches become dead code without needing a full rewrite of AdaptiveLightingManager. - Remove handle_set_manual_control service + its registration. - Replace astral-driven curve init with the new SunLightSettings call shape; add AdaptiveSwitch._today_sun_events() helper that reads the configured sunrise/sunset entities. - Set _attr_icon on AdaptiveSwitch. color_and_brightness.py: - Rewrite SunLightSettings as a pure curve-math wrapper (5 fields: name + bounds + ramp half-width); methods take t_sunrise/t_sunset as args, never reads HA state. - Implement piecewise tanh ramp curve per spec R4 / design D11 in _tanh_day_curve(). Both brightness and color-temp use the same shape. - Drop SunEvents, sleep-mode branches, brightness_mode-switch, astral dependency, force_rgb_color, lerp_color_hsv sleep-tinted color blending. config_flow.py: - Rewrite as sectioned schema (Targets / Daytime curve / Sun schedule / Light control / Advanced / Diagnostics) via HA's section() helper. - Native HA selectors throughout (NumberSelector, EntitySelector, BooleanSelector). Strict typing on sun-event entity pickers. - Conditional visibility for send_split_delay (driver: separate_turn_on_commands). - Extend OptionsFlowWithReload (with ImportError fallback for HA < 2025.1 dev environment); async_abort(reason="yaml_managed") for SOURCE_IMPORT. - VERSION = CONFIG_ENTRY_VERSION. __init__.py: - Reject older config entries with ConfigEntryError ("recreate the entry") per spec R8 / design D4. - Add _remove_orphan_sleep_entities tombstone helper that scans the entity registry for sleep-mode entities owned by this entry and removes them on first setup. Idempotent and config_entry-scoped. _docs_helpers.py: stub the removed DOCS_MANUAL_CONTROL / SET_MANUAL_CONTROL_SCHEMA so the docs-generator script keeps importing. Validation: - ALL modules import cleanly under HA 2024.12.5 (dev env). - openspec validate cdit-config-redesign --strict: green. - ruff check --select=F: clean. Remaining: groups 7 (16 tests), 8 (strings + plain-language pass), 9 (docs).
2026-05-16 14:27:39 +02:00
"""Adaptive Lighting integration in Home Assistant (CDiT fork)."""
2020-09-19 11:35:28 +02:00
import logging
2022-04-17 19:51:44 -07:00
from typing import Any
2020-09-23 13:11:50 +02:00
import homeassistant.helpers.config_validation as cv
import voluptuous as vol
2020-09-20 18:38:01 +02:00
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
2020-10-05 23:41:57 +02:00
from homeassistant.const import CONF_SOURCE
2025-11-27 21:01:05 +01:00
from homeassistant.core import Event, HomeAssistant
Implement cdit-config-redesign groups 1-6 (30/53 tasks) const.py: - Drop 21 retired CONF_*/DEFAULT_* (sleep cluster, manual sun timing, brightness curve variants, take-over-control cluster). - Add CONF_SUNRISE_ENTITY / CONF_SUNSET_ENTITY (default sensor.sun_next_rising / _setting). - Add RAMP_HALF_WIDTH_SECONDS = 1800. - Add CONFIG_ENTRY_VERSION = 2 (gate for strict version-break). - Re-default DEFAULT_MIN_BRIGHTNESS 1→5, DEFAULT_MIN_COLOR_TEMP 2000→2200. - Update ICON_MAIN / _BRIGHTNESS / _COLOR_TEMP to the CDiT picks. manifest.json: bump to 2.0.0-cdit.1, pin homeassistant: 2025.1.0, re-point codeowners/documentation/issue_tracker to the CaseyRo fork. switch.py: - Drop sleep_mode_switch creation in async_setup_entry; integration now creates 3 switches per profile (master, adapt_color, adapt_brightness). - Strip sleep-mode state machine from AdaptiveSwitch (sleep_mode_switch attribute, sleep_transition, adapt_until_sleep, the state-change listener, the _sleep_mode_switch_state_event_action method). - Bridge-stub _take_over_control / _detect_non_ha_changes / _adapt_only_on_bare_turn_on / _only_once / _auto_reset_manual_control_time as class-level False/0 so Manager-side branches become dead code without needing a full rewrite of AdaptiveLightingManager. - Remove handle_set_manual_control service + its registration. - Replace astral-driven curve init with the new SunLightSettings call shape; add AdaptiveSwitch._today_sun_events() helper that reads the configured sunrise/sunset entities. - Set _attr_icon on AdaptiveSwitch. color_and_brightness.py: - Rewrite SunLightSettings as a pure curve-math wrapper (5 fields: name + bounds + ramp half-width); methods take t_sunrise/t_sunset as args, never reads HA state. - Implement piecewise tanh ramp curve per spec R4 / design D11 in _tanh_day_curve(). Both brightness and color-temp use the same shape. - Drop SunEvents, sleep-mode branches, brightness_mode-switch, astral dependency, force_rgb_color, lerp_color_hsv sleep-tinted color blending. config_flow.py: - Rewrite as sectioned schema (Targets / Daytime curve / Sun schedule / Light control / Advanced / Diagnostics) via HA's section() helper. - Native HA selectors throughout (NumberSelector, EntitySelector, BooleanSelector). Strict typing on sun-event entity pickers. - Conditional visibility for send_split_delay (driver: separate_turn_on_commands). - Extend OptionsFlowWithReload (with ImportError fallback for HA < 2025.1 dev environment); async_abort(reason="yaml_managed") for SOURCE_IMPORT. - VERSION = CONFIG_ENTRY_VERSION. __init__.py: - Reject older config entries with ConfigEntryError ("recreate the entry") per spec R8 / design D4. - Add _remove_orphan_sleep_entities tombstone helper that scans the entity registry for sleep-mode entities owned by this entry and removes them on first setup. Idempotent and config_entry-scoped. _docs_helpers.py: stub the removed DOCS_MANUAL_CONTROL / SET_MANUAL_CONTROL_SCHEMA so the docs-generator script keeps importing. Validation: - ALL modules import cleanly under HA 2024.12.5 (dev env). - openspec validate cdit-config-redesign --strict: green. - ruff check --select=F: clean. Remaining: groups 7 (16 tests), 8 (strings + plain-language pass), 9 (docs).
2026-05-16 14:27:39 +02:00
from homeassistant.exceptions import ConfigEntryError
from homeassistant.helpers import entity_registry as er
2020-09-19 11:10:54 +02:00
2020-09-30 00:42:27 +02:00
from .const import (
2025-12-12 22:37:42 +01:00
_DOMAIN_SCHEMA, # pyright: ignore[reportPrivateUsage]
ATTR_ADAPTIVE_LIGHTING_MANAGER,
2020-09-30 00:42:27 +02:00
CONF_NAME,
Implement cdit-config-redesign groups 1-6 (30/53 tasks) const.py: - Drop 21 retired CONF_*/DEFAULT_* (sleep cluster, manual sun timing, brightness curve variants, take-over-control cluster). - Add CONF_SUNRISE_ENTITY / CONF_SUNSET_ENTITY (default sensor.sun_next_rising / _setting). - Add RAMP_HALF_WIDTH_SECONDS = 1800. - Add CONFIG_ENTRY_VERSION = 2 (gate for strict version-break). - Re-default DEFAULT_MIN_BRIGHTNESS 1→5, DEFAULT_MIN_COLOR_TEMP 2000→2200. - Update ICON_MAIN / _BRIGHTNESS / _COLOR_TEMP to the CDiT picks. manifest.json: bump to 2.0.0-cdit.1, pin homeassistant: 2025.1.0, re-point codeowners/documentation/issue_tracker to the CaseyRo fork. switch.py: - Drop sleep_mode_switch creation in async_setup_entry; integration now creates 3 switches per profile (master, adapt_color, adapt_brightness). - Strip sleep-mode state machine from AdaptiveSwitch (sleep_mode_switch attribute, sleep_transition, adapt_until_sleep, the state-change listener, the _sleep_mode_switch_state_event_action method). - Bridge-stub _take_over_control / _detect_non_ha_changes / _adapt_only_on_bare_turn_on / _only_once / _auto_reset_manual_control_time as class-level False/0 so Manager-side branches become dead code without needing a full rewrite of AdaptiveLightingManager. - Remove handle_set_manual_control service + its registration. - Replace astral-driven curve init with the new SunLightSettings call shape; add AdaptiveSwitch._today_sun_events() helper that reads the configured sunrise/sunset entities. - Set _attr_icon on AdaptiveSwitch. color_and_brightness.py: - Rewrite SunLightSettings as a pure curve-math wrapper (5 fields: name + bounds + ramp half-width); methods take t_sunrise/t_sunset as args, never reads HA state. - Implement piecewise tanh ramp curve per spec R4 / design D11 in _tanh_day_curve(). Both brightness and color-temp use the same shape. - Drop SunEvents, sleep-mode branches, brightness_mode-switch, astral dependency, force_rgb_color, lerp_color_hsv sleep-tinted color blending. config_flow.py: - Rewrite as sectioned schema (Targets / Daytime curve / Sun schedule / Light control / Advanced / Diagnostics) via HA's section() helper. - Native HA selectors throughout (NumberSelector, EntitySelector, BooleanSelector). Strict typing on sun-event entity pickers. - Conditional visibility for send_split_delay (driver: separate_turn_on_commands). - Extend OptionsFlowWithReload (with ImportError fallback for HA < 2025.1 dev environment); async_abort(reason="yaml_managed") for SOURCE_IMPORT. - VERSION = CONFIG_ENTRY_VERSION. __init__.py: - Reject older config entries with ConfigEntryError ("recreate the entry") per spec R8 / design D4. - Add _remove_orphan_sleep_entities tombstone helper that scans the entity registry for sleep-mode entities owned by this entry and removes them on first setup. Idempotent and config_entry-scoped. _docs_helpers.py: stub the removed DOCS_MANUAL_CONTROL / SET_MANUAL_CONTROL_SCHEMA so the docs-generator script keeps importing. Validation: - ALL modules import cleanly under HA 2024.12.5 (dev env). - openspec validate cdit-config-redesign --strict: green. - ruff check --select=F: clean. Remaining: groups 7 (16 tests), 8 (strings + plain-language pass), 9 (docs).
2026-05-16 14:27:39 +02:00
CONFIG_ENTRY_VERSION,
2020-09-30 00:42:27 +02:00
DOMAIN,
)
2020-09-19 11:10:54 +02:00
2020-09-20 18:38:01 +02:00
_LOGGER = logging.getLogger(__name__)
PLATFORMS = ["switch"]
2020-09-19 11:10:54 +02:00
Implement cdit-config-redesign groups 1-6 (30/53 tasks) const.py: - Drop 21 retired CONF_*/DEFAULT_* (sleep cluster, manual sun timing, brightness curve variants, take-over-control cluster). - Add CONF_SUNRISE_ENTITY / CONF_SUNSET_ENTITY (default sensor.sun_next_rising / _setting). - Add RAMP_HALF_WIDTH_SECONDS = 1800. - Add CONFIG_ENTRY_VERSION = 2 (gate for strict version-break). - Re-default DEFAULT_MIN_BRIGHTNESS 1→5, DEFAULT_MIN_COLOR_TEMP 2000→2200. - Update ICON_MAIN / _BRIGHTNESS / _COLOR_TEMP to the CDiT picks. manifest.json: bump to 2.0.0-cdit.1, pin homeassistant: 2025.1.0, re-point codeowners/documentation/issue_tracker to the CaseyRo fork. switch.py: - Drop sleep_mode_switch creation in async_setup_entry; integration now creates 3 switches per profile (master, adapt_color, adapt_brightness). - Strip sleep-mode state machine from AdaptiveSwitch (sleep_mode_switch attribute, sleep_transition, adapt_until_sleep, the state-change listener, the _sleep_mode_switch_state_event_action method). - Bridge-stub _take_over_control / _detect_non_ha_changes / _adapt_only_on_bare_turn_on / _only_once / _auto_reset_manual_control_time as class-level False/0 so Manager-side branches become dead code without needing a full rewrite of AdaptiveLightingManager. - Remove handle_set_manual_control service + its registration. - Replace astral-driven curve init with the new SunLightSettings call shape; add AdaptiveSwitch._today_sun_events() helper that reads the configured sunrise/sunset entities. - Set _attr_icon on AdaptiveSwitch. color_and_brightness.py: - Rewrite SunLightSettings as a pure curve-math wrapper (5 fields: name + bounds + ramp half-width); methods take t_sunrise/t_sunset as args, never reads HA state. - Implement piecewise tanh ramp curve per spec R4 / design D11 in _tanh_day_curve(). Both brightness and color-temp use the same shape. - Drop SunEvents, sleep-mode branches, brightness_mode-switch, astral dependency, force_rgb_color, lerp_color_hsv sleep-tinted color blending. config_flow.py: - Rewrite as sectioned schema (Targets / Daytime curve / Sun schedule / Light control / Advanced / Diagnostics) via HA's section() helper. - Native HA selectors throughout (NumberSelector, EntitySelector, BooleanSelector). Strict typing on sun-event entity pickers. - Conditional visibility for send_split_delay (driver: separate_turn_on_commands). - Extend OptionsFlowWithReload (with ImportError fallback for HA < 2025.1 dev environment); async_abort(reason="yaml_managed") for SOURCE_IMPORT. - VERSION = CONFIG_ENTRY_VERSION. __init__.py: - Reject older config entries with ConfigEntryError ("recreate the entry") per spec R8 / design D4. - Add _remove_orphan_sleep_entities tombstone helper that scans the entity registry for sleep-mode entities owned by this entry and removes them on first setup. Idempotent and config_entry-scoped. _docs_helpers.py: stub the removed DOCS_MANUAL_CONTROL / SET_MANUAL_CONTROL_SCHEMA so the docs-generator script keeps importing. Validation: - ALL modules import cleanly under HA 2024.12.5 (dev env). - openspec validate cdit-config-redesign --strict: green. - ruff check --select=F: clean. Remaining: groups 7 (16 tests), 8 (strings + plain-language pass), 9 (docs).
2026-05-16 14:27:39 +02:00
# unique_id suffix(es) that this fork no longer creates. Any entity in the
# registry whose unique_id ends with one of these strings AND that is owned
# by an Adaptive Lighting config entry is a leftover from upstream and is
# removed on first setup (spec R9, design D12).
_REMOVED_UNIQUE_ID_SUFFIXES = ("_sleep_mode",)
2020-09-23 13:11:50 +02:00
2025-11-27 21:01:05 +01:00
def _all_unique_names(value: list[dict[str, Any]]) -> list[dict[str, Any]]:
2020-10-05 23:41:57 +02:00
"""Validate that all entities have a unique profile name."""
2020-09-23 18:20:25 +02:00
hosts = [device[CONF_NAME] for device in value]
schema = vol.Schema(vol.Unique())
schema(hosts)
return value
2020-09-24 20:41:24 +02:00
CONFIG_SCHEMA = vol.Schema(
2020-09-26 13:13:44 +02:00
{DOMAIN: vol.All(cv.ensure_list, [_DOMAIN_SCHEMA], _all_unique_names)},
2020-09-24 20:41:24 +02:00
extra=vol.ALLOW_EXTRA,
)
2020-09-23 18:20:25 +02:00
2025-11-27 21:01:05 +01:00
async def reload_configuration_yaml(event: Event) -> None:
"""Reload configuration.yaml."""
2025-11-27 21:01:05 +01:00
hass: HomeAssistant | None = event.data.get("hass")
if hass is not None:
await hass.services.async_call("homeassistant", "check_config", {})
else:
_LOGGER.error("HomeAssistant instance not found in event data.")
2025-11-27 21:01:05 +01:00
async def async_setup(hass: HomeAssistant, config: dict[str, Any]) -> bool:
2020-09-19 11:10:54 +02:00
"""Import integration from config."""
if DOMAIN in config:
for entry in config[DOMAIN]:
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN,
context={CONF_SOURCE: SOURCE_IMPORT},
data=entry,
),
2020-09-19 11:10:54 +02:00
)
return True
Implement cdit-config-redesign groups 1-6 (30/53 tasks) const.py: - Drop 21 retired CONF_*/DEFAULT_* (sleep cluster, manual sun timing, brightness curve variants, take-over-control cluster). - Add CONF_SUNRISE_ENTITY / CONF_SUNSET_ENTITY (default sensor.sun_next_rising / _setting). - Add RAMP_HALF_WIDTH_SECONDS = 1800. - Add CONFIG_ENTRY_VERSION = 2 (gate for strict version-break). - Re-default DEFAULT_MIN_BRIGHTNESS 1→5, DEFAULT_MIN_COLOR_TEMP 2000→2200. - Update ICON_MAIN / _BRIGHTNESS / _COLOR_TEMP to the CDiT picks. manifest.json: bump to 2.0.0-cdit.1, pin homeassistant: 2025.1.0, re-point codeowners/documentation/issue_tracker to the CaseyRo fork. switch.py: - Drop sleep_mode_switch creation in async_setup_entry; integration now creates 3 switches per profile (master, adapt_color, adapt_brightness). - Strip sleep-mode state machine from AdaptiveSwitch (sleep_mode_switch attribute, sleep_transition, adapt_until_sleep, the state-change listener, the _sleep_mode_switch_state_event_action method). - Bridge-stub _take_over_control / _detect_non_ha_changes / _adapt_only_on_bare_turn_on / _only_once / _auto_reset_manual_control_time as class-level False/0 so Manager-side branches become dead code without needing a full rewrite of AdaptiveLightingManager. - Remove handle_set_manual_control service + its registration. - Replace astral-driven curve init with the new SunLightSettings call shape; add AdaptiveSwitch._today_sun_events() helper that reads the configured sunrise/sunset entities. - Set _attr_icon on AdaptiveSwitch. color_and_brightness.py: - Rewrite SunLightSettings as a pure curve-math wrapper (5 fields: name + bounds + ramp half-width); methods take t_sunrise/t_sunset as args, never reads HA state. - Implement piecewise tanh ramp curve per spec R4 / design D11 in _tanh_day_curve(). Both brightness and color-temp use the same shape. - Drop SunEvents, sleep-mode branches, brightness_mode-switch, astral dependency, force_rgb_color, lerp_color_hsv sleep-tinted color blending. config_flow.py: - Rewrite as sectioned schema (Targets / Daytime curve / Sun schedule / Light control / Advanced / Diagnostics) via HA's section() helper. - Native HA selectors throughout (NumberSelector, EntitySelector, BooleanSelector). Strict typing on sun-event entity pickers. - Conditional visibility for send_split_delay (driver: separate_turn_on_commands). - Extend OptionsFlowWithReload (with ImportError fallback for HA < 2025.1 dev environment); async_abort(reason="yaml_managed") for SOURCE_IMPORT. - VERSION = CONFIG_ENTRY_VERSION. __init__.py: - Reject older config entries with ConfigEntryError ("recreate the entry") per spec R8 / design D4. - Add _remove_orphan_sleep_entities tombstone helper that scans the entity registry for sleep-mode entities owned by this entry and removes them on first setup. Idempotent and config_entry-scoped. _docs_helpers.py: stub the removed DOCS_MANUAL_CONTROL / SET_MANUAL_CONTROL_SCHEMA so the docs-generator script keeps importing. Validation: - ALL modules import cleanly under HA 2024.12.5 (dev env). - openspec validate cdit-config-redesign --strict: green. - ruff check --select=F: clean. Remaining: groups 7 (16 tests), 8 (strings + plain-language pass), 9 (docs).
2026-05-16 14:27:39 +02:00
def _remove_orphan_sleep_entities(
hass: HomeAssistant,
config_entry: ConfigEntry,
) -> None:
"""Remove sleep-mode switch entities left behind by upstream AL.
Idempotent: subsequent runs find nothing and emit no log lines. Only
removes entities whose config_entry_id matches the current entry, so
foreign entities matching the name pattern are not touched.
Spec R9, design D12.
"""
registry = er.async_get(hass)
entries_to_remove = [
entry.entity_id
for entry in registry.entities.values()
if entry.config_entry_id == config_entry.entry_id
and any(
entry.unique_id.endswith(suffix)
for suffix in _REMOVED_UNIQUE_ID_SUFFIXES
)
]
for entity_id in entries_to_remove:
_LOGGER.info(
"Removing orphan entity %s left behind by upstream Adaptive Lighting "
"(sleep mode is not supported in the CDiT fork).",
entity_id,
)
registry.async_remove(entity_id)
Group 7: tests — 94 passing in 0.57s (53/53 + 9.4 deferred) Test infrastructure: - Add `pytest-homeassistant-custom-component` (PHACC) as a `test` dependency group. PHACC ships `hass`, `enable_custom_integrations`, `MockConfigEntry`, and friends without needing to clone HA core as a sibling directory. Modernizes the test setup from upstream's `setup-symlinks` pattern. - conftest.py: add `auto_enable_custom_integrations` autouse fixture so HA discovers the integration under `custom_components/` during tests. Keep the upstream template-deprecation no-op. - Import paths: all tests now import from `custom_components.adaptive_lighting` (not `homeassistant.components.adaptive_lighting`) and from `pytest_homeassistant_custom_component.common` (not `tests.common`). New tests (groups 7.2-7.16): - tests/test_color_and_brightness.py (16 tests): TestBrightnessCurve asserts min-before-sunrise, midpoint-at-event, max-during-day, sunset ramp symmetry. TestColorTempCurve verifies the same shape applies to K. TestSunPosition checks the synthetic +1/-1/0 derivation. TestTanhDayCurveDirect exercises the helper directly. - tests/test_config_flow.py (12 tests): six sections in order, each section contains only its specified fields, conditional visibility of send_split_delay, default sun entities, strict-typed entity selectors, NumberSelector slider/box configs, BooleanSelector for every flag, full user→create-entry flow, YAML-managed entry aborts with `yaml_managed` reason, options flow renders the sectioned schema. - tests/test_init.py (6 tests): successful setup on current version, stale version raises ConfigEntryError via async_migrate_entry, unload is clean, tombstone removes orphan sleep entity + logs INFO, tombstone is idempotent, tombstone respects config_entry ownership. Source modernizations driven by the tests: - __init__.py: add `async_migrate_entry` that surfaces the "incompatible — delete and recreate" message and sets the entry to MIGRATION_ERROR. Removed direct `ConfigEntryError` from `async_setup_entry` (HA routes version mismatches through the migration handler now). - switch.py: removed upstream's YAML-managed-entry auto-remove hack. YAML profiles now load normally and the options flow handles the "you must edit configuration.yaml" message (spec R7). Existing tests updated to PHACC paths: test_adaptation_utils.py (38 tests), test_hass_utils.py (22 tests). Both pass without modification beyond the import fix. Deleted: tests/test_switch.py (2,999 LOC of upstream tests, most covering sleep mode / take-over-control / manual-control state machines that no longer exist; CDiT-specific switch tests deferred to a follow-up change). Result: `uv run --group test pytest tests/` → 94 passed in 0.57s. Deferred from this change: - 4.3: manual UI test that toggling a field and saving reloads cleanly (requires a real HA instance, can't be done from CLI). - 9.4: GitHub repo description / topics update (do via `gh repo edit` outside the change scope). openspec status: 4/4 artifacts complete; strict-validate green.
2026-05-16 15:11:49 +02:00
async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Reject older config-entry versions with a friendly recreate message.
Spec R8 + design D4: this fork deliberately does not migrate upstream
entries. Define a migration handler so HA routes version mismatches
here (instead of logging the generic "Migration handler not found")
and surface a `ConfigEntryError` whose message tells the user what to
do.
"""
msg = (
f"Adaptive Lighting v{CONFIG_ENTRY_VERSION} (CDiT fork) is incompatible "
f"with the existing config entry (version {config_entry.version}). "
"Delete the entry and recreate it from Settings → Devices & Services."
)
raise ConfigEntryError(msg)
2025-11-27 21:01:05 +01:00
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Set up the component.
Note: `OptionsFlowWithReload` (in config_flow.py) handles reload-on-save
automatically — HA rejects `config_entry.add_update_listener` when used
with `OptionsFlowWithReload`, so we deliberately do NOT register one.
"""
Implement cdit-config-redesign groups 1-6 (30/53 tasks) const.py: - Drop 21 retired CONF_*/DEFAULT_* (sleep cluster, manual sun timing, brightness curve variants, take-over-control cluster). - Add CONF_SUNRISE_ENTITY / CONF_SUNSET_ENTITY (default sensor.sun_next_rising / _setting). - Add RAMP_HALF_WIDTH_SECONDS = 1800. - Add CONFIG_ENTRY_VERSION = 2 (gate for strict version-break). - Re-default DEFAULT_MIN_BRIGHTNESS 1→5, DEFAULT_MIN_COLOR_TEMP 2000→2200. - Update ICON_MAIN / _BRIGHTNESS / _COLOR_TEMP to the CDiT picks. manifest.json: bump to 2.0.0-cdit.1, pin homeassistant: 2025.1.0, re-point codeowners/documentation/issue_tracker to the CaseyRo fork. switch.py: - Drop sleep_mode_switch creation in async_setup_entry; integration now creates 3 switches per profile (master, adapt_color, adapt_brightness). - Strip sleep-mode state machine from AdaptiveSwitch (sleep_mode_switch attribute, sleep_transition, adapt_until_sleep, the state-change listener, the _sleep_mode_switch_state_event_action method). - Bridge-stub _take_over_control / _detect_non_ha_changes / _adapt_only_on_bare_turn_on / _only_once / _auto_reset_manual_control_time as class-level False/0 so Manager-side branches become dead code without needing a full rewrite of AdaptiveLightingManager. - Remove handle_set_manual_control service + its registration. - Replace astral-driven curve init with the new SunLightSettings call shape; add AdaptiveSwitch._today_sun_events() helper that reads the configured sunrise/sunset entities. - Set _attr_icon on AdaptiveSwitch. color_and_brightness.py: - Rewrite SunLightSettings as a pure curve-math wrapper (5 fields: name + bounds + ramp half-width); methods take t_sunrise/t_sunset as args, never reads HA state. - Implement piecewise tanh ramp curve per spec R4 / design D11 in _tanh_day_curve(). Both brightness and color-temp use the same shape. - Drop SunEvents, sleep-mode branches, brightness_mode-switch, astral dependency, force_rgb_color, lerp_color_hsv sleep-tinted color blending. config_flow.py: - Rewrite as sectioned schema (Targets / Daytime curve / Sun schedule / Light control / Advanced / Diagnostics) via HA's section() helper. - Native HA selectors throughout (NumberSelector, EntitySelector, BooleanSelector). Strict typing on sun-event entity pickers. - Conditional visibility for send_split_delay (driver: separate_turn_on_commands). - Extend OptionsFlowWithReload (with ImportError fallback for HA < 2025.1 dev environment); async_abort(reason="yaml_managed") for SOURCE_IMPORT. - VERSION = CONFIG_ENTRY_VERSION. __init__.py: - Reject older config entries with ConfigEntryError ("recreate the entry") per spec R8 / design D4. - Add _remove_orphan_sleep_entities tombstone helper that scans the entity registry for sleep-mode entities owned by this entry and removes them on first setup. Idempotent and config_entry-scoped. _docs_helpers.py: stub the removed DOCS_MANUAL_CONTROL / SET_MANUAL_CONTROL_SCHEMA so the docs-generator script keeps importing. Validation: - ALL modules import cleanly under HA 2024.12.5 (dev env). - openspec validate cdit-config-redesign --strict: green. - ruff check --select=F: clean. Remaining: groups 7 (16 tests), 8 (strings + plain-language pass), 9 (docs).
2026-05-16 14:27:39 +02:00
_remove_orphan_sleep_entities(hass, config_entry)
2020-09-28 23:39:55 +02:00
data = hass.data.setdefault(DOMAIN, {})
2020-09-19 11:10:54 +02:00
Implement cdit-config-redesign groups 1-6 (30/53 tasks) const.py: - Drop 21 retired CONF_*/DEFAULT_* (sleep cluster, manual sun timing, brightness curve variants, take-over-control cluster). - Add CONF_SUNRISE_ENTITY / CONF_SUNSET_ENTITY (default sensor.sun_next_rising / _setting). - Add RAMP_HALF_WIDTH_SECONDS = 1800. - Add CONFIG_ENTRY_VERSION = 2 (gate for strict version-break). - Re-default DEFAULT_MIN_BRIGHTNESS 1→5, DEFAULT_MIN_COLOR_TEMP 2000→2200. - Update ICON_MAIN / _BRIGHTNESS / _COLOR_TEMP to the CDiT picks. manifest.json: bump to 2.0.0-cdit.1, pin homeassistant: 2025.1.0, re-point codeowners/documentation/issue_tracker to the CaseyRo fork. switch.py: - Drop sleep_mode_switch creation in async_setup_entry; integration now creates 3 switches per profile (master, adapt_color, adapt_brightness). - Strip sleep-mode state machine from AdaptiveSwitch (sleep_mode_switch attribute, sleep_transition, adapt_until_sleep, the state-change listener, the _sleep_mode_switch_state_event_action method). - Bridge-stub _take_over_control / _detect_non_ha_changes / _adapt_only_on_bare_turn_on / _only_once / _auto_reset_manual_control_time as class-level False/0 so Manager-side branches become dead code without needing a full rewrite of AdaptiveLightingManager. - Remove handle_set_manual_control service + its registration. - Replace astral-driven curve init with the new SunLightSettings call shape; add AdaptiveSwitch._today_sun_events() helper that reads the configured sunrise/sunset entities. - Set _attr_icon on AdaptiveSwitch. color_and_brightness.py: - Rewrite SunLightSettings as a pure curve-math wrapper (5 fields: name + bounds + ramp half-width); methods take t_sunrise/t_sunset as args, never reads HA state. - Implement piecewise tanh ramp curve per spec R4 / design D11 in _tanh_day_curve(). Both brightness and color-temp use the same shape. - Drop SunEvents, sleep-mode branches, brightness_mode-switch, astral dependency, force_rgb_color, lerp_color_hsv sleep-tinted color blending. config_flow.py: - Rewrite as sectioned schema (Targets / Daytime curve / Sun schedule / Light control / Advanced / Diagnostics) via HA's section() helper. - Native HA selectors throughout (NumberSelector, EntitySelector, BooleanSelector). Strict typing on sun-event entity pickers. - Conditional visibility for send_split_delay (driver: separate_turn_on_commands). - Extend OptionsFlowWithReload (with ImportError fallback for HA < 2025.1 dev environment); async_abort(reason="yaml_managed") for SOURCE_IMPORT. - VERSION = CONFIG_ENTRY_VERSION. __init__.py: - Reject older config entries with ConfigEntryError ("recreate the entry") per spec R8 / design D4. - Add _remove_orphan_sleep_entities tombstone helper that scans the entity registry for sleep-mode entities owned by this entry and removes them on first setup. Idempotent and config_entry-scoped. _docs_helpers.py: stub the removed DOCS_MANUAL_CONTROL / SET_MANUAL_CONTROL_SCHEMA so the docs-generator script keeps importing. Validation: - ALL modules import cleanly under HA 2024.12.5 (dev env). - openspec validate cdit-config-redesign --strict: green. - ruff check --select=F: clean. Remaining: groups 7 (16 tests), 8 (strings + plain-language pass), 9 (docs).
2026-05-16 14:27:39 +02:00
# Reload YAML configs on `hass.config.entry_updated` (covers `quick reload`
# and explicit `hass.reload_config_entry` calls).
hass.bus.async_listen("hass.config.entry_updated", reload_configuration_yaml)
data[config_entry.entry_id] = {}
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
2020-09-19 11:10:54 +02:00
return True
2025-11-27 07:35:09 -10:00
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Unload a config entry."""
2020-09-29 13:13:08 +02:00
unload_ok = await hass.config_entries.async_forward_entry_unload(
config_entry,
"switch",
)
2020-09-28 23:39:55 +02:00
data = hass.data[DOMAIN]
2020-10-17 15:43:24 +02:00
if unload_ok:
data.pop(config_entry.entry_id, None)
2020-10-17 15:43:24 +02:00
if len(data) == 1 and ATTR_ADAPTIVE_LIGHTING_MANAGER in data:
2020-10-17 15:43:24 +02:00
# no more config_entries
manager = data.pop(ATTR_ADAPTIVE_LIGHTING_MANAGER)
manager.disable()
2020-10-17 15:43:24 +02:00
if not data:
hass.data.pop(DOMAIN)
2020-09-20 18:38:01 +02:00
return unload_ok