diff --git a/homeassistant/components/wled/config_flow.py b/homeassistant/components/wled/config_flow.py index fb9967e321a227..337d608ae11dab 100644 --- a/homeassistant/components/wled/config_flow.py +++ b/homeassistant/components/wled/config_flow.py @@ -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 ( @@ -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" except WLEDConnectionError: errors["base"] = "cannot_connect" else: @@ -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") diff --git a/homeassistant/components/wled/coordinator.py b/homeassistant/components/wled/coordinator.py index fc84d5084909b8..af3d1f583cb4dd 100644 --- a/homeassistant/components/wled/coordinator.py +++ b/homeassistant/components/wled/coordinator.py @@ -9,6 +9,7 @@ WLEDConnectionClosedError, WLEDError, WLEDReleases, + WLEDUnsupportedVersionError, ) from homeassistant.config_entries import ConfigEntry @@ -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, diff --git a/homeassistant/components/wled/strings.json b/homeassistant/components/wled/strings.json index 4cea5ef235f2b7..9719406472e638 100644 --- a/homeassistant/components/wled/strings.json +++ b/homeassistant/components/wled/strings.json @@ -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": { @@ -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}" } }, "options": { diff --git a/tests/components/wled/test_config_flow.py b/tests/components/wled/test_config_flow.py index d3ed9ffa962213..984b511be7a11d 100644 --- a/tests/components/wled/test_config_flow.py +++ b/tests/components/wled/test_config_flow.py @@ -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 @@ -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: @@ -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, diff --git a/tests/components/wled/test_coordinator.py b/tests/components/wled/test_coordinator.py index 2460a887e19165..8c45888422acc2 100644 --- a/tests/components/wled/test_coordinator.py +++ b/tests/components/wled/test_coordinator.py @@ -11,6 +11,7 @@ WLEDConnectionClosedError, WLEDConnectionError, WLEDError, + WLEDUnsupportedVersionError, ) from homeassistant.components.wled.const import SCAN_INTERVAL @@ -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