Skip to content

Normalize unique ID in WLED#157901

Merged
joostlek merged 17 commits into
home-assistant:devfrom
mik-laj:wled-normalize-unique-id
Dec 23, 2025
Merged

Normalize unique ID in WLED#157901
joostlek merged 17 commits into
home-assistant:devfrom
mik-laj:wled-normalize-unique-id

Conversation

@mik-laj
Copy link
Copy Markdown
Contributor

@mik-laj mik-laj commented Dec 4, 2025

Breaking change

Proposed change

Close: #157879

We recently started using unique IDs to verify that we were connecting to the correct device. However, it turned out that some users had their unique IDs set to uppercase. I'm not sure how this could have happened, as WLED always returns lowercase letters, but this prevented them from using this integration.

This PR normalizes WLED MAC addresses to lowercase to fix the issue. It adds a migration from version 1.1 to 1.2 that normalizes existing unique IDs and handles duplicate entries during the migration process.

Key changes:

  • Adds normalize_mac_address() function to convert MAC addresses to lowercase and remove separators
  • Implements config entry migration from version 1.1 to 1.2 to normalize existing unique IDs
  • Applies normalization consistently in config flows and coordinator MAC address comparisons

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 link to the changelog, or at minimum a diff between library versions is added to the PR description.

To help with the load of incoming pull requests:

@home-assistant
Copy link
Copy Markdown
Contributor

home-assistant Bot commented Dec 4, 2025

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 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 add-label needs-more-information Add a label (needs-more-information, problem in dependency, problem in custom component) to the pull request.
  • @home-assistant remove-label needs-more-information Remove a label (needs-more-information, problem in dependency, problem in custom component) 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 normalizes MAC addresses (unique IDs) in the WLED integration to lowercase format to fix issues where some users had uppercase MAC addresses stored in their configuration entries. The change includes duplicate detection, user-facing repair issues, and normalization in both existing entries and new config flows.

Key Changes

  • Added MAC address normalization function to ensure consistent lowercase format
  • Implemented duplicate entry detection with user-facing repair issues
  • Applied normalization throughout config flow and coordinator initialization

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
homeassistant/components/wled/__init__.py Added duplicate detection logic, repair issue creation, and unique ID normalization for existing entries
homeassistant/components/wled/coordinator.py Added normalize_mac_address() function and applied normalization when comparing device MAC to config entry
homeassistant/components/wled/config_flow.py Applied MAC normalization in user and zeroconf config flows
homeassistant/components/wled/strings.json Added repair issue descriptions for duplicate config entries
tests/components/wled/conftest.py Added title to mock config entry fixture for testing
tests/components/wled/test_init.py Added tests for duplicate detection and normalization scenarios
tests/components/wled/test_config_flow.py Added parameterized tests to verify normalization in config flows

Comment thread homeassistant/components/wled/strings.json Outdated
Comment thread homeassistant/components/wled/coordinator.py Outdated
Comment thread tests/components/wled/test_init.py Outdated
Copy link
Copy Markdown
Contributor

@deviantintegral deviantintegral left a comment

Choose a reason for hiding this comment

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

I left a few notes. Otherwise, I can test this live sometime tomorrow. Thanks for the quick PR!

