Skip to content
Merged
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
6 changes: 5 additions & 1 deletion homeassistant/components/wled/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing import Any

import voluptuous as vol
from wled import WLED, Device, WLEDConnectionError
from wled import WLED, Device, WLEDConnectionError, WLEDUnsupportedVersionError

from homeassistant.components import onboarding
from homeassistant.config_entries import (
Expand Down Expand Up @@ -48,6 +48,8 @@ async def async_step_user(
if user_input is not None:
try:
device = await self._async_get_device(user_input[CONF_HOST])
except WLEDUnsupportedVersionError:
errors["base"] = "unsupported_version"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ideally, I'd like to display the original error message here as well, but I have no idea how to do that. Any ideas?

Copy link
Member

Choose a reason for hiding this comment

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

You can use placeholders, but that isn't meant for big errors tbf

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now that we have this merged, I’m not going to worry about it any further.

Thank you very much for the quick review. It genuinely made me happy to see this change merged so fast. My previous PR for the WLED integration waited several months before it finally got merged, and this time we were even faster than the GitHub copilot.

My next step is the quality scale, since that was one of the missing pieces: #155482

except WLEDConnectionError:
errors["base"] = "cannot_connect"
else:
Expand Down Expand Up @@ -110,6 +112,8 @@ async def async_step_zeroconf(
self.discovered_host = discovery_info.host
try:
self.discovered_device = await self._async_get_device(discovery_info.host)
except WLEDUnsupportedVersionError:
return self.async_abort(reason="unsupported_version")
except WLEDConnectionError:
return self.async_abort(reason="cannot_connect")

Expand Down
9 changes: 9 additions & 0 deletions homeassistant/components/wled/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
WLEDConnectionClosedError,
WLEDError,
WLEDReleases,
WLEDUnsupportedVersionError,
)

from homeassistant.config_entries import ConfigEntry
Expand Down Expand Up @@ -115,6 +116,14 @@ async def _async_update_data(self) -> WLEDDevice:
"""Fetch data from WLED."""
try:
device = await self.wled.update()
except WLEDUnsupportedVersionError as error:
# Error message from WLED library contains version info
# better to show that to user, but it is not translatable.
raise ConfigEntryError(
translation_domain=DOMAIN,
translation_key="unsupported_version",
translation_placeholders={"error": str(error)},
) from error
except WLEDError as error:
raise UpdateFailed(
translation_domain=DOMAIN,
Expand Down
12 changes: 10 additions & 2 deletions homeassistant/components/wled/strings.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
{
"common": {
"unsupported_version": "The WLED device's firmware version is not supported."
},
"config": {
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]",
"unique_id_mismatch": "MAC address does not match the configured device. Expected to connect to device with MAC: `{expected_mac}`, but connected to device with MAC: `{actual_mac}`. \n\nPlease ensure you reconfigure against the same device."
"unique_id_mismatch": "MAC address does not match the configured device. Expected to connect to device with MAC: `{expected_mac}`, but connected to device with MAC: `{actual_mac}`. \n\nPlease ensure you reconfigure against the same device.",
"unsupported_version": "[%key:component::wled::common::unsupported_version%]"
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"unsupported_version": "[%key:component::wled::common::unsupported_version%]"
},
"flow_title": "{name}",
"step": {
Expand Down Expand Up @@ -138,6 +143,9 @@
},
"mac_address_mismatch": {
"message": "MAC address does not match the configured device. Expected to connect to device with MAC: {expected_mac}, but connected to device with MAC: {actual_mac}."
},
"unsupported_version": {
"message": "The WLED device's firmware version is not supported: {error}"
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

The error message lacks actionable guidance for users. According to the coding guidelines, error messages should be clear and helpful. Consider providing specific steps users can take to resolve the issue, such as:

"message": "The WLED device's firmware version is not supported: {error}. Please update your WLED device firmware to a supported version."

This gives users a clear action they can take to resolve the problem.

Suggested change
"message": "The WLED device's firmware version is not supported: {error}"
"message": "The WLED device's firmware version is not supported: {error}. To fix this issue, please update your WLED device to the latest firmware version. You can find update instructions on the WLED website (https://kno.wled.ge/firmware-updates/) or in the WLED app."

Copilot uses AI. Check for mistakes.
}
},
"options": {
Expand Down
43 changes: 42 additions & 1 deletion tests/components/wled/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from unittest.mock import AsyncMock, MagicMock

import pytest
from wled import WLEDConnectionError
from wled import WLEDConnectionError, WLEDUnsupportedVersionError

from homeassistant.components.wled.const import CONF_KEEP_MAIN_LIGHT, DOMAIN
from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF
Expand Down Expand Up @@ -215,6 +215,23 @@ async def test_connection_error(hass: HomeAssistant, mock_wled: MagicMock) -> No
assert result.get("errors") == {"base": "cannot_connect"}


async def test_unsupported_version_error(
hass: HomeAssistant, mock_wled: MagicMock
) -> None:
"""Test we show user form on WLED unsupported version error."""
mock_wled.update.side_effect = WLEDUnsupportedVersionError

result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_USER},
data={CONF_HOST: "example.com"},
)

assert result.get("type") is FlowResultType.FORM
assert result.get("step_id") == "user"
assert result.get("errors") == {"base": "unsupported_version"}


async def test_zeroconf_connection_error(
hass: HomeAssistant, mock_wled: MagicMock
) -> None:
Expand All @@ -239,6 +256,30 @@ async def test_zeroconf_connection_error(
assert result.get("reason") == "cannot_connect"


async def test_zeroconf_unsupported_version_error(
hass: HomeAssistant, mock_wled: MagicMock
) -> None:
"""Test we abort zeroconf flow on WLED unsupported version error."""
mock_wled.update.side_effect = WLEDUnsupportedVersionError

result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_ZEROCONF},
data=ZeroconfServiceInfo(
ip_address=ip_address("192.168.1.123"),
ip_addresses=[ip_address("192.168.1.123")],
hostname="example.local.",
name="mock_name",
port=None,
properties={CONF_MAC: "aabbccddeeff"},
type="mock_type",
),
)

assert result.get("type") is FlowResultType.ABORT
assert result.get("reason") == "unsupported_version"


@pytest.mark.usefixtures("mock_wled")
async def test_user_device_exists_abort(
hass: HomeAssistant,
Expand Down
27 changes: 27 additions & 0 deletions tests/components/wled/test_coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
WLEDConnectionClosedError,
WLEDConnectionError,
WLEDError,
WLEDUnsupportedVersionError,
)

from homeassistant.components.wled.const import SCAN_INTERVAL
Expand Down Expand Up @@ -218,3 +219,29 @@ async def test_fail_when_other_device(
assert (
"MAC address does not match the configured device." in mock_config_entry.reason
)


async def test_fail_when_unsupported_version(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_wled: MagicMock,
) -> None:
"""Ensure entry fails to setup when unsupported version."""
mock_wled.update.side_effect = WLEDUnsupportedVersionError(
"Unsupported firmware version 0.14.0-b1. Minimum required version is 0.14.0. "
"Please update your WLED device."
)

mock_config_entry.add_to_hass(hass)

await hass.config_entries.async_setup(mock_config_entry.entry_id)

await hass.async_block_till_done()

assert mock_config_entry.state == ConfigEntryState.SETUP_ERROR
assert mock_config_entry.reason
assert (
"The WLED device's firmware version is not supported:"
in mock_config_entry.reason
)
assert "0.14.0-b1" in mock_config_entry.reason
Loading