mirror of
https://github.com/Electric-Special/ha-core.git
synced 2026-03-21 03:03:17 +01:00
Improve scan interval for Airthings Corentium Home 2 (#155694)
Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
committed by
GitHub
parent
568ed2f0f6
commit
c9e76ae5d4
@@ -23,7 +23,7 @@ from homeassistant.components.bluetooth import (
|
||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.const import CONF_ADDRESS
|
||||
|
||||
from .const import DOMAIN, MFCT_ID
|
||||
from .const import DEVICE_MODEL, DOMAIN, MFCT_ID
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -128,15 +128,15 @@ class AirthingsConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
"""Confirm discovery."""
|
||||
assert self._discovered_device is not None
|
||||
|
||||
if user_input is not None:
|
||||
if (
|
||||
self._discovered_device is not None
|
||||
and self._discovered_device.device.firmware.need_firmware_upgrade
|
||||
):
|
||||
if self._discovered_device.device.firmware.need_firmware_upgrade:
|
||||
return self.async_abort(reason="firmware_upgrade_required")
|
||||
|
||||
return self.async_create_entry(
|
||||
title=self.context["title_placeholders"]["name"], data={}
|
||||
title=self.context["title_placeholders"]["name"],
|
||||
data={DEVICE_MODEL: self._discovered_device.device.model.value},
|
||||
)
|
||||
|
||||
self._set_confirm_only()
|
||||
@@ -164,7 +164,10 @@ class AirthingsConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
self._discovered_device = discovery
|
||||
|
||||
return self.async_create_entry(title=discovery.name, data={})
|
||||
return self.async_create_entry(
|
||||
title=discovery.name,
|
||||
data={DEVICE_MODEL: discovery.device.model.value},
|
||||
)
|
||||
|
||||
current_addresses = self._async_current_ids(include_ignore=False)
|
||||
devices: list[BluetoothServiceInfoBleak] = []
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
"""Constants for Airthings BLE."""
|
||||
|
||||
from airthings_ble import AirthingsDeviceType
|
||||
|
||||
DOMAIN = "airthings_ble"
|
||||
MFCT_ID = 820
|
||||
|
||||
VOLUME_BECQUEREL = "Bq/m³"
|
||||
VOLUME_PICOCURIE = "pCi/L"
|
||||
|
||||
DEVICE_MODEL = "device_model"
|
||||
|
||||
DEFAULT_SCAN_INTERVAL = 300
|
||||
DEVICE_SPECIFIC_SCAN_INTERVAL = {AirthingsDeviceType.CORENTIUM_HOME_2.value: 1800}
|
||||
|
||||
MAX_RETRIES_AFTER_STARTUP = 5
|
||||
|
||||
@@ -16,7 +16,12 @@ from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
from homeassistant.util.unit_system import METRIC_SYSTEM
|
||||
|
||||
from .const import DEFAULT_SCAN_INTERVAL, DOMAIN
|
||||
from .const import (
|
||||
DEFAULT_SCAN_INTERVAL,
|
||||
DEVICE_MODEL,
|
||||
DEVICE_SPECIFIC_SCAN_INTERVAL,
|
||||
DOMAIN,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -34,12 +39,18 @@ class AirthingsBLEDataUpdateCoordinator(DataUpdateCoordinator[AirthingsDevice]):
|
||||
self.airthings = AirthingsBluetoothDeviceData(
|
||||
_LOGGER, hass.config.units is METRIC_SYSTEM
|
||||
)
|
||||
|
||||
device_model = entry.data.get(DEVICE_MODEL)
|
||||
interval = DEVICE_SPECIFIC_SCAN_INTERVAL.get(
|
||||
device_model, DEFAULT_SCAN_INTERVAL
|
||||
)
|
||||
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=entry,
|
||||
name=DOMAIN,
|
||||
update_interval=timedelta(seconds=DEFAULT_SCAN_INTERVAL),
|
||||
update_interval=timedelta(seconds=interval),
|
||||
)
|
||||
|
||||
async def _async_setup(self) -> None:
|
||||
@@ -58,11 +69,29 @@ class AirthingsBLEDataUpdateCoordinator(DataUpdateCoordinator[AirthingsDevice]):
|
||||
)
|
||||
self.ble_device = ble_device
|
||||
|
||||
if DEVICE_MODEL not in self.config_entry.data:
|
||||
_LOGGER.debug("Fetching device info for migration")
|
||||
try:
|
||||
data = await self.airthings.update_device(self.ble_device)
|
||||
except Exception as err:
|
||||
raise UpdateFailed(
|
||||
f"Unable to fetch data for migration: {err}"
|
||||
) from err
|
||||
|
||||
self.hass.config_entries.async_update_entry(
|
||||
self.config_entry,
|
||||
data={**self.config_entry.data, DEVICE_MODEL: data.model.value},
|
||||
)
|
||||
self.update_interval = timedelta(
|
||||
seconds=DEVICE_SPECIFIC_SCAN_INTERVAL.get(
|
||||
data.model.value, DEFAULT_SCAN_INTERVAL
|
||||
)
|
||||
)
|
||||
|
||||
async def _async_update_data(self) -> AirthingsDevice:
|
||||
"""Get data from Airthings BLE."""
|
||||
try:
|
||||
data = await self.airthings.update_device(self.ble_device)
|
||||
except Exception as err:
|
||||
raise UpdateFailed(f"Unable to fetch data: {err}") from err
|
||||
|
||||
return data
|
||||
|
||||
@@ -135,6 +135,27 @@ WAVE_ENHANCE_SERVICE_INFO = BluetoothServiceInfoBleak(
|
||||
tx_power=0,
|
||||
)
|
||||
|
||||
CORENTIUM_HOME_2_SERVICE_INFO = BluetoothServiceInfoBleak(
|
||||
name="cc-cc-cc-cc-cc-cc",
|
||||
address="cc:cc:cc:cc:cc:cc",
|
||||
device=generate_ble_device(
|
||||
address="cc:cc:cc:cc:cc:cc",
|
||||
name="Airthings Corentium Home 2",
|
||||
),
|
||||
rssi=-61,
|
||||
manufacturer_data={820: b"\xe4/\xa5\xae\t\x00"},
|
||||
service_data={},
|
||||
service_uuids=[],
|
||||
source="local",
|
||||
advertisement=generate_advertisement_data(
|
||||
manufacturer_data={820: b"\xe4/\xa5\xae\t\x00"},
|
||||
service_uuids=[],
|
||||
),
|
||||
connectable=True,
|
||||
time=0,
|
||||
tx_power=0,
|
||||
)
|
||||
|
||||
VIEW_PLUS_SERVICE_INFO = BluetoothServiceInfoBleak(
|
||||
name="cc-cc-cc-cc-cc-cc",
|
||||
address="cc:cc:cc:cc:cc:cc",
|
||||
@@ -265,6 +286,24 @@ WAVE_ENHANCE_DEVICE_INFO = AirthingsDevice(
|
||||
address="cc:cc:cc:cc:cc:cc",
|
||||
)
|
||||
|
||||
CORENTIUM_HOME_2_DEVICE_INFO = AirthingsDevice(
|
||||
manufacturer="Airthings AS",
|
||||
hw_version="REV X",
|
||||
sw_version="R-SUB-1.3.4-master+0",
|
||||
model=AirthingsDeviceType.CORENTIUM_HOME_2,
|
||||
name="Airthings Corentium Home 2",
|
||||
identifier="123456",
|
||||
sensors={
|
||||
"connectivity_mode": "Bluetooth",
|
||||
"battery": 90,
|
||||
"temperature": 20.0,
|
||||
"humidity": 55.0,
|
||||
"radon_1day_avg": 45,
|
||||
"radon_1day_level": "low",
|
||||
},
|
||||
address="cc:cc:cc:cc:cc:cc",
|
||||
)
|
||||
|
||||
TEMPERATURE_V1 = MockEntity(
|
||||
unique_id="Airthings Wave Plus 123456_temperature",
|
||||
name="Airthings Wave Plus 123456 Temperature",
|
||||
|
||||
@@ -7,7 +7,7 @@ from bleak import BleakError
|
||||
from home_assistant_bluetooth import BluetoothServiceInfoBleak
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.airthings_ble.const import DOMAIN
|
||||
from homeassistant.components.airthings_ble.const import DEVICE_MODEL, DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_BLUETOOTH, SOURCE_IGNORE, SOURCE_USER
|
||||
from homeassistant.const import CONF_ADDRESS
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -29,12 +29,13 @@ from tests.common import MockConfigEntry
|
||||
|
||||
async def test_bluetooth_discovery(hass: HomeAssistant) -> None:
|
||||
"""Test discovery via bluetooth with a valid device."""
|
||||
wave_plus_device = AirthingsDeviceType.WAVE_PLUS
|
||||
with (
|
||||
patch_async_ble_device_from_address(WAVE_SERVICE_INFO),
|
||||
patch_airthings_ble(
|
||||
AirthingsDevice(
|
||||
manufacturer="Airthings AS",
|
||||
model=AirthingsDeviceType.WAVE_PLUS,
|
||||
model=wave_plus_device,
|
||||
name="Airthings Wave Plus",
|
||||
identifier="123456",
|
||||
)
|
||||
@@ -60,6 +61,8 @@ async def test_bluetooth_discovery(hass: HomeAssistant) -> None:
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Airthings Wave Plus (2930123456)"
|
||||
assert result["result"].unique_id == "cc:cc:cc:cc:cc:cc"
|
||||
assert result["data"] == {DEVICE_MODEL: wave_plus_device.value}
|
||||
assert result["result"].data == {DEVICE_MODEL: wave_plus_device.value}
|
||||
|
||||
|
||||
async def test_bluetooth_discovery_no_BLEDevice(hass: HomeAssistant) -> None:
|
||||
@@ -118,6 +121,7 @@ async def test_bluetooth_discovery_already_setup(hass: HomeAssistant) -> None:
|
||||
|
||||
async def test_user_setup(hass: HomeAssistant) -> None:
|
||||
"""Test the user initiated form."""
|
||||
wave_plus_device = AirthingsDeviceType.WAVE_PLUS
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.airthings_ble.config_flow.async_discovered_service_info",
|
||||
@@ -127,7 +131,7 @@ async def test_user_setup(hass: HomeAssistant) -> None:
|
||||
patch_airthings_ble(
|
||||
AirthingsDevice(
|
||||
manufacturer="Airthings AS",
|
||||
model=AirthingsDeviceType.WAVE_PLUS,
|
||||
model=wave_plus_device,
|
||||
name="Airthings Wave Plus",
|
||||
identifier="123456",
|
||||
)
|
||||
@@ -158,6 +162,8 @@ async def test_user_setup(hass: HomeAssistant) -> None:
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Airthings Wave Plus (2930123456)"
|
||||
assert result["result"].unique_id == "cc:cc:cc:cc:cc:cc"
|
||||
assert result["data"] == {DEVICE_MODEL: wave_plus_device.value}
|
||||
assert result["result"].data == {DEVICE_MODEL: wave_plus_device.value}
|
||||
|
||||
|
||||
async def test_user_setup_replaces_ignored_device(hass: HomeAssistant) -> None:
|
||||
@@ -168,6 +174,7 @@ async def test_user_setup_replaces_ignored_device(hass: HomeAssistant) -> None:
|
||||
source=SOURCE_IGNORE,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
wave_plus_device = AirthingsDeviceType.WAVE_PLUS
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.airthings_ble.config_flow.async_discovered_service_info",
|
||||
@@ -177,7 +184,7 @@ async def test_user_setup_replaces_ignored_device(hass: HomeAssistant) -> None:
|
||||
patch_airthings_ble(
|
||||
AirthingsDevice(
|
||||
manufacturer="Airthings AS",
|
||||
model=AirthingsDeviceType.WAVE_PLUS,
|
||||
model=wave_plus_device,
|
||||
name="Airthings Wave Plus",
|
||||
identifier="123456",
|
||||
)
|
||||
@@ -208,6 +215,8 @@ async def test_user_setup_replaces_ignored_device(hass: HomeAssistant) -> None:
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Airthings Wave Plus (2930123456)"
|
||||
assert result["result"].unique_id == "cc:cc:cc:cc:cc:cc"
|
||||
assert result["data"] == {DEVICE_MODEL: wave_plus_device.value}
|
||||
assert result["result"].data == {DEVICE_MODEL: wave_plus_device.value}
|
||||
|
||||
|
||||
async def test_user_setup_no_device(hass: HomeAssistant) -> None:
|
||||
|
||||
192
tests/components/airthings_ble/test_init.py
Normal file
192
tests/components/airthings_ble/test_init.py
Normal file
@@ -0,0 +1,192 @@
|
||||
"""Test the Airthings BLE integration init."""
|
||||
|
||||
from copy import deepcopy
|
||||
|
||||
from airthings_ble import AirthingsDeviceType
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.airthings_ble.const import (
|
||||
DEFAULT_SCAN_INTERVAL,
|
||||
DEVICE_MODEL,
|
||||
DEVICE_SPECIFIC_SCAN_INTERVAL,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import (
|
||||
CORENTIUM_HOME_2_DEVICE_INFO,
|
||||
CORENTIUM_HOME_2_SERVICE_INFO,
|
||||
WAVE_DEVICE_INFO,
|
||||
WAVE_ENHANCE_DEVICE_INFO,
|
||||
WAVE_ENHANCE_SERVICE_INFO,
|
||||
WAVE_SERVICE_INFO,
|
||||
patch_airthings_ble,
|
||||
patch_async_ble_device_from_address,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
from tests.components.bluetooth import inject_bluetooth_service_info
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("service_info", "device_info"),
|
||||
[
|
||||
(WAVE_SERVICE_INFO, WAVE_DEVICE_INFO),
|
||||
(WAVE_ENHANCE_SERVICE_INFO, WAVE_ENHANCE_DEVICE_INFO),
|
||||
(CORENTIUM_HOME_2_SERVICE_INFO, CORENTIUM_HOME_2_DEVICE_INFO),
|
||||
],
|
||||
)
|
||||
async def test_migration_existing_entries(
|
||||
hass: HomeAssistant,
|
||||
service_info,
|
||||
device_info,
|
||||
) -> None:
|
||||
"""Test migration of existing config entry without device model."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id=service_info.address,
|
||||
data={},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
inject_bluetooth_service_info(hass, service_info)
|
||||
|
||||
assert DEVICE_MODEL not in entry.data
|
||||
|
||||
with (
|
||||
patch_async_ble_device_from_address(service_info.device),
|
||||
patch_airthings_ble(device_info),
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Migration should have added device_model to entry data
|
||||
assert DEVICE_MODEL in entry.data
|
||||
assert entry.data[DEVICE_MODEL] == device_info.model.value
|
||||
|
||||
|
||||
async def test_no_migration_when_device_model_exists(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test that migration does not run when device_model already exists."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id=WAVE_SERVICE_INFO.address,
|
||||
data={DEVICE_MODEL: WAVE_DEVICE_INFO.model.value},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
inject_bluetooth_service_info(hass, WAVE_SERVICE_INFO)
|
||||
|
||||
with (
|
||||
patch_async_ble_device_from_address(WAVE_SERVICE_INFO.device),
|
||||
patch_airthings_ble(WAVE_DEVICE_INFO) as mock_update,
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Should have only 1 call for initial refresh (no migration call)
|
||||
assert mock_update.call_count == 1
|
||||
assert entry.data[DEVICE_MODEL] == WAVE_DEVICE_INFO.model.value
|
||||
|
||||
|
||||
async def test_scan_interval_corentium_home_2(
|
||||
hass: HomeAssistant, freezer: FrozenDateTimeFactory
|
||||
) -> None:
|
||||
"""Test that coordinator uses radon scan interval for Corentium Home 2."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id=WAVE_SERVICE_INFO.address,
|
||||
data={DEVICE_MODEL: CORENTIUM_HOME_2_DEVICE_INFO.model.value},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
inject_bluetooth_service_info(hass, WAVE_SERVICE_INFO)
|
||||
|
||||
with (
|
||||
patch_async_ble_device_from_address(WAVE_SERVICE_INFO.device),
|
||||
patch_airthings_ble(CORENTIUM_HOME_2_DEVICE_INFO),
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
hass.states.get("sensor.airthings_corentium_home_2_123456_battery").state
|
||||
== "90"
|
||||
)
|
||||
|
||||
changed_info = deepcopy(CORENTIUM_HOME_2_DEVICE_INFO)
|
||||
changed_info.sensors["battery"] = 89
|
||||
|
||||
with patch_airthings_ble(changed_info):
|
||||
freezer.tick(DEFAULT_SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
hass.states.get("sensor.airthings_corentium_home_2_123456_battery").state
|
||||
== "90"
|
||||
)
|
||||
|
||||
freezer.tick(
|
||||
DEVICE_SPECIFIC_SCAN_INTERVAL.get(
|
||||
AirthingsDeviceType.CORENTIUM_HOME_2.value
|
||||
)
|
||||
- DEFAULT_SCAN_INTERVAL
|
||||
)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
hass.states.get("sensor.airthings_corentium_home_2_123456_battery").state
|
||||
== "89"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("service_info", "device_info", "battery_entity_id"),
|
||||
[
|
||||
(WAVE_SERVICE_INFO, WAVE_DEVICE_INFO, "sensor.airthings_wave_123456_battery"),
|
||||
(
|
||||
WAVE_ENHANCE_SERVICE_INFO,
|
||||
WAVE_ENHANCE_DEVICE_INFO,
|
||||
"sensor.airthings_wave_enhance_123456_battery",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_coordinator_default_scan_interval(
|
||||
hass: HomeAssistant,
|
||||
service_info,
|
||||
device_info,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
battery_entity_id: str,
|
||||
) -> None:
|
||||
"""Test that coordinator uses default scan interval."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id=service_info.address,
|
||||
data={DEVICE_MODEL: device_info.model.value},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
inject_bluetooth_service_info(hass, service_info)
|
||||
|
||||
with (
|
||||
patch_async_ble_device_from_address(service_info.device),
|
||||
patch_airthings_ble(device_info),
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(battery_entity_id).state == "85"
|
||||
|
||||
changed_info = deepcopy(device_info)
|
||||
changed_info.sensors["battery"] = 84
|
||||
|
||||
with patch_airthings_ble(changed_info):
|
||||
freezer.tick(DEFAULT_SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(battery_entity_id).state == "84"
|
||||
@@ -1,10 +1,17 @@
|
||||
"""Test the Airthings Wave sensor."""
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.airthings_ble.const import DOMAIN
|
||||
from homeassistant.components.airthings_ble.const import (
|
||||
DEFAULT_SCAN_INTERVAL,
|
||||
DEVICE_MODEL,
|
||||
DEVICE_SPECIFIC_SCAN_INTERVAL,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
@@ -12,6 +19,7 @@ from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from . import (
|
||||
CO2_V1,
|
||||
CO2_V2,
|
||||
CORENTIUM_HOME_2_DEVICE_INFO,
|
||||
HUMIDITY_V2,
|
||||
TEMPERATURE_V1,
|
||||
VOC_V1,
|
||||
@@ -21,6 +29,8 @@ from . import (
|
||||
WAVE_ENHANCE_DEVICE_INFO,
|
||||
WAVE_ENHANCE_SERVICE_INFO,
|
||||
WAVE_SERVICE_INFO,
|
||||
AirthingsDevice,
|
||||
BluetoothServiceInfoBleak,
|
||||
create_device,
|
||||
create_entry,
|
||||
patch_airthings_ble,
|
||||
@@ -29,6 +39,7 @@ from . import (
|
||||
patch_async_discovered_service_info,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
from tests.components.bluetooth import inject_bluetooth_service_info
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -267,3 +278,102 @@ async def test_translation_keys(
|
||||
|
||||
expected_name = f"Airthings Wave Enhance (123456) {expected_sensor_name}"
|
||||
assert state.attributes.get("friendly_name") == expected_name
|
||||
|
||||
|
||||
async def test_scan_interval_migration_corentium_home_2(
|
||||
hass: HomeAssistant,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test that radon device migration uses 30-minute scan interval."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id=WAVE_SERVICE_INFO.address,
|
||||
data={},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
inject_bluetooth_service_info(hass, WAVE_SERVICE_INFO)
|
||||
|
||||
with (
|
||||
patch_async_ble_device_from_address(WAVE_SERVICE_INFO.device),
|
||||
patch_airthings_ble(CORENTIUM_HOME_2_DEVICE_INFO) as mock_update,
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Migration should have added device_model to entry data
|
||||
assert DEVICE_MODEL in entry.data
|
||||
assert entry.data[DEVICE_MODEL] == CORENTIUM_HOME_2_DEVICE_INFO.model.value
|
||||
|
||||
# Coordinator should have been configured with radon scan interval
|
||||
coordinator = entry.runtime_data
|
||||
assert coordinator.update_interval == timedelta(
|
||||
seconds=DEVICE_SPECIFIC_SCAN_INTERVAL.get(
|
||||
CORENTIUM_HOME_2_DEVICE_INFO.model.value
|
||||
)
|
||||
)
|
||||
|
||||
# Should have 2 calls: 1 for migration + 1 for initial refresh
|
||||
assert mock_update.call_count == 2
|
||||
|
||||
# Fast forward by default interval (300s) - should NOT trigger update
|
||||
freezer.tick(DEFAULT_SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_update.call_count == 2
|
||||
|
||||
# Fast forward to radon interval (1800s) - should trigger update
|
||||
freezer.tick(
|
||||
DEVICE_SPECIFIC_SCAN_INTERVAL.get(CORENTIUM_HOME_2_DEVICE_INFO.model.value)
|
||||
)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_update.call_count == 3
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("service_info", "device_info"),
|
||||
[
|
||||
(WAVE_SERVICE_INFO, WAVE_DEVICE_INFO),
|
||||
(WAVE_ENHANCE_SERVICE_INFO, WAVE_ENHANCE_DEVICE_INFO),
|
||||
],
|
||||
)
|
||||
async def test_default_scan_interval_migration(
|
||||
hass: HomeAssistant,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
service_info: BluetoothServiceInfoBleak,
|
||||
device_info: AirthingsDevice,
|
||||
) -> None:
|
||||
"""Test that non-radon device migration uses default 5-minute scan interval."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
unique_id=service_info.address,
|
||||
data={},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
inject_bluetooth_service_info(hass, service_info)
|
||||
|
||||
with (
|
||||
patch_async_ble_device_from_address(service_info.device),
|
||||
patch_airthings_ble(device_info) as mock_update,
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Migration should have added device_model to entry data
|
||||
assert DEVICE_MODEL in entry.data
|
||||
assert entry.data[DEVICE_MODEL] == device_info.model.value
|
||||
|
||||
# Coordinator should have been configured with default scan interval
|
||||
coordinator = entry.runtime_data
|
||||
assert coordinator.update_interval == timedelta(seconds=DEFAULT_SCAN_INTERVAL)
|
||||
|
||||
# Should have 2 calls: 1 for migration + 1 for initial refresh
|
||||
assert mock_update.call_count == 2
|
||||
|
||||
# Fast forward by default interval (300s) - SHOULD trigger update
|
||||
freezer.tick(DEFAULT_SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_update.call_count == 3
|
||||
|
||||
Reference in New Issue
Block a user