Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion homeassistant/components/wled/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from homeassistant.helpers.typing import ConfigType
from homeassistant.util.hass_dict import HassKey

from .const import DOMAIN
from .const import CONF_KEEP_MAIN_LIGHT, DOMAIN
from .coordinator import (
WLEDConfigEntry,
WLEDDataUpdateCoordinator,
Expand Down Expand Up @@ -127,6 +127,14 @@ async def async_migrate_entry(
version=1,
minor_version=2,
)
if config_entry.minor_version < 3:
# 1.3: Keep existing behavior for users upgrading — new installs default to True.
hass.config_entries.async_update_entry(
config_entry,
options={CONF_KEEP_MAIN_LIGHT: False} | config_entry.options,
version=1,
minor_version=3,
)

_LOGGER.debug(
"Migration to configuration version %s.%s successful",
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/wled/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class WLEDFlowHandler(ConfigFlow, domain=DOMAIN):
"""Handle a WLED config flow."""

VERSION = 1
MINOR_VERSION = 2
MINOR_VERSION = 3
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional and consistent with how we handle options in other integration — storing no value distinguishes "user has never changed this setting" from "user explicitly set it to True/False". If we ever change DEFAULT_KEEP_MAIN_LIGHT again, we'll do it the same way we did here: write a migration that explicitly sets the option on all entries that should keep the old behavior, and let new entries inherit the new default. The 1.2 → 1.3 migration is exactly that pattern — it locks existing users to False rather than leaving them at the mercy of the constant.

discovered_host: str
discovered_device: Device

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/wled/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# Options
CONF_KEEP_MAIN_LIGHT = "keep_master_light"
DEFAULT_KEEP_MAIN_LIGHT = False
DEFAULT_KEEP_MAIN_LIGHT = True

# Attributes
ATTR_CCT = "cct"
Expand Down
8 changes: 5 additions & 3 deletions homeassistant/components/wled/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
"""Initialize WLED main light."""
super().__init__(coordinator=coordinator)
self._attr_unique_id = coordinator.data.info.mac_address
if coordinator.keep_main_light:
self._attr_name = None
Comment on lines +69 to +70
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is expected. I covered this scenario in PR description. Migration would be too risky.

Comment on lines +69 to +70
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, it's too risky to change an entity ID that's already assigned or to delete entities that have already been created. If the keep main light option is enabled, the entity will be marked as unavailable and the user can manually delete it from the UI.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides, I think we should discourage disabling the "Keep Main Light" option and instead describe how to achieve a similar effect using automation. I even have such automations for multi-segment installations, and now there will also be a recommendation to use it for single-segment installations too.

One day, we might even retire the "Keep Main Light" option and leave it on by default but that's another thread.


@property
def brightness(self) -> int | None:
Expand Down Expand Up @@ -122,9 +124,9 @@ def __init__(
super().__init__(coordinator=coordinator)
self._segment = segment

# Segment 0 uses a simpler name, which is more natural for when using
# a single segment / using WLED with one big LED strip.
if segment == 0:
# With keep_main_light disabled, a single-segment setup uses segment 0
# as the primary entity — it drops the "Segment N" qualifier.
if segment == 0 and not coordinator.keep_main_light:
self._attr_name = None
else:
self._attr_translation_placeholders = {"segment": str(segment)}
Expand Down
13 changes: 9 additions & 4 deletions homeassistant/components/wled/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@ class WLEDNumberEntityDescription(NumberEntityDescription):
"""Class describing WLED number entities."""

value_fn: Callable[[Segment], int | None]
segment_translation_key: str


NUMBERS = [
WLEDNumberEntityDescription(
key=ATTR_SPEED,
translation_key="speed",
segment_translation_key="segment_speed",
entity_category=EntityCategory.CONFIG,
native_step=1,
native_min_value=0,
Expand All @@ -57,6 +59,7 @@ class WLEDNumberEntityDescription(NumberEntityDescription):
WLEDNumberEntityDescription(
key=ATTR_INTENSITY,
translation_key="intensity",
segment_translation_key="segment_intensity",
entity_category=EntityCategory.CONFIG,
native_step=1,
native_min_value=0,
Expand All @@ -81,10 +84,12 @@ def __init__(
super().__init__(coordinator=coordinator)
self.entity_description = description

# Segment 0 uses a simpler name, which is more natural for when using
# a single segment / using WLED with one big LED strip.
if segment != 0:
self._attr_translation_key = f"segment_{description.translation_key}"
# With keep_main_light disabled, a single-segment setup uses segment 0
# as the primary entity — it drops the "Segment N" qualifier.
if segment == 0 and not coordinator.keep_main_light:
self._attr_translation_key = description.translation_key
else:
self._attr_translation_key = description.segment_translation_key
self._attr_translation_placeholders = {"segment": str(segment)}

self._attr_unique_id = (
Expand Down
6 changes: 3 additions & 3 deletions homeassistant/components/wled/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ def __init__(self, coordinator: WLEDDataUpdateCoordinator, segment: int) -> None
"""Initialize WLED ."""
super().__init__(coordinator=coordinator)

# Segment 0 uses a simpler name, which is more natural for when using
# a single segment / using WLED with one big LED strip.
if segment != 0:
# With keep_main_light disabled, a single-segment setup uses segment 0
# as the primary entity — it drops the "Segment N" qualifier.
if segment != 0 or coordinator.keep_main_light:
self._attr_translation_key = "segment_color_palette"
self._attr_translation_placeholders = {"segment": str(segment)}

Expand Down
10 changes: 5 additions & 5 deletions homeassistant/components/wled/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,13 @@ def __init__(
self.entity_description = description
self._segment = segment

# Segment 0 uses a simpler name, which is more natural for when using
# a single segment / using WLED with one big LED strip.
if segment != 0:
# With keep_main_light disabled, a single-segment setup uses segment 0
# as the primary entity — it drops the "Segment N" qualifier.
if segment == 0 and not coordinator.keep_main_light:
self._attr_translation_key = description.translation_key
else:
self._attr_translation_key = description.segment_translation_key
self._attr_translation_placeholders = {"segment": str(segment)}
else:
self._attr_translation_key = description.translation_key

self._attr_unique_id = (
f"{coordinator.data.info.mac_address}_{description.key}_{segment}"
Expand Down
17 changes: 16 additions & 1 deletion tests/components/wled/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import pytest
from wled import Device as WLEDDevice, Releases

from homeassistant.components.wled.config_flow import CONF_KEEP_MAIN_LIGHT
from homeassistant.components.wled.const import DOMAIN
from homeassistant.const import CONF_HOST
from homeassistant.core import HomeAssistant
Expand All @@ -22,7 +23,7 @@ def mock_config_entry() -> MockConfigEntry:
domain=DOMAIN,
data={CONF_HOST: "192.168.1.123"},
unique_id="aabbccddeeff",
minor_version=2,
minor_version=3,
)


Expand Down Expand Up @@ -89,12 +90,19 @@ def mock_wled(
yield wled


@pytest.fixture
def opt_keep_main_light() -> bool | None:
"""Return the conf_keep_main_light option."""
return None


@pytest.fixture
async def init_integration(
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
mock_config_entry: MockConfigEntry,
mock_wled: MagicMock,
opt_keep_main_light: bool | None,
) -> MockConfigEntry:
"""Set up the WLED integration for testing."""
mock_config_entry.add_to_hass(hass)
Expand All @@ -106,4 +114,11 @@ async def init_integration(
# time by SCAN_INTERVAL
freezer.tick(1)

if opt_keep_main_light is not None:
hass.config_entries.async_update_entry(
mock_config_entry, options={CONF_KEEP_MAIN_LIGHT: opt_keep_main_light}
)
await hass.config_entries.async_reload(mock_config_entry.entry_id)
await hass.async_block_till_done()

return mock_config_entry
Loading
Loading