Skip to content

Fix WLED entity naming for multi-segment setups#169670

Open
mik-laj wants to merge 2 commits intohome-assistant:devfrom
mik-laj:feat/wled-main-light
Open

Fix WLED entity naming for multi-segment setups#169670
mik-laj wants to merge 2 commits intohome-assistant:devfrom
mik-laj:feat/wled-main-light

Conversation

@mik-laj
Copy link
Copy Markdown
Contributor

@mik-laj mik-laj commented May 2, 2026

Part of: #124271.

Breaking change

No breaking change for existing installations — the migration sets keep_main_light = False, preserving the current entity names and IDs.

Users who had previously enabled Keep main light manually will see friendly name changes: the main light loses the "Main" suffix, and segment 0 gains a "Segment 0" qualifier. Entity IDs are not affected.

Problems solved

  • Main light as the primary entity — the main light controlled the whole device but was named "Main", while segment 0 carried the device name. This PR inverts that: the main light gets the device name and segment 0 gets a "Segment 0" qualifier.
  • More predictable entity IDs for multi-segment setups — the main light is now light.<device> for new installations, instead of light.<device>_main.
  • Consistent segment names across all controls — segment 0 was missing the "Segment 0" qualifier on color palette, speed, intensity, freeze, and reverse, while segment 1 had it. With keep_main_light = True, all segments are named consistently.
  • Predictable entity IDs for segment controls — with consistent names, entity IDs follow a uniform pattern: select.<device>_segment_0_color_palette, select.<device>_segment_1_color_palette, etc.
  • keep_main_light enabled by default — promotes the more idiomatic approach where the master controller and individual segments are separate entities, rather than merging both roles into segment 0.

Proposed change

This PR makes the main light the primary entity when keep_main_light is enabled:

  • WLEDMainLight gets name = None → uses the device name (e.g. "Garage Door Light"), becoming the true primary entity of the device.
  • WLEDSegmentLight segment 0 gets its proper "Segment 0" name (instead of inheriting the device name).
  • The same naming correction is applied consistently across all segment-based entities: number (speed, intensity), select (color palette), and switch (freeze, reverse).

keep_main_light is now True by default for new installations (config entry version 1.3). This ensures the main light registers first and naturally claims light.<device>, avoiding entity ID collisions. It also brings the integration closer to best practices: the old default merged two distinct concepts into one entity (segment 0 acted as both segment and master controller). With keep_main_light = True, the main light controls the device and each segment controls only itself.

Users with a single segment who prefer a simpler setup can still disable Keep Master Light in the integration options. In that mode, no main light entity is created, segment 0 becomes the primary entity (named after the device, without a "Segment 0" qualifier), and associated controls (color palette, speed, intensity, freeze, reverse) also drop the segment prefix.

Entity ID scenarios

All examples use a device named Garage Door Light.

New installation (v1.3, keep_main_light = True by default)

  • light.garage_door_light — main light (primary entity, controls the whole strip)
  • light.garage_door_light_segment_0 — segment 0
  • light.garage_door_light_segment_1 — segment 1 (if present)
  • select.garage_door_light_segment_0_color_palette — color palette for segment 0
  • select.garage_door_light_segment_1_color_palette — color palette for segment 1

Existing single-segment installation upgrading from v1.2 (migration sets keep_main_light = False)

No entity IDs change. The migration preserves the current layout exactly:

  • light.garage_door_light — segment 0 (same as before, no main light entity)
  • select.garage_door_light_color_palette — color palette for segment 0 (no segment qualifier)
  • switch.garage_door_light_freeze — freeze for segment 0 (no segment qualifier)

Existing single-segment installation upgrading from v1.2, then adding a second segment

