Skip to content

Commit ead5ce9

Browse files
LaStradajoostlek
authored andcommitted
Improve scan interval for Airthings Corentium Home 2 (home-assistant#155694)
Co-authored-by: Joostlek <[email protected]>
1 parent f233f2d commit ead5ce9

File tree

7 files changed

+402
-15
lines changed

7 files changed

+402
-15
lines changed

homeassistant/components/airthings_ble/config_flow.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
2424
from homeassistant.const import CONF_ADDRESS
2525

26-
from .const import DOMAIN, MFCT_ID
26+
from .const import DEVICE_MODEL, DOMAIN, MFCT_ID
2727

2828
_LOGGER = logging.getLogger(__name__)
2929

@@ -128,15 +128,15 @@ async def async_step_bluetooth_confirm(
128128
self, user_input: dict[str, Any] | None = None
129129
) -> ConfigFlowResult:
130130
"""Confirm discovery."""
131+
assert self._discovered_device is not None
132+
131133
if user_input is not None:
132-
if (
133-
self._discovered_device is not None
134-
and self._discovered_device.device.firmware.need_firmware_upgrade
135-
):
134+
if self._discovered_device.device.firmware.need_firmware_upgrade:
136135
return self.async_abort(reason="firmware_upgrade_required")
137136

138137
return self.async_create_entry(
139-
title=self.context["title_placeholders"]["name"], data={}
138+
title=self.context["title_placeholders"]["name"],
139+
data={DEVICE_MODEL: self._discovered_device.device.model.value},
140140
)
141141

142142
self._set_confirm_only()
@@ -164,7 +164,10 @@ async def async_step_user(
164164

165165
self._discovered_device = discovery
166166

167-
return self.async_create_entry(title=discovery.name, data={})
167+
return self.async_create_entry(
168+
title=discovery.name,
169+
data={DEVICE_MODEL: discovery.device.model.value},
170+
)
168171

169172
current_addresses = self._async_current_ids(include_ignore=False)
170173
devices: list[BluetoothServiceInfoBleak] = []
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
"""Constants for Airthings BLE."""
22

3+
from airthings_ble import AirthingsDeviceType
4+
35
DOMAIN = "airthings_ble"
46
MFCT_ID = 820
57

68
VOLUME_BECQUEREL = "Bq/m³"
79
VOLUME_PICOCURIE = "pCi/L"
810

11+
DEVICE_MODEL = "device_model"
12+
913
DEFAULT_SCAN_INTERVAL = 300
14+
DEVICE_SPECIFIC_SCAN_INTERVAL = {AirthingsDeviceType.CORENTIUM_HOME_2.value: 1800}
1015

1116
MAX_RETRIES_AFTER_STARTUP = 5

homeassistant/components/airthings_ble/coordinator.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@
1616
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
1717
from homeassistant.util.unit_system import METRIC_SYSTEM
1818

19-
from .const import DEFAULT_SCAN_INTERVAL, DOMAIN
19+
from .const import (
20+
DEFAULT_SCAN_INTERVAL,
21+
DEVICE_MODEL,
22+
DEVICE_SPECIFIC_SCAN_INTERVAL,
23+
DOMAIN,
24+
)
2025

2126
_LOGGER = logging.getLogger(__name__)
2227

@@ -34,12 +39,18 @@ def __init__(self, hass: HomeAssistant, entry: AirthingsBLEConfigEntry) -> None:
3439
self.airthings = AirthingsBluetoothDeviceData(
3540
_LOGGER, hass.config.units is METRIC_SYSTEM
3641
)
42+
43+
device_model = entry.data.get(DEVICE_MODEL)
44+
interval = DEVICE_SPECIFIC_SCAN_INTERVAL.get(
45+
device_model, DEFAULT_SCAN_INTERVAL
46+
)
47+
3748
super().__init__(
3849
hass,
3950
_LOGGER,
4051
config_entry=entry,
4152
name=DOMAIN,
42-
update_interval=timedelta(seconds=DEFAULT_SCAN_INTERVAL),
53+
update_interval=timedelta(seconds=interval),
4354
)
4455

4556
async def _async_setup(self) -> None:
@@ -58,11 +69,29 @@ async def _async_setup(self) -> None:
5869
)
5970
self.ble_device = ble_device
6071

72+
if DEVICE_MODEL not in self.config_entry.data:
73+
_LOGGER.debug("Fetching device info for migration")
74+
try:
75+
data = await self.airthings.update_device(self.ble_device)
76+
except Exception as err:
77+
raise UpdateFailed(
78+
f"Unable to fetch data for migration: {err}"
79+
) from err
80+
81+
self.hass.config_entries.async_update_entry(
82+
self.config_entry,
83+
data={**self.config_entry.data, DEVICE_MODEL: data.model.value},
84+
)
85+
self.update_interval = timedelta(
86+
seconds=DEVICE_SPECIFIC_SCAN_INTERVAL.get(
87+
data.model.value, DEFAULT_SCAN_INTERVAL
88+
)
89+
)
90+
6191
async def _async_update_data(self) -> AirthingsDevice:
6292
"""Get data from Airthings BLE."""
6393
try:
6494
data = await self.airthings.update_device(self.ble_device)
6595
except Exception as err:
6696
raise UpdateFailed(f"Unable to fetch data: {err}") from err
67-
6897
return data

tests/components/airthings_ble/__init__.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,27 @@ def patch_airthings_device_update():
135135
tx_power=0,
136136
)
137137

