mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Add support for dimmable bond lights (#38203)
* Add support for dimmable lights * Fix formatting * Add supported features test on Bond Light * Add more tests to bond light and fixes comments * Fix rebase conflict resolution * Apply suggestions from code review Co-authored-by: Chris Talkington <chris@talkingtontech.com>
This commit is contained in:
parent
fa9866db96
commit
8ab1b41974
@ -47,19 +47,44 @@ class BondLight(BondEntity, LightEntity):
|
|||||||
def __init__(self, hub: BondHub, device: BondDevice):
|
def __init__(self, hub: BondHub, device: BondDevice):
|
||||||
"""Create HA entity representing Bond fan."""
|
"""Create HA entity representing Bond fan."""
|
||||||
super().__init__(hub, device)
|
super().__init__(hub, device)
|
||||||
|
self._brightness: Optional[int] = None
|
||||||
self._light: Optional[int] = None
|
self._light: Optional[int] = None
|
||||||
|
|
||||||
def _apply_state(self, state: dict):
|
def _apply_state(self, state: dict):
|
||||||
self._light = state.get("light")
|
self._light = state.get("light")
|
||||||
|
self._brightness = state.get("brightness")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supported_features(self) -> Optional[int]:
|
||||||
|
"""Flag supported features."""
|
||||||
|
features = 0
|
||||||
|
if self._device.supports_set_brightness():
|
||||||
|
features |= SUPPORT_BRIGHTNESS
|
||||||
|
|
||||||
|
return features
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self) -> bool:
|
def is_on(self) -> bool:
|
||||||
"""Return if light is currently on."""
|
"""Return if light is currently on."""
|
||||||
return self._light == 1
|
return self._light == 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def brightness(self) -> int:
|
||||||
|
"""Return the brightness of this light between 1..255."""
|
||||||
|
brightness_value = (
|
||||||
|
round(self._brightness * 255 / 100) if self._brightness else None
|
||||||
|
)
|
||||||
|
return brightness_value
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn on the light."""
|
"""Turn on the light."""
|
||||||
|
brightness = kwargs.get(ATTR_BRIGHTNESS)
|
||||||
|
if brightness:
|
||||||
|
await self._hub.bond.action(
|
||||||
|
self._device.device_id,
|
||||||
|
Action(Action.SET_BRIGHTNESS, round((brightness * 100) / 255)),
|
||||||
|
)
|
||||||
|
else:
|
||||||
await self._hub.bond.action(self._device.device_id, Action.turn_light_on())
|
await self._hub.bond.action(self._device.device_id, Action.turn_light_on())
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
|
@ -3,10 +3,6 @@
|
|||||||
"name": "Bond",
|
"name": "Bond",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/bond",
|
"documentation": "https://www.home-assistant.io/integrations/bond",
|
||||||
"requirements": [
|
"requirements": ["bond-api==0.1.7"],
|
||||||
"bond-api==0.1.7"
|
"codeowners": ["@prystupa"]
|
||||||
],
|
|
||||||
"codeowners": [
|
|
||||||
"@prystupa"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,11 @@ class BondDevice:
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def supports_set_brightness(self) -> bool:
|
||||||
|
"""Return True if this device supports setting a light brightness."""
|
||||||
|
actions: List[str] = self._attrs["actions"]
|
||||||
|
return bool([action for action in actions if action in [Action.SET_BRIGHTNESS]])
|
||||||
|
|
||||||
|
|
||||||
class BondHub:
|
class BondHub:
|
||||||
"""Hub device representing Bond Bridge."""
|
"""Hub device representing Bond Bridge."""
|
||||||
|
@ -5,10 +5,15 @@ import logging
|
|||||||
from bond_api import Action, DeviceType
|
from bond_api import Action, DeviceType
|
||||||
|
|
||||||
from homeassistant import core
|
from homeassistant import core
|
||||||
from homeassistant.components.light import ATTR_BRIGHTNESS, DOMAIN as LIGHT_DOMAIN
|
from homeassistant.components.light import (
|
||||||
|
ATTR_BRIGHTNESS,
|
||||||
|
DOMAIN as LIGHT_DOMAIN,
|
||||||
|
SUPPORT_BRIGHTNESS,
|
||||||
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ASSUMED_STATE,
|
ATTR_ASSUMED_STATE,
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
|
ATTR_SUPPORTED_FEATURES,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
)
|
)
|
||||||
@ -36,6 +41,15 @@ def ceiling_fan(name: str):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def dimmable_ceiling_fan(name: str):
|
||||||
|
"""Create a ceiling fan (that has built-in light) with given name."""
|
||||||
|
return {
|
||||||
|
"name": name,
|
||||||
|
"type": DeviceType.CEILING_FAN,
|
||||||
|
"actions": [Action.TURN_LIGHT_ON, Action.TURN_LIGHT_OFF, Action.SET_BRIGHTNESS],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def fireplace(name: str):
|
def fireplace(name: str):
|
||||||
"""Create a fireplace with given name."""
|
"""Create a fireplace with given name."""
|
||||||
return {"name": name, "type": DeviceType.FIREPLACE}
|
return {"name": name, "type": DeviceType.FIREPLACE}
|
||||||
@ -128,6 +142,52 @@ async def test_turn_off_light(hass: core.HomeAssistant):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_brightness_support(hass: core.HomeAssistant):
|
||||||
|
"""Tests that a dimmable light should support the brightness feature."""
|
||||||
|
await setup_platform(
|
||||||
|
hass,
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
dimmable_ceiling_fan("name-1"),
|
||||||
|
bond_device_id="test-device-id",
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("light.name_1")
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] & SUPPORT_BRIGHTNESS
|
||||||
|
|
||||||
|
|
||||||
|
async def test_brightness_not_supported(hass: core.HomeAssistant):
|
||||||
|
"""Tests that a non-dimmable light should not support the brightness feature."""
|
||||||
|
await setup_platform(
|
||||||
|
hass, LIGHT_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id",
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("light.name_1")
|
||||||
|
assert not state.attributes[ATTR_SUPPORTED_FEATURES] & SUPPORT_BRIGHTNESS
|
||||||
|
|
||||||
|
|
||||||
|
async def test_turn_on_light_with_brightness(hass: core.HomeAssistant):
|
||||||
|
"""Tests that turn on command, on a dimmable light, delegates to API and parses brightness."""
|
||||||
|
await setup_platform(
|
||||||
|
hass,
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
dimmable_ceiling_fan("name-1"),
|
||||||
|
bond_device_id="test-device-id",
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch_bond_action() as mock_set_brightness, patch_bond_device_state():
|
||||||
|
await hass.services.async_call(
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{ATTR_ENTITY_ID: "light.name_1", ATTR_BRIGHTNESS: 128},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
mock_set_brightness.assert_called_once_with(
|
||||||
|
"test-device-id", Action(Action.SET_BRIGHTNESS, 50)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_update_reports_light_is_on(hass: core.HomeAssistant):
|
async def test_update_reports_light_is_on(hass: core.HomeAssistant):
|
||||||
"""Tests that update command sets correct state when Bond API reports the light is on."""
|
"""Tests that update command sets correct state when Bond API reports the light is on."""
|
||||||
await setup_platform(hass, LIGHT_DOMAIN, ceiling_fan("name-1"))
|
await setup_platform(hass, LIGHT_DOMAIN, ceiling_fan("name-1"))
|
||||||
@ -220,3 +280,14 @@ async def test_light_available(hass: core.HomeAssistant):
|
|||||||
await help_test_entity_available(
|
await help_test_entity_available(
|
||||||
hass, LIGHT_DOMAIN, ceiling_fan("name-1"), "light.name_1"
|
hass, LIGHT_DOMAIN, ceiling_fan("name-1"), "light.name_1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_parse_brightness(hass: core.HomeAssistant):
|
||||||
|
"""Tests that reported brightness level (0..100) converted to HA brightness (0...255)."""
|
||||||
|
await setup_platform(hass, LIGHT_DOMAIN, dimmable_ceiling_fan("name-1"))
|
||||||
|
|
||||||
|
with patch_bond_device_state(return_value={"light": 1, "brightness": 50}):
|
||||||
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=30))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert hass.states.get("light.name_1").attributes[ATTR_BRIGHTNESS] == 128
|
||||||
|
Loading…
x
Reference in New Issue
Block a user