mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 22:27:07 +00:00
Add services to bond to start and stop increase/decrease brightness (#55006)
This commit is contained in:
parent
e6e8d7eded
commit
35d943ba56
@ -12,7 +12,9 @@ from homeassistant.components.light import (
|
|||||||
LightEntity,
|
LightEntity,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers import entity_platform
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
@ -23,6 +25,16 @@ from .utils import BondDevice
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
SERVICE_START_INCREASING_BRIGHTNESS = "start_increasing_brightness"
|
||||||
|
SERVICE_START_DECREASING_BRIGHTNESS = "start_decreasing_brightness"
|
||||||
|
SERVICE_STOP = "stop"
|
||||||
|
|
||||||
|
ENTITY_SERVICES = [
|
||||||
|
SERVICE_START_INCREASING_BRIGHTNESS,
|
||||||
|
SERVICE_START_DECREASING_BRIGHTNESS,
|
||||||
|
SERVICE_STOP,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -34,6 +46,14 @@ async def async_setup_entry(
|
|||||||
hub: BondHub = data[HUB]
|
hub: BondHub = data[HUB]
|
||||||
bpup_subs: BPUPSubscriptions = data[BPUP_SUBS]
|
bpup_subs: BPUPSubscriptions = data[BPUP_SUBS]
|
||||||
|
|
||||||
|
platform = entity_platform.async_get_current_platform()
|
||||||
|
for service in ENTITY_SERVICES:
|
||||||
|
platform.async_register_entity_service(
|
||||||
|
service,
|
||||||
|
{},
|
||||||
|
f"async_{service}",
|
||||||
|
)
|
||||||
|
|
||||||
fan_lights: list[Entity] = [
|
fan_lights: list[Entity] = [
|
||||||
BondLight(hub, device, bpup_subs)
|
BondLight(hub, device, bpup_subs)
|
||||||
for device in hub.devices
|
for device in hub.devices
|
||||||
@ -119,6 +139,31 @@ class BondLight(BondBaseLight, BondEntity, LightEntity):
|
|||||||
"""Turn off the light."""
|
"""Turn off the light."""
|
||||||
await self._hub.bond.action(self._device.device_id, Action.turn_light_off())
|
await self._hub.bond.action(self._device.device_id, Action.turn_light_off())
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _async_has_action_or_raise(self, action: str) -> None:
|
||||||
|
"""Raise HomeAssistantError if the device does not support an action."""
|
||||||
|
if not self._device.has_action(action):
|
||||||
|
raise HomeAssistantError(f"{self.entity_id} does not support {action}")
|
||||||
|
|
||||||
|
async def async_start_increasing_brightness(self) -> None:
|
||||||
|
"""Start increasing the light brightness."""
|
||||||
|
self._async_has_action_or_raise(Action.START_INCREASING_BRIGHTNESS)
|
||||||
|
await self._hub.bond.action(
|
||||||
|
self._device.device_id, Action(Action.START_INCREASING_BRIGHTNESS)
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_start_decreasing_brightness(self) -> None:
|
||||||
|
"""Start decreasing the light brightness."""
|
||||||
|
self._async_has_action_or_raise(Action.START_DECREASING_BRIGHTNESS)
|
||||||
|
await self._hub.bond.action(
|
||||||
|
self._device.device_id, Action(Action.START_DECREASING_BRIGHTNESS)
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_stop(self) -> None:
|
||||||
|
"""Stop all actions and clear the queue."""
|
||||||
|
self._async_has_action_or_raise(Action.STOP)
|
||||||
|
await self._hub.bond.action(self._device.device_id, Action(Action.STOP))
|
||||||
|
|
||||||
|
|
||||||
class BondDownLight(BondBaseLight, BondEntity, LightEntity):
|
class BondDownLight(BondBaseLight, BondEntity, LightEntity):
|
||||||
"""Representation of a Bond light."""
|
"""Representation of a Bond light."""
|
||||||
|
23
homeassistant/components/bond/services.yaml
Normal file
23
homeassistant/components/bond/services.yaml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
start_increasing_brightness:
|
||||||
|
name: Start increasing brightness
|
||||||
|
description: "Start increasing the brightness of the light."
|
||||||
|
target:
|
||||||
|
entity:
|
||||||
|
integration: bond
|
||||||
|
domain: light
|
||||||
|
|
||||||
|
start_decreasing_brightness:
|
||||||
|
name: Start decreasing brightness
|
||||||
|
description: "Start decreasing the brightness of the light."
|
||||||
|
target:
|
||||||
|
entity:
|
||||||
|
integration: bond
|
||||||
|
domain: light
|
||||||
|
|
||||||
|
stop:
|
||||||
|
name: Stop
|
||||||
|
description: "Stop any in-progress action and empty the queue."
|
||||||
|
target:
|
||||||
|
entity:
|
||||||
|
integration: bond
|
||||||
|
domain: light
|
@ -25,7 +25,8 @@ class BondDevice:
|
|||||||
"""Create a helper device from ID and attributes returned by API."""
|
"""Create a helper device from ID and attributes returned by API."""
|
||||||
self.device_id = device_id
|
self.device_id = device_id
|
||||||
self.props = props
|
self.props = props
|
||||||
self._attrs = attrs
|
self._attrs = attrs or {}
|
||||||
|
self._supported_actions: set[str] = set(self._attrs.get("actions", []))
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
"""Return readable representation of a bond device."""
|
"""Return readable representation of a bond device."""
|
||||||
@ -65,13 +66,13 @@ class BondDevice:
|
|||||||
"""Check if Trust State is turned on."""
|
"""Check if Trust State is turned on."""
|
||||||
return self.props.get("trust_state", False)
|
return self.props.get("trust_state", False)
|
||||||
|
|
||||||
|
def has_action(self, action: str) -> bool:
|
||||||
|
"""Check to see if the device supports an actions."""
|
||||||
|
return action in self._supported_actions
|
||||||
|
|
||||||
def _has_any_action(self, actions: set[str]) -> bool:
|
def _has_any_action(self, actions: set[str]) -> bool:
|
||||||
"""Check to see if the device supports any of the actions."""
|
"""Check to see if the device supports any of the actions."""
|
||||||
supported_actions: list[str] = self._attrs["actions"]
|
return bool(self._supported_actions.intersection(actions))
|
||||||
for action in supported_actions:
|
|
||||||
if action in actions:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def supports_speed(self) -> bool:
|
def supports_speed(self) -> bool:
|
||||||
"""Return True if this device supports any of the speed related commands."""
|
"""Return True if this device supports any of the speed related commands."""
|
||||||
|
@ -2,8 +2,15 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from bond_api import Action, DeviceType
|
from bond_api import Action, DeviceType
|
||||||
|
import pytest
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
|
from homeassistant.components.bond.const import DOMAIN
|
||||||
|
from homeassistant.components.bond.light import (
|
||||||
|
SERVICE_START_DECREASING_BRIGHTNESS,
|
||||||
|
SERVICE_START_INCREASING_BRIGHTNESS,
|
||||||
|
SERVICE_STOP,
|
||||||
|
)
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS,
|
ATTR_BRIGHTNESS,
|
||||||
DOMAIN as LIGHT_DOMAIN,
|
DOMAIN as LIGHT_DOMAIN,
|
||||||
@ -16,6 +23,7 @@ from homeassistant.const import (
|
|||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
)
|
)
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers.entity_registry import EntityRegistry
|
from homeassistant.helpers.entity_registry import EntityRegistry
|
||||||
from homeassistant.util import utcnow
|
from homeassistant.util import utcnow
|
||||||
@ -98,6 +106,21 @@ def fireplace_with_light(name: str):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def light_brightness_increase_decrease_only(name: str):
|
||||||
|
"""Create a light that can only increase or decrease brightness."""
|
||||||
|
return {
|
||||||
|
"name": name,
|
||||||
|
"type": DeviceType.LIGHT,
|
||||||
|
"actions": [
|
||||||
|
Action.TURN_LIGHT_ON,
|
||||||
|
Action.TURN_LIGHT_OFF,
|
||||||
|
Action.START_INCREASING_BRIGHTNESS,
|
||||||
|
Action.START_DECREASING_BRIGHTNESS,
|
||||||
|
Action.STOP,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_fan_entity_registry(hass: core.HomeAssistant):
|
async def test_fan_entity_registry(hass: core.HomeAssistant):
|
||||||
"""Tests that fan with light devices are registered in the entity registry."""
|
"""Tests that fan with light devices are registered in the entity registry."""
|
||||||
await setup_platform(
|
await setup_platform(
|
||||||
@ -231,6 +254,133 @@ async def test_no_trust_state(hass: core.HomeAssistant):
|
|||||||
assert device.attributes.get(ATTR_ASSUMED_STATE) is not True
|
assert device.attributes.get(ATTR_ASSUMED_STATE) is not True
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_start_increasing_brightness(hass: core.HomeAssistant):
|
||||||
|
"""Tests a light that can only increase or decrease brightness delegates to API can start increasing brightness."""
|
||||||
|
await setup_platform(
|
||||||
|
hass,
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
light_brightness_increase_decrease_only("name-1"),
|
||||||
|
bond_device_id="test-device-id",
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch_bond_action() as mock_bond_action, patch_bond_device_state():
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_START_INCREASING_BRIGHTNESS,
|
||||||
|
{ATTR_ENTITY_ID: "light.name_1"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
mock_bond_action.assert_called_once_with(
|
||||||
|
"test-device-id", Action(Action.START_INCREASING_BRIGHTNESS)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_start_increasing_brightness_missing_service(
|
||||||
|
hass: core.HomeAssistant,
|
||||||
|
):
|
||||||
|
"""Tests a light does not have start increasing brightness throws."""
|
||||||
|
await setup_platform(
|
||||||
|
hass, LIGHT_DOMAIN, light("name-1"), bond_device_id="test-device-id"
|
||||||
|
)
|
||||||
|
|
||||||
|
with pytest.raises(HomeAssistantError), patch_bond_device_state():
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_START_INCREASING_BRIGHTNESS,
|
||||||
|
{ATTR_ENTITY_ID: "light.name_1"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_start_decreasing_brightness(hass: core.HomeAssistant):
|
||||||
|
"""Tests a light that can only increase or decrease brightness delegates to API can start decreasing brightness."""
|
||||||
|
await setup_platform(
|
||||||
|
hass,
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
light_brightness_increase_decrease_only("name-1"),
|
||||||
|
bond_device_id="test-device-id",
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch_bond_action() as mock_bond_action, patch_bond_device_state():
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_START_DECREASING_BRIGHTNESS,
|
||||||
|
{ATTR_ENTITY_ID: "light.name_1"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
mock_bond_action.assert_called_once_with(
|
||||||
|
"test-device-id", Action(Action.START_DECREASING_BRIGHTNESS)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_start_decreasing_brightness_missing_service(
|
||||||
|
hass: core.HomeAssistant,
|
||||||
|
):
|
||||||
|
"""Tests a light does not have start decreasing brightness throws."""
|
||||||
|
await setup_platform(
|
||||||
|
hass,
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
light("name-1"),
|
||||||
|
bond_device_id="test-device-id",
|
||||||
|
)
|
||||||
|
|
||||||
|
with pytest.raises(HomeAssistantError), patch_bond_device_state():
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_START_DECREASING_BRIGHTNESS,
|
||||||
|
{ATTR_ENTITY_ID: "light.name_1"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_stop(hass: core.HomeAssistant):
|
||||||
|
"""Tests a light that can only increase or decrease brightness delegates to API can stop."""
|
||||||
|
await setup_platform(
|
||||||
|
hass,
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
light_brightness_increase_decrease_only("name-1"),
|
||||||
|
bond_device_id="test-device-id",
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch_bond_action() as mock_bond_action, patch_bond_device_state():
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_STOP,
|
||||||
|
{ATTR_ENTITY_ID: "light.name_1"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
mock_bond_action.assert_called_once_with("test-device-id", Action(Action.STOP))
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_stop_missing_service(
|
||||||
|
hass: core.HomeAssistant,
|
||||||
|
):
|
||||||
|
"""Tests a light does not have stop throws."""
|
||||||
|
await setup_platform(
|
||||||
|
hass,
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
light("name-1"),
|
||||||
|
bond_device_id="test-device-id",
|
||||||
|
)
|
||||||
|
|
||||||
|
with pytest.raises(HomeAssistantError), patch_bond_device_state():
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_STOP,
|
||||||
|
{ATTR_ENTITY_ID: "light.name_1"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
async def test_turn_on_light(hass: core.HomeAssistant):
|
async def test_turn_on_light(hass: core.HomeAssistant):
|
||||||
"""Tests that turn on command delegates to API."""
|
"""Tests that turn on command delegates to API."""
|
||||||
await setup_platform(
|
await setup_platform(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user