"""The soundtouch component.""" import logging from libsoundtouch import soundtouch_device from libsoundtouch.device import SoundTouchDevice import voluptuous as vol from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, Platform from homeassistant.core import HomeAssistant, ServiceCall import homeassistant.helpers.config_validation as cv from homeassistant.helpers.typing import ConfigType from .const import ( DOMAIN, SERVICE_ADD_ZONE_SLAVE, SERVICE_CREATE_ZONE, SERVICE_PLAY_EVERYWHERE, SERVICE_REMOVE_ZONE_SLAVE, ) _LOGGER = logging.getLogger(__name__) SERVICE_PLAY_EVERYWHERE_SCHEMA = vol.Schema({vol.Required("master"): cv.entity_id}) SERVICE_CREATE_ZONE_SCHEMA = vol.Schema( { vol.Required("master"): cv.entity_id, vol.Required("slaves"): cv.entity_ids, } ) SERVICE_ADD_ZONE_SCHEMA = vol.Schema( { vol.Required("master"): cv.entity_id, vol.Required("slaves"): cv.entity_ids, } ) SERVICE_REMOVE_ZONE_SCHEMA = vol.Schema( { vol.Required("master"): cv.entity_id, vol.Required("slaves"): cv.entity_ids, } ) PLATFORMS = [Platform.MEDIA_PLAYER] class SoundTouchData: """SoundTouch data stored in the Home Assistant data object.""" def __init__(self, device: SoundTouchDevice) -> None: """Initialize the SoundTouch data object for a device.""" self.device = device self.media_player = None async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up Bose SoundTouch component.""" async def service_handle(service: ServiceCall) -> None: """Handle the applying of a service.""" master_id = service.data.get("master") slaves_ids = service.data.get("slaves") slaves = [] if slaves_ids: slaves = [ data.media_player for data in hass.data[DOMAIN].values() if data.media_player.entity_id in slaves_ids ] master = next( iter( [ data.media_player for data in hass.data[DOMAIN].values() if data.media_player.entity_id == master_id ] ), None, ) if master is None: _LOGGER.warning("Unable to find master with entity_id: %s", str(master_id)) return if service.service == SERVICE_PLAY_EVERYWHERE: slaves = [ data.media_player for data in hass.data[DOMAIN].values() if data.media_player.entity_id != master_id ] await hass.async_add_executor_job(master.create_zone, slaves) elif service.service == SERVICE_CREATE_ZONE: await hass.async_add_executor_job(master.create_zone, slaves) elif service.service == SERVICE_REMOVE_ZONE_SLAVE: await hass.async_add_executor_job(master.remove_zone_slave, slaves) elif service.service == SERVICE_ADD_ZONE_SLAVE: await hass.async_add_executor_job(master.add_zone_slave, slaves) hass.services.async_register( DOMAIN, SERVICE_PLAY_EVERYWHERE, service_handle, schema=SERVICE_PLAY_EVERYWHERE_SCHEMA, ) hass.services.async_register( DOMAIN, SERVICE_CREATE_ZONE, service_handle, schema=SERVICE_CREATE_ZONE_SCHEMA, ) hass.services.async_register( DOMAIN, SERVICE_REMOVE_ZONE_SLAVE, service_handle, schema=SERVICE_REMOVE_ZONE_SCHEMA, ) hass.services.async_register( DOMAIN, SERVICE_ADD_ZONE_SLAVE, service_handle, schema=SERVICE_ADD_ZONE_SCHEMA, ) return True async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Bose SoundTouch from a config entry.""" device = await hass.async_add_executor_job(soundtouch_device, entry.data[CONF_HOST]) hass.data.setdefault(DOMAIN, {})[entry.entry_id] = SoundTouchData(device) hass.config_entries.async_setup_platforms(entry, PLATFORMS) return True async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): del hass.data[DOMAIN][entry.entry_id] return unload_ok