Add switch to enable/disable music mode in Magic Home/flux_led (#62320)
This commit is contained in:
parent
5d5b6bef55
commit
c3a963e12a
3 changed files with 95 additions and 9 deletions
|
@ -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"
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue