Skip to content

Commit 9c749a6

Browse files
abmantisfrenck
authored andcommitted
Fix duplicated IP port usage in Govee Light Local (home-assistant#152087)
1 parent 2e33222 commit 9c749a6

File tree

4 files changed

+33
-30
lines changed

4 files changed

+33
-30
lines changed

homeassistant/components/govee_light_local/__init__.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,11 @@
2626
async def async_setup_entry(hass: HomeAssistant, entry: GoveeLocalConfigEntry) -> bool:
2727
"""Set up Govee light local from a config entry."""
2828

29-
# Get source IPs for all enabled adapters
30-
source_ips = await network.async_get_enabled_source_ips(hass)
29+
source_ips = await async_get_source_ips(hass)
3130
_LOGGER.debug("Enabled source IPs: %s", source_ips)
3231

3332
coordinator: GoveeLocalApiCoordinator = GoveeLocalApiCoordinator(
34-
hass=hass,
35-
config_entry=entry,
36-
source_ips=[
37-
source_ip for source_ip in source_ips if isinstance(source_ip, IPv4Address)
38-
],
33+
hass=hass, config_entry=entry, source_ips=source_ips
3934
)
4035

4136
async def await_cleanup():
@@ -76,3 +71,13 @@ async def await_cleanup():
7671
async def async_unload_entry(hass: HomeAssistant, entry: GoveeLocalConfigEntry) -> bool:
7772
"""Unload a config entry."""
7873
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
74+
75+
76+
async def async_get_source_ips(
77+
hass: HomeAssistant,
78+
) -> set[str]:
79+
"""Get the source ips for Govee local."""
80+
source_ips = await network.async_get_enabled_source_ips(hass)
81+
return {
82+
str(source_ip) for source_ip in source_ips if isinstance(source_ip, IPv4Address)
83+
}

homeassistant/components/govee_light_local/config_flow.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44

55
import asyncio
66
from contextlib import suppress
7-
from ipaddress import IPv4Address
87
import logging
98

109
from govee_local_api import GoveeController
1110

12-
from homeassistant.components import network
1311
from homeassistant.core import HomeAssistant
1412
from homeassistant.helpers import config_entry_flow
1513

14+
from . import async_get_source_ips
1615
from .const import (
1716
CONF_LISTENING_PORT_DEFAULT,
1817
CONF_MULTICAST_ADDRESS_DEFAULT,
@@ -24,11 +23,11 @@
2423
_LOGGER = logging.getLogger(__name__)
2524

2625

27-
async def _async_discover(hass: HomeAssistant, adapter_ip: IPv4Address) -> bool:
26+
async def _async_discover(hass: HomeAssistant, adapter_ip: str) -> bool:
2827
controller: GoveeController = GoveeController(
2928
loop=hass.loop,
3029
logger=_LOGGER,
31-
listening_address=str(adapter_ip),
30+
listening_address=adapter_ip,
3231
broadcast_address=CONF_MULTICAST_ADDRESS_DEFAULT,
3332
broadcast_port=CONF_TARGET_PORT_DEFAULT,
3433
listening_port=CONF_LISTENING_PORT_DEFAULT,
@@ -62,14 +61,8 @@ async def _async_discover(hass: HomeAssistant, adapter_ip: IPv4Address) -> bool:
6261
async def _async_has_devices(hass: HomeAssistant) -> bool:
6362
"""Return if there are devices that can be discovered."""
6463

65-
# Get source IPs for all enabled adapters
66-
source_ips = await network.async_get_enabled_source_ips(hass)
67-
_LOGGER.debug("Enabled source IPs: %s", source_ips)
68-
69-
# Run discovery on every IPv4 address and gather results
70-
results = await asyncio.gather(
71-
*[_async_discover(hass, ip) for ip in source_ips if isinstance(ip, IPv4Address)]
72-
)
64+
source_ips = await async_get_source_ips(hass)
65+
results = await asyncio.gather(*[_async_discover(hass, ip) for ip in source_ips])
7366

7467
return any(results)
7568

homeassistant/components/govee_light_local/coordinator.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import asyncio
44
from collections.abc import Callable
5-
from ipaddress import IPv4Address
65
import logging
76

87
from govee_local_api import GoveeController, GoveeDevice
@@ -30,7 +29,7 @@ def __init__(
3029
self,
3130
hass: HomeAssistant,
3231
config_entry: GoveeLocalConfigEntry,
33-
source_ips: list[IPv4Address],
32+
source_ips: set[str],
3433
) -> None:
3534
"""Initialize my coordinator."""
3635
super().__init__(
@@ -45,7 +44,7 @@ def __init__(
4544
GoveeController(
4645
loop=hass.loop,
4746
logger=_LOGGER,
48-
listening_address=str(source_ip),
47+
listening_address=source_ip,
4948
broadcast_address=CONF_MULTICAST_ADDRESS_DEFAULT,
5049
broadcast_port=CONF_TARGET_PORT_DEFAULT,
5150
listening_port=CONF_LISTENING_PORT_DEFAULT,

tests/components/govee_light_local/test_config_flow.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Test Govee light local config flow."""
22

33
from errno import EADDRINUSE
4+
from ipaddress import IPv4Address
45
from unittest.mock import AsyncMock, patch
56

67
from govee_local_api import GoveeDevice
@@ -61,17 +62,22 @@ async def test_creating_entry_has_with_devices(
6162

6263
mock_govee_api.devices = _get_devices(mock_govee_api)
6364

64-
result = await hass.config_entries.flow.async_init(
65-
DOMAIN, context={"source": config_entries.SOURCE_USER}
66-
)
65+
# Mock duplicated IPs to ensure that only one GoveeController is started
66+
with patch(
67+
"homeassistant.components.network.async_get_enabled_source_ips",
68+
return_value=[IPv4Address("192.168.1.2"), IPv4Address("192.168.1.2")],
69+
):
70+
result = await hass.config_entries.flow.async_init(
71+
DOMAIN, context={"source": config_entries.SOURCE_USER}
72+
)
6773

68-
# Confirmation form
69-
assert result["type"] is FlowResultType.FORM
74+
# Confirmation form
75+
assert result["type"] is FlowResultType.FORM
7076

71-
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
72-
assert result["type"] is FlowResultType.CREATE_ENTRY
77+
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
78+
assert result["type"] is FlowResultType.CREATE_ENTRY
7379

74-
await hass.async_block_till_done()
80+
await hass.async_block_till_done()
7581

7682
mock_govee_api.start.assert_awaited_once()
7783
mock_setup_entry.assert_awaited_once()

0 commit comments

Comments
 (0)