Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions homeassistant/components/wled/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"""Support for WLED."""
import asyncio
from datetime import timedelta
import logging
from typing import Any, Dict, Optional, Union

from wled import WLED, WLEDConnectionError, WLEDError

from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_NAME, CONF_HOST
from homeassistant.core import HomeAssistant, callback
Expand Down Expand Up @@ -58,9 +60,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data[DOMAIN][entry.entry_id] = {DATA_WLED_CLIENT: wled}

# Set up all platforms for this device/entry.
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, LIGHT_DOMAIN)
)
for component in LIGHT_DOMAIN, SWITCH_DOMAIN:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)

async def interval_update(now: dt_util.dt.datetime = None) -> None:
"""Poll WLED device function, dispatches event after update."""
Expand Down Expand Up @@ -89,7 +92,10 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
cancel_timer()

# Unload entities for this entry/device.
await hass.config_entries.async_forward_entry_unload(entry, LIGHT_DOMAIN)
await asyncio.gather(
hass.config_entries.async_forward_entry_unload(entry, LIGHT_DOMAIN),
hass.config_entries.async_forward_entry_unload(entry, SWITCH_DOMAIN),
)

# Cleanup
del hass.data[DOMAIN][entry.entry_id]
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/wled/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# Attributes
ATTR_COLOR_PRIMARY = "color_primary"
ATTR_DURATION = "duration"
ATTR_FADE = "fade"
ATTR_IDENTIFIERS = "identifiers"
ATTR_INTENSITY = "intensity"
ATTR_MANUFACTURER = "manufacturer"
Expand All @@ -23,3 +24,4 @@
ATTR_SOFTWARE_VERSION = "sw_version"
ATTR_SPEED = "speed"
ATTR_TARGET_BRIGHTNESS = "target_brightness"
ATTR_UDP_PORT = "udp_port"
175 changes: 175 additions & 0 deletions homeassistant/components/wled/switch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
"""Support for WLED switches."""
import logging
from typing import Any, Callable, List

from wled import WLED, WLEDError

from homeassistant.components.switch import SwitchDevice
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.typing import HomeAssistantType

from . import WLEDDeviceEntity
from .const import (
ATTR_DURATION,
ATTR_FADE,
ATTR_TARGET_BRIGHTNESS,
ATTR_UDP_PORT,
DATA_WLED_CLIENT,
DOMAIN,
)

_LOGGER = logging.getLogger(__name__)

PARALLEL_UPDATES = 1


async def async_setup_entry(
hass: HomeAssistantType,
entry: ConfigEntry,
async_add_entities: Callable[[List[Entity], bool], None],
) -> None:
"""Set up WLED switch based on a config entry."""
wled: WLED = hass.data[DOMAIN][entry.entry_id][DATA_WLED_CLIENT]

switches = [
WLEDNightlightSwitch(entry.entry_id, wled),
WLEDSyncSendSwitch(entry.entry_id, wled),
WLEDSyncReceiveSwitch(entry.entry_id, wled),
]
async_add_entities(switches, True)


class WLEDSwitch(WLEDDeviceEntity, SwitchDevice):
"""Defines a WLED switch."""

def __init__(
self, entry_id: str, wled: WLED, name: str, icon: str, key: str
) -> None:
"""Initialize WLED switch."""
self._key = key
self._state = False
super().__init__(entry_id, wled, name, icon)

@property
def unique_id(self) -> str:
"""Return the unique ID for this sensor."""
return f"{self.wled.device.info.mac_address}_{self._key}"

@property
def is_on(self) -> bool:
"""Return the state of the switch."""
return self._state

async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off the switch."""
try:
await self._wled_turn_off()
self._state = False
except WLEDError:
_LOGGER.error("An error occurred while turning off WLED switch.")
Comment thread
frenck marked this conversation as resolved.
self._available = False
self.async_schedule_update_ha_state()

async def _wled_turn_off(self) -> None:
"""Turn off the switch."""
raise NotImplementedError()

async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on the switch."""
try:
await self._wled_turn_on()
self._state = True
except WLEDError:
_LOGGER.error("An error occurred while turning on WLED switch")
self._available = False
self.async_schedule_update_ha_state()

async def _wled_turn_on(self) -> None:
"""Turn on the switch."""
raise NotImplementedError()


class WLEDNightlightSwitch(WLEDSwitch):
"""Defines a WLED nightlight switch."""

def __init__(self, entry_id: str, wled: WLED) -> None:
"""Initialize WLED nightlight switch."""
super().__init__(
entry_id,
wled,
f"{wled.device.info.name} Nightlight",
"mdi:weather-night",
"nightlight",
)

async def _wled_turn_off(self) -> None:
"""Turn off the WLED nightlight switch."""
await self.wled.nightlight(on=False)

async def _wled_turn_on(self) -> None:
"""Turn on the WLED nightlight switch."""
await self.wled.nightlight(on=True)

async def _wled_update(self) -> None:
"""Update WLED entity."""
self._state = self.wled.device.state.nightlight.on
self._attributes = {
ATTR_DURATION: self.wled.device.state.nightlight.duration,
ATTR_FADE: self.wled.device.state.nightlight.fade,
ATTR_TARGET_BRIGHTNESS: self.wled.device.state.nightlight.target_brightness,
}


class WLEDSyncSendSwitch(WLEDSwitch):
"""Defines a WLED sync send switch."""

def __init__(self, entry_id: str, wled: WLED) -> None:
"""Initialize WLED sync send switch."""
super().__init__(
entry_id,
wled,
f"{wled.device.info.name} Sync Send",
"mdi:upload-network-outline",
"sync_send",
)

async def _wled_turn_off(self) -> None:
"""Turn off the WLED sync send switch."""
await self.wled.sync(send=False)

async def _wled_turn_on(self) -> None:
"""Turn on the WLED sync send switch."""
await self.wled.sync(send=True)

async def _wled_update(self) -> None:
"""Update WLED entity."""
self._state = self.wled.device.state.sync.send
self._attributes = {ATTR_UDP_PORT: self.wled.device.info.udp_port}


class WLEDSyncReceiveSwitch(WLEDSwitch):
"""Defines a WLED sync receive switch."""

def __init__(self, entry_id: str, wled: WLED):
"""Initialize WLED sync receive switch."""
super().__init__(
entry_id,
wled,
f"{wled.device.info.name} Sync Receive",
"mdi:download-network-outline",
"sync_receive",
)

async def _wled_turn_off(self) -> None:
"""Turn off the WLED sync receive switch."""
await self.wled.sync(receive=False)

async def _wled_turn_on(self) -> None:
"""Turn on the WLED sync receive switch."""
await self.wled.sync(receive=True)

async def _wled_update(self) -> None:
"""Update WLED entity."""
self._state = self.wled.device.state.sync.receive
self._attributes = {ATTR_UDP_PORT: self.wled.device.info.udp_port}
Loading