2021-02-02 01:51:20 +00:00
|
|
|
"""Support for Honeywell Lyric sensor platform."""
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
|
|
|
|
from aiolyric.objects.device import LyricDevice
|
|
|
|
from aiolyric.objects.location import LyricLocation
|
|
|
|
|
2021-03-22 18:59:03 +00:00
|
|
|
from homeassistant.components.sensor import SensorEntity
|
2021-02-02 01:51:20 +00:00
|
|
|
from homeassistant.config_entries import ConfigEntry
|
|
|
|
from homeassistant.const import (
|
|
|
|
DEVICE_CLASS_HUMIDITY,
|
|
|
|
DEVICE_CLASS_TEMPERATURE,
|
|
|
|
DEVICE_CLASS_TIMESTAMP,
|
|
|
|
)
|
|
|
|
from homeassistant.helpers.typing import HomeAssistantType
|
|
|
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
|
|
|
from homeassistant.util import dt as dt_util
|
|
|
|
|
|
|
|
from . import LyricDeviceEntity
|
|
|
|
from .const import (
|
|
|
|
DOMAIN,
|
|
|
|
PRESET_HOLD_UNTIL,
|
|
|
|
PRESET_NO_HOLD,
|
|
|
|
PRESET_PERMANENT_HOLD,
|
|
|
|
PRESET_TEMPORARY_HOLD,
|
|
|
|
PRESET_VACATION_HOLD,
|
|
|
|
)
|
|
|
|
|
|
|
|
LYRIC_SETPOINT_STATUS_NAMES = {
|
|
|
|
PRESET_NO_HOLD: "Following Schedule",
|
|
|
|
PRESET_PERMANENT_HOLD: "Held Permanently",
|
|
|
|
PRESET_TEMPORARY_HOLD: "Held Temporarily",
|
|
|
|
PRESET_VACATION_HOLD: "Holiday",
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async def async_setup_entry(
|
|
|
|
hass: HomeAssistantType, entry: ConfigEntry, async_add_entities
|
|
|
|
) -> None:
|
|
|
|
"""Set up the Honeywell Lyric sensor platform based on a config entry."""
|
|
|
|
coordinator: DataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
|
|
|
|
|
|
|
entities = []
|
|
|
|
|
|
|
|
for location in coordinator.data.locations:
|
|
|
|
for device in location.devices:
|
|
|
|
cls_list = []
|
|
|
|
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(
|
|
|
|
cls(
|
|
|
|
coordinator,
|
|
|
|
location,
|
|
|
|
device,
|
|
|
|
hass.config.units.temperature_unit,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
async_add_entities(entities, True)
|
|
|
|
|
|
|
|
|
2021-03-22 18:59:03 +00:00
|
|
|
class LyricSensor(LyricDeviceEntity, SensorEntity):
|
2021-02-02 01:51:20 +00:00
|
|
|
"""Defines a Honeywell Lyric sensor."""
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
coordinator: DataUpdateCoordinator,
|
|
|
|
location: LyricLocation,
|
|
|
|
device: LyricDevice,
|
|
|
|
key: str,
|
|
|
|
name: str,
|
|
|
|
icon: str,
|
|
|
|
device_class: str = None,
|
|
|
|
unit_of_measurement: str = None,
|
|
|
|
) -> None:
|
|
|
|
"""Initialize Honeywell Lyric sensor."""
|
|
|
|
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 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__(
|
|
|
|
coordinator,
|
|
|
|
location,
|
|
|
|
device,
|
|
|
|
f"{device.macID}_indoor_temperature",
|
|
|
|
"Indoor Temperature",
|
|
|
|
None,
|
|
|
|
DEVICE_CLASS_TEMPERATURE,
|
|
|
|
unit_of_measurement,
|
|
|
|
)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def state(self) -> str:
|
|
|
|
"""Return the state of the sensor."""
|
|
|
|
return self.device.indoorTemperature
|
|
|
|
|
|
|
|
|
|
|
|
class LyricOutdoorTemperatureSensor(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_temperature",
|
|
|
|
"Outdoor Temperature",
|
|
|
|
None,
|
|
|
|
DEVICE_CLASS_TEMPERATURE,
|
|
|
|
unit_of_measurement,
|
|
|
|
)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def state(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 state(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 state(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 state(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"
|
|
|
|
)
|