Remove deprecated yaml config from androidtv (#68339)
parent
b2d7fe15bb
commit
a11a5366be
|
@ -1,13 +1,11 @@
|
|||
"""Support for functionality to interact with Android TV/Fire TV devices."""
|
||||
import logging
|
||||
import os
|
||||
|
||||
from adb_shell.auth.keygen import keygen
|
||||
from androidtv.adb_manager.adb_manager_sync import ADBPythonSync
|
||||
from androidtv.setup_async import setup
|
||||
|
||||
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_CLASS,
|
||||
CONF_HOST,
|
||||
|
@ -17,7 +15,6 @@ from homeassistant.const import (
|
|||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers.device_registry import format_mac
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.storage import STORAGE_DIR
|
||||
|
@ -35,7 +32,6 @@ from .const import (
|
|||
DEVICE_FIRETV,
|
||||
DOMAIN,
|
||||
PROP_ETHMAC,
|
||||
PROP_SERIALNO,
|
||||
PROP_WIFIMAC,
|
||||
SIGNAL_CONFIG_ENTITY,
|
||||
)
|
||||
|
@ -45,8 +41,6 @@ RELOAD_OPTIONS = [CONF_STATE_DETECTION_RULES]
|
|||
|
||||
_INVALID_MACS = {"ff:ff:ff:ff:ff:ff"}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_androidtv_mac(dev_props):
|
||||
"""Return formatted mac from device properties."""
|
||||
|
@ -116,30 +110,6 @@ async def async_connect_androidtv(
|
|||
return aftv, None
|
||||
|
||||
|
||||
def _migrate_aftv_entity(hass, aftv, entry_unique_id):
|
||||
"""Migrate a entity to new unique id."""
|
||||
entity_reg = er.async_get(hass)
|
||||
|
||||
entity_unique_id = entry_unique_id
|
||||
if entity_reg.async_get_entity_id(MP_DOMAIN, DOMAIN, entity_unique_id):
|
||||
# entity already exist, nothing to do
|
||||
return
|
||||
|
||||
if not (old_unique_id := aftv.device_properties.get(PROP_SERIALNO)):
|
||||
# serial no not found, exit
|
||||
return
|
||||
|
||||
migr_entity = entity_reg.async_get_entity_id(MP_DOMAIN, DOMAIN, old_unique_id)
|
||||
if not migr_entity:
|
||||
# old entity not found, exit
|
||||
return
|
||||
|
||||
try:
|
||||
entity_reg.async_update_entity(migr_entity, new_unique_id=entity_unique_id)
|
||||
except ValueError as exp:
|
||||
_LOGGER.warning("Migration of old entity failed: %s", exp)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the Android TV integration."""
|
||||
return True
|
||||
|
@ -155,10 +125,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
if not aftv:
|
||||
raise ConfigEntryNotReady(error_message)
|
||||
|
||||
# migrate existing entity to new unique ID
|
||||
if entry.source == SOURCE_IMPORT:
|
||||
_migrate_aftv_entity(hass, aftv, entry.unique_id)
|
||||
|
||||
async def async_close_connection(event):
|
||||
"""Close Android TV connection on HA Stop."""
|
||||
await aftv.adb_close()
|
||||
|
|
|
@ -20,7 +20,6 @@ from .const import (
|
|||
CONF_APPS,
|
||||
CONF_EXCLUDE_UNNAMED_APPS,
|
||||
CONF_GET_SOURCES,
|
||||
CONF_MIGRATION_OPTIONS,
|
||||
CONF_SCREENCAP,
|
||||
CONF_STATE_DETECTION_RULES,
|
||||
CONF_TURN_OFF_COMMAND,
|
||||
|
@ -72,10 +71,6 @@ class AndroidTVFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
VERSION = 1
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize AndroidTV config flow."""
|
||||
self._import_options = None
|
||||
|
||||
@callback
|
||||
def _show_setup_form(self, user_input=None, error=None):
|
||||
"""Show the setup form to the user."""
|
||||
|
@ -171,24 +166,11 @@ class AndroidTVFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
return self.async_create_entry(
|
||||
title=user_input.get(CONF_NAME) or host,
|
||||
data=user_input,
|
||||
options=self._import_options,
|
||||
)
|
||||
|
||||
user_input = user_input or {}
|
||||
return self._show_setup_form(user_input, error)
|
||||
|
||||
async def async_step_import(self, import_config=None):
|
||||
"""Import a config entry."""
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data[CONF_HOST] == import_config[CONF_HOST]:
|
||||
_LOGGER.warning(
|
||||
"Host [%s] already configured. This yaml configuration has already been imported. Please remove it",
|
||||
import_config[CONF_HOST],
|
||||
)
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._import_options = import_config.pop(CONF_MIGRATION_OPTIONS, None)
|
||||
return await self.async_step_user(import_config)
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
def async_get_options_flow(config_entry):
|
||||
|
|
|
@ -10,7 +10,6 @@ CONF_ADBKEY = "adbkey"
|
|||
CONF_APPS = "apps"
|
||||
CONF_EXCLUDE_UNNAMED_APPS = "exclude_unnamed_apps"
|
||||
CONF_GET_SOURCES = "get_sources"
|
||||
CONF_MIGRATION_OPTIONS = "migration_options"
|
||||
CONF_SCREENCAP = "screencap"
|
||||
CONF_STATE_DETECTION_RULES = "state_detection_rules"
|
||||
CONF_TURN_OFF_COMMAND = "turn_off_command"
|
||||
|
@ -28,7 +27,6 @@ DEVICE_FIRETV = "firetv"
|
|||
DEVICE_CLASSES = [DEFAULT_DEVICE_CLASS, DEVICE_ANDROIDTV, DEVICE_FIRETV]
|
||||
|
||||
PROP_ETHMAC = "ethmac"
|
||||
PROP_SERIALNO = "serialno"
|
||||
PROP_WIFIMAC = "wifimac"
|
||||
|
||||
SIGNAL_CONFIG_ENTITY = "androidtv_config"
|
||||
|
|
|
@ -12,13 +12,12 @@ from adb_shell.exceptions import (
|
|||
InvalidResponseError,
|
||||
TcpTimeoutException,
|
||||
)
|
||||
from androidtv import ha_state_detection_rules_validator
|
||||
from androidtv.constants import APPS, KEYS
|
||||
from androidtv.exceptions import LockNotAcquiredException
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import persistent_notification
|
||||
from homeassistant.components.media_player import PLATFORM_SCHEMA, MediaPlayerEntity
|
||||
from homeassistant.components.media_player import MediaPlayerEntity
|
||||
from homeassistant.components.media_player.const import (
|
||||
SUPPORT_NEXT_TRACK,
|
||||
SUPPORT_PAUSE,
|
||||
|
@ -32,17 +31,14 @@ from homeassistant.components.media_player.const import (
|
|||
SUPPORT_VOLUME_SET,
|
||||
SUPPORT_VOLUME_STEP,
|
||||
)
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_COMMAND,
|
||||
ATTR_CONNECTIONS,
|
||||
ATTR_MANUFACTURER,
|
||||
ATTR_MODEL,
|
||||
ATTR_SW_VERSION,
|
||||
CONF_DEVICE_CLASS,
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
CONF_PORT,
|
||||
STATE_IDLE,
|
||||
STATE_OFF,
|
||||
STATE_PAUSED,
|
||||
|
@ -55,31 +51,21 @@ from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
|
|||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from . import get_androidtv_mac
|
||||
from .const import (
|
||||
ANDROID_DEV,
|
||||
ANDROID_DEV_OPT,
|
||||
CONF_ADB_SERVER_IP,
|
||||
CONF_ADB_SERVER_PORT,
|
||||
CONF_ADBKEY,
|
||||
CONF_APPS,
|
||||
CONF_EXCLUDE_UNNAMED_APPS,
|
||||
CONF_GET_SOURCES,
|
||||
CONF_MIGRATION_OPTIONS,
|
||||
CONF_SCREENCAP,
|
||||
CONF_STATE_DETECTION_RULES,
|
||||
CONF_TURN_OFF_COMMAND,
|
||||
CONF_TURN_ON_COMMAND,
|
||||
DEFAULT_ADB_SERVER_PORT,
|
||||
DEFAULT_DEVICE_CLASS,
|
||||
DEFAULT_EXCLUDE_UNNAMED_APPS,
|
||||
DEFAULT_GET_SOURCES,
|
||||
DEFAULT_PORT,
|
||||
DEFAULT_SCREENCAP,
|
||||
DEVICE_ANDROIDTV,
|
||||
DEVICE_CLASSES,
|
||||
DOMAIN,
|
||||
SIGNAL_CONFIG_ENTITY,
|
||||
)
|
||||
|
@ -123,34 +109,6 @@ SERVICE_UPLOAD = "upload"
|
|||
|
||||
DEFAULT_NAME = "Android TV"
|
||||
|
||||
# Deprecated in Home Assistant 2022.2
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_DEVICE_CLASS, default=DEFAULT_DEVICE_CLASS): vol.In(
|
||||
DEVICE_CLASSES
|
||||
),
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
||||
vol.Optional(CONF_ADBKEY): cv.isfile,
|
||||
vol.Optional(CONF_ADB_SERVER_IP): cv.string,
|
||||
vol.Optional(CONF_ADB_SERVER_PORT, default=DEFAULT_ADB_SERVER_PORT): cv.port,
|
||||
vol.Optional(CONF_GET_SOURCES, default=DEFAULT_GET_SOURCES): cv.boolean,
|
||||
vol.Optional(CONF_APPS, default={}): vol.Schema(
|
||||
{cv.string: vol.Any(cv.string, None)}
|
||||
),
|
||||
vol.Optional(CONF_TURN_ON_COMMAND): cv.string,
|
||||
vol.Optional(CONF_TURN_OFF_COMMAND): cv.string,
|
||||
vol.Optional(CONF_STATE_DETECTION_RULES, default={}): vol.Schema(
|
||||
{cv.string: ha_state_detection_rules_validator(vol.Invalid)}
|
||||
),
|
||||
vol.Optional(
|
||||
CONF_EXCLUDE_UNNAMED_APPS, default=DEFAULT_EXCLUDE_UNNAMED_APPS
|
||||
): cv.boolean,
|
||||
vol.Optional(CONF_SCREENCAP, default=DEFAULT_SCREENCAP): cv.boolean,
|
||||
}
|
||||
)
|
||||
|
||||
# Translate from `AndroidTV` / `FireTV` reported state to HA state.
|
||||
ANDROIDTV_STATES = {
|
||||
"off": STATE_OFF,
|
||||
|
@ -161,53 +119,6 @@ ANDROIDTV_STATES = {
|
|||
}
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the Android TV / Fire TV platform."""
|
||||
|
||||
host = config[CONF_HOST]
|
||||
|
||||
# get main data
|
||||
config_data = {
|
||||
CONF_HOST: host,
|
||||
CONF_DEVICE_CLASS: config.get(CONF_DEVICE_CLASS, DEFAULT_DEVICE_CLASS),
|
||||
CONF_PORT: config.get(CONF_PORT, DEFAULT_PORT),
|
||||
}
|
||||
for key in (CONF_ADBKEY, CONF_ADB_SERVER_IP, CONF_ADB_SERVER_PORT, CONF_NAME):
|
||||
if key in config:
|
||||
config_data[key] = config[key]
|
||||
|
||||
# get options
|
||||
config_options = {
|
||||
key: config[key]
|
||||
for key in (
|
||||
CONF_APPS,
|
||||
CONF_EXCLUDE_UNNAMED_APPS,
|
||||
CONF_GET_SOURCES,
|
||||
CONF_SCREENCAP,
|
||||
CONF_STATE_DETECTION_RULES,
|
||||
CONF_TURN_OFF_COMMAND,
|
||||
CONF_TURN_ON_COMMAND,
|
||||
)
|
||||
if key in config
|
||||
}
|
||||
|
||||
# save option to use with entry
|
||||
if config_options:
|
||||
config_data[CONF_MIGRATION_OPTIONS] = config_options
|
||||
|
||||
# Launch config entries setup
|
||||
hass.async_create_task(
|
||||
hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_IMPORT}, data=config_data
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: ConfigEntry,
|
||||
|
@ -217,10 +128,7 @@ async def async_setup_entry(
|
|||
aftv = hass.data[DOMAIN][entry.entry_id][ANDROID_DEV]
|
||||
device_class = aftv.DEVICE_CLASS
|
||||
device_type = "Android TV" if device_class == DEVICE_ANDROIDTV else "Fire TV"
|
||||
if CONF_NAME in entry.data:
|
||||
device_name = entry.data[CONF_NAME]
|
||||
else:
|
||||
device_name = f"{device_type} {entry.data[CONF_HOST]}"
|
||||
device_name = f"{device_type} {entry.data[CONF_HOST]}"
|
||||
|
||||
device_args = [
|
||||
aftv,
|
||||
|
|
|
@ -33,10 +33,8 @@ from homeassistant.components.androidtv.const import (
|
|||
PROP_ETHMAC,
|
||||
PROP_WIFIMAC,
|
||||
)
|
||||
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER
|
||||
from homeassistant.const import CONF_DEVICE_CLASS, CONF_HOST, CONF_PLATFORM, CONF_PORT
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.config_entries import SOURCE_USER
|
||||
from homeassistant.const import CONF_DEVICE_CLASS, CONF_HOST, CONF_PORT
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.components.androidtv.patchers import isfile
|
||||
|
@ -132,28 +130,6 @@ async def test_user(hass, config, eth_mac, wifi_mac):
|
|||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_import(hass):
|
||||
"""Test import config."""
|
||||
|
||||
# test with all provided
|
||||
with patch(
|
||||
CONNECT_METHOD,
|
||||
return_value=(MockConfigDevice(), None),
|
||||
), PATCH_SETUP_ENTRY as mock_setup_entry, PATCH_GET_HOST_IP:
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_IMPORT},
|
||||
data=CONFIG_PYTHON_ADB,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result["title"] == HOST
|
||||
assert result["data"] == CONFIG_PYTHON_ADB
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_user_adbkey(hass):
|
||||
"""Test user step with adbkey file."""
|
||||
config_data = CONFIG_PYTHON_ADB.copy()
|
||||
|
@ -178,25 +154,6 @@ async def test_user_adbkey(hass):
|
|||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_import_data(hass):
|
||||
"""Test import from configuration file."""
|
||||
config_data = CONFIG_PYTHON_ADB.copy()
|
||||
config_data[CONF_PLATFORM] = DOMAIN
|
||||
config_data[CONF_ADBKEY] = ADBKEY
|
||||
config_data[CONF_TURN_OFF_COMMAND] = "off"
|
||||
platform_data = {MP_DOMAIN: config_data}
|
||||
|
||||
with patch(
|
||||
CONNECT_METHOD,
|
||||
return_value=(MockConfigDevice(), None),
|
||||
), PATCH_SETUP_ENTRY as mock_setup_entry, PATCH_GET_HOST_IP, PATCH_ISFILE, PATCH_ACCESS:
|
||||
|
||||
assert await async_setup_component(hass, MP_DOMAIN, platform_data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_error_both_key_server(hass):
|
||||
"""Test we abort if both adb key and server are provided."""
|
||||
config_data = CONFIG_ADB_SERVER.copy()
|
||||
|
@ -317,23 +274,6 @@ async def test_abort_if_host_exist(hass):
|
|||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_abort_import_if_host_exist(hass):
|
||||
"""Test we abort if component is already setup."""
|
||||
MockConfigEntry(
|
||||
domain=DOMAIN, data=CONFIG_ADB_SERVER, unique_id=ETH_MAC
|
||||
).add_to_hass(hass)
|
||||
|
||||
# Should fail, same Host in entry
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": SOURCE_IMPORT},
|
||||
data=CONFIG_ADB_SERVER,
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_abort_if_unique_exist(hass):
|
||||
"""Test we abort if component is already setup."""
|
||||
config_data = CONFIG_ADB_SERVER.copy()
|
||||
|
|
Loading…
Reference in New Issue