mirror of
https://github.com/home-assistant/core.git
synced 2025-07-26 06:37:52 +00:00
Add Remote entity to Xbox Integration (#41809)
This commit is contained in:
parent
ba55cb8955
commit
3013f39191
@ -1006,6 +1006,7 @@ omit =
|
|||||||
homeassistant/components/xbox/api.py
|
homeassistant/components/xbox/api.py
|
||||||
homeassistant/components/xbox/browse_media.py
|
homeassistant/components/xbox/browse_media.py
|
||||||
homeassistant/components/xbox/media_player.py
|
homeassistant/components/xbox/media_player.py
|
||||||
|
homeassistant/components/xbox/remote.py
|
||||||
homeassistant/components/xbox_live/sensor.py
|
homeassistant/components/xbox_live/sensor.py
|
||||||
homeassistant/components/xeoma/camera.py
|
homeassistant/components/xeoma/camera.py
|
||||||
homeassistant/components/xfinity/device_tracker.py
|
homeassistant/components/xfinity/device_tracker.py
|
||||||
|
@ -1,8 +1,18 @@
|
|||||||
"""The xbox integration."""
|
"""The xbox integration."""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
from typing import Dict, Optional
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from xbox.webapi.api.client import XboxLiveClient
|
from xbox.webapi.api.client import XboxLiveClient
|
||||||
|
from xbox.webapi.api.provider.catalog.const import HOME_APP_IDS, SYSTEM_PFN_ID_MAP
|
||||||
|
from xbox.webapi.api.provider.catalog.models import AlternateIdType, Product
|
||||||
|
from xbox.webapi.api.provider.smartglass.models import (
|
||||||
|
SmartglassConsoleList,
|
||||||
|
SmartglassConsoleStatus,
|
||||||
|
)
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
||||||
@ -12,10 +22,14 @@ from homeassistant.helpers import (
|
|||||||
config_entry_oauth2_flow,
|
config_entry_oauth2_flow,
|
||||||
config_validation as cv,
|
config_validation as cv,
|
||||||
)
|
)
|
||||||
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
from . import api, config_flow
|
from . import api, config_flow
|
||||||
from .const import DOMAIN, OAUTH2_AUTHORIZE, OAUTH2_TOKEN
|
from .const import DOMAIN, OAUTH2_AUTHORIZE, OAUTH2_TOKEN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
CONFIG_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
DOMAIN: vol.Schema(
|
DOMAIN: vol.Schema(
|
||||||
@ -28,7 +42,7 @@ CONFIG_SCHEMA = vol.Schema(
|
|||||||
extra=vol.ALLOW_EXTRA,
|
extra=vol.ALLOW_EXTRA,
|
||||||
)
|
)
|
||||||
|
|
||||||
PLATFORMS = ["media_player"]
|
PLATFORMS = ["media_player", "remote"]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: dict):
|
async def async_setup(hass: HomeAssistant, config: dict):
|
||||||
@ -65,7 +79,22 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
aiohttp_client.async_get_clientsession(hass), session
|
aiohttp_client.async_get_clientsession(hass), session
|
||||||
)
|
)
|
||||||
|
|
||||||
hass.data[DOMAIN][entry.entry_id] = XboxLiveClient(auth)
|
client = XboxLiveClient(auth)
|
||||||
|
consoles: SmartglassConsoleList = await client.smartglass.get_console_list()
|
||||||
|
_LOGGER.debug(
|
||||||
|
"Found %d consoles: %s",
|
||||||
|
len(consoles.result),
|
||||||
|
consoles.dict(),
|
||||||
|
)
|
||||||
|
|
||||||
|
coordinator = XboxUpdateCoordinator(hass, client, consoles)
|
||||||
|
await coordinator.async_refresh()
|
||||||
|
|
||||||
|
hass.data[DOMAIN][entry.entry_id] = {
|
||||||
|
"client": XboxLiveClient(auth),
|
||||||
|
"consoles": consoles,
|
||||||
|
"coordinator": coordinator,
|
||||||
|
}
|
||||||
|
|
||||||
for component in PLATFORMS:
|
for component in PLATFORMS:
|
||||||
hass.async_create_task(
|
hass.async_create_task(
|
||||||
@ -89,3 +118,83 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
hass.data[DOMAIN].pop(entry.entry_id)
|
hass.data[DOMAIN].pop(entry.entry_id)
|
||||||
|
|
||||||
return unload_ok
|
return unload_ok
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class XboxData:
|
||||||
|
"""Xbox dataclass for update coordinator."""
|
||||||
|
|
||||||
|
status: SmartglassConsoleStatus
|
||||||
|
app_details: Optional[Product]
|
||||||
|
|
||||||
|
|
||||||
|
class XboxUpdateCoordinator(DataUpdateCoordinator):
|
||||||
|
"""Store Xbox Console Status."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
client: XboxLiveClient,
|
||||||
|
consoles: SmartglassConsoleList,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize."""
|
||||||
|
super().__init__(
|
||||||
|
hass,
|
||||||
|
_LOGGER,
|
||||||
|
name=DOMAIN,
|
||||||
|
update_interval=timedelta(seconds=10),
|
||||||
|
)
|
||||||
|
self.data: Dict[str, XboxData] = {}
|
||||||
|
self.client: XboxLiveClient = client
|
||||||
|
self.consoles: SmartglassConsoleList = consoles
|
||||||
|
|
||||||
|
async def _async_update_data(self) -> Dict[str, XboxData]:
|
||||||
|
"""Fetch the latest console status."""
|
||||||
|
new_data: Dict[str, XboxData] = {}
|
||||||
|
for console in self.consoles.result:
|
||||||
|
current_state: Optional[XboxData] = self.data.get(console.id, None)
|
||||||
|
status: SmartglassConsoleStatus = (
|
||||||
|
await self.client.smartglass.get_console_status(console.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
_LOGGER.debug(
|
||||||
|
"%s status: %s",
|
||||||
|
console.name,
|
||||||
|
status.dict(),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Setup focus app
|
||||||
|
app_details: Optional[Product] = None
|
||||||
|
if current_state is not None:
|
||||||
|
app_details = current_state.app_details
|
||||||
|
|
||||||
|
if status.focus_app_aumid:
|
||||||
|
if (
|
||||||
|
not current_state
|
||||||
|
or status.focus_app_aumid != current_state.status.focus_app_aumid
|
||||||
|
):
|
||||||
|
app_id = status.focus_app_aumid.split("!")[0]
|
||||||
|
id_type = AlternateIdType.PACKAGE_FAMILY_NAME
|
||||||
|
if app_id in SYSTEM_PFN_ID_MAP:
|
||||||
|
id_type = AlternateIdType.LEGACY_XBOX_PRODUCT_ID
|
||||||
|
app_id = SYSTEM_PFN_ID_MAP[app_id][id_type]
|
||||||
|
catalog_result = (
|
||||||
|
await self.client.catalog.get_product_from_alternate_id(
|
||||||
|
app_id, id_type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if catalog_result and catalog_result.products:
|
||||||
|
app_details = catalog_result.products[0]
|
||||||
|
else:
|
||||||
|
if not current_state or not current_state.status.focus_app_aumid:
|
||||||
|
id_type = AlternateIdType.LEGACY_XBOX_PRODUCT_ID
|
||||||
|
catalog_result = (
|
||||||
|
await self.client.catalog.get_product_from_alternate_id(
|
||||||
|
HOME_APP_IDS[id_type], id_type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
app_details = catalog_result.products[0]
|
||||||
|
|
||||||
|
new_data[console.id] = XboxData(status=status, app_details=app_details)
|
||||||
|
|
||||||
|
return new_data
|
||||||
|
@ -4,14 +4,12 @@ import re
|
|||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from xbox.webapi.api.client import XboxLiveClient
|
from xbox.webapi.api.client import XboxLiveClient
|
||||||
from xbox.webapi.api.provider.catalog.const import HOME_APP_IDS, SYSTEM_PFN_ID_MAP
|
from xbox.webapi.api.provider.catalog.models import Image
|
||||||
from xbox.webapi.api.provider.catalog.models import AlternateIdType, Image, Product
|
|
||||||
from xbox.webapi.api.provider.smartglass.models import (
|
from xbox.webapi.api.provider.smartglass.models import (
|
||||||
PlaybackState,
|
PlaybackState,
|
||||||
PowerState,
|
PowerState,
|
||||||
SmartglassConsole,
|
SmartglassConsole,
|
||||||
SmartglassConsoleList,
|
SmartglassConsoleList,
|
||||||
SmartglassConsoleStatus,
|
|
||||||
VolumeDirection,
|
VolumeDirection,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,7 +29,9 @@ from homeassistant.components.media_player.const import (
|
|||||||
SUPPORT_VOLUME_STEP,
|
SUPPORT_VOLUME_STEP,
|
||||||
)
|
)
|
||||||
from homeassistant.const import STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING
|
from homeassistant.const import STATE_OFF, STATE_ON, STATE_PAUSED, STATE_PLAYING
|
||||||
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
|
from . import XboxData, XboxUpdateCoordinator
|
||||||
from .browse_media import build_item_response
|
from .browse_media import build_item_response
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
|
|
||||||
@ -63,29 +63,31 @@ XBOX_STATE_MAP = {
|
|||||||
|
|
||||||
async def async_setup_entry(hass, entry, async_add_entities):
|
async def async_setup_entry(hass, entry, async_add_entities):
|
||||||
"""Set up Xbox media_player from a config entry."""
|
"""Set up Xbox media_player from a config entry."""
|
||||||
client: XboxLiveClient = hass.data[DOMAIN][entry.entry_id]
|
client: XboxLiveClient = hass.data[DOMAIN][entry.entry_id]["client"]
|
||||||
consoles: SmartglassConsoleList = await client.smartglass.get_console_list()
|
consoles: SmartglassConsoleList = hass.data[DOMAIN][entry.entry_id]["consoles"]
|
||||||
_LOGGER.debug(
|
coordinator: XboxUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][
|
||||||
"Found %d consoles: %s",
|
"coordinator"
|
||||||
len(consoles.result),
|
]
|
||||||
consoles.dict(),
|
|
||||||
)
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
[XboxMediaPlayer(client, console) for console in consoles.result], True
|
[XboxMediaPlayer(client, console, coordinator) for console in consoles.result]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class XboxMediaPlayer(MediaPlayerEntity):
|
class XboxMediaPlayer(CoordinatorEntity, MediaPlayerEntity):
|
||||||
"""Representation of an Xbox device."""
|
"""Representation of an Xbox Media Player."""
|
||||||
|
|
||||||
def __init__(self, client: XboxLiveClient, console: SmartglassConsole) -> None:
|
def __init__(
|
||||||
"""Initialize the Plex device."""
|
self,
|
||||||
|
client: XboxLiveClient,
|
||||||
|
console: SmartglassConsole,
|
||||||
|
coordinator: XboxUpdateCoordinator,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the Xbox Media Player."""
|
||||||
|
super().__init__(coordinator)
|
||||||
self.client: XboxLiveClient = client
|
self.client: XboxLiveClient = client
|
||||||
self._console: SmartglassConsole = console
|
self._console: SmartglassConsole = console
|
||||||
|
|
||||||
self._console_status: SmartglassConsoleStatus = None
|
|
||||||
self._app_details: Optional[Product] = None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the device name."""
|
"""Return the device name."""
|
||||||
@ -96,12 +98,18 @@ class XboxMediaPlayer(MediaPlayerEntity):
|
|||||||
"""Console device ID."""
|
"""Console device ID."""
|
||||||
return self._console.id
|
return self._console.id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data(self) -> XboxData:
|
||||||
|
"""Return coordinator data for this console."""
|
||||||
|
return self.coordinator.data[self._console.id]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
"""State of the player."""
|
"""State of the player."""
|
||||||
if self._console_status.playback_state in XBOX_STATE_MAP:
|
status = self.data.status
|
||||||
return XBOX_STATE_MAP[self._console_status.playback_state]
|
if status.playback_state in XBOX_STATE_MAP:
|
||||||
return XBOX_STATE_MAP[self._console_status.power_state]
|
return XBOX_STATE_MAP[status.playback_state]
|
||||||
|
return XBOX_STATE_MAP[status.power_state]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self):
|
||||||
@ -109,33 +117,36 @@ class XboxMediaPlayer(MediaPlayerEntity):
|
|||||||
active_support = SUPPORT_XBOX
|
active_support = SUPPORT_XBOX
|
||||||
if self.state not in [STATE_PLAYING, STATE_PAUSED]:
|
if self.state not in [STATE_PLAYING, STATE_PAUSED]:
|
||||||
active_support &= ~SUPPORT_NEXT_TRACK & ~SUPPORT_PREVIOUS_TRACK
|
active_support &= ~SUPPORT_NEXT_TRACK & ~SUPPORT_PREVIOUS_TRACK
|
||||||
if not self._console_status.is_tv_configured:
|
if not self.data.status.is_tv_configured:
|
||||||
active_support &= ~SUPPORT_VOLUME_MUTE & ~SUPPORT_VOLUME_STEP
|
active_support &= ~SUPPORT_VOLUME_MUTE & ~SUPPORT_VOLUME_STEP
|
||||||
return active_support
|
return active_support
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_content_type(self):
|
def media_content_type(self):
|
||||||
"""Media content type."""
|
"""Media content type."""
|
||||||
if self._app_details and self._app_details.product_family == "Games":
|
app_details = self.data.app_details
|
||||||
|
if app_details and app_details.product_family == "Games":
|
||||||
return MEDIA_TYPE_GAME
|
return MEDIA_TYPE_GAME
|
||||||
return MEDIA_TYPE_APP
|
return MEDIA_TYPE_APP
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_title(self):
|
def media_title(self):
|
||||||
"""Title of current playing media."""
|
"""Title of current playing media."""
|
||||||
if not self._app_details:
|
app_details = self.data.app_details
|
||||||
|
if not app_details:
|
||||||
return None
|
return None
|
||||||
return (
|
return (
|
||||||
self._app_details.localized_properties[0].product_title
|
app_details.localized_properties[0].product_title
|
||||||
or self._app_details.localized_properties[0].short_title
|
or app_details.localized_properties[0].short_title
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def media_image_url(self):
|
def media_image_url(self):
|
||||||
"""Image url of current playing media."""
|
"""Image url of current playing media."""
|
||||||
if not self._app_details:
|
app_details = self.data.app_details
|
||||||
|
if not app_details:
|
||||||
return None
|
return None
|
||||||
image = _find_media_image(self._app_details.localized_properties[0].images)
|
image = _find_media_image(app_details.localized_properties[0].images)
|
||||||
|
|
||||||
if not image:
|
if not image:
|
||||||
return None
|
return None
|
||||||
@ -150,49 +161,6 @@ class XboxMediaPlayer(MediaPlayerEntity):
|
|||||||
"""If the image url is remotely accessible."""
|
"""If the image url is remotely accessible."""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def async_update(self) -> None:
|
|
||||||
"""Update Xbox state."""
|
|
||||||
status: SmartglassConsoleStatus = (
|
|
||||||
await self.client.smartglass.get_console_status(self._console.id)
|
|
||||||
)
|
|
||||||
|
|
||||||
_LOGGER.debug(
|
|
||||||
"%s status: %s",
|
|
||||||
self._console.name,
|
|
||||||
status.dict(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if status.focus_app_aumid:
|
|
||||||
if (
|
|
||||||
not self._console_status
|
|
||||||
or status.focus_app_aumid != self._console_status.focus_app_aumid
|
|
||||||
):
|
|
||||||
app_id = status.focus_app_aumid.split("!")[0]
|
|
||||||
id_type = AlternateIdType.PACKAGE_FAMILY_NAME
|
|
||||||
if app_id in SYSTEM_PFN_ID_MAP:
|
|
||||||
id_type = AlternateIdType.LEGACY_XBOX_PRODUCT_ID
|
|
||||||
app_id = SYSTEM_PFN_ID_MAP[app_id][id_type]
|
|
||||||
catalog_result = (
|
|
||||||
await self.client.catalog.get_product_from_alternate_id(
|
|
||||||
app_id, id_type
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if catalog_result and catalog_result.products:
|
|
||||||
self._app_details = catalog_result.products[0]
|
|
||||||
else:
|
|
||||||
self._app_details = None
|
|
||||||
else:
|
|
||||||
if self.media_title != "Home":
|
|
||||||
id_type = AlternateIdType.LEGACY_XBOX_PRODUCT_ID
|
|
||||||
catalog_result = (
|
|
||||||
await self.client.catalog.get_product_from_alternate_id(
|
|
||||||
HOME_APP_IDS[id_type], id_type
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self._app_details = catalog_result.products[0]
|
|
||||||
|
|
||||||
self._console_status = status
|
|
||||||
|
|
||||||
async def async_turn_on(self):
|
async def async_turn_on(self):
|
||||||
"""Turn the media player on."""
|
"""Turn the media player on."""
|
||||||
await self.client.smartglass.wake_up(self._console.id)
|
await self.client.smartglass.wake_up(self._console.id)
|
||||||
@ -237,7 +205,7 @@ class XboxMediaPlayer(MediaPlayerEntity):
|
|||||||
return await build_item_response(
|
return await build_item_response(
|
||||||
self.client,
|
self.client,
|
||||||
self._console.id,
|
self._console.id,
|
||||||
self._console_status.is_tv_configured,
|
self.data.status.is_tv_configured,
|
||||||
media_content_type,
|
media_content_type,
|
||||||
media_content_id,
|
media_content_id,
|
||||||
)
|
)
|
||||||
|
94
homeassistant/components/xbox/remote.py
Normal file
94
homeassistant/components/xbox/remote.py
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
"""Xbox Remote support."""
|
||||||
|
import asyncio
|
||||||
|
from typing import Any, Iterable
|
||||||
|
|
||||||
|
from xbox.webapi.api.client import XboxLiveClient
|
||||||
|
from xbox.webapi.api.provider.smartglass.models import (
|
||||||
|
InputKeyType,
|
||||||
|
PowerState,
|
||||||
|
SmartglassConsole,
|
||||||
|
SmartglassConsoleList,
|
||||||
|
)
|
||||||
|
|
||||||
|
from homeassistant.components.remote import (
|
||||||
|
ATTR_DELAY_SECS,
|
||||||
|
ATTR_NUM_REPEATS,
|
||||||
|
DEFAULT_DELAY_SECS,
|
||||||
|
RemoteEntity,
|
||||||
|
)
|
||||||
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
|
from . import XboxData, XboxUpdateCoordinator
|
||||||
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass, entry, async_add_entities):
|
||||||
|
"""Set up Xbox media_player from a config entry."""
|
||||||
|
client: XboxLiveClient = hass.data[DOMAIN][entry.entry_id]["client"]
|
||||||
|
consoles: SmartglassConsoleList = hass.data[DOMAIN][entry.entry_id]["consoles"]
|
||||||
|
coordinator: XboxUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][
|
||||||
|
"coordinator"
|
||||||
|
]
|
||||||
|
|
||||||
|
async_add_entities(
|
||||||
|
[XboxRemote(client, console, coordinator) for console in consoles.result]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class XboxRemote(CoordinatorEntity, RemoteEntity):
|
||||||
|
"""Representation of an Xbox remote."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
client: XboxLiveClient,
|
||||||
|
console: SmartglassConsole,
|
||||||
|
coordinator: XboxUpdateCoordinator,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the Xbox Media Player."""
|
||||||
|
super().__init__(coordinator)
|
||||||
|
self.client: XboxLiveClient = client
|
||||||
|
self._console: SmartglassConsole = console
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Return the device name."""
|
||||||
|
return f"{self._console.name} Remote"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
"""Console device ID."""
|
||||||
|
return self._console.id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data(self) -> XboxData:
|
||||||
|
"""Return coordinator data for this console."""
|
||||||
|
return self.coordinator.data[self._console.id]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_on(self):
|
||||||
|
"""Return True if device is on."""
|
||||||
|
return self.data.status.power_state == PowerState.On
|
||||||
|
|
||||||
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
|
"""Turn the Xbox on."""
|
||||||
|
await self.client.smartglass.wake_up(self._console.id)
|
||||||
|
|
||||||
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
|
"""Turn the Xbox off."""
|
||||||
|
await self.client.smartglass.turn_off(self._console.id)
|
||||||
|
|
||||||
|
async def async_send_command(self, command: Iterable[str], **kwargs: Any) -> None:
|
||||||
|
"""Send controller or text input to the Xbox."""
|
||||||
|
num_repeats = kwargs[ATTR_NUM_REPEATS]
|
||||||
|
delay = kwargs.get(ATTR_DELAY_SECS, DEFAULT_DELAY_SECS)
|
||||||
|
|
||||||
|
for _ in range(num_repeats):
|
||||||
|
for single_command in command:
|
||||||
|
try:
|
||||||
|
button = InputKeyType(single_command)
|
||||||
|
await self.client.smartglass.press_button(self._console.id, button)
|
||||||
|
except ValueError:
|
||||||
|
await self.client.smartglass.insert_text(
|
||||||
|
self._console.id, single_command
|
||||||
|
)
|
||||||
|
await asyncio.sleep(delay)
|
Loading…
x
Reference in New Issue
Block a user