Merge coordinators in Airgradient (#124714)

This commit is contained in:
Joost Lekkerkerker 2024-08-31 16:40:12 +02:00 committed by GitHub
parent 9da5dd0090
commit 30aa3a26ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 98 additions and 124 deletions

View File

@ -2,18 +2,14 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass from airgradient import AirGradientClient
from airgradient import AirGradientClient, get_model_name
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, Platform from homeassistant.const import CONF_HOST, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import DOMAIN from .coordinator import AirGradientCoordinator
from .coordinator import AirGradientConfigCoordinator, AirGradientMeasurementCoordinator
PLATFORMS: list[Platform] = [ PLATFORMS: list[Platform] = [
Platform.BUTTON, Platform.BUTTON,
@ -25,15 +21,7 @@ PLATFORMS: list[Platform] = [
] ]
@dataclass type AirGradientConfigEntry = ConfigEntry[AirGradientCoordinator]
class AirGradientData:
"""AirGradient data class."""
measurement: AirGradientMeasurementCoordinator
config: AirGradientConfigCoordinator
type AirGradientConfigEntry = ConfigEntry[AirGradientData]
async def async_setup_entry(hass: HomeAssistant, entry: AirGradientConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: AirGradientConfigEntry) -> bool:
@ -43,27 +31,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: AirGradientConfigEntry)
entry.data[CONF_HOST], session=async_get_clientsession(hass) entry.data[CONF_HOST], session=async_get_clientsession(hass)
) )
measurement_coordinator = AirGradientMeasurementCoordinator(hass, client) coordinator = AirGradientCoordinator(hass, client)
config_coordinator = AirGradientConfigCoordinator(hass, client)
await measurement_coordinator.async_config_entry_first_refresh() await coordinator.async_config_entry_first_refresh()
await config_coordinator.async_config_entry_first_refresh()
device_registry = dr.async_get(hass) entry.runtime_data = coordinator
device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, measurement_coordinator.serial_number)},
manufacturer="AirGradient",
model=get_model_name(measurement_coordinator.data.model),
model_id=measurement_coordinator.data.model,
serial_number=measurement_coordinator.data.serial_number,
sw_version=measurement_coordinator.data.firmware_version,
)
entry.runtime_data = AirGradientData(
measurement=measurement_coordinator,
config=config_coordinator,
)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

View File

