diff --git a/homeassistant/components/aqvify/coordinator.py b/homeassistant/components/aqvify/coordinator.py index db5b1cd43dee..2a4116819cc4 100644 --- a/homeassistant/components/aqvify/coordinator.py +++ b/homeassistant/components/aqvify/coordinator.py @@ -152,3 +152,10 @@ class AqvifyCoordinator(DataUpdateCoordinator[AqvifyCoordinatorData]): devices=devices, device_data=device_data, ) + + def async_add_devices(self, added_devices: set[str]) -> tuple[set[str], set[str]]: + """Return newly discovered device keys and the full current device set.""" + + current_devices = set(self.data.devices.devices) + new_devices: set[str] = current_devices - added_devices + return (new_devices, current_devices) diff --git a/homeassistant/components/aqvify/sensor.py b/homeassistant/components/aqvify/sensor.py index e20ebb5f989f..49d458052cd6 100644 --- a/homeassistant/components/aqvify/sensor.py +++ b/homeassistant/components/aqvify/sensor.py @@ -59,11 +59,23 @@ async def async_setup_entry( async_add_entities: AddConfigEntryEntitiesCallback, ) -> None: """Set up Aqvify sensor entities from a config entry.""" - async_add_entities( - AqvifySensor(entry.runtime_data, description, device_key) - for description in ENTITIES - for device_key in entry.runtime_data.data.devices.devices - ) + + coordinator = entry.runtime_data + added_devices: set[str] = set() + + def _async_add_new_devices() -> None: + nonlocal added_devices + new_devices_set, current_devices = coordinator.async_add_devices(added_devices) + added_devices = current_devices + + async_add_entities( + AqvifySensor(coordinator, description, device_key) + for description in ENTITIES + for device_key in new_devices_set + ) + + entry.async_on_unload(coordinator.async_add_listener(_async_add_new_devices)) + _async_add_new_devices() class AqvifySensor(AqvifyBaseEntity, SensorEntity): diff --git a/tests/components/aqvify/fixtures/added_devices.json b/tests/components/aqvify/fixtures/added_devices.json new file mode 100644 index 000000000000..c83c776db510 --- /dev/null +++ b/tests/components/aqvify/fixtures/added_devices.json @@ -0,0 +1,14 @@ +[ + { + "deviceKey": "DeviceKey_1", + "name": "Device 1" + }, + { + "deviceKey": "DeviceKey_2", + "name": "Device 2" + }, + { + "deviceKey": "DeviceKey_3", + "name": "Device 3" + } +] diff --git a/tests/components/aqvify/test_init.py b/tests/components/aqvify/test_init.py index 0c65964abeed..62a06e1783ed 100644 --- a/tests/components/aqvify/test_init.py +++ b/tests/components/aqvify/test_init.py @@ -84,8 +84,10 @@ async def test_device_registry_integration( device_registry, mock_config_entry.entry_id ) - # Snapshot the devices to ensure they have the correct structure - assert device_entries == snapshot + sorted_devices = sorted( + device_entries, key=lambda dev_entry: dev_entry.serial_number + ) + assert sorted_devices == snapshot async def test_setup_entry_auth_error_triggers_reauth( @@ -132,6 +134,31 @@ async def test_autoremove_stale_devices( assert hass.states.get("sensor.device_2_water_level") is None +async def test_devices_multiple_created_count( + hass: HomeAssistant, + device_registry: dr.DeviceRegistry, + mock_aqvify_client: MagicMock, + mock_config_entry: MockConfigEntry, + freezer: FrozenDateTimeFactory, +) -> None: + """Test that added devices are created.""" + await setup_integration(hass, mock_config_entry) + + assert len(device_registry.devices) == 2 + assert hass.states.get("sensor.device_3_water_level") is None + + mock_aqvify_client.async_get_devices.return_value = AqvifyDevices( + await async_load_json_array_fixture(hass, "added_devices.json", DOMAIN) + ) + + freezer.tick(timedelta(seconds=240)) + async_fire_time_changed(hass) + await hass.async_block_till_done() + + assert len(device_registry.devices) == 3 + assert hass.states.get("sensor.device_3_water_level").state == EXPECTED_WATER_LEVEL + + @pytest.mark.parametrize( ("exception", "log_message", "expected_state"), [