Comment thread homeassistant/components/wled/strings.json Outdated
Comment thread homeassistant/components/wled/coordinator.py Outdated
},
"issues": {
"config_entry_unique_id_collision": {
"description": "There are multiple WLED config entries with the same device MAC addres.\nThe config entries are named {titles}.\n\nTo fix this error, [configure the integration]({configure_url}) and remove all except one of the duplicates.\n\nNote: Another group of duplicates may be revealed after removing these duplicates.",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this text remind users to look for disabled or ignored integrations too? Since they don't show up in the list at the integration level. I only figured it out because I knew enough to splunk through the underlying JSON.

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.

We can skip completely ignored entries. If the user ignore them, we should too.

Comment thread homeassistant/components/wled/__init__.py Outdated
Comment thread homeassistant/components/wled/__init__.py Outdated
@deviantintegral
Copy link
Copy Markdown
Contributor

  • In the case where the duplicate config entry is ignored, the WLED integration is able to connect to the device with no repairs and no user interactions.
  • When I stopped ignoring the duplicate integration, after a restart it went away entirely from the config registry.

This means I didn't test the repair workflow, but I'd say the PR as is fixes the issues I encountered well. Thanks!

@joostlek joostlek added this to the 2025.12.1 milestone Dec 4, 2025
Copy link
Copy Markdown
Member

@joostlek joostlek left a comment

Choose a reason for hiding this comment

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

I would say let's bump the minor version of the config entry and implement such thing in the migration of the entry.

Do we have any reason to believe people have duplicate entries? What about entity unique ids?

Comment thread homeassistant/components/wled/coordinator.py Outdated
@home-assistant home-assistant Bot marked this pull request as draft December 4, 2025 13:40
@home-assistant
Copy link
Copy Markdown
Contributor

home-assistant Bot commented Dec 4, 2025

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

@mik-laj
Copy link
Copy Markdown
Contributor Author

mik-laj commented Dec 4, 2025

I would say let's bump the minor version of the config entry and implement such thing in the migration of the entry.

I thought about it, but it wouldn't allow us to handle conflicts because the migration can only be run once. Here this code needs to be run multiple times until the user fixes all the conflicts. I could just set a unique ID without checking for duplicates, but that will stop working in 2025.11.

breaks_in_ha_version="2025.11.0",

Do we have any reason to believe people have duplicate entries?

Yes. Users in the discussion reported that they had duplicates because Zeroconf/DHCP discovery was likely creating entries with the wrong MAC address. and they created their entries manually and had duplicates, but that's just speculation, as I haven't been able to confirm this with certainty. I only saw that WLED always returned lowercase letters, and Discovery is another source for the MAC address, and I saw that it wasn't normalized.

Here is normalization in WLED:
https://github.com/wled/WLED/blob/cc5b5047719668b4e36d9ba70e8cf7896c3b9471/wled00/wled.cpp#L441-L444
https://github.com/wled/WLED/blob/cc5b5047719668b4e36d9ba70e8cf7896c3b9471/wled00/json.cpp#L886

An alternative is to completely drop the unique ID repair, because when we compare the MAC address, we normalize it anyway. It's not a big deal if someone created a config entry and has the unique ID in the wrong format, because now the integration will still work.

What about entity unique ids?

This shouldn't cause a problem as they are always set based on the values ​​from the WLED API.

self._attr_unique_id = f"{coordinator.data.info.mac_address}_{description.key}"

Comment thread homeassistant/components/wled/__init__.py Outdated
Comment thread homeassistant/components/wled/coordinator.py Outdated
Comment on lines +120 to +124
if len(duplicate_entries) - len(ignored_entries) > 1:
_LOGGER.warning(
"Found multiple WLED config entries with the same MAC address, cannot migrate to version 1.2"
)
return False
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What would the other ones be? mDNS? Maybe disabled? Which ones are ones we don't know what to do with?

Copy link
Copy Markdown
Contributor Author

@mik-laj mik-laj Dec 5, 2025

Choose a reason for hiding this comment

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

The problem is with those entries that were created with an incorrect unique ID, e.g. AABBCCDDEEFF. The WLED API always returns a lowercase value, so I don't know where the invalid entries came from or how many there are. My guess is that if someone managed to get two non-ignored entries to work, one will likely have no entities, because entities always assign a unique ID based on the API data. This seems to me to be a very special edge case and it won't happen in practice now.

@home-assistant home-assistant Bot marked this pull request as draft December 5, 2025 12:29
@frenck frenck modified the milestones: 2025.12.1, 2025.12.2 Dec 5, 2025
@altShiftDev
Copy link
Copy Markdown

Any ETA on when this will go out? I've had LED strips that I haven't been able to control for the past 4 days since this issue appeared.

@mik-laj
Copy link
Copy Markdown
Contributor Author

mik-laj commented Dec 5, 2025

@altShiftDev Does deleting and re-adding the device solve the problem? Can you verify this?

We don't have an ETA, but we're working hard on it.

@altShiftDev
Copy link
Copy Markdown

@altShiftDev Does deleting and re-adding the device solve the problem? Can you verify this?

It likely would but it would also remove those entities from all scenes and automations. That's quite disruptive and I'd like to avoid doing so if this fix is around the corner.

I can confirm that the right-click menu "reconfigure" does unfortunately not "reconfigure" anything but the IP address and gets tripped up at the mac address comparison. It would be extremely helpful to allow both IP and Mac address reconfiguring to avoid these lockouts in the future. I see no reason this can't be exposed to the user.

image

@mik-laj
Copy link
Copy Markdown
Contributor Author

mik-laj commented Dec 5, 2025

It would be extremely helpful to allow both IP and Mac address reconfiguring to avoid these lockouts in the future. I see no reason this can't be exposed to the user.

Allowing users to edit the MAC address isn’t a good idea because the MAC is used as the unique_id for the config entry and as the primary device identifier in Home Assistant. Changing it would break the link between the entry, the device registry and all related entities, potentially creating duplicates, collisions or orphaned entities.

It would also recreate the exact problems previous PR was designed to prevent. The original bug was that HA could accidentally associate a WLED entry with the wrong physical device when only the host/IP changed. This sometimes caused a single device to be linked to multiple config entries or made entities appear under the wrong controller. That is why explicit MAC verification was added in the first place:
#155491

Letting the MAC be user-editable would effectively disable that protection and open the door to the same class of issues again.

@altShiftDev
Copy link
Copy Markdown

Respectfully I disagree.

Allowing the power users to edit the MAC is a better idea than doing a blind string comparison without first sanitizing your inputs. It also allows users to fix their own issues instead of waiting on hotfixes when things break again in the future.

Allowing explicit MAC verification is fine, enforcing it without bulletproof sanitizing of formats like uppercase/lowercase with and without colons is not fine.

Letting the MAC be user-editable would effectively disable that protection and open the door to the same class of issues again.

There's no reason why allowing user-editable MAC addresses would recreate the past bug you're describing. I'm not saying to rollback the past protections, I'm asking you to allow power users to fix their own issues when things go wrong.

@mik-laj
Copy link
Copy Markdown
Contributor Author

mik-laj commented Dec 6, 2025

If you need the change sooner, you can override the integration locally. Home Assistant supports loading a core integration as a custom component:

  1. Copy the wled folder from homeassistant/components/wled into <config>/custom_components/wled.
  2. Add a "version" field with a dummy value (for example "0.0.0") to the manifest.json file.
  3. Apply whatever modifications you want, including making the MAC editable, or cherry-pick this PR.
  4. Restart Home Assistant so your custom version is used instead of the core one.

Alternatively, you can stay on the previous Home Assistant version that didn’t yet include MAC validation and wait until the fix is released. Both approaches let you continue using the setup you prefer while the upstream review runs its course.

@mik-laj mik-laj requested a review from joostlek December 6, 2025 13:02
@frenck frenck modified the milestones: 2025.12.2, 2025.12.3 Dec 8, 2025
@mik-laj mik-laj marked this pull request as ready for review December 8, 2025 23:35
@altShiftDev
Copy link
Copy Markdown

1. Copy the `wled` folder from `homeassistant/components/wled` into `<config>/custom_components/wled`.

Alternatively, you can stay on the previous Home Assistant version that didn’t yet include MAC validation and wait until the fix is released. Both approaches let you continue using the setup you prefer while the upstream review runs its course.

This folder doesn't exist, not sure if it's because I'm on the docker version or something else.

It would be great if you accelerated this PR given it's broken the HA wled functionality for at least a few users.

@mik-laj
Copy link
Copy Markdown
Contributor Author

mik-laj commented Dec 9, 2025

Here is folder with WLED component: https://github.com/home-assistant/core/tree/dev/homeassistant/components/wled

For HAOS, the /config directory is accessible from Visual Studio Server or Terminal.
Screenshot 2025-12-09 at 22 50 32
Screenshot 2025-12-09 at 22 51 45

For plain docker, the /config directory is mounted in user-controlled volume

I'm doing my best to finish this PR, but I have to wait for the reviewers, who also have other challenges and have to divide their time between other components.

@frenck frenck modified the milestones: 2025.12.3, 2025.12.4 Dec 12, 2025
@bramkragten bramkragten modified the milestones: 2025.12.4, 2025.12.5 Dec 19, 2025
@joostlek joostlek merged commit 7c14862 into home-assistant:dev Dec 23, 2025
36 checks passed
@mik-laj mik-laj deleted the wled-normalize-unique-id branch December 24, 2025 07:21
@github-actions github-actions Bot locked and limited conversation to collaborators Dec 25, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MAC address does not match the configured device in 2025.12.0

7 participants