mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Add number entities to control SleepIQ actuator positions (#67770)
This commit is contained in:
parent
8e3454e46a
commit
6831be67f4
@ -3,6 +3,7 @@
|
|||||||
DATA_SLEEPIQ = "data_sleepiq"
|
DATA_SLEEPIQ = "data_sleepiq"
|
||||||
DOMAIN = "sleepiq"
|
DOMAIN = "sleepiq"
|
||||||
|
|
||||||
|
ACTUATOR = "actuator"
|
||||||
BED = "bed"
|
BED = "bed"
|
||||||
FIRMNESS = "firmness"
|
FIRMNESS = "firmness"
|
||||||
ICON_EMPTY = "mdi:bed-empty"
|
ICON_EMPTY = "mdi:bed-empty"
|
||||||
@ -10,7 +11,8 @@ ICON_OCCUPIED = "mdi:bed"
|
|||||||
IS_IN_BED = "is_in_bed"
|
IS_IN_BED = "is_in_bed"
|
||||||
PRESSURE = "pressure"
|
PRESSURE = "pressure"
|
||||||
SLEEP_NUMBER = "sleep_number"
|
SLEEP_NUMBER = "sleep_number"
|
||||||
SENSOR_TYPES = {
|
ENTITY_TYPES = {
|
||||||
|
ACTUATOR: "Position",
|
||||||
FIRMNESS: "Firmness",
|
FIRMNESS: "Firmness",
|
||||||
PRESSURE: "Pressure",
|
PRESSURE: "Pressure",
|
||||||
IS_IN_BED: "Is In Bed",
|
IS_IN_BED: "Is In Bed",
|
||||||
|
@ -34,9 +34,11 @@ class SleepIQDataUpdateCoordinator(DataUpdateCoordinator[None]):
|
|||||||
self.client = client
|
self.client = client
|
||||||
|
|
||||||
async def _async_update_data(self) -> None:
|
async def _async_update_data(self) -> None:
|
||||||
tasks = [self.client.fetch_bed_statuses()] + [
|
tasks = (
|
||||||
bed.foundation.update_lights() for bed in self.client.beds.values()
|
[self.client.fetch_bed_statuses()]
|
||||||
]
|
+ [bed.foundation.update_lights() for bed in self.client.beds.values()]
|
||||||
|
+ [bed.foundation.update_actuators() for bed in self.client.beds.values()]
|
||||||
|
)
|
||||||
await asyncio.gather(*tasks)
|
await asyncio.gather(*tasks)
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ from homeassistant.helpers.update_coordinator import (
|
|||||||
DataUpdateCoordinator,
|
DataUpdateCoordinator,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .const import ICON_OCCUPIED, SENSOR_TYPES
|
from .const import ENTITY_TYPES, ICON_OCCUPIED
|
||||||
|
|
||||||
|
|
||||||
def device_from_bed(bed: SleepIQBed) -> DeviceInfo:
|
def device_from_bed(bed: SleepIQBed) -> DeviceInfo:
|
||||||
@ -77,5 +77,5 @@ class SleepIQSleeperEntity(SleepIQBedEntity):
|
|||||||
self.sleeper = sleeper
|
self.sleeper = sleeper
|
||||||
super().__init__(coordinator, bed)
|
super().__init__(coordinator, bed)
|
||||||
|
|
||||||
self._attr_name = f"SleepNumber {bed.name} {sleeper.name} {SENSOR_TYPES[name]}"
|
self._attr_name = f"SleepNumber {bed.name} {sleeper.name} {ENTITY_TYPES[name]}"
|
||||||
self._attr_unique_id = f"{bed.id}_{sleeper.name}_{name}"
|
self._attr_unique_id = f"{bed.id}_{sleeper.name}_{name}"
|
||||||
|
@ -1,15 +1,98 @@
|
|||||||
"""Support for SleepIQ SleepNumber firmness number entities."""
|
"""Support for SleepIQ SleepNumber firmness number entities."""
|
||||||
from asyncsleepiq import SleepIQBed, SleepIQSleeper
|
from __future__ import annotations
|
||||||
|
|
||||||
from homeassistant.components.number import NumberEntity
|
from collections.abc import Callable, Coroutine
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any, cast
|
||||||
|
|
||||||
|
from asyncsleepiq import SleepIQActuator, SleepIQBed, SleepIQSleeper
|
||||||
|
|
||||||
|
from homeassistant.components.number import NumberEntity, NumberEntityDescription
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
from .const import DOMAIN, FIRMNESS
|
from .const import ACTUATOR, DOMAIN, ENTITY_TYPES, FIRMNESS, ICON_OCCUPIED
|
||||||
from .coordinator import SleepIQData
|
from .coordinator import SleepIQData
|
||||||
from .entity import SleepIQSleeperEntity
|
from .entity import SleepIQBedEntity
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SleepIQNumberEntityDescriptionMixin:
|
||||||
|
"""Mixin to describe a SleepIQ number entity."""
|
||||||
|
|
||||||
|
value_fn: Callable[[Any], float]
|
||||||
|
set_value_fn: Callable[[Any, int], Coroutine[None, None, None]]
|
||||||
|
get_name_fn: Callable[[SleepIQBed, Any], str]
|
||||||
|
get_unique_id_fn: Callable[[SleepIQBed, Any], str]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SleepIQNumberEntityDescription(
|
||||||
|
NumberEntityDescription, SleepIQNumberEntityDescriptionMixin
|
||||||
|
):
|
||||||
|
"""Class to describe a SleepIQ number entity."""
|
||||||
|
|
||||||
|
|
||||||
|
async def _async_set_firmness(sleeper: SleepIQSleeper, firmness: int) -> None:
|
||||||
|
await sleeper.set_sleepnumber(firmness)
|
||||||
|
|
||||||
|
|
||||||
|
async def _async_set_actuator_position(
|
||||||
|
actuator: SleepIQActuator, position: int
|
||||||
|
) -> None:
|
||||||
|
await actuator.set_position(position)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_actuator_name(bed: SleepIQBed, actuator: SleepIQActuator) -> str:
|
||||||
|
if actuator.side:
|
||||||
|
return f"SleepNumber {bed.name} {actuator.side_full} {actuator.actuator_full} {ENTITY_TYPES[ACTUATOR]}"
|
||||||
|
|
||||||
|
return f"SleepNumber {bed.name} {actuator.actuator_full} {ENTITY_TYPES[ACTUATOR]}"
|
||||||
|
|
||||||
|
|
||||||
|
def _get_actuator_unique_id(bed: SleepIQBed, actuator: SleepIQActuator) -> str:
|
||||||
|
if actuator.side:
|
||||||
|
return f"{bed.id}_{actuator.side}_{actuator.actuator}"
|
||||||
|
|
||||||
|
return f"{bed.id}_{actuator.actuator}"
|
||||||
|
|
||||||
|
|
||||||
|
def _get_sleeper_name(bed: SleepIQBed, sleeper: SleepIQSleeper) -> str:
|
||||||
|
return f"SleepNumber {bed.name} {sleeper.name} {ENTITY_TYPES[FIRMNESS]}"
|
||||||
|
|
||||||
|
|
||||||
|
def _get_sleeper_unique_id(bed: SleepIQBed, sleeper: SleepIQSleeper) -> str:
|
||||||
|
return f"{sleeper.sleeper_id}_{FIRMNESS}"
|
||||||
|
|
||||||
|
|
||||||
|
NUMBER_DESCRIPTIONS: dict[str, SleepIQNumberEntityDescription] = {
|
||||||
|
FIRMNESS: SleepIQNumberEntityDescription(
|
||||||
|
key=FIRMNESS,
|
||||||
|
min_value=5,
|
||||||
|
max_value=100,
|
||||||
|
step=5,
|
||||||
|
name=ENTITY_TYPES[FIRMNESS],
|
||||||
|
icon=ICON_OCCUPIED,
|
||||||
|
value_fn=lambda sleeper: cast(float, sleeper.sleep_number),
|
||||||
|
set_value_fn=_async_set_firmness,
|
||||||
|
get_name_fn=_get_sleeper_name,
|
||||||
|
get_unique_id_fn=_get_sleeper_unique_id,
|
||||||
|
),
|
||||||
|
ACTUATOR: SleepIQNumberEntityDescription(
|
||||||
|
key=ACTUATOR,
|
||||||
|
min_value=0,
|
||||||
|
max_value=100,
|
||||||
|
step=1,
|
||||||
|
name=ENTITY_TYPES[ACTUATOR],
|
||||||
|
icon=ICON_OCCUPIED,
|
||||||
|
value_fn=lambda actuator: cast(float, actuator.position),
|
||||||
|
set_value_fn=_async_set_actuator_position,
|
||||||
|
get_name_fn=_get_actuator_name,
|
||||||
|
get_unique_id_fn=_get_actuator_unique_id,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
@ -19,37 +102,59 @@ async def async_setup_entry(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the SleepIQ bed sensors."""
|
"""Set up the SleepIQ bed sensors."""
|
||||||
data: SleepIQData = hass.data[DOMAIN][entry.entry_id]
|
data: SleepIQData = hass.data[DOMAIN][entry.entry_id]
|
||||||
async_add_entities(
|
|
||||||
SleepNumberFirmnessEntity(data.data_coordinator, bed, sleeper)
|
entities = []
|
||||||
for bed in data.client.beds.values()
|
for bed in data.client.beds.values():
|
||||||
for sleeper in bed.sleepers
|
for sleeper in bed.sleepers:
|
||||||
)
|
entities.append(
|
||||||
|
SleepIQNumberEntity(
|
||||||
|
data.data_coordinator,
|
||||||
|
bed,
|
||||||
|
sleeper,
|
||||||
|
NUMBER_DESCRIPTIONS[FIRMNESS],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for actuator in bed.foundation.actuators:
|
||||||
|
entities.append(
|
||||||
|
SleepIQNumberEntity(
|
||||||
|
data.data_coordinator,
|
||||||
|
bed,
|
||||||
|
actuator,
|
||||||
|
NUMBER_DESCRIPTIONS[ACTUATOR],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
class SleepNumberFirmnessEntity(SleepIQSleeperEntity, NumberEntity):
|
class SleepIQNumberEntity(SleepIQBedEntity, NumberEntity):
|
||||||
"""Representation of an SleepIQ Entity with CoordinatorEntity."""
|
"""Representation of a SleepIQ number entity."""
|
||||||
|
|
||||||
_attr_icon = "mdi:bed"
|
_attr_icon = "mdi:bed"
|
||||||
_attr_max_value: float = 100
|
|
||||||
_attr_min_value: float = 5
|
|
||||||
_attr_step: float = 5
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
coordinator: DataUpdateCoordinator,
|
coordinator: DataUpdateCoordinator,
|
||||||
bed: SleepIQBed,
|
bed: SleepIQBed,
|
||||||
sleeper: SleepIQSleeper,
|
device: Any,
|
||||||
|
description: SleepIQNumberEntityDescription,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the number."""
|
||||||
super().__init__(coordinator, bed, sleeper, FIRMNESS)
|
self.description = description
|
||||||
|
self.device = device
|
||||||
|
|
||||||
|
self._attr_name = description.get_name_fn(bed, device)
|
||||||
|
self._attr_unique_id = description.get_unique_id_fn(bed, device)
|
||||||
|
|
||||||
|
super().__init__(coordinator, bed)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_attrs(self) -> None:
|
def _async_update_attrs(self) -> None:
|
||||||
"""Update sensor attributes."""
|
"""Update number attributes."""
|
||||||
self._attr_value = float(self.sleeper.sleep_number)
|
self._attr_value = float(self.description.value_fn(self.device))
|
||||||
|
|
||||||
async def async_set_value(self, value: float) -> None:
|
async def async_set_value(self, value: float) -> None:
|
||||||
"""Set the firmness value."""
|
"""Set the number value."""
|
||||||
await self.sleeper.set_sleepnumber(int(value))
|
await self.description.set_value_fn(self.device, int(value))
|
||||||
self._attr_value = value
|
self._attr_value = value
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
@ -3,7 +3,13 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from unittest.mock import create_autospec, patch
|
from unittest.mock import create_autospec, patch
|
||||||
|
|
||||||
from asyncsleepiq import SleepIQBed, SleepIQFoundation, SleepIQLight, SleepIQSleeper
|
from asyncsleepiq import (
|
||||||
|
SleepIQActuator,
|
||||||
|
SleepIQBed,
|
||||||
|
SleepIQFoundation,
|
||||||
|
SleepIQLight,
|
||||||
|
SleepIQSleeper,
|
||||||
|
)
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.sleepiq import DOMAIN
|
from homeassistant.components.sleepiq import DOMAIN
|
||||||
@ -16,12 +22,13 @@ from tests.common import MockConfigEntry
|
|||||||
BED_ID = "123456"
|
BED_ID = "123456"
|
||||||
BED_NAME = "Test Bed"
|
BED_NAME = "Test Bed"
|
||||||
BED_NAME_LOWER = BED_NAME.lower().replace(" ", "_")
|
BED_NAME_LOWER = BED_NAME.lower().replace(" ", "_")
|
||||||
|
SLEEPER_L_ID = "98765"
|
||||||
|
SLEEPER_R_ID = "43219"
|
||||||
SLEEPER_L_NAME = "SleeperL"
|
SLEEPER_L_NAME = "SleeperL"
|
||||||
SLEEPER_R_NAME = "Sleeper R"
|
SLEEPER_R_NAME = "Sleeper R"
|
||||||
SLEEPER_L_NAME_LOWER = SLEEPER_L_NAME.lower().replace(" ", "_")
|
SLEEPER_L_NAME_LOWER = SLEEPER_L_NAME.lower().replace(" ", "_")
|
||||||
SLEEPER_R_NAME_LOWER = SLEEPER_R_NAME.lower().replace(" ", "_")
|
SLEEPER_R_NAME_LOWER = SLEEPER_R_NAME.lower().replace(" ", "_")
|
||||||
|
|
||||||
|
|
||||||
SLEEPIQ_CONFIG = {
|
SLEEPIQ_CONFIG = {
|
||||||
CONF_USERNAME: "user@email.com",
|
CONF_USERNAME: "user@email.com",
|
||||||
CONF_PASSWORD: "password",
|
CONF_PASSWORD: "password",
|
||||||
@ -49,12 +56,14 @@ def mock_asyncsleepiq():
|
|||||||
sleeper_l.in_bed = True
|
sleeper_l.in_bed = True
|
||||||
sleeper_l.sleep_number = 40
|
sleeper_l.sleep_number = 40
|
||||||
sleeper_l.pressure = 1000
|
sleeper_l.pressure = 1000
|
||||||
|
sleeper_l.sleeper_id = SLEEPER_L_ID
|
||||||
|
|
||||||
sleeper_r.side = "R"
|
sleeper_r.side = "R"
|
||||||
sleeper_r.name = SLEEPER_R_NAME
|
sleeper_r.name = SLEEPER_R_NAME
|
||||||
sleeper_r.in_bed = False
|
sleeper_r.in_bed = False
|
||||||
sleeper_r.sleep_number = 80
|
sleeper_r.sleep_number = 80
|
||||||
sleeper_r.pressure = 1400
|
sleeper_r.pressure = 1400
|
||||||
|
sleeper_r.sleeper_id = SLEEPER_R_ID
|
||||||
|
|
||||||
bed.foundation = create_autospec(SleepIQFoundation)
|
bed.foundation = create_autospec(SleepIQFoundation)
|
||||||
light_1 = create_autospec(SleepIQLight)
|
light_1 = create_autospec(SleepIQLight)
|
||||||
@ -65,6 +74,28 @@ def mock_asyncsleepiq():
|
|||||||
light_2.is_on = False
|
light_2.is_on = False
|
||||||
bed.foundation.lights = [light_1, light_2]
|
bed.foundation.lights = [light_1, light_2]
|
||||||
|
|
||||||
|
actuator_h_r = create_autospec(SleepIQActuator)
|
||||||
|
actuator_h_l = create_autospec(SleepIQActuator)
|
||||||
|
actuator_f = create_autospec(SleepIQActuator)
|
||||||
|
bed.foundation.actuators = [actuator_h_r, actuator_h_l, actuator_f]
|
||||||
|
|
||||||
|
actuator_h_r.side = "R"
|
||||||
|
actuator_h_r.side_full = "Right"
|
||||||
|
actuator_h_r.actuator = "H"
|
||||||
|
actuator_h_r.actuator_full = "Head"
|
||||||
|
actuator_h_r.position = 60
|
||||||
|
|
||||||
|
actuator_h_l.side = "L"
|
||||||
|
actuator_h_l.side_full = "Left"
|
||||||
|
actuator_h_l.actuator = "H"
|
||||||
|
actuator_h_l.actuator_full = "Head"
|
||||||
|
actuator_h_l.position = 50
|
||||||
|
|
||||||
|
actuator_f.side = None
|
||||||
|
actuator_f.actuator = "F"
|
||||||
|
actuator_f.actuator_full = "Foot"
|
||||||
|
actuator_f.position = 10
|
||||||
|
|
||||||
yield client
|
yield client
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,8 +8,10 @@ from tests.components.sleepiq.conftest import (
|
|||||||
BED_ID,
|
BED_ID,
|
||||||
BED_NAME,
|
BED_NAME,
|
||||||
BED_NAME_LOWER,
|
BED_NAME_LOWER,
|
||||||
|
SLEEPER_L_ID,
|
||||||
SLEEPER_L_NAME,
|
SLEEPER_L_NAME,
|
||||||
SLEEPER_L_NAME_LOWER,
|
SLEEPER_L_NAME_LOWER,
|
||||||
|
SLEEPER_R_ID,
|
||||||
SLEEPER_R_NAME,
|
SLEEPER_R_NAME,
|
||||||
SLEEPER_R_NAME_LOWER,
|
SLEEPER_R_NAME_LOWER,
|
||||||
setup_platform,
|
setup_platform,
|
||||||
@ -35,7 +37,7 @@ async def test_firmness(hass, mock_asyncsleepiq):
|
|||||||
f"number.sleepnumber_{BED_NAME_LOWER}_{SLEEPER_L_NAME_LOWER}_firmness"
|
f"number.sleepnumber_{BED_NAME_LOWER}_{SLEEPER_L_NAME_LOWER}_firmness"
|
||||||
)
|
)
|
||||||
assert entry
|
assert entry
|
||||||
assert entry.unique_id == f"{BED_ID}_{SLEEPER_L_NAME}_firmness"
|
assert entry.unique_id == f"{SLEEPER_L_ID}_firmness"
|
||||||
|
|
||||||
state = hass.states.get(
|
state = hass.states.get(
|
||||||
f"number.sleepnumber_{BED_NAME_LOWER}_{SLEEPER_R_NAME_LOWER}_firmness"
|
f"number.sleepnumber_{BED_NAME_LOWER}_{SLEEPER_R_NAME_LOWER}_firmness"
|
||||||
@ -51,7 +53,7 @@ async def test_firmness(hass, mock_asyncsleepiq):
|
|||||||
f"number.sleepnumber_{BED_NAME_LOWER}_{SLEEPER_R_NAME_LOWER}_firmness"
|
f"number.sleepnumber_{BED_NAME_LOWER}_{SLEEPER_R_NAME_LOWER}_firmness"
|
||||||
)
|
)
|
||||||
assert entry
|
assert entry
|
||||||
assert entry.unique_id == f"{BED_ID}_{SLEEPER_R_NAME}_firmness"
|
assert entry.unique_id == f"{SLEEPER_R_ID}_firmness"
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@ -66,3 +68,69 @@ async def test_firmness(hass, mock_asyncsleepiq):
|
|||||||
|
|
||||||
mock_asyncsleepiq.beds[BED_ID].sleepers[0].set_sleepnumber.assert_called_once()
|
mock_asyncsleepiq.beds[BED_ID].sleepers[0].set_sleepnumber.assert_called_once()
|
||||||
mock_asyncsleepiq.beds[BED_ID].sleepers[0].set_sleepnumber.assert_called_with(42)
|
mock_asyncsleepiq.beds[BED_ID].sleepers[0].set_sleepnumber.assert_called_with(42)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_actuators(hass, mock_asyncsleepiq):
|
||||||
|
"""Test the SleepIQ actuator position values for a bed with adjustable head and foot."""
|
||||||
|
entry = await setup_platform(hass, DOMAIN)
|
||||||
|
entity_registry = er.async_get(hass)
|
||||||
|
|
||||||
|
state = hass.states.get(f"number.sleepnumber_{BED_NAME_LOWER}_right_head_position")
|
||||||
|
assert state.state == "60.0"
|
||||||
|
assert state.attributes.get(ATTR_ICON) == "mdi:bed"
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_FRIENDLY_NAME)
|
||||||
|
== f"SleepNumber {BED_NAME} Right Head Position"
|
||||||
|
)
|
||||||
|
|
||||||
|
entry = entity_registry.async_get(
|
||||||
|
f"number.sleepnumber_{BED_NAME_LOWER}_right_head_position"
|
||||||
|
)
|
||||||
|
assert entry
|
||||||
|
assert entry.unique_id == f"{BED_ID}_R_H"
|
||||||
|
|
||||||
|
state = hass.states.get(f"number.sleepnumber_{BED_NAME_LOWER}_left_head_position")
|
||||||
|
assert state.state == "50.0"
|
||||||
|
assert state.attributes.get(ATTR_ICON) == "mdi:bed"
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_FRIENDLY_NAME)
|
||||||
|
== f"SleepNumber {BED_NAME} Left Head Position"
|
||||||
|
)
|
||||||
|
|
||||||
|
entry = entity_registry.async_get(
|
||||||
|
f"number.sleepnumber_{BED_NAME_LOWER}_left_head_position"
|
||||||
|
)
|
||||||
|
assert entry
|
||||||
|
assert entry.unique_id == f"{BED_ID}_L_H"
|
||||||
|
|
||||||
|
state = hass.states.get(f"number.sleepnumber_{BED_NAME_LOWER}_foot_position")
|
||||||
|
assert state.state == "10.0"
|
||||||
|
assert state.attributes.get(ATTR_ICON) == "mdi:bed"
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_FRIENDLY_NAME)
|
||||||
|
== f"SleepNumber {BED_NAME} Foot Position"
|
||||||
|
)
|
||||||
|
|
||||||
|
entry = entity_registry.async_get(
|
||||||
|
f"number.sleepnumber_{BED_NAME_LOWER}_foot_position"
|
||||||
|
)
|
||||||
|
assert entry
|
||||||
|
assert entry.unique_id == f"{BED_ID}_F"
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_SET_VALUE,
|
||||||
|
{
|
||||||
|
ATTR_ENTITY_ID: f"number.sleepnumber_{BED_NAME_LOWER}_right_head_position",
|
||||||
|
ATTR_VALUE: 42,
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
mock_asyncsleepiq.beds[BED_ID].foundation.actuators[
|
||||||
|
0
|
||||||
|
].set_position.assert_called_once()
|
||||||
|
mock_asyncsleepiq.beds[BED_ID].foundation.actuators[
|
||||||
|
0
|
||||||
|
].set_position.assert_called_with(42)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user