core/homeassistant/components/hue/v2/sensor.py

172 lines
5.7 KiB
Python

"""Support for Hue sensors."""
from __future__ import annotations
from typing import Any, Union
from aiohue.v2 import HueBridgeV2
from aiohue.v2.controllers.events import EventType
from aiohue.v2.controllers.sensors import (
DevicePowerController,
LightLevelController,
SensorsController,
TemperatureController,
ZigbeeConnectivityController,
)
from aiohue.v2.models.connectivity import ZigbeeConnectivity
from aiohue.v2.models.device_power import DevicePower
from aiohue.v2.models.light_level import LightLevel
from aiohue.v2.models.temperature import Temperature
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import LIGHT_LUX, PERCENTAGE, TEMP_CELSIUS
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from ..bridge import HueBridge
from ..const import DOMAIN
from .entity import HueBaseEntity
SensorType = Union[DevicePower, LightLevel, Temperature, ZigbeeConnectivity]
ControllerType = Union[
DevicePowerController,
LightLevelController,
TemperatureController,
ZigbeeConnectivityController,
]
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Hue Sensors from Config Entry."""
bridge: HueBridge = hass.data[DOMAIN][config_entry.entry_id]
api: HueBridgeV2 = bridge.api
ctrl_base: SensorsController = api.sensors
@callback
def register_items(controller: ControllerType, sensor_class: SensorType):
@callback
def async_add_sensor(event_type: EventType, resource: SensorType) -> None:
"""Add Hue Sensor."""
async_add_entities([sensor_class(bridge, controller, resource)])
# add all current items in controller
for sensor in controller:
async_add_sensor(EventType.RESOURCE_ADDED, sensor)
# register listener for new sensors
config_entry.async_on_unload(
controller.subscribe(
async_add_sensor, event_filter=EventType.RESOURCE_ADDED
)
)
# setup for each sensor-type hue resource
register_items(ctrl_base.temperature, HueTemperatureSensor)
register_items(ctrl_base.light_level, HueLightLevelSensor)
register_items(ctrl_base.device_power, HueBatterySensor)
register_items(ctrl_base.zigbee_connectivity, HueZigbeeConnectivitySensor)
class HueSensorBase(HueBaseEntity, SensorEntity):
"""Representation of a Hue sensor."""
_attr_state_class = SensorStateClass.MEASUREMENT
def __init__(
self,
bridge: HueBridge,
controller: ControllerType,
resource: SensorType,
) -> None:
"""Initialize the light."""
super().__init__(bridge, controller, resource)
self.resource = resource
self.controller = controller
class HueTemperatureSensor(HueSensorBase):
"""Representation of a Hue Temperature sensor."""
_attr_native_unit_of_measurement = TEMP_CELSIUS
_attr_device_class = SensorDeviceClass.TEMPERATURE
@property
def native_value(self) -> float:
"""Return the value reported by the sensor."""
return round(self.resource.temperature.temperature, 1)
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the optional state attributes."""
return {"temperature_valid": self.resource.temperature.temperature_valid}
class HueLightLevelSensor(HueSensorBase):
"""Representation of a Hue LightLevel (illuminance) sensor."""
_attr_native_unit_of_measurement = LIGHT_LUX
_attr_device_class = SensorDeviceClass.ILLUMINANCE
@property
def native_value(self) -> int:
"""Return the value reported by the sensor."""
# Light level in 10000 log10 (lux) +1 measured by sensor. Logarithm
# scale used because the human eye adjusts to light levels and small
# changes at low lux levels are more noticeable than at high lux
# levels.
return int(10 ** ((self.resource.light.light_level - 1) / 10000))
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the optional state attributes."""
return {
"light_level": self.resource.light.light_level,
"light_level_valid": self.resource.light.light_level_valid,
}
class HueBatterySensor(HueSensorBase):
"""Representation of a Hue Battery sensor."""
_attr_native_unit_of_measurement = PERCENTAGE
_attr_device_class = SensorDeviceClass.BATTERY
_attr_entity_category = EntityCategory.DIAGNOSTIC
@property
def native_value(self) -> int:
"""Return the value reported by the sensor."""
return self.resource.power_state.battery_level
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the optional state attributes."""
return {"battery_state": self.resource.power_state.battery_state.value}
class HueZigbeeConnectivitySensor(HueSensorBase):
"""Representation of a Hue ZigbeeConnectivity sensor."""
_attr_device_class = BinarySensorDeviceClass.CONNECTIVITY
_attr_entity_category = EntityCategory.DIAGNOSTIC
_attr_entity_registry_enabled_default = False
@property
def native_value(self) -> str:
"""Return the value reported by the sensor."""
return self.resource.status.value
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the optional state attributes."""
return {"mac_address": self.resource.mac_address}