import voluptuous as vol from homeassistant.components.media_player.const import MediaPlayerEntityFeature from homeassistant.core import State from homeassistant.helpers import config_validation as cv from homeassistant.helpers.intent import ( Intent, IntentResponse, ) from smartinspectpython.siauto import SILevel, SIColors from ..appmessages import STAppMessages from ..intent_loader import IntentLoader from ..const import ( CONF_VALUE, DOMAIN, PLATFORM_SPOTIFYPLUS, INTENT_PLAYER_TRANSFER_PLAYBACK, SERVICE_SPOTIFY_PLAYER_TRANSFER_PLAYBACK, SLOT_AREA, SLOT_DELAY, SLOT_DEVICE_NAME, SLOT_FLOOR, SLOT_NAME, SLOT_PREFERRED_AREA_ID, SLOT_PREFERRED_FLOOR_ID, ) from .spotifyplusintenthandler import SpotifyPlusIntentHandler class SpotifyPlusPlayerTransferPlayback_Handler(SpotifyPlusIntentHandler): """ Handles intents for SpotifyPlusPlayerTransferPlayback """ def __init__(self, intentLoader:IntentLoader) -> None: """ Initializes a new instance of the IntentHandler class. """ # invoke base class method. super().__init__(intentLoader) # set intent handler basics. self.description = "Transfer playback to another Spotify Connect device name." self.intent_type = INTENT_PLAYER_TRANSFER_PLAYBACK self.platforms = {PLATFORM_SPOTIFYPLUS} @property def slot_schema(self) -> dict | None: """ Returns the slot schema for this intent. """ return { # slots that determine which media player entity will be used. vol.Optional(SLOT_NAME): cv.string, vol.Optional(SLOT_AREA): cv.string, vol.Optional(SLOT_FLOOR): cv.string, vol.Optional(SLOT_PREFERRED_AREA_ID): cv.string, vol.Optional(SLOT_PREFERRED_FLOOR_ID): cv.string, # slots for other service arguments. vol.Optional(SLOT_DELAY, default=0.50): vol.Any(None, vol.All(vol.Coerce(float), vol.Range(min=0, max=10.0))), vol.Optional(SLOT_DEVICE_NAME): cv.string, } async def async_HandleIntent( self, intentObj: Intent, intentResponse: IntentResponse ) -> IntentResponse: """ Handles the intent. Args: intentObj (Intent): Intent object. intentResponse (IntentResponse) Intent response object. Returns: An IntentResponse object. """ # invoke base class method to resolve the player entity and its state. playerEntityState:State = await super().async_GetMatchingPlayerState( intentObj, intentResponse, desiredFeatures=MediaPlayerEntityFeature.PLAY_MEDIA, desiredStates=None, desiredStateResponseKey=None, requiresSpotifyPremium=True, ) # if media player was not resolved, then we are done; # note that the base class method above already called `async_set_speech` with a response. if playerEntityState is None: return intentResponse # get optional arguments (if provided). delay = intentObj.slots.get(SLOT_DELAY, {}).get(CONF_VALUE, None) device_name = intentObj.slots.get(SLOT_DEVICE_NAME, {}).get(CONF_VALUE, None) # set service name and build parameters. svcName:str = SERVICE_SPOTIFY_PLAYER_TRANSFER_PLAYBACK svcData:dict = \ { "entity_id": playerEntityState.entity_id, "device_id": device_name, "delay": delay, "play": True, } # transfer playback to specified device. self.logsi.LogVerbose(STAppMessages.MSG_SERVICE_EXECUTE % (svcName, playerEntityState.entity_id), colorValue=SIColors.Khaki) await intentObj.hass.services.async_call( DOMAIN, svcName, svcData, blocking=True, context=intentObj.context, return_response=False, ) # return intent response. intentResponse.speech_slots = intentObj.slots self.logsi.LogObject(SILevel.Verbose, STAppMessages.MSG_INTENT_HANDLER_RESPONSE % (intentObj.intent_type), intentResponse, colorValue=SIColors.Khaki) return intentResponse