138+
CORENTIUM_HOME_2_SERVICE_INFO = BluetoothServiceInfoBleak(
139+
name="cc-cc-cc-cc-cc-cc",
140+
address="cc:cc:cc:cc:cc:cc",
141+
device=generate_ble_device(
142+
address="cc:cc:cc:cc:cc:cc",
143+
name="Airthings Corentium Home 2",
144+
),
145+
rssi=-61,
146+
manufacturer_data={820: b"\xe4/\xa5\xae\t\x00"},
147+
service_data={},
148+
service_uuids=[],
149+
source="local",
150+
advertisement=generate_advertisement_data(
151+
manufacturer_data={820: b"\xe4/\xa5\xae\t\x00"},
152+
service_uuids=[],
153+
),
154+
connectable=True,
155+
time=0,
156+
tx_power=0,
157+
)
158+
138159
VIEW_PLUS_SERVICE_INFO = BluetoothServiceInfoBleak(
139160
name="cc-cc-cc-cc-cc-cc",
140161
address="cc:cc:cc:cc:cc:cc",
@@ -265,6 +286,24 @@ def patch_airthings_device_update():
265286
address="cc:cc:cc:cc:cc:cc",
266287
)
267288

289+
CORENTIUM_HOME_2_DEVICE_INFO = AirthingsDevice(
290+
manufacturer="Airthings AS",
291+
hw_version="REV X",
292+
sw_version="R-SUB-1.3.4-master+0",
293+
model=AirthingsDeviceType.CORENTIUM_HOME_2,
294+
name="Airthings Corentium Home 2",
295+
identifier="123456",
296+
sensors={
297+
"connectivity_mode": "Bluetooth",
298+
"battery": 90,
299+
"temperature": 20.0,
300+
"humidity": 55.0,
301+
"radon_1day_avg": 45,
302+
"radon_1day_level": "low",
303+
},
304+
address="cc:cc:cc:cc:cc:cc",
305+
)
306+
268307
TEMPERATURE_V1 = MockEntity(
269308
unique_id="Airthings Wave Plus 123456_temperature",
270309
name="Airthings Wave Plus 123456 Temperature",

tests/components/airthings_ble/test_config_flow.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from home_assistant_bluetooth import BluetoothServiceInfoBleak
88
import pytest
99

10-
from homeassistant.components.airthings_ble.const import DOMAIN
10+
from homeassistant.components.airthings_ble.const import DEVICE_MODEL, DOMAIN
1111
from homeassistant.config_entries import SOURCE_BLUETOOTH, SOURCE_IGNORE, SOURCE_USER
1212
from homeassistant.const import CONF_ADDRESS
1313
from homeassistant.core import HomeAssistant
@@ -29,12 +29,13 @@
2929

3030
async def test_bluetooth_discovery(hass: HomeAssistant) -> None:
3131
"""Test discovery via bluetooth with a valid device."""
32+
wave_plus_device = AirthingsDeviceType.WAVE_PLUS
3233
with (
3334
patch_async_ble_device_from_address(WAVE_SERVICE_INFO),
3435
patch_airthings_ble(
3536
AirthingsDevice(
3637
manufacturer="Airthings AS",
37-
model=AirthingsDeviceType.WAVE_PLUS,
38+
model=wave_plus_device,
3839
name="Airthings Wave Plus",
3940
identifier="123456",
4041
)
@@ -60,6 +61,8 @@ async def test_bluetooth_discovery(hass: HomeAssistant) -> None:
6061
assert result["type"] is FlowResultType.CREATE_ENTRY
6162
assert result["title"] == "Airthings Wave Plus (2930123456)"
6263
assert result["result"].unique_id == "cc:cc:cc:cc:cc:cc"
64+
assert result["data"] == {DEVICE_MODEL: wave_plus_device.value}
65+
assert result["result"].data == {DEVICE_MODEL: wave_plus_device.value}
6366

6467

6568
async def test_bluetooth_discovery_no_BLEDevice(hass: HomeAssistant) -> None:
@@ -118,6 +121,7 @@ async def test_bluetooth_discovery_already_setup(hass: HomeAssistant) -> None:
118121

119122
async def test_user_setup(hass: HomeAssistant) -> None:
120123
"""Test the user initiated form."""
124+
wave_plus_device = AirthingsDeviceType.WAVE_PLUS
121125
with (
122126
patch(
123127
"homeassistant.components.airthings_ble.config_flow.async_discovered_service_info",
@@ -127,7 +131,7 @@ async def test_user_setup(hass: HomeAssistant) -> None:
127131
patch_airthings_ble(
128132
AirthingsDevice(
129133
manufacturer="Airthings AS",
130-
model=AirthingsDeviceType.WAVE_PLUS,
134+
model=wave_plus_device,
131135
name="Airthings Wave Plus",
132136
identifier="123456",
133137
)
@@ -158,6 +162,8 @@ async def test_user_setup(hass: HomeAssistant) -> None:
158162
assert result["type"] is FlowResultType.CREATE_ENTRY
159163
assert result["title"] == "Airthings Wave Plus (2930123456)"
160164
assert result["result"].unique_id == "cc:cc:cc:cc:cc:cc"
165+
assert result["data"] == {DEVICE_MODEL: wave_plus_device.value}
166+
assert result["result"].data == {DEVICE_MODEL: wave_plus_device.value}
161167

162168

163169
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:
168174
source=SOURCE_IGNORE,
169175
)
170176
entry.add_to_hass(hass)
177+
wave_plus_device = AirthingsDeviceType.WAVE_PLUS
171178
with (
172179
patch(
173180
"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:
177184
patch_airthings_ble(
178185
AirthingsDevice(
179186
manufacturer="Airthings AS",
180-
model=AirthingsDeviceType.WAVE_PLUS,
187+
model=wave_plus_device,
181188
name="Airthings Wave Plus",
182189
identifier="123456",
183190
)
@@ -208,6 +215,8 @@ async def test_user_setup_replaces_ignored_device(hass: HomeAssistant) -> None:
208215
assert result["type"] is FlowResultType.CREATE_ENTRY
209216
assert result["title"] == "Airthings Wave Plus (2930123456)"
210217
assert result["result"].unique_id == "cc:cc:cc:cc:cc:cc"
218+
assert result["data"] == {DEVICE_MODEL: wave_plus_device.value}
219+
assert result["result"].data == {DEVICE_MODEL: wave_plus_device.value}
211220

212221

213222
async def test_user_setup_no_device(hass: HomeAssistant) -> None:

0 commit comments

Comments
 (0)