mirror of
https://github.com/home-assistant/core.git
synced 2025-07-20 19:57:07 +00:00
Honeywell Lyric - Entity Descriptions (#54956)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
parent
d4b506e5e4
commit
e062d7aec0
@ -140,18 +140,12 @@ class LyricEntity(CoordinatorEntity):
|
|||||||
location: LyricLocation,
|
location: LyricLocation,
|
||||||
device: LyricDevice,
|
device: LyricDevice,
|
||||||
key: str,
|
key: str,
|
||||||
name: str,
|
|
||||||
icon: str | None,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the Honeywell Lyric entity."""
|
"""Initialize the Honeywell Lyric entity."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._key = key
|
self._key = key
|
||||||
self._name = name
|
|
||||||
self._icon = icon
|
|
||||||
self._location = location
|
self._location = location
|
||||||
self._mac_id = device.macID
|
self._mac_id = device.macID
|
||||||
self._device_name = device.name
|
|
||||||
self._device_model = device.deviceModel
|
|
||||||
self._update_thermostat = coordinator.data.update_thermostat
|
self._update_thermostat = coordinator.data.update_thermostat
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -159,16 +153,6 @@ class LyricEntity(CoordinatorEntity):
|
|||||||
"""Return the unique ID for this entity."""
|
"""Return the unique ID for this entity."""
|
||||||
return self._key
|
return self._key
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self) -> str:
|
|
||||||
"""Return the name of the entity."""
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def icon(self) -> str:
|
|
||||||
"""Return the mdi icon of the entity."""
|
|
||||||
return self._icon
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def location(self) -> LyricLocation:
|
def location(self) -> LyricLocation:
|
||||||
"""Get the Lyric Location."""
|
"""Get the Lyric Location."""
|
||||||
@ -189,6 +173,6 @@ class LyricDeviceEntity(LyricEntity):
|
|||||||
return {
|
return {
|
||||||
"connections": {(dr.CONNECTION_NETWORK_MAC, self._mac_id)},
|
"connections": {(dr.CONNECTION_NETWORK_MAC, self._mac_id)},
|
||||||
"manufacturer": "Honeywell",
|
"manufacturer": "Honeywell",
|
||||||
"model": self._device_model,
|
"model": self.device.deviceModel,
|
||||||
"name": self._device_name,
|
"name": self.device.name,
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ from aiolyric.objects.device import LyricDevice
|
|||||||
from aiolyric.objects.location import LyricLocation
|
from aiolyric.objects.location import LyricLocation
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.climate import ClimateEntity
|
from homeassistant.components.climate import ClimateEntity, ClimateEntityDescription
|
||||||
from homeassistant.components.climate.const import (
|
from homeassistant.components.climate.const import (
|
||||||
ATTR_TARGET_TEMP_HIGH,
|
ATTR_TARGET_TEMP_HIGH,
|
||||||
ATTR_TARGET_TEMP_LOW,
|
ATTR_TARGET_TEMP_LOW,
|
||||||
@ -99,7 +99,14 @@ async def async_setup_entry(
|
|||||||
for device in location.devices:
|
for device in location.devices:
|
||||||
entities.append(
|
entities.append(
|
||||||
LyricClimate(
|
LyricClimate(
|
||||||
coordinator, location, device, hass.config.units.temperature_unit
|
coordinator,
|
||||||
|
ClimateEntityDescription(
|
||||||
|
key=f"{device.macID}_thermostat",
|
||||||
|
name=device.name,
|
||||||
|
),
|
||||||
|
location,
|
||||||
|
device,
|
||||||
|
hass.config.units.temperature_unit,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -117,9 +124,13 @@ async def async_setup_entry(
|
|||||||
class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
||||||
"""Defines a Honeywell Lyric climate entity."""
|
"""Defines a Honeywell Lyric climate entity."""
|
||||||
|
|
||||||
|
coordinator: DataUpdateCoordinator
|
||||||
|
entity_description: ClimateEntityDescription
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
coordinator: DataUpdateCoordinator,
|
coordinator: DataUpdateCoordinator,
|
||||||
|
description: ClimateEntityDescription,
|
||||||
location: LyricLocation,
|
location: LyricLocation,
|
||||||
device: LyricDevice,
|
device: LyricDevice,
|
||||||
temperature_unit: str,
|
temperature_unit: str,
|
||||||
@ -148,9 +159,8 @@ class LyricClimate(LyricDeviceEntity, ClimateEntity):
|
|||||||
location,
|
location,
|
||||||
device,
|
device,
|
||||||
f"{device.macID}_thermostat",
|
f"{device.macID}_thermostat",
|
||||||
device.name,
|
|
||||||
None,
|
|
||||||
)
|
)
|
||||||
|
self.entity_description = description
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self) -> int:
|
def supported_features(self) -> int:
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
"""Support for Honeywell Lyric sensor platform."""
|
"""Support for Honeywell Lyric sensor platform."""
|
||||||
|
from dataclasses import dataclass
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from typing import Callable, cast
|
||||||
|
|
||||||
from aiolyric.objects.device import LyricDevice
|
from aiolyric.objects.device import LyricDevice
|
||||||
from aiolyric.objects.location import LyricLocation
|
from aiolyric.objects.location import LyricLocation
|
||||||
|
|
||||||
from homeassistant.components.sensor import SensorEntity
|
from homeassistant.components.sensor import (
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
SensorEntity,
|
||||||
|
SensorEntityDescription,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
DEVICE_CLASS_HUMIDITY,
|
DEVICE_CLASS_HUMIDITY,
|
||||||
@ -12,6 +18,7 @@ from homeassistant.const import (
|
|||||||
DEVICE_CLASS_TIMESTAMP,
|
DEVICE_CLASS_TIMESTAMP,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.typing import StateType
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
@ -33,6 +40,22 @@ LYRIC_SETPOINT_STATUS_NAMES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LyricSensorEntityDescription(SensorEntityDescription):
|
||||||
|
"""Class describing Honeywell Lyric sensor entities."""
|
||||||
|
|
||||||
|
value: Callable[[LyricDevice], StateType] = round
|
||||||
|
|
||||||
|
|
||||||
|
def get_datetime_from_future_time(time: str) -> datetime:
|
||||||
|
"""Get datetime from future time provided."""
|
||||||
|
time = dt_util.parse_time(time)
|
||||||
|
now = dt_util.utcnow()
|
||||||
|
if time <= now.time():
|
||||||
|
now = now + timedelta(days=1)
|
||||||
|
return dt_util.as_utc(datetime.combine(now.date(), time))
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -41,212 +64,126 @@ async def async_setup_entry(
|
|||||||
|
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
|
def get_setpoint_status(status: str, time: str) -> str:
|
||||||
|
if status == PRESET_HOLD_UNTIL:
|
||||||
|
return f"Held until {time}"
|
||||||
|
return LYRIC_SETPOINT_STATUS_NAMES.get(status, None)
|
||||||
|
|
||||||
for location in coordinator.data.locations:
|
for location in coordinator.data.locations:
|
||||||
for device in location.devices:
|
for device in location.devices:
|
||||||
cls_list = []
|
|
||||||
if device.indoorTemperature:
|
if device.indoorTemperature:
|
||||||
cls_list.append(LyricIndoorTemperatureSensor)
|
|
||||||
if device.outdoorTemperature:
|
|
||||||
cls_list.append(LyricOutdoorTemperatureSensor)
|
|
||||||
if device.displayedOutdoorHumidity:
|
|
||||||
cls_list.append(LyricOutdoorHumiditySensor)
|
|
||||||
if device.changeableValues:
|
|
||||||
if device.changeableValues.nextPeriodTime:
|
|
||||||
cls_list.append(LyricNextPeriodSensor)
|
|
||||||
if device.changeableValues.thermostatSetpointStatus:
|
|
||||||
cls_list.append(LyricSetpointStatusSensor)
|
|
||||||
for cls in cls_list:
|
|
||||||
entities.append(
|
entities.append(
|
||||||
cls(
|
LyricSensor(
|
||||||
coordinator,
|
coordinator,
|
||||||
|
LyricSensorEntityDescription(
|
||||||
|
key=f"{device.macID}_indoor_temperature",
|
||||||
|
name="Indoor Temperature",
|
||||||
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
native_unit_of_measurement=hass.config.units.temperature_unit,
|
||||||
|
value=lambda device: device.indoorTemperature,
|
||||||
|
),
|
||||||
location,
|
location,
|
||||||
device,
|
device,
|
||||||
hass.config.units.temperature_unit,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if device.outdoorTemperature:
|
||||||
|
entities.append(
|
||||||
|
LyricSensor(
|
||||||
|
coordinator,
|
||||||
|
LyricSensorEntityDescription(
|
||||||
|
key=f"{device.macID}_outdoor_temperature",
|
||||||
|
name="Outdoor Temperature",
|
||||||
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
native_unit_of_measurement=hass.config.units.temperature_unit,
|
||||||
|
value=lambda device: device.outdoorTemperature,
|
||||||
|
),
|
||||||
|
location,
|
||||||
|
device,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if device.displayedOutdoorHumidity:
|
||||||
|
entities.append(
|
||||||
|
LyricSensor(
|
||||||
|
coordinator,
|
||||||
|
LyricSensorEntityDescription(
|
||||||
|
key=f"{device.macID}_outdoor_humidity",
|
||||||
|
name="Outdoor Humidity",
|
||||||
|
device_class=DEVICE_CLASS_HUMIDITY,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
native_unit_of_measurement="%",
|
||||||
|
value=lambda device: device.displayedOutdoorHumidity,
|
||||||
|
),
|
||||||
|
location,
|
||||||
|
device,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if device.changeableValues:
|
||||||
|
if device.changeableValues.nextPeriodTime:
|
||||||
|
entities.append(
|
||||||
|
LyricSensor(
|
||||||
|
coordinator,
|
||||||
|
LyricSensorEntityDescription(
|
||||||
|
key=f"{device.macID}_next_period_time",
|
||||||
|
name="Next Period Time",
|
||||||
|
device_class=DEVICE_CLASS_TIMESTAMP,
|
||||||
|
value=lambda device: get_datetime_from_future_time(
|
||||||
|
device.changeableValues.nextPeriodTime
|
||||||
|
).isoformat(),
|
||||||
|
),
|
||||||
|
location,
|
||||||
|
device,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if device.changeableValues.thermostatSetpointStatus:
|
||||||
|
entities.append(
|
||||||
|
LyricSensor(
|
||||||
|
coordinator,
|
||||||
|
LyricSensorEntityDescription(
|
||||||
|
key=f"{device.macID}_setpoint_status",
|
||||||
|
name="Setpoint Status",
|
||||||
|
icon="mdi:thermostat",
|
||||||
|
value=lambda device: get_setpoint_status(
|
||||||
|
device.changeableValues.thermostatSetpointStatus,
|
||||||
|
device.changeableValues.nextPeriodTime,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
location,
|
||||||
|
device,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
async_add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
|
|
||||||
class LyricSensor(LyricDeviceEntity, SensorEntity):
|
class LyricSensor(LyricDeviceEntity, SensorEntity):
|
||||||
"""Defines a Honeywell Lyric sensor."""
|
"""Define a Honeywell Lyric sensor."""
|
||||||
|
|
||||||
|
coordinator: DataUpdateCoordinator
|
||||||
|
entity_description: LyricSensorEntityDescription
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
coordinator: DataUpdateCoordinator,
|
coordinator: DataUpdateCoordinator,
|
||||||
|
description: LyricSensorEntityDescription,
|
||||||
location: LyricLocation,
|
location: LyricLocation,
|
||||||
device: LyricDevice,
|
device: LyricDevice,
|
||||||
key: str,
|
|
||||||
name: str,
|
|
||||||
icon: str,
|
|
||||||
device_class: str = None,
|
|
||||||
unit_of_measurement: str = None,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize Honeywell Lyric sensor."""
|
"""Initialize."""
|
||||||
self._device_class = device_class
|
|
||||||
self._unit_of_measurement = unit_of_measurement
|
|
||||||
|
|
||||||
super().__init__(coordinator, location, device, key, name, icon)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def device_class(self) -> str:
|
|
||||||
"""Return the device class of the sensor."""
|
|
||||||
return self._device_class
|
|
||||||
|
|
||||||
@property
|
|
||||||
def native_unit_of_measurement(self) -> str:
|
|
||||||
"""Return the unit this state is expressed in."""
|
|
||||||
return self._unit_of_measurement
|
|
||||||
|
|
||||||
|
|
||||||
class LyricIndoorTemperatureSensor(LyricSensor):
|
|
||||||
"""Defines a Honeywell Lyric sensor."""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
coordinator: DataUpdateCoordinator,
|
|
||||||
location: LyricLocation,
|
|
||||||
device: LyricDevice,
|
|
||||||
unit_of_measurement: str = None,
|
|
||||||
) -> None:
|
|
||||||
"""Initialize Honeywell Lyric sensor."""
|
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
coordinator,
|
coordinator,
|
||||||
location,
|
location,
|
||||||
device,
|
device,
|
||||||
f"{device.macID}_indoor_temperature",
|
description.key,
|
||||||
"Indoor Temperature",
|
|
||||||
None,
|
|
||||||
DEVICE_CLASS_TEMPERATURE,
|
|
||||||
unit_of_measurement,
|
|
||||||
)
|
)
|
||||||
|
self.entity_description = description
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self) -> str:
|
def native_value(self) -> StateType:
|
||||||
"""Return the state of the sensor."""
|
"""Return the state."""
|
||||||
return self.device.indoorTemperature
|
device: LyricDevice = self.device
|
||||||
|
try:
|
||||||
|
return cast(StateType, self.entity_description.value(device))
|
||||||
class LyricOutdoorTemperatureSensor(LyricSensor):
|
except TypeError:
|
||||||
"""Defines a Honeywell Lyric sensor."""
|
return None
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
coordinator: DataUpdateCoordinator,
|
|
||||||
location: LyricLocation,
|
|
||||||
device: LyricDevice,
|
|
||||||
unit_of_measurement: str = None,
|
|
||||||
) -> None:
|
|
||||||
"""Initialize Honeywell Lyric sensor."""
|
|
||||||
|
|
||||||
super().__init__(
|
|
||||||
coordinator,
|
|
||||||
location,
|
|
||||||
device,
|
|
||||||
f"{device.macID}_outdoor_temperature",
|
|
||||||
"Outdoor Temperature",
|
|
||||||
None,
|
|
||||||
DEVICE_CLASS_TEMPERATURE,
|
|
||||||
unit_of_measurement,
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def native_value(self) -> str:
|
|
||||||
"""Return the state of the sensor."""
|
|
||||||
return self.device.outdoorTemperature
|
|
||||||
|
|
||||||
|
|
||||||
class LyricOutdoorHumiditySensor(LyricSensor):
|
|
||||||
"""Defines a Honeywell Lyric sensor."""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
coordinator: DataUpdateCoordinator,
|
|
||||||
location: LyricLocation,
|
|
||||||
device: LyricDevice,
|
|
||||||
unit_of_measurement: str = None,
|
|
||||||
) -> None:
|
|
||||||
"""Initialize Honeywell Lyric sensor."""
|
|
||||||
|
|
||||||
super().__init__(
|
|
||||||
coordinator,
|
|
||||||
location,
|
|
||||||
device,
|
|
||||||
f"{device.macID}_outdoor_humidity",
|
|
||||||
"Outdoor Humidity",
|
|
||||||
None,
|
|
||||||
DEVICE_CLASS_HUMIDITY,
|
|
||||||
"%",
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def native_value(self) -> str:
|
|
||||||
"""Return the state of the sensor."""
|
|
||||||
return self.device.displayedOutdoorHumidity
|
|
||||||
|
|
||||||
|
|
||||||
class LyricNextPeriodSensor(LyricSensor):
|
|
||||||
"""Defines a Honeywell Lyric sensor."""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
coordinator: DataUpdateCoordinator,
|
|
||||||
location: LyricLocation,
|
|
||||||
device: LyricDevice,
|
|
||||||
unit_of_measurement: str = None,
|
|
||||||
) -> None:
|
|
||||||
"""Initialize Honeywell Lyric sensor."""
|
|
||||||
|
|
||||||
super().__init__(
|
|
||||||
coordinator,
|
|
||||||
location,
|
|
||||||
device,
|
|
||||||
f"{device.macID}_next_period_time",
|
|
||||||
"Next Period Time",
|
|
||||||
None,
|
|
||||||
DEVICE_CLASS_TIMESTAMP,
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def native_value(self) -> datetime:
|
|
||||||
"""Return the state of the sensor."""
|
|
||||||
device = self.device
|
|
||||||
time = dt_util.parse_time(device.changeableValues.nextPeriodTime)
|
|
||||||
now = dt_util.utcnow()
|
|
||||||
if time <= now.time():
|
|
||||||
now = now + timedelta(days=1)
|
|
||||||
return dt_util.as_utc(datetime.combine(now.date(), time))
|
|
||||||
|
|
||||||
|
|
||||||
class LyricSetpointStatusSensor(LyricSensor):
|
|
||||||
"""Defines a Honeywell Lyric sensor."""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
coordinator: DataUpdateCoordinator,
|
|
||||||
location: LyricLocation,
|
|
||||||
device: LyricDevice,
|
|
||||||
unit_of_measurement: str = None,
|
|
||||||
) -> None:
|
|
||||||
"""Initialize Honeywell Lyric sensor."""
|
|
||||||
|
|
||||||
super().__init__(
|
|
||||||
coordinator,
|
|
||||||
location,
|
|
||||||
device,
|
|
||||||
f"{device.macID}_setpoint_status",
|
|
||||||
"Setpoint Status",
|
|
||||||
"mdi:thermostat",
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def native_value(self) -> str:
|
|
||||||
"""Return the state of the sensor."""
|
|
||||||
device = self.device
|
|
||||||
if device.changeableValues.thermostatSetpointStatus == PRESET_HOLD_UNTIL:
|
|
||||||
return f"Held until {device.changeableValues.nextPeriodTime}"
|
|
||||||
return LYRIC_SETPOINT_STATUS_NAMES.get(
|
|
||||||
device.changeableValues.thermostatSetpointStatus, "Unknown"
|
|
||||||
)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user