@ -15,8 +15,9 @@ from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import DOMAIN, AirGradientConfigEntry from . import AirGradientConfigEntry
from .coordinator import AirGradientConfigCoordinator from .const import DOMAIN
from .coordinator import AirGradientCoordinator
from .entity import AirGradientEntity from .entity import AirGradientEntity
@ -47,8 +48,8 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up AirGradient button entities based on a config entry.""" """Set up AirGradient button entities based on a config entry."""
model = entry.runtime_data.measurement.data.model coordinator = entry.runtime_data
coordinator = entry.runtime_data.config model = coordinator.data.measures.model
added_entities = False added_entities = False
@ -57,7 +58,7 @@ async def async_setup_entry(
nonlocal added_entities nonlocal added_entities
if ( if (
coordinator.data.configuration_control is ConfigurationControl.LOCAL coordinator.data.config.configuration_control is ConfigurationControl.LOCAL
and not added_entities and not added_entities
): ):
entities = [AirGradientButton(coordinator, CO2_CALIBRATION)] entities = [AirGradientButton(coordinator, CO2_CALIBRATION)]
@ -67,7 +68,8 @@ async def async_setup_entry(
async_add_entities(entities) async_add_entities(entities)
added_entities = True added_entities = True
elif ( elif (
coordinator.data.configuration_control is not ConfigurationControl.LOCAL coordinator.data.config.configuration_control
is not ConfigurationControl.LOCAL
and added_entities and added_entities
): ):
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -87,11 +89,10 @@ class AirGradientButton(AirGradientEntity, ButtonEntity):
"""Defines an AirGradient button.""" """Defines an AirGradient button."""
entity_description: AirGradientButtonEntityDescription entity_description: AirGradientButtonEntityDescription
coordinator: AirGradientConfigCoordinator
def __init__( def __init__(
self, self,
coordinator: AirGradientConfigCoordinator, coordinator: AirGradientCoordinator,
description: AirGradientButtonEntityDescription, description: AirGradientButtonEntityDescription,
) -> None: ) -> None:
"""Initialize airgradient button.""" """Initialize airgradient button."""

View File

@ -2,6 +2,7 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass
from datetime import timedelta from datetime import timedelta
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -16,7 +17,15 @@ if TYPE_CHECKING:
from . import AirGradientConfigEntry from . import AirGradientConfigEntry
class AirGradientCoordinator[_DataT](DataUpdateCoordinator[_DataT]): @dataclass
class AirGradientData:
"""Class for AirGradient data."""
measures: Measures
config: Config
class AirGradientCoordinator(DataUpdateCoordinator[AirGradientData]):
"""Class to manage fetching AirGradient data.""" """Class to manage fetching AirGradient data."""
config_entry: AirGradientConfigEntry config_entry: AirGradientConfigEntry
@ -33,25 +42,11 @@ class AirGradientCoordinator[_DataT](DataUpdateCoordinator[_DataT]):
assert self.config_entry.unique_id assert self.config_entry.unique_id
self.serial_number = self.config_entry.unique_id self.serial_number = self.config_entry.unique_id
async def _async_update_data(self) -> _DataT: async def _async_update_data(self) -> AirGradientData:
try: try:
return await self._update_data() measures = await self.client.get_current_measures()
config = await self.client.get_config()
except AirGradientError as error: except AirGradientError as error:
raise UpdateFailed(error) from error raise UpdateFailed(error) from error
else:
async def _update_data(self) -> _DataT: return AirGradientData(measures, config)
raise NotImplementedError
class AirGradientMeasurementCoordinator(AirGradientCoordinator[Measures]):
"""Class to manage fetching AirGradient data."""
async def _update_data(self) -> Measures:
return await self.client.get_current_measures()
class AirGradientConfigCoordinator(AirGradientCoordinator[Config]):
"""Class to manage fetching AirGradient data."""
async def _update_data(self) -> Config:
return await self.client.get_config()

View File

@ -1,5 +1,7 @@
"""Base class for AirGradient entities.""" """Base class for AirGradient entities."""
from airgradient import get_model_name
from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.update_coordinator import CoordinatorEntity
@ -15,6 +17,12 @@ class AirGradientEntity(CoordinatorEntity[AirGradientCoordinator]):
def __init__(self, coordinator: AirGradientCoordinator) -> None: def __init__(self, coordinator: AirGradientCoordinator) -> None:
"""Initialize airgradient entity.""" """Initialize airgradient entity."""
super().__init__(coordinator) super().__init__(coordinator)
measures = coordinator.data.measures
self._attr_device_info = DeviceInfo( self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, coordinator.serial_number)}, identifiers={(DOMAIN, coordinator.serial_number)},
manufacturer="AirGradient",
model=get_model_name(measures.model),
model_id=measures.model,
serial_number=coordinator.serial_number,
sw_version=measures.firmware_version,
) )

View File

@ -18,7 +18,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AirGradientConfigEntry from . import AirGradientConfigEntry
from .const import DOMAIN from .const import DOMAIN
from .coordinator import AirGradientConfigCoordinator from .coordinator import AirGradientCoordinator
from .entity import AirGradientEntity from .entity import AirGradientEntity
@ -62,8 +62,8 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up AirGradient number entities based on a config entry.""" """Set up AirGradient number entities based on a config entry."""
model = entry.runtime_data.measurement.data.model coordinator = entry.runtime_data
coordinator = entry.runtime_data.config model = coordinator.data.measures.model
added_entities = False added_entities = False
@ -72,7 +72,7 @@ async def async_setup_entry(
nonlocal added_entities nonlocal added_entities
if ( if (
coordinator.data.configuration_control is ConfigurationControl.LOCAL coordinator.data.config.configuration_control is ConfigurationControl.LOCAL
and not added_entities and not added_entities
): ):
entities = [] entities = []
@ -84,7 +84,8 @@ async def async_setup_entry(
async_add_entities(entities) async_add_entities(entities)
added_entities = True added_entities = True
elif ( elif (
coordinator.data.configuration_control is not ConfigurationControl.LOCAL coordinator.data.config.configuration_control
is not ConfigurationControl.LOCAL
and added_entities and added_entities
): ):
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -104,11 +105,10 @@ class AirGradientNumber(AirGradientEntity, NumberEntity):
"""Defines an AirGradient number entity.""" """Defines an AirGradient number entity."""
entity_description: AirGradientNumberEntityDescription entity_description: AirGradientNumberEntityDescription
coordinator: AirGradientConfigCoordinator
def __init__( def __init__(
self, self,
coordinator: AirGradientConfigCoordinator, coordinator: AirGradientCoordinator,
description: AirGradientNumberEntityDescription, description: AirGradientNumberEntityDescription,
) -> None: ) -> None:
"""Initialize AirGradient number.""" """Initialize AirGradient number."""
@ -119,7 +119,7 @@ class AirGradientNumber(AirGradientEntity, NumberEntity):
@property @property
def native_value(self) -> int | None: def native_value(self) -> int | None:
"""Return the state of the number.""" """Return the state of the number."""
return self.entity_description.value_fn(self.coordinator.data) return self.entity_description.value_fn(self.coordinator.data.config)
async def async_set_native_value(self, value: float) -> None: async def async_set_native_value(self, value: float) -> None:
"""Set the selected value.""" """Set the selected value."""

View File

@ -18,7 +18,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AirGradientConfigEntry from . import AirGradientConfigEntry
from .const import DOMAIN, PM_STANDARD, PM_STANDARD_REVERSE from .const import DOMAIN, PM_STANDARD, PM_STANDARD_REVERSE
from .coordinator import AirGradientConfigCoordinator from .coordinator import AirGradientCoordinator
from .entity import AirGradientEntity from .entity import AirGradientEntity
@ -144,13 +144,11 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up AirGradient select entities based on a config entry.""" """Set up AirGradient select entities based on a config entry."""
coordinator = entry.runtime_data.config coordinator = entry.runtime_data
measurement_coordinator = entry.runtime_data.measurement model = coordinator.data.measures.model
async_add_entities([AirGradientSelect(coordinator, CONFIG_CONTROL_ENTITY)]) async_add_entities([AirGradientSelect(coordinator, CONFIG_CONTROL_ENTITY)])
model = measurement_coordinator.data.model
added_entities = False added_entities = False
@callback @callback
@ -158,7 +156,7 @@ async def async_setup_entry(
nonlocal added_entities nonlocal added_entities
if ( if (
coordinator.data.configuration_control is ConfigurationControl.LOCAL coordinator.data.config.configuration_control is ConfigurationControl.LOCAL
and not added_entities and not added_entities
): ):
entities: list[AirGradientSelect] = [ entities: list[AirGradientSelect] = [
@ -179,7 +177,8 @@ async def async_setup_entry(
async_add_entities(entities) async_add_entities(entities)
added_entities = True added_entities = True
elif ( elif (
coordinator.data.configuration_control is not ConfigurationControl.LOCAL coordinator.data.config.configuration_control
is not ConfigurationControl.LOCAL
and added_entities and added_entities
): ):
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -201,11 +200,10 @@ class AirGradientSelect(AirGradientEntity, SelectEntity):
"""Defines an AirGradient select entity.""" """Defines an AirGradient select entity."""
entity_description: AirGradientSelectEntityDescription entity_description: AirGradientSelectEntityDescription
coordinator: AirGradientConfigCoordinator
def __init__( def __init__(
self, self,
coordinator: AirGradientConfigCoordinator, coordinator: AirGradientCoordinator,
description: AirGradientSelectEntityDescription, description: AirGradientSelectEntityDescription,
) -> None: ) -> None:
"""Initialize AirGradient select.""" """Initialize AirGradient select."""
@ -216,7 +214,7 @@ class AirGradientSelect(AirGradientEntity, SelectEntity):
@property @property
def current_option(self) -> str | None: def current_option(self) -> str | None:
"""Return the state of the select.""" """Return the state of the select."""
return self.entity_description.value_fn(self.coordinator.data) return self.entity_description.value_fn(self.coordinator.data.config)
async def async_select_option(self, option: str) -> None: async def async_select_option(self, option: str) -> None:
"""Change the selected option.""" """Change the selected option."""

View File

@ -32,7 +32,7 @@ from homeassistant.helpers.typing import StateType
from . import AirGradientConfigEntry from . import AirGradientConfigEntry
from .const import PM_STANDARD, PM_STANDARD_REVERSE from .const import PM_STANDARD, PM_STANDARD_REVERSE
from .coordinator import AirGradientConfigCoordinator, AirGradientMeasurementCoordinator from .coordinator import AirGradientCoordinator
from .entity import AirGradientEntity from .entity import AirGradientEntity
@ -218,7 +218,7 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up AirGradient sensor entities based on a config entry.""" """Set up AirGradient sensor entities based on a config entry."""
coordinator = entry.runtime_data.measurement coordinator = entry.runtime_data
listener: Callable[[], None] | None = None listener: Callable[[], None] | None = None
not_setup: set[AirGradientMeasurementSensorEntityDescription] = set( not_setup: set[AirGradientMeasurementSensorEntityDescription] = set(
MEASUREMENT_SENSOR_TYPES MEASUREMENT_SENSOR_TYPES
@ -232,7 +232,7 @@ async def async_setup_entry(
not_setup = set() not_setup = set()
sensors = [] sensors = []
for description in sensor_descriptions: for description in sensor_descriptions:
if description.value_fn(coordinator.data) is None: if description.value_fn(coordinator.data.measures) is None:
not_setup.add(description) not_setup.add(description)
else: else:
sensors.append(AirGradientMeasurementSensor(coordinator, description)) sensors.append(AirGradientMeasurementSensor(coordinator, description))
@ -248,64 +248,65 @@ async def async_setup_entry(
add_entities() add_entities()
entities = [ entities = [
AirGradientConfigSensor(entry.runtime_data.config, description) AirGradientConfigSensor(coordinator, description)
for description in CONFIG_SENSOR_TYPES for description in CONFIG_SENSOR_TYPES
] ]
if "L" in coordinator.data.model: if "L" in coordinator.data.measures.model:
entities.extend( entities.extend(
AirGradientConfigSensor(entry.runtime_data.config, description) AirGradientConfigSensor(coordinator, description)
for description in CONFIG_LED_BAR_SENSOR_TYPES for description in CONFIG_LED_BAR_SENSOR_TYPES
) )
if "I" in coordinator.data.model: if "I" in coordinator.data.measures.model:
entities.extend( entities.extend(
AirGradientConfigSensor(entry.runtime_data.config, description) AirGradientConfigSensor(coordinator, description)
for description in CONFIG_DISPLAY_SENSOR_TYPES for description in CONFIG_DISPLAY_SENSOR_TYPES
) )
async_add_entities(entities) async_add_entities(entities)
class AirGradientMeasurementSensor(AirGradientEntity, SensorEntity): class AirGradientSensor(AirGradientEntity, SensorEntity):
"""Defines an AirGradient sensor.""" """Defines an AirGradient sensor."""
entity_description: AirGradientMeasurementSensorEntityDescription
coordinator: AirGradientMeasurementCoordinator
def __init__( def __init__(
self, self,
coordinator: AirGradientMeasurementCoordinator, coordinator: AirGradientCoordinator,
description: AirGradientMeasurementSensorEntityDescription, description: SensorEntityDescription,
) -> None: ) -> None:
"""Initialize airgradient sensor.""" """Initialize airgradient sensor."""
super().__init__(coordinator) super().__init__(coordinator)
self.entity_description = description self.entity_description = description
self._attr_unique_id = f"{coordinator.serial_number}-{description.key}" self._attr_unique_id = f"{coordinator.serial_number}-{description.key}"
class AirGradientMeasurementSensor(AirGradientSensor):
"""Defines an AirGradient sensor."""
entity_description: AirGradientMeasurementSensorEntityDescription
@property @property
def native_value(self) -> StateType: def native_value(self) -> StateType:
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self.entity_description.value_fn(self.coordinator.data) return self.entity_description.value_fn(self.coordinator.data.measures)
class AirGradientConfigSensor(AirGradientEntity, SensorEntity): class AirGradientConfigSensor(AirGradientSensor):
"""Defines an AirGradient sensor.""" """Defines an AirGradient sensor."""
entity_description: AirGradientConfigSensorEntityDescription entity_description: AirGradientConfigSensorEntityDescription
coordinator: AirGradientConfigCoordinator
def __init__( def __init__(
self, self,
coordinator: AirGradientConfigCoordinator, coordinator: AirGradientCoordinator,
description: AirGradientConfigSensorEntityDescription, description: AirGradientConfigSensorEntityDescription,
) -> None: ) -> None:
"""Initialize airgradient sensor.""" """Initialize airgradient sensor."""
super().__init__(coordinator) super().__init__(coordinator, description)
self.entity_description = description
self._attr_unique_id = f"{coordinator.serial_number}-{description.key}"
self._attr_entity_registry_enabled_default = ( self._attr_entity_registry_enabled_default = (
coordinator.data.configuration_control is not ConfigurationControl.LOCAL coordinator.data.config.configuration_control
is not ConfigurationControl.LOCAL
) )
@property @property
def native_value(self) -> StateType: def native_value(self) -> StateType:
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self.entity_description.value_fn(self.coordinator.data) return self.entity_description.value_fn(self.coordinator.data.config)

View File

@ -19,7 +19,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AirGradientConfigEntry from . import AirGradientConfigEntry
from .const import DOMAIN from .const import DOMAIN
from .coordinator import AirGradientConfigCoordinator from .coordinator import AirGradientCoordinator
from .entity import AirGradientEntity from .entity import AirGradientEntity
@ -46,7 +46,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up AirGradient switch entities based on a config entry.""" """Set up AirGradient switch entities based on a config entry."""
coordinator = entry.runtime_data.config coordinator = entry.runtime_data
added_entities = False added_entities = False
@ -55,7 +55,7 @@ async def async_setup_entry(
nonlocal added_entities nonlocal added_entities
if ( if (
coordinator.data.configuration_control is ConfigurationControl.LOCAL coordinator.data.config.configuration_control is ConfigurationControl.LOCAL
and not added_entities and not added_entities
): ):
async_add_entities( async_add_entities(
@ -63,7 +63,8 @@ async def async_setup_entry(
) )
added_entities = True added_entities = True
elif ( elif (
coordinator.data.configuration_control is not ConfigurationControl.LOCAL coordinator.data.config.configuration_control
is not ConfigurationControl.LOCAL
and added_entities and added_entities
): ):
entity_registry = er.async_get(hass) entity_registry = er.async_get(hass)
@ -82,11 +83,10 @@ class AirGradientSwitch(AirGradientEntity, SwitchEntity):
"""Defines an AirGradient switch entity.""" """Defines an AirGradient switch entity."""
entity_description: AirGradientSwitchEntityDescription entity_description: AirGradientSwitchEntityDescription
coordinator: AirGradientConfigCoordinator
def __init__( def __init__(
self, self,
coordinator: AirGradientConfigCoordinator, coordinator: AirGradientCoordinator,
description: AirGradientSwitchEntityDescription, description: AirGradientSwitchEntityDescription,
) -> None: ) -> None:
"""Initialize AirGradient switch.""" """Initialize AirGradient switch."""
@ -97,7 +97,7 @@ class AirGradientSwitch(AirGradientEntity, SwitchEntity):
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
"""Return the state of the switch.""" """Return the state of the switch."""
return self.entity_description.value_fn(self.coordinator.data) return self.entity_description.value_fn(self.coordinator.data.config)
async def async_turn_on(self, **kwargs: Any) -> None: async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the switch on.""" """Turn the switch on."""

View File

@ -7,7 +7,7 @@ from homeassistant.components.update import UpdateDeviceClass, UpdateEntity
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AirGradientConfigEntry, AirGradientMeasurementCoordinator from . import AirGradientConfigEntry, AirGradientCoordinator
from .entity import AirGradientEntity from .entity import AirGradientEntity
SCAN_INTERVAL = timedelta(hours=1) SCAN_INTERVAL = timedelta(hours=1)
@ -20,18 +20,17 @@ async def async_setup_entry(
) -> None: ) -> None:
"""Set up Airgradient update platform.""" """Set up Airgradient update platform."""
data = config_entry.runtime_data coordinator = config_entry.runtime_data
async_add_entities([AirGradientUpdate(data.measurement)], True) async_add_entities([AirGradientUpdate(coordinator)], True)
class AirGradientUpdate(AirGradientEntity, UpdateEntity): class AirGradientUpdate(AirGradientEntity, UpdateEntity):
"""Representation of Airgradient Update.""" """Representation of Airgradient Update."""
_attr_device_class = UpdateDeviceClass.FIRMWARE _attr_device_class = UpdateDeviceClass.FIRMWARE
coordinator: AirGradientMeasurementCoordinator
def __init__(self, coordinator: AirGradientMeasurementCoordinator) -> None: def __init__(self, coordinator: AirGradientCoordinator) -> None:
"""Initialize the entity.""" """Initialize the entity."""
super().__init__(coordinator) super().__init__(coordinator)
self._attr_unique_id = f"{coordinator.serial_number}-update" self._attr_unique_id = f"{coordinator.serial_number}-update"
@ -44,7 +43,7 @@ class AirGradientUpdate(AirGradientEntity, UpdateEntity):
@property @property
def installed_version(self) -> str: def installed_version(self) -> str:
"""Return the installed version of the entity.""" """Return the installed version of the entity."""
return self.coordinator.data.firmware_version return self.coordinator.data.measures.firmware_version
async def async_update(self) -> None: async def async_update(self) -> None:
"""Update the entity.""" """Update the entity."""

View File

@ -57,7 +57,7 @@
'name': 'Airgradient', 'name': 'Airgradient',
'name_by_user': None, 'name_by_user': None,
'primary_config_entry': <ANY>, 'primary_config_entry': <ANY>,
'serial_number': '84fce60bec38', 'serial_number': '84fce612f5b8',
'suggested_area': None, 'suggested_area': None,
'sw_version': '3.1.1', 'sw_version': '3.1.1',
'via_device_id': None, 'via_device_id': None,

View File

@ -7,7 +7,7 @@ from airgradient import Config
from freezegun.api import FrozenDateTimeFactory from freezegun.api import FrozenDateTimeFactory
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.airgradient import DOMAIN from homeassistant.components.airgradient.const import DOMAIN
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
from homeassistant.const import ATTR_ENTITY_ID, Platform from homeassistant.const import ATTR_ENTITY_ID, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant

View File

@ -9,7 +9,7 @@ from airgradient import (
ConfigurationControl, ConfigurationControl,
) )
from homeassistant.components.airgradient import DOMAIN from homeassistant.components.airgradient.const import DOMAIN
from homeassistant.components.zeroconf import ZeroconfServiceInfo from homeassistant.components.zeroconf import ZeroconfServiceInfo
from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF from homeassistant.config_entries import SOURCE_USER, SOURCE_ZEROCONF
from homeassistant.const import CONF_HOST from homeassistant.const import CONF_HOST

View File

@ -4,7 +4,7 @@ from unittest.mock import AsyncMock
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.airgradient import DOMAIN from homeassistant.components.airgradient.const import DOMAIN
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr from homeassistant.helpers import device_registry as dr

View File

@ -7,7 +7,7 @@ from airgradient import Config
from freezegun.api import FrozenDateTimeFactory from freezegun.api import FrozenDateTimeFactory
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.airgradient import DOMAIN from homeassistant.components.airgradient.const import DOMAIN
from homeassistant.components.number import ( from homeassistant.components.number import (
ATTR_VALUE, ATTR_VALUE,
DOMAIN as NUMBER_DOMAIN, DOMAIN as NUMBER_DOMAIN,

View File

@ -8,7 +8,7 @@ from freezegun.api import FrozenDateTimeFactory
import pytest import pytest
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.airgradient import DOMAIN from homeassistant.components.airgradient.const import DOMAIN
from homeassistant.components.select import ( from homeassistant.components.select import (
DOMAIN as SELECT_DOMAIN, DOMAIN as SELECT_DOMAIN,
SERVICE_SELECT_OPTION, SERVICE_SELECT_OPTION,

View File

@ -8,7 +8,7 @@ from freezegun.api import FrozenDateTimeFactory
import pytest import pytest
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.airgradient import DOMAIN from homeassistant.components.airgradient.const import DOMAIN
from homeassistant.const import STATE_UNAVAILABLE, Platform from homeassistant.const import STATE_UNAVAILABLE, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er

View File

@ -7,7 +7,7 @@ from airgradient import Config
from freezegun.api import FrozenDateTimeFactory from freezegun.api import FrozenDateTimeFactory
from syrupy import SnapshotAssertion from syrupy import SnapshotAssertion
from homeassistant.components.airgradient import DOMAIN from homeassistant.components.airgradient.const import DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,