Add switch to enable/disable music mode in Magic Home/flux_led (#62320)

This commit is contained in:
J. Nick Koston 2021-12-19 10:57:33 -06:00 committed by GitHub
parent 5d5b6bef55
commit c3a963e12a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 9 deletions

View file

@ -5,6 +5,7 @@ from typing import Any
from flux_led import DeviceType
from flux_led.aio import AIOWifiLedBulb
from flux_led.const import MODE_MUSIC
from homeassistant import config_entries
from homeassistant.components.switch import SwitchEntity
@ -22,7 +23,7 @@ from .const import (
)
from .coordinator import FluxLedUpdateCoordinator
from .discovery import async_clear_discovery_cache
from .entity import FluxBaseEntity, FluxOnOffEntity
from .entity import FluxBaseEntity, FluxEntity, FluxOnOffEntity
async def async_setup_entry(
@ -32,20 +33,19 @@ async def async_setup_entry(
) -> None:
"""Set up the Flux lights."""
coordinator: FluxLedUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
entities: list[FluxSwitch | FluxRemoteAccessSwitch] = []
entities: list[FluxSwitch | FluxRemoteAccessSwitch | FluxMusicSwitch] = []
unique_id = entry.unique_id
name = entry.data[CONF_NAME]
if coordinator.device.device_type == DeviceType.Switch:
entities.append(
FluxSwitch(
coordinator,
entry.unique_id,
entry.data[CONF_NAME],
)
)
entities.append(FluxSwitch(coordinator, unique_id, name))
if entry.data.get(CONF_REMOTE_ACCESS_HOST):
entities.append(FluxRemoteAccessSwitch(coordinator.device, entry))
if coordinator.device.microphone:
entities.append(FluxMusicSwitch(coordinator, unique_id, name))
if entities:
async_add_entities(entities)
@ -107,3 +107,43 @@ class FluxRemoteAccessSwitch(FluxBaseEntity, SwitchEntity):
def icon(self) -> str:
"""Return icon based on state."""
return "mdi:cloud-outline" if self.is_on else "mdi:cloud-off-outline"
class FluxMusicSwitch(FluxEntity, SwitchEntity):
"""Representation of a Flux music switch."""
def __init__(
self,
coordinator: FluxLedUpdateCoordinator,
unique_id: str | None,
name: str,
) -> None:
"""Initialize the flux music switch."""
super().__init__(coordinator, unique_id, name)
self._attr_name = f"{name} Music"
if unique_id:
self._attr_unique_id = f"{unique_id}_music"
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the microphone on."""
if self._device.requires_turn_on and not self._device.is_on:
await self._device.async_turn_on()
await self._device.async_set_music_mode()
self.async_write_ha_state()
await self.coordinator.async_request_refresh()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the microphone off."""
await self._device.async_set_levels(*self._device.rgb, brightness=255)
self.async_write_ha_state()
await self.coordinator.async_request_refresh()
@property
def is_on(self) -> bool:
"""Return true if microphone is is on."""
return self._device.is_on and self._device.effect == MODE_MUSIC
@property
def icon(self) -> str:
"""Return icon based on state."""
return "mdi:microphone" if self.is_on else "mdi:microphone-off"

View file

@ -73,6 +73,7 @@ def _mocked_bulb() -> AIOWifiLedBulb:
bulb.requires_turn_on = True
bulb.async_setup = AsyncMock(side_effect=_save_setup_callback)
bulb.effect_list = ["some_effect"]
bulb.async_set_music_mode = AsyncMock()
bulb.async_set_custom_pattern = AsyncMock()
bulb.async_set_preset_pattern = AsyncMock()
bulb.async_set_effect = AsyncMock()

View file

@ -1,4 +1,6 @@
"""Tests for switch platform."""
from flux_led.const import MODE_MUSIC
from homeassistant.components import flux_led
from homeassistant.components.flux_led.const import CONF_REMOTE_ACCESS_ENABLED, DOMAIN
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
@ -95,3 +97,46 @@ async def test_remote_access_on_off(hass: HomeAssistant) -> None:
assert hass.states.get(entity_id).state == STATE_ON
assert config_entry.data[CONF_REMOTE_ACCESS_ENABLED] is True
async def test_music_mode_switch(hass: HomeAssistant) -> None:
"""Test music mode switch."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data={CONF_HOST: IP_ADDRESS, CONF_NAME: DEFAULT_ENTRY_TITLE},
unique_id=MAC_ADDRESS,
)
config_entry.add_to_hass(hass)
bulb = _mocked_bulb()
bulb.raw_state = bulb.raw_state._replace(model_num=0xA3) # has music mode
bulb.microphone = True
with _patch_discovery(), _patch_wifibulb(device=bulb):
await async_setup_component(hass, flux_led.DOMAIN, {flux_led.DOMAIN: {}})
await hass.async_block_till_done()
entity_id = "switch.bulb_rgbcw_ddeeff_music"
assert hass.states.get(entity_id).state == STATE_OFF
bulb.effect = MODE_MUSIC
bulb.is_on = False
await hass.services.async_call(
SWITCH_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True
)
bulb.async_set_music_mode.assert_called_once()
assert hass.states.get(entity_id).state == STATE_OFF
bulb.async_set_music_mode.reset_mock()
bulb.is_on = True
await hass.services.async_call(
SWITCH_DOMAIN, "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True
)
bulb.async_set_music_mode.assert_called_once()
assert hass.states.get(entity_id).state == STATE_ON
bulb.effect = None
await hass.services.async_call(
SWITCH_DOMAIN, "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True
)
bulb.async_set_levels.assert_called_once()
assert hass.states.get(entity_id).state == STATE_OFF