mirror of
https://github.com/home-assistant/core.git
synced 2025-07-26 22:57:17 +00:00
Improve eight sleep code quality and fix bug (#71622)
This commit is contained in:
parent
557cba118f
commit
34d4eb7c15
@ -156,14 +156,12 @@ class EightSleepBaseEntity(CoordinatorEntity[DataUpdateCoordinator]):
|
|||||||
eight: EightSleep,
|
eight: EightSleep,
|
||||||
user_id: str | None,
|
user_id: str | None,
|
||||||
sensor: str,
|
sensor: str,
|
||||||
units: str | None = None,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the data object."""
|
"""Initialize the data object."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._eight = eight
|
self._eight = eight
|
||||||
self._user_id = user_id
|
self._user_id = user_id
|
||||||
self._sensor = sensor
|
self._sensor = sensor
|
||||||
self._units = units
|
|
||||||
self._user_obj: EightUser | None = None
|
self._user_obj: EightUser | None = None
|
||||||
if self._user_id:
|
if self._user_id:
|
||||||
self._user_obj = self._eight.users[user_id]
|
self._user_obj = self._eight.users[user_id]
|
||||||
|
@ -45,6 +45,8 @@ async def async_setup_platform(
|
|||||||
class EightHeatSensor(EightSleepBaseEntity, BinarySensorEntity):
|
class EightHeatSensor(EightSleepBaseEntity, BinarySensorEntity):
|
||||||
"""Representation of a Eight Sleep heat-based sensor."""
|
"""Representation of a Eight Sleep heat-based sensor."""
|
||||||
|
|
||||||
|
_attr_device_class = BinarySensorDeviceClass.OCCUPANCY
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
coordinator: DataUpdateCoordinator,
|
coordinator: DataUpdateCoordinator,
|
||||||
@ -54,7 +56,6 @@ class EightHeatSensor(EightSleepBaseEntity, BinarySensorEntity):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
super().__init__(coordinator, eight, user_id, sensor)
|
super().__init__(coordinator, eight, user_id, sensor)
|
||||||
self._attr_device_class = BinarySensorDeviceClass.OCCUPANCY
|
|
||||||
assert self._user_obj
|
assert self._user_obj
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Presence Sensor: %s, Side: %s, User: %s",
|
"Presence Sensor: %s, Side: %s, User: %s",
|
||||||
|
@ -6,8 +6,8 @@ from typing import Any
|
|||||||
|
|
||||||
from pyeight.eight import EightSleep
|
from pyeight.eight import EightSleep
|
||||||
|
|
||||||
from homeassistant.components.sensor import SensorEntity
|
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
|
||||||
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
@ -68,24 +68,19 @@ async def async_setup_platform(
|
|||||||
heat_coordinator: DataUpdateCoordinator = hass.data[DOMAIN][DATA_HEAT]
|
heat_coordinator: DataUpdateCoordinator = hass.data[DOMAIN][DATA_HEAT]
|
||||||
user_coordinator: DataUpdateCoordinator = hass.data[DOMAIN][DATA_USER]
|
user_coordinator: DataUpdateCoordinator = hass.data[DOMAIN][DATA_USER]
|
||||||
|
|
||||||
if hass.config.units.is_metric:
|
|
||||||
units = "si"
|
|
||||||
else:
|
|
||||||
units = "us"
|
|
||||||
|
|
||||||
all_sensors: list[SensorEntity] = []
|
all_sensors: list[SensorEntity] = []
|
||||||
|
|
||||||
for obj in eight.users.values():
|
for obj in eight.users.values():
|
||||||
for sensor in EIGHT_USER_SENSORS:
|
for sensor in EIGHT_USER_SENSORS:
|
||||||
all_sensors.append(
|
all_sensors.append(
|
||||||
EightUserSensor(user_coordinator, eight, obj.userid, sensor, units)
|
EightUserSensor(user_coordinator, eight, obj.userid, sensor)
|
||||||
)
|
)
|
||||||
for sensor in EIGHT_HEAT_SENSORS:
|
for sensor in EIGHT_HEAT_SENSORS:
|
||||||
all_sensors.append(
|
all_sensors.append(
|
||||||
EightHeatSensor(heat_coordinator, eight, obj.userid, sensor)
|
EightHeatSensor(heat_coordinator, eight, obj.userid, sensor)
|
||||||
)
|
)
|
||||||
for sensor in EIGHT_ROOM_SENSORS:
|
for sensor in EIGHT_ROOM_SENSORS:
|
||||||
all_sensors.append(EightRoomSensor(user_coordinator, eight, sensor, units))
|
all_sensors.append(EightRoomSensor(user_coordinator, eight, sensor))
|
||||||
|
|
||||||
async_add_entities(all_sensors)
|
async_add_entities(all_sensors)
|
||||||
|
|
||||||
@ -93,6 +88,8 @@ async def async_setup_platform(
|
|||||||
class EightHeatSensor(EightSleepBaseEntity, SensorEntity):
|
class EightHeatSensor(EightSleepBaseEntity, SensorEntity):
|
||||||
"""Representation of an eight sleep heat-based sensor."""
|
"""Representation of an eight sleep heat-based sensor."""
|
||||||
|
|
||||||
|
_attr_native_unit_of_measurement = PERCENTAGE
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
coordinator: DataUpdateCoordinator,
|
coordinator: DataUpdateCoordinator,
|
||||||
@ -102,7 +99,6 @@ class EightHeatSensor(EightSleepBaseEntity, SensorEntity):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
super().__init__(coordinator, eight, user_id, sensor)
|
super().__init__(coordinator, eight, user_id, sensor)
|
||||||
self._attr_native_unit_of_measurement = PERCENTAGE
|
|
||||||
assert self._user_obj
|
assert self._user_obj
|
||||||
|
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
@ -139,6 +135,13 @@ def _get_breakdown_percent(
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def _get_rounded_value(attr: dict[str, Any], key: str) -> int | float | None:
|
||||||
|
"""Get rounded value for given key."""
|
||||||
|
if (val := attr.get(key)) is None:
|
||||||
|
return None
|
||||||
|
return round(val, 2)
|
||||||
|
|
||||||
|
|
||||||
class EightUserSensor(EightSleepBaseEntity, SensorEntity):
|
class EightUserSensor(EightSleepBaseEntity, SensorEntity):
|
||||||
"""Representation of an eight sleep user-based sensor."""
|
"""Representation of an eight sleep user-based sensor."""
|
||||||
|
|
||||||
@ -148,14 +151,17 @@ class EightUserSensor(EightSleepBaseEntity, SensorEntity):
|
|||||||
eight: EightSleep,
|
eight: EightSleep,
|
||||||
user_id: str,
|
user_id: str,
|
||||||
sensor: str,
|
sensor: str,
|
||||||
units: str,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
super().__init__(coordinator, eight, user_id, sensor, units)
|
super().__init__(coordinator, eight, user_id, sensor)
|
||||||
assert self._user_obj
|
assert self._user_obj
|
||||||
|
|
||||||
if self._sensor == "bed_temperature":
|
if self._sensor == "bed_temperature":
|
||||||
self._attr_icon = "mdi:thermometer"
|
self._attr_icon = "mdi:thermometer"
|
||||||
|
self._attr_device_class = SensorDeviceClass.TEMPERATURE
|
||||||
|
self._attr_native_unit_of_measurement = TEMP_CELSIUS
|
||||||
|
elif self._sensor in ("current_sleep", "last_sleep", "current_sleep_fitness"):
|
||||||
|
self._attr_native_unit_of_measurement = "Score"
|
||||||
|
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"User Sensor: %s, Side: %s, User: %s",
|
"User Sensor: %s, Side: %s, User: %s",
|
||||||
@ -179,41 +185,13 @@ class EightUserSensor(EightSleepBaseEntity, SensorEntity):
|
|||||||
return self._user_obj.last_sleep_score
|
return self._user_obj.last_sleep_score
|
||||||
|
|
||||||
if self._sensor == "bed_temperature":
|
if self._sensor == "bed_temperature":
|
||||||
temp = self._user_obj.current_values["bed_temp"]
|
return self._user_obj.current_values["bed_temp"]
|
||||||
try:
|
|
||||||
if self._units == "si":
|
|
||||||
return round(temp, 2)
|
|
||||||
return round((temp * 1.8) + 32, 2)
|
|
||||||
except TypeError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if self._sensor == "sleep_stage":
|
if self._sensor == "sleep_stage":
|
||||||
return self._user_obj.current_values["stage"]
|
return self._user_obj.current_values["stage"]
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
|
||||||
def native_unit_of_measurement(self) -> str | None:
|
|
||||||
"""Return the unit the value is expressed in."""
|
|
||||||
if self._sensor in ("current_sleep", "last_sleep", "current_sleep_fitness"):
|
|
||||||
return "Score"
|
|
||||||
if self._sensor == "bed_temperature":
|
|
||||||
if self._units == "si":
|
|
||||||
return TEMP_CELSIUS
|
|
||||||
return TEMP_FAHRENHEIT
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _get_rounded_value(
|
|
||||||
self, attr: dict[str, Any], key: str, use_units: bool = True
|
|
||||||
) -> int | float | None:
|
|
||||||
"""Get rounded value based on units for given key."""
|
|
||||||
try:
|
|
||||||
if self._units == "si" or not use_units:
|
|
||||||
return round(attr["room_temp"], 2)
|
|
||||||
return round((attr["room_temp"] * 1.8) + 32, 2)
|
|
||||||
except TypeError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> dict[str, Any] | None:
|
def extra_state_attributes(self) -> dict[str, Any] | None:
|
||||||
"""Return device state attributes."""
|
"""Return device state attributes."""
|
||||||
@ -255,26 +233,18 @@ class EightUserSensor(EightSleepBaseEntity, SensorEntity):
|
|||||||
)
|
)
|
||||||
state_attr[ATTR_REM_PERC] = _get_breakdown_percent(attr, "rem", sleep_time)
|
state_attr[ATTR_REM_PERC] = _get_breakdown_percent(attr, "rem", sleep_time)
|
||||||
|
|
||||||
room_temp = self._get_rounded_value(attr, "room_temp")
|
room_temp = _get_rounded_value(attr, "room_temp")
|
||||||
bed_temp = self._get_rounded_value(attr, "bed_temp")
|
bed_temp = _get_rounded_value(attr, "bed_temp")
|
||||||
|
|
||||||
if "current" in self._sensor:
|
if "current" in self._sensor:
|
||||||
state_attr[ATTR_RESP_RATE] = self._get_rounded_value(
|
state_attr[ATTR_RESP_RATE] = _get_rounded_value(attr, "resp_rate")
|
||||||
attr, "resp_rate", False
|
state_attr[ATTR_HEART_RATE] = _get_rounded_value(attr, "heart_rate")
|
||||||
)
|
|
||||||
state_attr[ATTR_HEART_RATE] = self._get_rounded_value(
|
|
||||||
attr, "heart_rate", False
|
|
||||||
)
|
|
||||||
state_attr[ATTR_SLEEP_STAGE] = attr["stage"]
|
state_attr[ATTR_SLEEP_STAGE] = attr["stage"]
|
||||||
state_attr[ATTR_ROOM_TEMP] = room_temp
|
state_attr[ATTR_ROOM_TEMP] = room_temp
|
||||||
state_attr[ATTR_BED_TEMP] = bed_temp
|
state_attr[ATTR_BED_TEMP] = bed_temp
|
||||||
elif "last" in self._sensor:
|
elif "last" in self._sensor:
|
||||||
state_attr[ATTR_AVG_RESP_RATE] = self._get_rounded_value(
|
state_attr[ATTR_AVG_RESP_RATE] = _get_rounded_value(attr, "resp_rate")
|
||||||
attr, "resp_rate", False
|
state_attr[ATTR_AVG_HEART_RATE] = _get_rounded_value(attr, "heart_rate")
|
||||||
)
|
|
||||||
state_attr[ATTR_AVG_HEART_RATE] = self._get_rounded_value(
|
|
||||||
attr, "heart_rate", False
|
|
||||||
)
|
|
||||||
state_attr[ATTR_AVG_ROOM_TEMP] = room_temp
|
state_attr[ATTR_AVG_ROOM_TEMP] = room_temp
|
||||||
state_attr[ATTR_AVG_BED_TEMP] = bed_temp
|
state_attr[ATTR_AVG_BED_TEMP] = bed_temp
|
||||||
|
|
||||||
@ -284,28 +254,20 @@ class EightUserSensor(EightSleepBaseEntity, SensorEntity):
|
|||||||
class EightRoomSensor(EightSleepBaseEntity, SensorEntity):
|
class EightRoomSensor(EightSleepBaseEntity, SensorEntity):
|
||||||
"""Representation of an eight sleep room sensor."""
|
"""Representation of an eight sleep room sensor."""
|
||||||
|
|
||||||
|
_attr_icon = "mdi:thermometer"
|
||||||
|
_attr_device_class = SensorDeviceClass.TEMPERATURE
|
||||||
|
_attr_native_unit_of_measurement = TEMP_CELSIUS
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
coordinator: DataUpdateCoordinator,
|
coordinator: DataUpdateCoordinator,
|
||||||
eight: EightSleep,
|
eight: EightSleep,
|
||||||
sensor: str,
|
sensor: str,
|
||||||
units: str,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
super().__init__(coordinator, eight, None, sensor, units)
|
super().__init__(coordinator, eight, None, sensor)
|
||||||
|
|
||||||
self._attr_icon = "mdi:thermometer"
|
|
||||||
self._attr_native_unit_of_measurement: str = (
|
|
||||||
TEMP_CELSIUS if self._units == "si" else TEMP_FAHRENHEIT
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self) -> int | float | None:
|
def native_value(self) -> int | float | None:
|
||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
temp = self._eight.room_temperature()
|
return self._eight.room_temperature()
|
||||||
try:
|
|
||||||
if self._units == "si":
|
|
||||||
return round(temp, 2)
|
|
||||||
return round((temp * 1.8) + 32, 2)
|
|
||||||
except TypeError:
|
|
||||||
return None
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user