After upgrade the user has keep_main_light = False and segment 0 at light.garage_door_light. When a second segment is added, the main light is created for the first time. Before this PR it would register as light.garage_door_light_main (name = "Main"); after this PR it tries to claim light.garage_door_light (name = None), but that is already taken by segment 0, so it lands on light.garage_door_light_2:

  • light.garage_door_light — segment 0 (frozen; with keep_main_light = False it keeps no "Segment 0" qualifier)
  • light.garage_door_light_2 — main light (new entity; suffix because light.garage_door_light is taken)
  • light.garage_door_light_segment_1 — segment 1 (new entity)
  • select.garage_door_light_color_palette — color palette for segment 0 (frozen; no qualifier)
  • select.garage_door_light_segment_1_color_palette — color palette for segment 1 (new entity)

This is an edge case. Users who end up with light.garage_door_light_2 can rename it via the entity registry.

Existing multi-segment installation upgrading from v1.2 (migration sets keep_main_light = False)

Nothing changes. With keep_main_light = False and multiple segments, the main light still uses the "Main" translation key — name = None is only applied when keep_main_light = True. All entity IDs and friendly names remain exactly as before:

  • light.garage_door_light_main — main light (unchanged)
  • light.garage_door_light — segment 0 (unchanged)
  • light.garage_door_light_segment_1 — segment 1 (unchanged)
  • select.garage_door_light_color_palette — color palette for segment 0 (unchanged)
  • select.garage_door_light_segment_1_color_palette — color palette for segment 1 (unchanged)

Existing installation where keep_main_light was manually enabled before this PR

All entity IDs are frozen — only friendly names change. Before this PR, segment 0 never had a "Segment 0" qualifier regardless of keep_main_light; this PR adds it for all segment 0 entities when keep_main_light = True.

  • light.garage_door_light_main — main light; friendly name changes from "Garage Door Light Main" → "Garage Door Light"
  • light.garage_door_light — segment 0; friendly name changes from "Garage Door Light" → "Garage Door Light Segment 0"
  • select.garage_door_light_color_palette — segment 0 color palette; friendly name changes from "Color Palette" → "Segment 0 Color Palette"
  • switch.garage_door_light_freeze — segment 0 freeze; friendly name changes from "Freeze" → "Segment 0 Freeze"
  • number.garage_door_light_speed — segment 0 speed; friendly name changes from "Speed" → "Segment 0 Speed"

New installation (v1.3) where the user later disables keep_main_light

The entity registry does not auto-remap entity IDs. After disabling the option:

  • light.garage_door_light — main light entity becomes unavailable (orphan in registry; unique_id = mac address)
  • light.garage_door_light_segment_0 — segment 0 stays at this ID; it does not reclaim light.garage_door_light
  • select.garage_door_light_color_palette — color palette for segment 0 becomes unavailable (orphan)
  • select.garage_door_light_segment_0_color_palette — new entity for segment 0 color palette

This is an edge case. The keep_main_light option is designed for users who want a stable master entity; disabling it after initial setup is an unusual transition. Orphaned entities can be removed via the entity registry UI.

Follow-up changes

To fully resolve the issues described in #124271, I plan two additional changes:

  • Add group support to WLED main light #169669 — Expose the main light as a light group, so that segments appear nested under the main switch in the UI. This will make the role of the main entity immediately clear to users — they will see the master control at the top and the individual segments beneath it.
  • Use segment names from WLED device #169633 — Copy segment names from the WLED device into Home Assistant, replacing the generic "Segment N" labels with the names the user already configured in the WLED app.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • I understand the code I am submitting and can explain how it works.
  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.
  • Any generated code has been carefully reviewed for correctness and compliance with project standards.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies a diff between library versions and ideally a link to the changelog/release notes is added to the PR description.

To help with the load of incoming pull requests:

… WLED

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 2, 2026 21:55
@home-assistant home-assistant Bot added cla-signed has-tests integration: wled small-pr PRs with less than 30 lines. Top 100 Integration is ranked within the top 100 by usage Top 200 Integration is ranked within the top 200 by usage labels May 2, 2026
@home-assistant
Copy link
Copy Markdown
Contributor

home-assistant Bot commented May 2, 2026

Hey there @frenck, mind taking a look at this pull request as it has been labeled with an integration (wled) you are listed as a code owner for? Thanks!

