1 """Support for the Foobot indoor air quality monitor."""
3 from __future__
import annotations
5 from datetime
import timedelta
10 from foobot_async
import FoobotClient
11 import voluptuous
as vol
14 PLATFORM_SCHEMA
as SENSOR_PLATFORM_SCHEMA,
17 SensorEntityDescription,
21 CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
22 CONCENTRATION_PARTS_PER_BILLION,
23 CONCENTRATION_PARTS_PER_MILLION,
37 _LOGGER = logging.getLogger(__name__)
39 ATTR_HUMIDITY =
"humidity"
41 ATTR_CARBON_DIOXIDE =
"CO2"
42 ATTR_VOLATILE_ORGANIC_COMPOUNDS =
"VOC"
43 ATTR_FOOBOT_INDEX =
"index"
45 SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
49 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
54 name=ATTR_TEMPERATURE,
55 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
56 device_class=SensorDeviceClass.TEMPERATURE,
61 native_unit_of_measurement=PERCENTAGE,
62 icon=
"mdi:water-percent",
66 name=ATTR_CARBON_DIOXIDE,
67 native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
68 icon=
"mdi:molecule-co2",
72 name=ATTR_VOLATILE_ORGANIC_COMPOUNDS,
73 native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
78 name=ATTR_FOOBOT_INDEX,
79 native_unit_of_measurement=PERCENTAGE,
89 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
90 {vol.Required(CONF_TOKEN): cv.string, vol.Required(CONF_USERNAME): cv.string}
97 async_add_entities: AddEntitiesCallback,
98 discovery_info: DiscoveryInfoType |
None =
None,
100 """Set up the devices associated with the account."""
101 token: str = config[CONF_TOKEN]
102 username: str = config[CONF_USERNAME]
104 client = FoobotClient(
107 entities: list[FoobotSensor] = []
109 devices: list[dict[str, Any]] = await client.get_devices()
110 _LOGGER.debug(
"The following devices were found: %s", devices)
111 for device
in devices:
112 foobot_data =
FoobotData(client, device[
"uuid"])
116 for description
in SENSOR_TYPES
120 aiohttp.client_exceptions.ClientConnectorError,
122 FoobotClient.TooManyRequests,
123 FoobotClient.InternalError,
125 _LOGGER.exception(
"Failed to connect to foobot servers")
126 raise PlatformNotReady
from err
127 except FoobotClient.ClientError:
128 _LOGGER.error(
"Failed to fetch data from foobot servers")
134 """Implementation of a Foobot sensor."""
139 device: dict[str, Any],
140 description: SensorEntityDescription,
142 """Initialize the sensor."""
146 self.
_attr_name_attr_name = f
"Foobot {device['name']} {description.name}"
151 """Return the state of the device."""
155 """Get the latest data."""
160 """Get data from Foobot API."""
162 def __init__(self, client: FoobotClient, uuid: str) ->
None:
163 """Initialize the data object."""
166 self.
datadata: dict[str, float] = {}
168 @Throttle(SCAN_INTERVAL)
170 """Get the data from Foobot API."""
171 interval = SCAN_INTERVAL.total_seconds()
173 response: list[dict[str, Any]] = await self.
_client_client.get_last_data(
174 self.
_uuid_uuid, interval, interval + 1
177 aiohttp.client_exceptions.ClientConnectorError,
179 self.
_client_client.TooManyRequests,
180 self.
_client_client.InternalError,
182 _LOGGER.debug(
"Couldn't fetch data")
184 _LOGGER.debug(
"The data response is: %s", response)
185 self.
datadata = {k: round(v, 1)
for k, v
in response[0].items()}
None __init__(self, FoobotClient client, str uuid)
None __init__(self, FoobotData data, dict[str, Any] device, SensorEntityDescription description)
float|None native_value(self)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)