2019-04-03 15:40:03 +00:00
|
|
|
"""Support for Canary sensors."""
|
2021-03-17 22:43:55 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from typing import Callable
|
2020-09-19 04:22:19 +00:00
|
|
|
|
2019-12-05 05:30:22 +00:00
|
|
|
from canary.api import SensorType
|
2018-01-28 23:30:46 +00:00
|
|
|
|
2021-03-22 11:37:16 +00:00
|
|
|
from homeassistant.components.sensor import SensorEntity
|
2020-09-19 04:22:19 +00:00
|
|
|
from homeassistant.config_entries import ConfigEntry
|
2020-09-14 02:29:59 +00:00
|
|
|
from homeassistant.const import (
|
|
|
|
DEVICE_CLASS_BATTERY,
|
|
|
|
DEVICE_CLASS_HUMIDITY,
|
|
|
|
DEVICE_CLASS_SIGNAL_STRENGTH,
|
|
|
|
DEVICE_CLASS_TEMPERATURE,
|
|
|
|
PERCENTAGE,
|
2020-10-01 14:14:29 +00:00
|
|
|
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
2020-09-14 02:29:59 +00:00
|
|
|
TEMP_CELSIUS,
|
|
|
|
)
|
2017-12-08 09:40:45 +00:00
|
|
|
from homeassistant.helpers.entity import Entity
|
2020-09-19 04:22:19 +00:00
|
|
|
from homeassistant.helpers.typing import HomeAssistantType
|
2020-10-01 08:26:26 +00:00
|
|
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
2017-12-08 09:40:45 +00:00
|
|
|
|
2020-10-01 08:26:26 +00:00
|
|
|
from .const import DATA_COORDINATOR, DOMAIN, MANUFACTURER
|
|
|
|
from .coordinator import CanaryDataUpdateCoordinator
|
2019-03-21 05:56:46 +00:00
|
|
|
|
2018-01-28 23:30:46 +00:00
|
|
|
SENSOR_VALUE_PRECISION = 2
|
|
|
|
ATTR_AIR_QUALITY = "air_quality"
|
|
|
|
|
2020-03-11 18:58:42 +00:00
|
|
|
# Define variables to store the device names, as referred to by the Canary API.
|
|
|
|
# Note: If Canary change the name of any of their devices (which they have done),
|
|
|
|
# then these variables will need updating, otherwise the sensors will stop working
|
|
|
|
# and disappear in Home Assistant.
|
|
|
|
CANARY_PRO = "Canary Pro"
|
|
|
|
CANARY_FLEX = "Canary Flex"
|
|
|
|
|
2018-01-28 23:30:46 +00:00
|
|
|
# Sensor types are defined like so:
|
2020-09-14 02:29:59 +00:00
|
|
|
# sensor type name, unit_of_measurement, icon, device class, products supported
|
2018-01-28 23:30:46 +00:00
|
|
|
SENSOR_TYPES = [
|
2020-09-14 02:29:59 +00:00
|
|
|
["temperature", TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE, [CANARY_PRO]],
|
|
|
|
["humidity", PERCENTAGE, None, DEVICE_CLASS_HUMIDITY, [CANARY_PRO]],
|
|
|
|
["air_quality", None, "mdi:weather-windy", None, [CANARY_PRO]],
|
2020-10-01 14:14:29 +00:00
|
|
|
[
|
|
|
|
"wifi",
|
|
|
|
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
|
|
|
None,
|
|
|
|
DEVICE_CLASS_SIGNAL_STRENGTH,
|
|
|
|
[CANARY_FLEX],
|
|
|
|
],
|
2020-09-14 02:29:59 +00:00
|
|
|
["battery", PERCENTAGE, None, DEVICE_CLASS_BATTERY, [CANARY_FLEX]],
|
2018-01-28 23:30:46 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
STATE_AIR_QUALITY_NORMAL = "normal"
|
|
|
|
STATE_AIR_QUALITY_ABNORMAL = "abnormal"
|
|
|
|
STATE_AIR_QUALITY_VERY_ABNORMAL = "very_abnormal"
|
2017-12-08 09:40:45 +00:00
|
|
|
|
|
|
|
|
2020-09-19 04:22:19 +00:00
|
|
|
async def async_setup_entry(
|
|
|
|
hass: HomeAssistantType,
|
|
|
|
entry: ConfigEntry,
|
2021-03-17 22:43:55 +00:00
|
|
|
async_add_entities: Callable[[list[Entity], bool], None],
|
2020-09-19 04:22:19 +00:00
|
|
|
) -> None:
|
|
|
|
"""Set up Canary sensors based on a config entry."""
|
2020-10-01 08:26:26 +00:00
|
|
|
coordinator: CanaryDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][
|
|
|
|
DATA_COORDINATOR
|
|
|
|
]
|
2020-09-19 04:22:19 +00:00
|
|
|
sensors = []
|
2017-12-08 09:40:45 +00:00
|
|
|
|
2020-10-01 08:26:26 +00:00
|
|
|
for location in coordinator.data["locations"].values():
|
2017-12-08 09:40:45 +00:00
|
|
|
for device in location.devices:
|
|
|
|
if device.is_online:
|
2018-03-30 21:38:29 +00:00
|
|
|
device_type = device.device_type
|
2018-01-28 23:30:46 +00:00
|
|
|
for sensor_type in SENSOR_TYPES:
|
2020-09-14 02:29:59 +00:00
|
|
|
if device_type.get("name") in sensor_type[4]:
|
2020-09-19 04:22:19 +00:00
|
|
|
sensors.append(
|
2020-10-01 08:26:26 +00:00
|
|
|
CanarySensor(coordinator, sensor_type, location, device)
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2017-12-08 09:40:45 +00:00
|
|
|
|
2020-09-19 04:22:19 +00:00
|
|
|
async_add_entities(sensors, True)
|
2017-12-08 09:40:45 +00:00
|
|
|
|
|
|
|
|
2021-03-22 11:37:16 +00:00
|
|
|
class CanarySensor(SensorEntity, CoordinatorEntity):
|
2017-12-08 09:40:45 +00:00
|
|
|
"""Representation of a Canary sensor."""
|
|
|
|
|
2020-10-01 08:26:26 +00:00
|
|
|
def __init__(self, coordinator, sensor_type, location, device):
|
2017-12-08 09:40:45 +00:00
|
|
|
"""Initialize the sensor."""
|
2020-10-01 08:26:26 +00:00
|
|
|
super().__init__(coordinator)
|
2017-12-08 09:40:45 +00:00
|
|
|
self._sensor_type = sensor_type
|
|
|
|
self._device_id = device.device_id
|
2020-09-19 15:09:40 +00:00
|
|
|
self._device_name = device.name
|
|
|
|
self._device_type_name = device.device_type["name"]
|
2017-12-08 09:40:45 +00:00
|
|
|
|
2018-01-28 23:30:46 +00:00
|
|
|
sensor_type_name = sensor_type[0].replace("_", " ").title()
|
2019-09-03 15:09:59 +00:00
|
|
|
self._name = f"{location.name} {device.name} {sensor_type_name}"
|
2017-12-08 09:40:45 +00:00
|
|
|
|
2020-10-01 08:26:26 +00:00
|
|
|
canary_sensor_type = None
|
|
|
|
if self._sensor_type[0] == "air_quality":
|
|
|
|
canary_sensor_type = SensorType.AIR_QUALITY
|
|
|
|
elif self._sensor_type[0] == "temperature":
|
|
|
|
canary_sensor_type = SensorType.TEMPERATURE
|
|
|
|
elif self._sensor_type[0] == "humidity":
|
|
|
|
canary_sensor_type = SensorType.HUMIDITY
|
|
|
|
elif self._sensor_type[0] == "wifi":
|
|
|
|
canary_sensor_type = SensorType.WIFI
|
|
|
|
elif self._sensor_type[0] == "battery":
|
|
|
|
canary_sensor_type = SensorType.BATTERY
|
|
|
|
|
|
|
|
self._canary_type = canary_sensor_type
|
|
|
|
|
|
|
|
@property
|
|
|
|
def reading(self):
|
|
|
|
"""Return the device sensor reading."""
|
|
|
|
readings = self.coordinator.data["readings"][self._device_id]
|
|
|
|
|
|
|
|
value = next(
|
|
|
|
(
|
|
|
|
reading.value
|
|
|
|
for reading in readings
|
|
|
|
if reading.sensor_type == self._canary_type
|
|
|
|
),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
|
|
|
|
if value is not None:
|
|
|
|
return round(float(value), SENSOR_VALUE_PRECISION)
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
2017-12-08 09:40:45 +00:00
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Return the name of the Canary sensor."""
|
|
|
|
return self._name
|
|
|
|
|
|
|
|
@property
|
|
|
|
def state(self):
|
|
|
|
"""Return the state of the sensor."""
|
2020-10-01 08:26:26 +00:00
|
|
|
return self.reading
|
2017-12-08 09:40:45 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def unique_id(self):
|
|
|
|
"""Return the unique ID of this sensor."""
|
2020-04-05 15:48:55 +00:00
|
|
|
return f"{self._device_id}_{self._sensor_type[0]}"
|
2017-12-08 09:40:45 +00:00
|
|
|
|
2020-09-19 15:09:40 +00:00
|
|
|
@property
|
|
|
|
def device_info(self):
|
|
|
|
"""Return the device_info of the device."""
|
|
|
|
return {
|
|
|
|
"identifiers": {(DOMAIN, str(self._device_id))},
|
|
|
|
"name": self._device_name,
|
|
|
|
"model": self._device_type_name,
|
|
|
|
"manufacturer": MANUFACTURER,
|
|
|
|
}
|
|
|
|
|
2017-12-08 09:40:45 +00:00
|
|
|
@property
|
|
|
|
def unit_of_measurement(self):
|
2018-01-28 23:30:46 +00:00
|
|
|
"""Return the unit of measurement."""
|
|
|
|
return self._sensor_type[1]
|
|
|
|
|
2020-09-14 02:29:59 +00:00
|
|
|
@property
|
|
|
|
def device_class(self):
|
|
|
|
"""Device class for the sensor."""
|
|
|
|
return self._sensor_type[3]
|
|
|
|
|
2018-01-28 23:30:46 +00:00
|
|
|
@property
|
|
|
|
def icon(self):
|
|
|
|
"""Icon for the sensor."""
|
|
|
|
return self._sensor_type[2]
|
|
|
|
|
|
|
|
@property
|
2021-03-11 15:51:03 +00:00
|
|
|
def extra_state_attributes(self):
|
2018-01-28 23:30:46 +00:00
|
|
|
"""Return the state attributes."""
|
2020-10-01 08:26:26 +00:00
|
|
|
reading = self.reading
|
|
|
|
|
|
|
|
if self._sensor_type[0] == "air_quality" and reading is not None:
|
2018-01-28 23:30:46 +00:00
|
|
|
air_quality = None
|
2020-10-01 08:26:26 +00:00
|
|
|
if reading <= 0.4:
|
2018-01-28 23:30:46 +00:00
|
|
|
air_quality = STATE_AIR_QUALITY_VERY_ABNORMAL
|
2020-10-01 08:26:26 +00:00
|
|
|
elif reading <= 0.59:
|
2018-01-28 23:30:46 +00:00
|
|
|
air_quality = STATE_AIR_QUALITY_ABNORMAL
|
2020-10-01 08:26:26 +00:00
|
|
|
elif reading <= 1.0:
|
2018-01-28 23:30:46 +00:00
|
|
|
air_quality = STATE_AIR_QUALITY_NORMAL
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
return {ATTR_AIR_QUALITY: air_quality}
|
2018-01-28 23:30:46 +00:00
|
|
|
|
2017-12-08 09:40:45 +00:00
|
|
|
return None
|