Code owner commands

Code owners of wled can trigger bot actions by commenting:

  • @home-assistant close Closes the pull request.
  • @home-assistant mark-draft Mark the pull request as draft.
  • @home-assistant ready-for-review Remove the draft status from the pull request.
  • @home-assistant rename Awesome new title Renames the pull request.
  • @home-assistant reopen Reopen the pull request.
  • @home-assistant unassign wled Removes the current integration label and assignees on the pull request, add the integration domain after the command.
  • @home-assistant update-branch Update the pull request branch with the base branch.
  • @home-assistant add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) to the pull request.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component, problem in config, problem in device, feature-request) on the pull request.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates WLED entity naming so that when keep_main_light is enabled, the master light becomes the device-named entity and segment-based entities expose explicit segment-0 names instead of reusing the base device name.

Changes:

  • Renames the WLED main light to use the device name when keep_main_light is enabled.
  • Applies segment-0-specific naming to WLED light, number, select, and switch entities when the main light is kept.
  • Adds tests covering expected friendly names for single- and multi-segment devices with keep_main_light enabled and disabled.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
homeassistant/components/wled/light.py Updates main light and segment-0 light naming behavior when keep_main_light is enabled.
homeassistant/components/wled/number.py Adds explicit segment translation keys and renames segment-0 number entities under keep_main_light.
homeassistant/components/wled/select.py Renames segment-0 palette select when the main light is retained.
homeassistant/components/wled/switch.py Renames segment-0 freeze/reverse switches when the main light is retained.
tests/components/wled/test_light.py Replaces single-case light test with parametrized friendly-name assertions.
tests/components/wled/test_number.py Adds parametrized friendly-name assertions for number entities.
tests/components/wled/test_select.py Adds parametrized friendly-name assertions for select entities.
tests/components/wled/test_switch.py Adds parametrized friendly-name assertions for switch entities.

Comment on lines +69 to +70
if coordinator.keep_main_light:
self._attr_name = None
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.

Copy link
Copy Markdown
Member

@arturpragacz arturpragacz left a comment

Choose a reason for hiding this comment

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

Changing segment 0's naming for users who never opted into keep_main_light would rename existing entities and silently break automations.

It would not break automations, unique_id remains the same.

@mik-laj mik-laj changed the title Make main light the primary entity when keep_main_light is on in WLED Make main light the primary entity in WLED May 3, 2026
@mik-laj mik-laj marked this pull request as ready for review May 3, 2026 21:25
@mik-laj mik-laj requested a review from frenck as a code owner May 3, 2026 21:25
Copilot AI review requested due to automatic review settings May 3, 2026 21:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.


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.

Comment on lines +69 to +70
if coordinator.keep_main_light:
self._attr_name = None
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.

@mik-laj
Copy link
Copy Markdown
Contributor Author

mik-laj commented May 3, 2026

@arturpragacz Yes and no. :-D

HA has a mechanism to prevent this from breaking the automation by assigning an different entity ID and not changing the ID unless the unique ID changes. However, what I wanted to point out here is that the main entity is "light.wled" by convention (without suffixes). If we now want another entity to have this ID, so we cannot simply assign this ID to our entity, because it may break the automation, because the first segment already uses this ID. Home Assistant has a mechanism to handle this situation by creating an entity called "lgiht.wled_2", but this is a bit confusing as now the main entity ID doesn't follow convention.

I've now looked into this issue deeper and enabled "main light" by default for new installs, so the IDs are now assigned correctly, and I think this approach is more in line with best practices.

@mik-laj mik-laj changed the title Make main light the primary entity in WLED Fix WLED entity naming for multi-segment setups May 3, 2026
@mik-laj mik-laj requested a review from arturpragacz May 4, 2026 00:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

by-code-owner cla-signed has-tests integration: wled Quality Scale: platinum small-pr PRs with less than 30 lines. Top 100 Integration is ranked within the top 100 by usage Top 200 Integration is ranked within the top 200 by usage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants