Fix WLED power and brightness with WLED 0.10+ (#36529)
This commit is contained in:
parent
233284056a
commit
215c7e0e14
5 changed files with 337 additions and 72 deletions
|
@ -83,20 +83,78 @@ async def async_setup_entry(
|
|||
update_segments()
|
||||
|
||||
|
||||
class WLEDLight(LightEntity, WLEDDeviceEntity):
|
||||
"""Defines a WLED light."""
|
||||
class WLEDMasterLight(LightEntity, WLEDDeviceEntity):
|
||||
"""Defines a WLED master light."""
|
||||
|
||||
def __init__(self, entry_id: str, coordinator: WLEDDataUpdateCoordinator):
|
||||
"""Initialize WLED master light."""
|
||||
super().__init__(
|
||||
entry_id=entry_id,
|
||||
coordinator=coordinator,
|
||||
name=f"{coordinator.data.info.name} Master",
|
||||
icon="mdi:led-strip-variant",
|
||||
)
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return the unique ID for this sensor."""
|
||||
return f"{self.coordinator.data.info.mac_address}"
|
||||
|
||||
@property
|
||||
def supported_features(self) -> int:
|
||||
"""Flag supported features."""
|
||||
return SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION
|
||||
|
||||
@property
|
||||
def brightness(self) -> Optional[int]:
|
||||
"""Return the brightness of this light between 1..255."""
|
||||
return self.coordinator.data.state.brightness
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state of the light."""
|
||||
return bool(self.coordinator.data.state.on)
|
||||
|
||||
@wled_exception_handler
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn off the light."""
|
||||
data = {ATTR_ON: False}
|
||||
|
||||
if ATTR_TRANSITION in kwargs:
|
||||
# WLED uses 100ms per unit, so 10 = 1 second.
|
||||
data[ATTR_TRANSITION] = round(kwargs[ATTR_TRANSITION] * 10)
|
||||
|
||||
await self.coordinator.wled.master(**data)
|
||||
|
||||
@wled_exception_handler
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on the light."""
|
||||
data = {ATTR_ON: True}
|
||||
|
||||
if ATTR_TRANSITION in kwargs:
|
||||
# WLED uses 100ms per unit, so 10 = 1 second.
|
||||
data[ATTR_TRANSITION] = round(kwargs[ATTR_TRANSITION] * 10)
|
||||
|
||||
if ATTR_BRIGHTNESS in kwargs:
|
||||
data[ATTR_BRIGHTNESS] = kwargs[ATTR_BRIGHTNESS]
|
||||
|
||||
await self.coordinator.wled.master(**data)
|
||||
|
||||
|
||||
class WLEDSegmentLight(LightEntity, WLEDDeviceEntity):
|
||||
"""Defines a WLED light based on a segment."""
|
||||
|
||||
def __init__(
|
||||
self, entry_id: str, coordinator: WLEDDataUpdateCoordinator, segment: int
|
||||
):
|
||||
"""Initialize WLED light."""
|
||||
"""Initialize WLED segment light."""
|
||||
self._rgbw = coordinator.data.info.leds.rgbw
|
||||
self._segment = segment
|
||||
|
||||
# Only apply the segment ID if it is not the first segment
|
||||
name = coordinator.data.info.name
|
||||
if segment != 0:
|
||||
name += f" {segment}"
|
||||
# If this is the one and only segment, use a simpler name
|
||||
name = f"{coordinator.data.info.name} Segment {self._segment}"
|
||||
if len(coordinator.data.state.segments) == 1:
|
||||
name = coordinator.data.info.name
|
||||
|
||||
super().__init__(
|
||||
entry_id=entry_id,
|
||||
|
@ -155,7 +213,16 @@ class WLEDLight(LightEntity, WLEDDeviceEntity):
|
|||
@property
|
||||
def brightness(self) -> Optional[int]:
|
||||
"""Return the brightness of this light between 1..255."""
|
||||
return self.coordinator.data.state.brightness
|
||||
state = self.coordinator.data.state
|
||||
|
||||
# If this is the one and only segment, calculate brightness based
|
||||
# on the master and segment brightness
|
||||
if len(state.segments) == 1:
|
||||
return int(
|
||||
(state.segments[self._segment].brightness * state.brightness) / 255
|
||||
)
|
||||
|
||||
return state.segments[self._segment].brightness
|
||||
|
||||
@property
|
||||
def white_value(self) -> Optional[int]:
|
||||
|
@ -187,18 +254,30 @@ class WLEDLight(LightEntity, WLEDDeviceEntity):
|
|||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state of the light."""
|
||||
return bool(self.coordinator.data.state.on)
|
||||
state = self.coordinator.data.state
|
||||
|
||||
# If there is a single segment, take master into account
|
||||
if len(state.segments) == 1 and not state.on:
|
||||
return False
|
||||
|
||||
return bool(state.segments[self._segment].on)
|
||||
|
||||
@wled_exception_handler
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn off the light."""
|
||||
data = {ATTR_ON: False, ATTR_SEGMENT_ID: self._segment}
|
||||
data = {ATTR_ON: False}
|
||||
|
||||
if ATTR_TRANSITION in kwargs:
|
||||
# WLED uses 100ms per unit, so 10 = 1 second.
|
||||
data[ATTR_TRANSITION] = round(kwargs[ATTR_TRANSITION] * 10)
|
||||
|
||||
await self.coordinator.wled.light(**data)
|
||||
# If there is a single segment, control via the master
|
||||
if len(self.coordinator.data.state.segments) == 1:
|
||||
await self.coordinator.wled.master(**data)
|
||||
return
|
||||
|
||||
data[ATTR_SEGMENT_ID] = self._segment
|
||||
await self.coordinator.wled.segment(**data)
|
||||
|
||||
@wled_exception_handler
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
|
@ -248,7 +327,23 @@ class WLEDLight(LightEntity, WLEDDeviceEntity):
|
|||
else:
|
||||
data[ATTR_COLOR_PRIMARY] += (self.white_value,)
|
||||
|
||||
await self.coordinator.wled.light(**data)
|
||||
# When only 1 segment is present, switch along the master, and use
|
||||
# the master for power/brightness control.
|
||||
if len(self.coordinator.data.state.segments) == 1:
|
||||
master_data = {ATTR_ON: True}
|
||||
if ATTR_BRIGHTNESS in data:
|
||||
master_data[ATTR_BRIGHTNESS] = data[ATTR_BRIGHTNESS]
|
||||
data[ATTR_BRIGHTNESS] = 255
|
||||
|
||||
if ATTR_TRANSITION in data:
|
||||
master_data[ATTR_TRANSITION] = data[ATTR_TRANSITION]
|
||||
del data[ATTR_TRANSITION]
|
||||
|
||||
await self.coordinator.wled.segment(**data)
|
||||
await self.coordinator.wled.master(**master_data)
|
||||
return
|
||||
|
||||
await self.coordinator.wled.segment(**data)
|
||||
|
||||
@wled_exception_handler
|
||||
async def async_effect(
|
||||
|
@ -273,45 +368,59 @@ class WLEDLight(LightEntity, WLEDDeviceEntity):
|
|||
if speed is not None:
|
||||
data[ATTR_SPEED] = speed
|
||||
|
||||
await self.coordinator.wled.light(**data)
|
||||
await self.coordinator.wled.segment(**data)
|
||||
|
||||
|
||||
@callback
|
||||
def async_update_segments(
|
||||
entry: ConfigEntry,
|
||||
coordinator: WLEDDataUpdateCoordinator,
|
||||
current: Dict[int, WLEDLight],
|
||||
current: Dict[int, WLEDSegmentLight],
|
||||
async_add_entities,
|
||||
) -> None:
|
||||
"""Update segments."""
|
||||
segment_ids = {light.segment_id for light in coordinator.data.state.segments}
|
||||
current_ids = set(current)
|
||||
|
||||
# Process new segments, add them to Home Assistant
|
||||
new_segments = []
|
||||
for segment_id in segment_ids - current_ids:
|
||||
current[segment_id] = WLEDLight(entry.entry_id, coordinator, segment_id)
|
||||
new_segments.append(current[segment_id])
|
||||
# Discard master (if present)
|
||||
current_ids.discard(-1)
|
||||
|
||||
if new_segments:
|
||||
async_add_entities(new_segments)
|
||||
# Process new segments, add them to Home Assistant
|
||||
new_entities = []
|
||||
for segment_id in segment_ids - current_ids:
|
||||
current[segment_id] = WLEDSegmentLight(entry.entry_id, coordinator, segment_id)
|
||||
new_entities.append(current[segment_id])
|
||||
|
||||
# More than 1 segment now? Add master controls
|
||||
if len(current_ids) < 2 and len(segment_ids) > 1:
|
||||
current[-1] = WLEDMasterLight(entry.entry_id, coordinator)
|
||||
new_entities.append(current[-1])
|
||||
|
||||
if new_entities:
|
||||
async_add_entities(new_entities)
|
||||
|
||||
# Process deleted segments, remove them from Home Assistant
|
||||
for segment_id in current_ids - segment_ids:
|
||||
coordinator.hass.async_create_task(
|
||||
async_remove_segment(segment_id, coordinator, current)
|
||||
async_remove_entity(segment_id, coordinator, current)
|
||||
)
|
||||
|
||||
# Remove master if there is only 1 segment left
|
||||
if len(current_ids) > 1 and len(segment_ids) < 2:
|
||||
coordinator.hass.async_create_task(
|
||||
async_remove_entity(-1, coordinator, current)
|
||||
)
|
||||
|
||||
|
||||
async def async_remove_segment(
|
||||
segment_id: int,
|
||||
async def async_remove_entity(
|
||||
index: int,
|
||||
coordinator: WLEDDataUpdateCoordinator,
|
||||
current: Dict[int, WLEDLight],
|
||||
current: Dict[int, WLEDSegmentLight],
|
||||
) -> None:
|
||||
"""Remove WLED segment light from Home Assistant."""
|
||||
entity = current[segment_id]
|
||||
entity = current[index]
|
||||
await entity.async_remove()
|
||||
registry = await async_get_entity_registry(coordinator.hass)
|
||||
if entity.entity_id in registry.entities:
|
||||
registry.async_remove(entity.entity_id)
|
||||
del current[segment_id]
|
||||
del current[index]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"name": "WLED",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/wled",
|
||||
"requirements": ["wled==0.4.1"],
|
||||
"requirements": ["wled==0.4.2"],
|
||||
"zeroconf": ["_wled._tcp.local."],
|
||||
"codeowners": ["@frenck"],
|
||||
"quality_scale": "platinum"
|
||||
|
|
|
@ -2201,7 +2201,7 @@ wirelesstagpy==0.4.0
|
|||
withings-api==2.1.3
|
||||
|
||||
# homeassistant.components.wled
|
||||
wled==0.4.1
|
||||
wled==0.4.2
|
||||
|
||||
# homeassistant.components.xbee
|
||||
xbee-helper==0.0.7
|
||||
|
|
|
@ -910,7 +910,7 @@ wiffi==1.0.0
|
|||
withings-api==2.1.3
|
||||
|
||||
# homeassistant.components.wled
|
||||
wled==0.4.1
|
||||
wled==0.4.2
|
||||
|
||||
# homeassistant.components.bluesound
|
||||
# homeassistant.components.rest
|
||||
|
|
|
@ -29,6 +29,7 @@ from homeassistant.const import (
|
|||
ATTR_ICON,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
STATE_UNAVAILABLE,
|
||||
)
|
||||
|
@ -50,7 +51,7 @@ async def test_rgb_light_state(
|
|||
entity_registry = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
# First segment of the strip
|
||||
state = hass.states.get("light.wled_rgb_light")
|
||||
state = hass.states.get("light.wled_rgb_light_segment_0")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 127
|
||||
assert state.attributes.get(ATTR_EFFECT) == "Solid"
|
||||
|
@ -64,12 +65,12 @@ async def test_rgb_light_state(
|
|||
assert state.attributes.get(ATTR_SPEED) == 32
|
||||
assert state.state == STATE_ON
|
||||
|
||||
entry = entity_registry.async_get("light.wled_rgb_light")
|
||||
entry = entity_registry.async_get("light.wled_rgb_light_segment_0")
|
||||
assert entry
|
||||
assert entry.unique_id == "aabbccddeeff_0"
|
||||
|
||||
# Second segment of the strip
|
||||
state = hass.states.get("light.wled_rgb_light_1")
|
||||
state = hass.states.get("light.wled_rgb_light_segment_1")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 127
|
||||
assert state.attributes.get(ATTR_EFFECT) == "Blink"
|
||||
|
@ -83,22 +84,32 @@ async def test_rgb_light_state(
|
|||
assert state.attributes.get(ATTR_SPEED) == 16
|
||||
assert state.state == STATE_ON
|
||||
|
||||
entry = entity_registry.async_get("light.wled_rgb_light_1")
|
||||
entry = entity_registry.async_get("light.wled_rgb_light_segment_1")
|
||||
assert entry
|
||||
assert entry.unique_id == "aabbccddeeff_1"
|
||||
|
||||
# Test master control of the lightstrip
|
||||
state = hass.states.get("light.wled_rgb_light_master")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 127
|
||||
assert state.state == STATE_ON
|
||||
|
||||
async def test_switch_change_state(
|
||||
entry = entity_registry.async_get("light.wled_rgb_light_master")
|
||||
assert entry
|
||||
assert entry.unique_id == "aabbccddeeff"
|
||||
|
||||
|
||||
async def test_segment_change_state(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, caplog
|
||||
) -> None:
|
||||
"""Test the change of state of the WLED switches."""
|
||||
"""Test the change of state of the WLED segments."""
|
||||
await init_integration(hass, aioclient_mock)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light", ATTR_TRANSITION: 5},
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0", ATTR_TRANSITION: 5},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -106,14 +117,14 @@ async def test_switch_change_state(
|
|||
on=False, segment_id=0, transition=50,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{
|
||||
ATTR_BRIGHTNESS: 42,
|
||||
ATTR_EFFECT: "Chase",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0",
|
||||
ATTR_RGB_COLOR: [255, 0, 0],
|
||||
ATTR_TRANSITION: 5,
|
||||
},
|
||||
|
@ -129,11 +140,11 @@ async def test_switch_change_state(
|
|||
transition=50,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light", ATTR_COLOR_TEMP: 400},
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0", ATTR_COLOR_TEMP: 400},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -142,33 +153,178 @@ async def test_switch_change_state(
|
|||
)
|
||||
|
||||
|
||||
async def test_master_change_state(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, caplog
|
||||
) -> None:
|
||||
"""Test the change of state of the WLED master light control."""
|
||||
await init_integration(hass, aioclient_mock)
|
||||
|
||||
with patch("wled.WLED.master") as light_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light_master", ATTR_TRANSITION: 5},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
light_mock.assert_called_once_with(
|
||||
on=False, transition=50,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.master") as light_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{
|
||||
ATTR_BRIGHTNESS: 42,
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light_master",
|
||||
ATTR_TRANSITION: 5,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
light_mock.assert_called_once_with(
|
||||
brightness=42, on=True, transition=50,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.master") as light_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light_master", ATTR_TRANSITION: 5},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
light_mock.assert_called_once_with(
|
||||
on=False, transition=50,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.master") as light_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{
|
||||
ATTR_BRIGHTNESS: 42,
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light_master",
|
||||
ATTR_TRANSITION: 5,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
light_mock.assert_called_once_with(
|
||||
brightness=42, on=True, transition=50,
|
||||
)
|
||||
|
||||
|
||||
async def test_dynamically_handle_segments(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test if a new/deleted segment is dynamically added/removed."""
|
||||
await init_integration(hass, aioclient_mock)
|
||||
|
||||
assert hass.states.get("light.wled_rgb_light")
|
||||
assert hass.states.get("light.wled_rgb_light_1")
|
||||
assert hass.states.get("light.wled_rgb_light_master")
|
||||
assert hass.states.get("light.wled_rgb_light_segment_0")
|
||||
assert hass.states.get("light.wled_rgb_light_segment_1")
|
||||
|
||||
data = json.loads(load_fixture("wled/rgb_single_segment.json"))
|
||||
device = WLEDDevice(data)
|
||||
|
||||
# Test removal if segment went missing
|
||||
# Test removal if segment went missing, including the master entity
|
||||
with patch(
|
||||
"homeassistant.components.wled.WLED.update", return_value=device,
|
||||
):
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get("light.wled_rgb_light")
|
||||
assert not hass.states.get("light.wled_rgb_light_1")
|
||||
assert hass.states.get("light.wled_rgb_light_segment_0")
|
||||
assert not hass.states.get("light.wled_rgb_light_segment_1")
|
||||
assert not hass.states.get("light.wled_rgb_light_master")
|
||||
|
||||
# Test adding if segment shows up again
|
||||
# Test adding if segment shows up again, including the master entity
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("light.wled_rgb_light")
|
||||
assert hass.states.get("light.wled_rgb_light_1")
|
||||
assert hass.states.get("light.wled_rgb_light_master")
|
||||
assert hass.states.get("light.wled_rgb_light_segment_0")
|
||||
assert hass.states.get("light.wled_rgb_light_segment_1")
|
||||
|
||||
|
||||
async def test_single_segment_behavior(
|
||||
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, caplog
|
||||
) -> None:
|
||||
"""Test the behavior of the integration with a single segment."""
|
||||
await init_integration(hass, aioclient_mock)
|
||||
|
||||
data = json.loads(load_fixture("wled/rgb_single_segment.json"))
|
||||
device = WLEDDevice(data)
|
||||
|
||||
# Test absent master
|
||||
with patch(
|
||||
"homeassistant.components.wled.WLED.update", return_value=device,
|
||||
):
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert not hass.states.get("light.wled_rgb_light_master")
|
||||
|
||||
state = hass.states.get("light.wled_rgb_light_segment_0")
|
||||
assert state
|
||||
assert state.state == STATE_ON
|
||||
|
||||
# Test segment brightness takes master into account
|
||||
device.state.brightness = 100
|
||||
device.state.segments[0].brightness = 255
|
||||
with patch(
|
||||
"homeassistant.components.wled.WLED.update", return_value=device,
|
||||
):
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.wled_rgb_light_segment_0")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_BRIGHTNESS) == 100
|
||||
|
||||
# Test segment is off when master is off
|
||||
device.state.on = False
|
||||
with patch(
|
||||
"homeassistant.components.wled.WLED.update", return_value=device,
|
||||
):
|
||||
async_fire_time_changed(hass, dt_util.utcnow() + SCAN_INTERVAL)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("light.wled_rgb_light_segment_0")
|
||||
assert state
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
# Test master is turned off when turning off a single segment
|
||||
with patch("wled.WLED.master") as master_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0", ATTR_TRANSITION: 5},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
master_mock.assert_called_once_with(
|
||||
on=False, transition=50,
|
||||
)
|
||||
|
||||
# Test master is turned on when turning on a single segment, and segment
|
||||
# brightness is set to 255.
|
||||
with patch("wled.WLED.master") as master_mock, patch(
|
||||
"wled.WLED.segment"
|
||||
) as segment_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0",
|
||||
ATTR_TRANSITION: 5,
|
||||
ATTR_BRIGHTNESS: 42,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
master_mock.assert_called_once_with(on=True, transition=50, brightness=42)
|
||||
segment_mock.assert_called_once_with(on=True, segment_id=0, brightness=255)
|
||||
|
||||
|
||||
async def test_light_error(
|
||||
|
@ -182,12 +338,12 @@ async def test_light_error(
|
|||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light"},
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.wled_rgb_light")
|
||||
state = hass.states.get("light.wled_rgb_light_segment_0")
|
||||
assert state.state == STATE_ON
|
||||
assert "Invalid response from API" in caplog.text
|
||||
|
||||
|
@ -199,17 +355,17 @@ async def test_light_connection_error(
|
|||
await init_integration(hass, aioclient_mock)
|
||||
|
||||
with patch("homeassistant.components.wled.WLED.update"), patch(
|
||||
"homeassistant.components.wled.WLED.light", side_effect=WLEDConnectionError
|
||||
"homeassistant.components.wled.WLED.segment", side_effect=WLEDConnectionError
|
||||
):
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light"},
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.wled_rgb_light")
|
||||
state = hass.states.get("light.wled_rgb_light_segment_0")
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
|
||||
|
@ -224,7 +380,7 @@ async def test_rgbw_light(
|
|||
assert state.attributes.get(ATTR_HS_COLOR) == (0.0, 100.0)
|
||||
assert state.attributes.get(ATTR_WHITE_VALUE) == 139
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
|
@ -236,7 +392,7 @@ async def test_rgbw_light(
|
|||
on=True, segment_id=0, color_primary=(255, 159, 70, 139),
|
||||
)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
|
@ -248,7 +404,7 @@ async def test_rgbw_light(
|
|||
color_primary=(255, 0, 0, 100), on=True, segment_id=0,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
|
@ -271,13 +427,13 @@ async def test_effect_service(
|
|||
"""Test the effect service of a WLED light."""
|
||||
await init_integration(hass, aioclient_mock)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT,
|
||||
{
|
||||
ATTR_EFFECT: "Rainbow",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0",
|
||||
ATTR_INTENSITY: 200,
|
||||
ATTR_REVERSE: True,
|
||||
ATTR_SPEED: 100,
|
||||
|
@ -289,11 +445,11 @@ async def test_effect_service(
|
|||
effect="Rainbow", intensity=200, reverse=True, segment_id=0, speed=100,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT,
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light", ATTR_EFFECT: 9},
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0", ATTR_EFFECT: 9},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -301,12 +457,12 @@ async def test_effect_service(
|
|||
segment_id=0, effect=9,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT,
|
||||
{
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0",
|
||||
ATTR_INTENSITY: 200,
|
||||
ATTR_REVERSE: True,
|
||||
ATTR_SPEED: 100,
|
||||
|
@ -318,13 +474,13 @@ async def test_effect_service(
|
|||
intensity=200, reverse=True, segment_id=0, speed=100,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT,
|
||||
{
|
||||
ATTR_EFFECT: "Rainbow",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0",
|
||||
ATTR_REVERSE: True,
|
||||
ATTR_SPEED: 100,
|
||||
},
|
||||
|
@ -335,13 +491,13 @@ async def test_effect_service(
|
|||
effect="Rainbow", reverse=True, segment_id=0, speed=100,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT,
|
||||
{
|
||||
ATTR_EFFECT: "Rainbow",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0",
|
||||
ATTR_INTENSITY: 200,
|
||||
ATTR_SPEED: 100,
|
||||
},
|
||||
|
@ -352,13 +508,13 @@ async def test_effect_service(
|
|||
effect="Rainbow", intensity=200, segment_id=0, speed=100,
|
||||
)
|
||||
|
||||
with patch("wled.WLED.light") as light_mock:
|
||||
with patch("wled.WLED.segment") as light_mock:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT,
|
||||
{
|
||||
ATTR_EFFECT: "Rainbow",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light",
|
||||
ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0",
|
||||
ATTR_INTENSITY: 200,
|
||||
ATTR_REVERSE: True,
|
||||
},
|
||||
|
@ -381,11 +537,11 @@ async def test_effect_service_error(
|
|||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_EFFECT,
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light", ATTR_EFFECT: 9},
|
||||
{ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0", ATTR_EFFECT: 9},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.wled_rgb_light")
|
||||
state = hass.states.get("light.wled_rgb_light_segment_0")
|
||||
assert state.state == STATE_ON
|
||||
assert "Invalid response from API" in caplog.text
|
||||
|
|
Loading…
Add table
Reference in a new issue