diff --git a/homeassistant/components/ping/__init__.py b/homeassistant/components/ping/__init__.py index 726bb212574..b9a9f6460db 100644 --- a/homeassistant/components/ping/__init__.py +++ b/homeassistant/components/ping/__init__.py @@ -24,20 +24,22 @@ async def async_setup(hass, config): @callback -def async_get_next_ping_id(hass): +def async_get_next_ping_id(hass, count=1): """Find the next id to use in the outbound ping. + When using multiping, we increment the id + by the number of ids that multiping + will use. + Must be called in async """ - current_id = hass.data[DOMAIN][PING_ID] - if current_id == MAX_PING_ID: - next_id = DEFAULT_START_ID - else: - next_id = current_id + 1 - - hass.data[DOMAIN][PING_ID] = next_id - - return next_id + allocated_id = hass.data[DOMAIN][PING_ID] + 1 + if allocated_id > MAX_PING_ID: + allocated_id -= MAX_PING_ID - DEFAULT_START_ID + hass.data[DOMAIN][PING_ID] += count + if hass.data[DOMAIN][PING_ID] > MAX_PING_ID: + hass.data[DOMAIN][PING_ID] -= MAX_PING_ID - DEFAULT_START_ID + return allocated_id def _can_use_icmp_lib_with_privilege() -> None | bool: diff --git a/homeassistant/components/ping/device_tracker.py b/homeassistant/components/ping/device_tracker.py index a6b75a9245b..256023263ba 100644 --- a/homeassistant/components/ping/device_tracker.py +++ b/homeassistant/components/ping/device_tracker.py @@ -125,7 +125,7 @@ async def async_setup_scanner(hass, config, async_see, discovery_info=None): count=PING_ATTEMPTS_COUNT, timeout=ICMP_TIMEOUT, privileged=privileged, - id=async_get_next_ping_id(hass), + id=async_get_next_ping_id(hass, len(ip_to_dev_id)), ) ) _LOGGER.debug("Multiping responses: %s", responses) diff --git a/tests/components/ping/test_init.py b/tests/components/ping/test_init.py new file mode 100644 index 00000000000..3dfe193c4d5 --- /dev/null +++ b/tests/components/ping/test_init.py @@ -0,0 +1,27 @@ +"""Test ping id allocation.""" + +from homeassistant.components.ping import async_get_next_ping_id +from homeassistant.components.ping.const import ( + DEFAULT_START_ID, + DOMAIN, + MAX_PING_ID, + PING_ID, +) + + +async def test_async_get_next_ping_id(hass): + """Verify we allocate ping ids as expected.""" + hass.data[DOMAIN] = {PING_ID: DEFAULT_START_ID} + + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 1 + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 2 + assert async_get_next_ping_id(hass, 2) == DEFAULT_START_ID + 3 + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 5 + + hass.data[DOMAIN][PING_ID] = MAX_PING_ID + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 1 + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 2 + + hass.data[DOMAIN][PING_ID] = MAX_PING_ID + assert async_get_next_ping_id(hass, 2) == DEFAULT_START_ID + 1 + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 3