diff --git a/homeassistant/components/flux_led/config_flow.py b/homeassistant/components/flux_led/config_flow.py index b6efc763b6d..d0190730ed7 100644 --- a/homeassistant/components/flux_led/config_flow.py +++ b/homeassistant/components/flux_led/config_flow.py @@ -238,7 +238,14 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): ) -> FluxLEDDiscovery: """Try to connect.""" self._async_abort_entries_match({CONF_HOST: host}) - if device := await async_discover_device(self.hass, host): + if (device := await async_discover_device(self.hass, host)) and device[ + ATTR_MODEL_DESCRIPTION + ]: + # Older models do not return enough information + # to build the model description via UDP so we have + # to fallback to making a tcp connection to avoid + # identifying the device as the chip model number + # AKA `HF-LPB100-ZJ200` return device bulb = async_wifi_bulb_for_host(host) try: diff --git a/tests/components/flux_led/__init__.py b/tests/components/flux_led/__init__.py index 764c33686b7..6bfe02990a2 100644 --- a/tests/components/flux_led/__init__.py +++ b/tests/components/flux_led/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations import asyncio +from contextlib import contextmanager import datetime from typing import Callable from unittest.mock import AsyncMock, MagicMock, patch @@ -162,11 +163,20 @@ def _patch_discovery(device=None, no_device=False): async def _discovery(*args, **kwargs): if no_device: raise OSError - return [FLUX_DISCOVERY] + return [] if no_device else [device or FLUX_DISCOVERY] - return patch( - "homeassistant.components.flux_led.AIOBulbScanner.async_scan", new=_discovery - ) + @contextmanager + def _patcher(): + with patch( + "homeassistant.components.flux_led.AIOBulbScanner.async_scan", + new=_discovery, + ), patch( + "homeassistant.components.flux_led.AIOBulbScanner.getBulbInfo", + return_value=[] if no_device else [device or FLUX_DISCOVERY], + ): + yield + + return _patcher() def _patch_wifibulb(device=None, no_device=False): diff --git a/tests/components/flux_led/test_config_flow.py b/tests/components/flux_led/test_config_flow.py index 4c956358818..a546120ae41 100644 --- a/tests/components/flux_led/test_config_flow.py +++ b/tests/components/flux_led/test_config_flow.py @@ -31,6 +31,7 @@ from . import ( DEFAULT_ENTRY_TITLE, DHCP_DISCOVERY, FLUX_DISCOVERY, + FLUX_DISCOVERY_PARTIAL, IP_ADDRESS, MAC_ADDRESS, MODULE, @@ -435,6 +436,35 @@ async def test_discovered_by_dhcp_no_udp_response(hass): assert mock_async_setup_entry.called +async def test_discovered_by_dhcp_partial_udp_response_fallback_tcp(hass): + """Test we can setup when discovered from dhcp but part of the udp response is missing.""" + + with _patch_discovery(no_device=True), _patch_wifibulb(): + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_DHCP}, data=DHCP_DISCOVERY + ) + await hass.async_block_till_done() + + assert result["type"] == RESULT_TYPE_FORM + assert result["errors"] is None + + with _patch_discovery(device=FLUX_DISCOVERY_PARTIAL), _patch_wifibulb(), patch( + f"{MODULE}.async_setup", return_value=True + ) as mock_async_setup, patch( + f"{MODULE}.async_setup_entry", return_value=True + ) as mock_async_setup_entry: + result2 = await hass.config_entries.flow.async_configure(result["flow_id"], {}) + await hass.async_block_till_done() + + assert result2["type"] == "create_entry" + assert result2["data"] == { + CONF_HOST: IP_ADDRESS, + CONF_NAME: DEFAULT_ENTRY_TITLE, + } + assert mock_async_setup.called + assert mock_async_setup_entry.called + + async def test_discovered_by_dhcp_no_udp_response_or_tcp_response(hass): """Test we can setup when discovered from dhcp but no udp response or tcp response.""" diff --git a/tests/components/flux_led/test_light.py b/tests/components/flux_led/test_light.py index 6f08ae8a307..92ea0fd8d39 100644 --- a/tests/components/flux_led/test_light.py +++ b/tests/components/flux_led/test_light.py @@ -80,7 +80,7 @@ async def test_light_unique_id(hass: HomeAssistant) -> None: ) config_entry.add_to_hass(hass) bulb = _mocked_bulb() - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -100,7 +100,7 @@ async def test_light_goes_unavailable_and_recovers(hass: HomeAssistant) -> None: ) config_entry.add_to_hass(hass) bulb = _mocked_bulb() - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -190,7 +190,7 @@ async def test_rgb_light(hass: HomeAssistant) -> None: bulb.raw_state = bulb.raw_state._replace(model_num=0x33) # RGB only model bulb.color_modes = {FLUX_COLOR_MODE_RGB} bulb.color_mode = FLUX_COLOR_MODE_RGB - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(no_device=True), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -294,7 +294,7 @@ async def test_rgb_light_auto_on(hass: HomeAssistant) -> None: bulb.raw_state = bulb.raw_state._replace(model_num=0x33) # RGB only model bulb.color_modes = {FLUX_COLOR_MODE_RGB} bulb.color_mode = FLUX_COLOR_MODE_RGB - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -407,7 +407,7 @@ async def test_rgb_cct_light(hass: HomeAssistant) -> None: bulb.raw_state = bulb.raw_state._replace(model_num=0x35) # RGB & CCT model bulb.color_modes = {FLUX_COLOR_MODE_RGB, FLUX_COLOR_MODE_CCT} bulb.color_mode = FLUX_COLOR_MODE_RGB - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -526,7 +526,7 @@ async def test_rgbw_light(hass: HomeAssistant) -> None: bulb = _mocked_bulb() bulb.color_modes = {FLUX_COLOR_MODE_RGBW} bulb.color_mode = FLUX_COLOR_MODE_RGBW - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -628,7 +628,7 @@ async def test_rgb_or_w_light(hass: HomeAssistant) -> None: bulb = _mocked_bulb() bulb.color_modes = FLUX_COLOR_MODES_RGB_W bulb.color_mode = FLUX_COLOR_MODE_RGB - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -739,7 +739,7 @@ async def test_rgbcw_light(hass: HomeAssistant) -> None: bulb.raw_state = bulb.raw_state._replace(warm_white=1, cool_white=2) bulb.color_modes = {FLUX_COLOR_MODE_RGBWW, FLUX_COLOR_MODE_CCT} bulb.color_mode = FLUX_COLOR_MODE_RGBWW - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -879,7 +879,7 @@ async def test_white_light(hass: HomeAssistant) -> None: bulb.protocol = None bulb.color_modes = {FLUX_COLOR_MODE_DIM} bulb.color_mode = FLUX_COLOR_MODE_DIM - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -930,7 +930,7 @@ async def test_no_color_modes(hass: HomeAssistant) -> None: bulb.protocol = None bulb.color_modes = set() bulb.color_mode = None - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -974,7 +974,7 @@ async def test_rgb_light_custom_effects(hass: HomeAssistant) -> None: bulb = _mocked_bulb() bulb.color_modes = {FLUX_COLOR_MODE_RGB} bulb.color_mode = FLUX_COLOR_MODE_RGB - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -1056,7 +1056,7 @@ async def test_rgb_light_custom_effects_invalid_colors( bulb = _mocked_bulb() bulb.color_modes = {FLUX_COLOR_MODE_RGB} bulb.color_mode = FLUX_COLOR_MODE_RGB - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -1085,7 +1085,7 @@ async def test_rgb_light_custom_effect_via_service( bulb = _mocked_bulb() bulb.color_modes = {FLUX_COLOR_MODE_RGB} bulb.color_mode = FLUX_COLOR_MODE_RGB - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -1230,7 +1230,7 @@ async def test_addressable_light(hass: HomeAssistant) -> None: bulb.raw_state = bulb.raw_state._replace(model_num=0x33) # RGB only model bulb.color_modes = {FLUX_COLOR_MODE_ADDRESSABLE} bulb.color_mode = FLUX_COLOR_MODE_ADDRESSABLE - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() diff --git a/tests/components/flux_led/test_number.py b/tests/components/flux_led/test_number.py index 11df6daae4a..325307f1f32 100644 --- a/tests/components/flux_led/test_number.py +++ b/tests/components/flux_led/test_number.py @@ -41,7 +41,7 @@ async def test_number_unique_id(hass: HomeAssistant) -> None: ) config_entry.add_to_hass(hass) bulb = _mocked_bulb() - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -64,7 +64,7 @@ async def test_rgb_light_effect_speed(hass: HomeAssistant) -> None: bulb.color_modes = {FLUX_COLOR_MODE_RGB} bulb.color_mode = FLUX_COLOR_MODE_RGB - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -129,7 +129,7 @@ async def test_original_addressable_light_effect_speed(hass: HomeAssistant) -> N bulb.color_mode = FLUX_COLOR_MODE_RGB bulb.effect = "7 colors change gradually" bulb.speed = 50 - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() @@ -186,7 +186,7 @@ async def test_addressable_light_effect_speed(hass: HomeAssistant) -> None: bulb.color_mode = FLUX_COLOR_MODE_RGB bulb.effect = "RBM 1" bulb.speed = 50 - with _patch_discovery(device=bulb), _patch_wifibulb(device=bulb): + with _patch_discovery(), _patch_wifibulb(device=bulb): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done() diff --git a/tests/components/flux_led/test_switch.py b/tests/components/flux_led/test_switch.py index 852e1efd49e..b569d51e13a 100644 --- a/tests/components/flux_led/test_switch.py +++ b/tests/components/flux_led/test_switch.py @@ -35,7 +35,7 @@ async def test_switch_on_off(hass: HomeAssistant) -> None: ) config_entry.add_to_hass(hass) switch = _mocked_switch() - with _patch_discovery(device=switch), _patch_wifibulb(device=switch): + with _patch_discovery(), _patch_wifibulb(device=switch): await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}}) await hass.async_block_till_done()