Add WLED Live Override controls (#59783)
parent
1d63ae8696
commit
70990ebf81
|
@ -1,6 +1,7 @@
|
|||
"""Constants for the WLED integration."""
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Final
|
||||
|
||||
# Integration domain
|
||||
DOMAIN = "wled"
|
||||
|
@ -30,3 +31,6 @@ ATTR_UDP_PORT = "udp_port"
|
|||
# Services
|
||||
SERVICE_EFFECT = "effect"
|
||||
SERVICE_PRESET = "preset"
|
||||
|
||||
# Device classes
|
||||
DEVICE_CLASS_WLED_LIVE_OVERRIDE: Final = "wled__live_override"
|
||||
|
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||
|
||||
from functools import partial
|
||||
|
||||
from wled import Playlist, Preset
|
||||
from wled import Live, Playlist, Preset
|
||||
|
||||
from homeassistant.components.select import SelectEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
|
@ -11,7 +11,7 @@ from homeassistant.const import ENTITY_CATEGORY_CONFIG
|
|||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .const import DEVICE_CLASS_WLED_LIVE_OVERRIDE, DOMAIN
|
||||
from .coordinator import WLEDDataUpdateCoordinator
|
||||
from .helpers import wled_exception_handler
|
||||
from .models import WLEDEntity
|
||||
|
@ -27,7 +27,13 @@ async def async_setup_entry(
|
|||
"""Set up WLED select based on a config entry."""
|
||||
coordinator: WLEDDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
|
||||
async_add_entities([WLEDPlaylistSelect(coordinator), WLEDPresetSelect(coordinator)])
|
||||
async_add_entities(
|
||||
[
|
||||
WLEDLiveOverrideSelect(coordinator),
|
||||
WLEDPlaylistSelect(coordinator),
|
||||
WLEDPresetSelect(coordinator),
|
||||
]
|
||||
)
|
||||
|
||||
update_segments = partial(
|
||||
async_update_segments,
|
||||
|
@ -39,6 +45,32 @@ async def async_setup_entry(
|
|||
update_segments()
|
||||
|
||||
|
||||
class WLEDLiveOverrideSelect(WLEDEntity, SelectEntity):
|
||||
"""Defined a WLED Live Override select."""
|
||||
|
||||
_attr_device_class = DEVICE_CLASS_WLED_LIVE_OVERRIDE
|
||||
_attr_entity_category = ENTITY_CATEGORY_CONFIG
|
||||
_attr_icon = "mdi:theater"
|
||||
|
||||
def __init__(self, coordinator: WLEDDataUpdateCoordinator) -> None:
|
||||
"""Initialize WLED ."""
|
||||
super().__init__(coordinator=coordinator)
|
||||
|
||||
self._attr_name = f"{coordinator.data.info.name} Live Override"
|
||||
self._attr_unique_id = f"{coordinator.data.info.mac_address}_live_override"
|
||||
self._attr_options = [str(live.value) for live in Live]
|
||||
|
||||
@property
|
||||
def current_option(self) -> str:
|
||||
"""Return the current selected live override."""
|
||||
return str(self.coordinator.data.state.lor.value)
|
||||
|
||||
@wled_exception_handler
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Set WLED state to the selected live override state."""
|
||||
await self.coordinator.wled.live(live=Live(int(option)))
|
||||
|
||||
|
||||
class WLEDPresetSelect(WLEDEntity, SelectEntity):
|
||||
"""Defined a WLED Preset select."""
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"state": {
|
||||
"wled__live_override": {
|
||||
"0": "[%key:common::state::off%]",
|
||||
"1": "[%key:common::state::on%]",
|
||||
"2": "Until device restarts"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"state": {
|
||||
"wled__live_override": {
|
||||
"0": "Off",
|
||||
"1": "On",
|
||||
"2": "Until device restart"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -451,3 +451,91 @@ async def test_playlist_select_connection_error(
|
|||
assert "Error communicating with API" in caplog.text
|
||||
assert mock_wled.playlist.call_count == 1
|
||||
mock_wled.playlist.assert_called_with(playlist="Playlist 2")
|
||||
|
||||
|
||||
async def test_live_override(
|
||||
hass: HomeAssistant,
|
||||
init_integration: MockConfigEntry,
|
||||
mock_wled: MagicMock,
|
||||
) -> None:
|
||||
"""Test the creation and values of the WLED selects."""
|
||||
entity_registry = er.async_get(hass)
|
||||
|
||||
state = hass.states.get("select.wled_rgb_light_live_override")
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_ICON) == "mdi:theater"
|
||||
assert state.attributes.get(ATTR_OPTIONS) == ["0", "1", "2"]
|
||||
assert state.state == "0"
|
||||
|
||||
entry = entity_registry.async_get("select.wled_rgb_light_live_override")
|
||||
assert entry
|
||||
assert entry.unique_id == "aabbccddeeff_live_override"
|
||||
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{
|
||||
ATTR_ENTITY_ID: "select.wled_rgb_light_live_override",
|
||||
ATTR_OPTION: "2",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_wled.live.call_count == 1
|
||||
mock_wled.live.assert_called_with(live=2)
|
||||
|
||||
|
||||
async def test_live_select_error(
|
||||
hass: HomeAssistant,
|
||||
init_integration: MockConfigEntry,
|
||||
mock_wled: MagicMock,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Test error handling of the WLED selects."""
|
||||
mock_wled.live.side_effect = WLEDError
|
||||
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{
|
||||
ATTR_ENTITY_ID: "select.wled_rgb_light_live_override",
|
||||
ATTR_OPTION: "1",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("select.wled_rgb_light_live_override")
|
||||
assert state
|
||||
assert state.state == "0"
|
||||
assert "Invalid response from API" in caplog.text
|
||||
assert mock_wled.live.call_count == 1
|
||||
mock_wled.live.assert_called_with(live=1)
|
||||
|
||||
|
||||
async def test_live_select_connection_error(
|
||||
hass: HomeAssistant,
|
||||
init_integration: MockConfigEntry,
|
||||
mock_wled: MagicMock,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Test error handling of the WLED selects."""
|
||||
mock_wled.live.side_effect = WLEDConnectionError
|
||||
|
||||
await hass.services.async_call(
|
||||
SELECT_DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{
|
||||
ATTR_ENTITY_ID: "select.wled_rgb_light_live_override",
|
||||
ATTR_OPTION: "2",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("select.wled_rgb_light_live_override")
|
||||
assert state
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
assert "Error communicating with API" in caplog.text
|
||||
assert mock_wled.live.call_count == 1
|
||||
mock_wled.live.assert_called_with(live=2)
|
||||
|
|
Loading…
Reference in New Issue