1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-08 17:49:37 +01:00

Add sleep health metrics to SleepIQ integration (#163403)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
rhcp011235
2026-02-18 19:02:43 -05:00
committed by GitHub
parent 2fcbd77c95
commit 37f0f1869f
8 changed files with 743 additions and 11 deletions
@@ -26,6 +26,7 @@ from .coordinator import (
SleepIQData,
SleepIQDataUpdateCoordinator,
SleepIQPauseUpdateCoordinator,
SleepIQSleepDataCoordinator,
)
_LOGGER = logging.getLogger(__name__)
@@ -96,14 +97,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
coordinator = SleepIQDataUpdateCoordinator(hass, entry, gateway)
pause_coordinator = SleepIQPauseUpdateCoordinator(hass, entry, gateway)
sleep_data_coordinator = SleepIQSleepDataCoordinator(hass, entry, gateway)
# Call the SleepIQ API to refresh data
await coordinator.async_config_entry_first_refresh()
await pause_coordinator.async_config_entry_first_refresh()
await sleep_data_coordinator.async_config_entry_first_refresh()
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = SleepIQData(
data_coordinator=coordinator,
pause_coordinator=pause_coordinator,
sleep_data_coordinator=sleep_data_coordinator,
client=gateway,
)
+10
View File
@@ -15,6 +15,11 @@ PRESSURE = "pressure"
SLEEP_NUMBER = "sleep_number"
FOOT_WARMING_TIMER = "foot_warming_timer"
FOOT_WARMER = "foot_warmer"
SLEEP_SCORE = "sleep_score"
SLEEP_DURATION = "sleep_duration"
HEART_RATE = "heart_rate"
RESPIRATORY_RATE = "respiratory_rate"
HRV = "hrv"
ENTITY_TYPES = {
ACTUATOR: "Position",
CORE_CLIMATE_TIMER: "Core Climate Timer",
@@ -25,6 +30,11 @@ ENTITY_TYPES = {
SLEEP_NUMBER: "SleepNumber",
FOOT_WARMING_TIMER: "Foot Warming Timer",
FOOT_WARMER: "Foot Warmer",
SLEEP_SCORE: "Sleep Score",
SLEEP_DURATION: "Sleep Duration",
HEART_RATE: "Heart Rate Average",
RESPIRATORY_RATE: "Respiratory Rate Average",
HRV: "Heart Rate Variability",
}
LEFT = "left"
@@ -5,17 +5,18 @@ from dataclasses import dataclass
from datetime import timedelta
import logging
from asyncsleepiq import AsyncSleepIQ
from asyncsleepiq import AsyncSleepIQ, SleepIQAPIException, SleepIQTimeoutException
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
_LOGGER = logging.getLogger(__name__)
UPDATE_INTERVAL = timedelta(seconds=60)
LONGER_UPDATE_INTERVAL = timedelta(minutes=5)
SLEEP_DATA_UPDATE_INTERVAL = timedelta(hours=1) # Sleep data doesn't change frequently
class SleepIQDataUpdateCoordinator(DataUpdateCoordinator[None]):
@@ -74,10 +75,48 @@ class SleepIQPauseUpdateCoordinator(DataUpdateCoordinator[None]):
)
class SleepIQSleepDataCoordinator(DataUpdateCoordinator[None]):
"""SleepIQ sleep health data coordinator."""
config_entry: ConfigEntry
def __init__(
self,
hass: HomeAssistant,
config_entry: ConfigEntry,
client: AsyncSleepIQ,
) -> None:
"""Initialize coordinator."""
super().__init__(
hass,
_LOGGER,
config_entry=config_entry,
name=f"{config_entry.data[CONF_USERNAME]}@SleepIQSleepData",
update_interval=SLEEP_DATA_UPDATE_INTERVAL,
)
self.client = client
async def _async_update_data(self) -> None:
"""Fetch sleep health data from API via asyncsleepiq library."""
try:
await asyncio.gather(
*[
sleeper.fetch_sleep_data()
for bed in self.client.beds.values()
for sleeper in bed.sleepers
]
)
except SleepIQTimeoutException as err:
raise UpdateFailed(f"Timed out fetching SleepIQ sleep data: {err}") from err
except SleepIQAPIException as err:
raise UpdateFailed(f"Failed to fetch SleepIQ sleep data: {err}") from err
@dataclass
class SleepIQData:
"""Data for the sleepiq integration."""
data_coordinator: SleepIQDataUpdateCoordinator
pause_coordinator: SleepIQPauseUpdateCoordinator
sleep_data_coordinator: SleepIQSleepDataCoordinator
client: AsyncSleepIQ
+10 -2
View File
@@ -11,9 +11,17 @@ from homeassistant.helpers.entity import Entity
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import ENTITY_TYPES, ICON_OCCUPIED
from .coordinator import SleepIQDataUpdateCoordinator, SleepIQPauseUpdateCoordinator
from .coordinator import (
SleepIQDataUpdateCoordinator,
SleepIQPauseUpdateCoordinator,
SleepIQSleepDataCoordinator,
)
type _DataCoordinatorType = SleepIQDataUpdateCoordinator | SleepIQPauseUpdateCoordinator
type _DataCoordinatorType = (
SleepIQDataUpdateCoordinator
| SleepIQPauseUpdateCoordinator
| SleepIQSleepDataCoordinator
)
def device_from_bed(bed: SleepIQBed) -> DeviceInfo:
@@ -0,0 +1,21 @@
{
"entity": {
"sensor": {
"heart_rate_avg": {
"default": "mdi:heart-pulse"
},
"hrv": {
"default": "mdi:heart-flash"
},
"respiratory_rate_avg": {
"default": "mdi:lungs"
},
"sleep_duration": {
"default": "mdi:sleep"
},
"sleep_score": {
"default": "mdi:sleep"
}
}
}
}
+86 -7
View File
@@ -8,16 +8,31 @@ from dataclasses import dataclass
from asyncsleepiq import SleepIQBed, SleepIQSleeper
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import UnitOfTime
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import DOMAIN, PRESSURE, SLEEP_NUMBER
from .coordinator import SleepIQData, SleepIQDataUpdateCoordinator
from .const import (
DOMAIN,
HEART_RATE,
HRV,
PRESSURE,
RESPIRATORY_RATE,
SLEEP_DURATION,
SLEEP_NUMBER,
SLEEP_SCORE,
)
from .coordinator import (
SleepIQData,
SleepIQDataUpdateCoordinator,
SleepIQSleepDataCoordinator,
)
from .entity import SleepIQSleeperEntity
@@ -28,7 +43,7 @@ class SleepIQSensorEntityDescription(SensorEntityDescription):
value_fn: Callable[[SleepIQSleeper], float | int | None]
SENSORS: tuple[SleepIQSensorEntityDescription, ...] = (
BED_SENSORS: tuple[SleepIQSensorEntityDescription, ...] = (
SleepIQSensorEntityDescription(
key=PRESSURE,
translation_key="pressure",
@@ -43,6 +58,57 @@ SENSORS: tuple[SleepIQSensorEntityDescription, ...] = (
),
)
SLEEP_HEALTH_SENSORS: tuple[SleepIQSensorEntityDescription, ...] = (
SleepIQSensorEntityDescription(
key=SLEEP_SCORE,
translation_key="sleep_score",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement="score",
value_fn=lambda sleeper: (
sleeper.sleep_data.sleep_score if sleeper.sleep_data else None
),
),
SleepIQSensorEntityDescription(
key=SLEEP_DURATION,
translation_key="sleep_duration",
device_class=SensorDeviceClass.DURATION,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTime.HOURS,
suggested_display_precision=1,
value_fn=lambda sleeper: (
round(sleeper.sleep_data.duration / 3600, 1)
if sleeper.sleep_data and sleeper.sleep_data.duration
else None
),
),
SleepIQSensorEntityDescription(
key=HEART_RATE,
translation_key="heart_rate_avg",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement="bpm",
value_fn=lambda sleeper: (
sleeper.sleep_data.heart_rate if sleeper.sleep_data else None
),
),
SleepIQSensorEntityDescription(
key=RESPIRATORY_RATE,
translation_key="respiratory_rate_avg",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement="brpm",
value_fn=lambda sleeper: (
sleeper.sleep_data.respiratory_rate if sleeper.sleep_data else None
),
),
SleepIQSensorEntityDescription(
key=HRV,
translation_key="hrv",
device_class=SensorDeviceClass.DURATION,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTime.MILLISECONDS,
value_fn=lambda sleeper: sleeper.sleep_data.hrv if sleeper.sleep_data else None,
),
)
async def async_setup_entry(
hass: HomeAssistant,
@@ -51,16 +117,29 @@ async def async_setup_entry(
) -> None:
"""Set up the SleepIQ bed sensors."""
data: SleepIQData = hass.data[DOMAIN][entry.entry_id]
async_add_entities(
entities: list[SensorEntity] = []
entities.extend(
SleepIQSensorEntity(data.data_coordinator, bed, sleeper, description)
for bed in data.client.beds.values()
for sleeper in bed.sleepers
for description in SENSORS
for description in BED_SENSORS
)
entities.extend(
SleepIQSensorEntity(data.sleep_data_coordinator, bed, sleeper, description)
for bed in data.client.beds.values()
for sleeper in bed.sleepers
for description in SLEEP_HEALTH_SENSORS
)
async_add_entities(entities)
class SleepIQSensorEntity(
SleepIQSleeperEntity[SleepIQDataUpdateCoordinator], SensorEntity
SleepIQSleeperEntity[SleepIQDataUpdateCoordinator | SleepIQSleepDataCoordinator],
SensorEntity,
):
"""Representation of a SleepIQ sensor."""
@@ -68,7 +147,7 @@ class SleepIQSensorEntity(
def __init__(
self,
coordinator: SleepIQDataUpdateCoordinator,
coordinator: SleepIQDataUpdateCoordinator | SleepIQSleepDataCoordinator,
bed: SleepIQBed,
sleeper: SleepIQSleeper,
description: SleepIQSensorEntityDescription,
+15
View File
@@ -10,6 +10,7 @@ from asyncsleepiq import (
CoreTemps,
FootWarmingTemps,
Side,
SleepData,
SleepIQActuator,
SleepIQBed,
SleepIQCoreClimate,
@@ -76,6 +77,13 @@ def mock_bed() -> MagicMock:
sleeper_l.sleep_number = 40
sleeper_l.pressure = 1000
sleeper_l.sleeper_id = SLEEPER_L_ID
sleeper_l.sleep_data = SleepData(
duration=28800, # 8 hours in seconds
sleep_score=85,
heart_rate=60,
respiratory_rate=14,
hrv=68,
)
sleeper_r.side = Side.RIGHT
sleeper_r.name = SLEEPER_R_NAME
@@ -83,6 +91,13 @@ def mock_bed() -> MagicMock:
sleeper_r.sleep_number = 80
sleeper_r.pressure = 1400
sleeper_r.sleeper_id = SLEEPER_R_ID
sleeper_r.sleep_data = SleepData(
duration=25200, # 7 hours in seconds
sleep_score=78,
heart_rate=65,
respiratory_rate=15,
hrv=72,
)
bed.foundation = create_autospec(SleepIQFoundation)
light_1 = create_autospec(SleepIQLight)
@@ -1,4 +1,116 @@
# serializer version: 1
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_heart_rate_average-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.sleepnumber_test_bed_sleeper_r_heart_rate_average',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'SleepNumber Test Bed Sleeper R Heart Rate Average',
'options': dict({
}),
'original_device_class': None,
'original_icon': 'mdi:bed',
'original_name': 'SleepNumber Test Bed Sleeper R Heart Rate Average',
'platform': 'sleepiq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'heart_rate_avg',
'unique_id': '43219_heart_rate',
'unit_of_measurement': 'bpm',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_heart_rate_average-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'SleepNumber Test Bed Sleeper R Heart Rate Average',
'icon': 'mdi:bed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'bpm',
}),
'context': <ANY>,
'entity_id': 'sensor.sleepnumber_test_bed_sleeper_r_heart_rate_average',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '65',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_heart_rate_variability-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.sleepnumber_test_bed_sleeper_r_heart_rate_variability',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'SleepNumber Test Bed Sleeper R Heart Rate Variability',
'options': dict({
'sensor': dict({
'suggested_display_precision': 0,
}),
}),
'original_device_class': <SensorDeviceClass.DURATION: 'duration'>,
'original_icon': 'mdi:bed',
'original_name': 'SleepNumber Test Bed Sleeper R Heart Rate Variability',
'platform': 'sleepiq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'hrv',
'unique_id': '43219_hrv',
'unit_of_measurement': <UnitOfTime.MILLISECONDS: 'ms'>,
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_heart_rate_variability-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'SleepNumber Test Bed Sleeper R Heart Rate Variability',
'icon': 'mdi:bed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfTime.MILLISECONDS: 'ms'>,
}),
'context': <ANY>,
'entity_id': 'sensor.sleepnumber_test_bed_sleeper_r_heart_rate_variability',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '72',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_pressure-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@@ -52,6 +164,172 @@
'state': '1400',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_respiratory_rate_average-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.sleepnumber_test_bed_sleeper_r_respiratory_rate_average',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'SleepNumber Test Bed Sleeper R Respiratory Rate Average',
'options': dict({
}),
'original_device_class': None,
'original_icon': 'mdi:bed',
'original_name': 'SleepNumber Test Bed Sleeper R Respiratory Rate Average',
'platform': 'sleepiq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'respiratory_rate_avg',
'unique_id': '43219_respiratory_rate',
'unit_of_measurement': 'brpm',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_respiratory_rate_average-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'SleepNumber Test Bed Sleeper R Respiratory Rate Average',
'icon': 'mdi:bed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'brpm',
}),
'context': <ANY>,
'entity_id': 'sensor.sleepnumber_test_bed_sleeper_r_respiratory_rate_average',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '15',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_sleep_duration-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.sleepnumber_test_bed_sleeper_r_sleep_duration',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'SleepNumber Test Bed Sleeper R Sleep Duration',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
}),
'original_device_class': <SensorDeviceClass.DURATION: 'duration'>,
'original_icon': 'mdi:bed',
'original_name': 'SleepNumber Test Bed Sleeper R Sleep Duration',
'platform': 'sleepiq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'sleep_duration',
'unique_id': '43219_sleep_duration',
'unit_of_measurement': <UnitOfTime.HOURS: 'h'>,
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_sleep_duration-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'SleepNumber Test Bed Sleeper R Sleep Duration',
'icon': 'mdi:bed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfTime.HOURS: 'h'>,
}),
'context': <ANY>,
'entity_id': 'sensor.sleepnumber_test_bed_sleeper_r_sleep_duration',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '7.0',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_sleep_score-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.sleepnumber_test_bed_sleeper_r_sleep_score',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'SleepNumber Test Bed Sleeper R Sleep Score',
'options': dict({
}),
'original_device_class': None,
'original_icon': 'mdi:bed',
'original_name': 'SleepNumber Test Bed Sleeper R Sleep Score',
'platform': 'sleepiq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'sleep_score',
'unique_id': '43219_sleep_score',
'unit_of_measurement': 'score',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_sleep_score-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'SleepNumber Test Bed Sleeper R Sleep Score',
'icon': 'mdi:bed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'score',
}),
'context': <ANY>,
'entity_id': 'sensor.sleepnumber_test_bed_sleeper_r_sleep_score',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '78',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeper_r_sleepnumber-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@@ -105,6 +383,118 @@
'state': '80',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_heart_rate_average-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.sleepnumber_test_bed_sleeperl_heart_rate_average',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'SleepNumber Test Bed SleeperL Heart Rate Average',
'options': dict({
}),
'original_device_class': None,
'original_icon': 'mdi:bed',
'original_name': 'SleepNumber Test Bed SleeperL Heart Rate Average',
'platform': 'sleepiq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'heart_rate_avg',
'unique_id': '98765_heart_rate',
'unit_of_measurement': 'bpm',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_heart_rate_average-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'SleepNumber Test Bed SleeperL Heart Rate Average',
'icon': 'mdi:bed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'bpm',
}),
'context': <ANY>,
'entity_id': 'sensor.sleepnumber_test_bed_sleeperl_heart_rate_average',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '60',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_heart_rate_variability-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.sleepnumber_test_bed_sleeperl_heart_rate_variability',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'SleepNumber Test Bed SleeperL Heart Rate Variability',
'options': dict({
'sensor': dict({
'suggested_display_precision': 0,
}),
}),
'original_device_class': <SensorDeviceClass.DURATION: 'duration'>,
'original_icon': 'mdi:bed',
'original_name': 'SleepNumber Test Bed SleeperL Heart Rate Variability',
'platform': 'sleepiq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'hrv',
'unique_id': '98765_hrv',
'unit_of_measurement': <UnitOfTime.MILLISECONDS: 'ms'>,
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_heart_rate_variability-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'SleepNumber Test Bed SleeperL Heart Rate Variability',
'icon': 'mdi:bed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfTime.MILLISECONDS: 'ms'>,
}),
'context': <ANY>,
'entity_id': 'sensor.sleepnumber_test_bed_sleeperl_heart_rate_variability',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '68',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_pressure-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@@ -158,6 +548,172 @@
'state': '1000',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_respiratory_rate_average-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.sleepnumber_test_bed_sleeperl_respiratory_rate_average',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'SleepNumber Test Bed SleeperL Respiratory Rate Average',
'options': dict({
}),
'original_device_class': None,
'original_icon': 'mdi:bed',
'original_name': 'SleepNumber Test Bed SleeperL Respiratory Rate Average',
'platform': 'sleepiq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'respiratory_rate_avg',
'unique_id': '98765_respiratory_rate',
'unit_of_measurement': 'brpm',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_respiratory_rate_average-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'SleepNumber Test Bed SleeperL Respiratory Rate Average',
'icon': 'mdi:bed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'brpm',
}),
'context': <ANY>,
'entity_id': 'sensor.sleepnumber_test_bed_sleeperl_respiratory_rate_average',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '14',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_sleep_duration-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.sleepnumber_test_bed_sleeperl_sleep_duration',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'SleepNumber Test Bed SleeperL Sleep Duration',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
}),
'original_device_class': <SensorDeviceClass.DURATION: 'duration'>,
'original_icon': 'mdi:bed',
'original_name': 'SleepNumber Test Bed SleeperL Sleep Duration',
'platform': 'sleepiq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'sleep_duration',
'unique_id': '98765_sleep_duration',
'unit_of_measurement': <UnitOfTime.HOURS: 'h'>,
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_sleep_duration-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'SleepNumber Test Bed SleeperL Sleep Duration',
'icon': 'mdi:bed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfTime.HOURS: 'h'>,
}),
'context': <ANY>,
'entity_id': 'sensor.sleepnumber_test_bed_sleeperl_sleep_duration',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '8.0',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_sleep_score-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.sleepnumber_test_bed_sleeperl_sleep_score',
'has_entity_name': False,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'SleepNumber Test Bed SleeperL Sleep Score',
'options': dict({
}),
'original_device_class': None,
'original_icon': 'mdi:bed',
'original_name': 'SleepNumber Test Bed SleeperL Sleep Score',
'platform': 'sleepiq',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'sleep_score',
'unique_id': '98765_sleep_score',
'unit_of_measurement': 'score',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_sleep_score-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'SleepNumber Test Bed SleeperL Sleep Score',
'icon': 'mdi:bed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'score',
}),
'context': <ANY>,
'entity_id': 'sensor.sleepnumber_test_bed_sleeperl_sleep_score',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '85',
})
# ---
# name: test_sensors[sensor.sleepnumber_test_bed_sleeperl_sleepnumber-entry]
EntityRegistryEntrySnapshot({
'aliases': set({