parent
8337d4613e
commit
772df02cce
|
@ -6,6 +6,13 @@ import os
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from adb_shell.auth.keygen import keygen
|
from adb_shell.auth.keygen import keygen
|
||||||
|
from adb_shell.exceptions import (
|
||||||
|
AdbTimeoutError,
|
||||||
|
InvalidChecksumError,
|
||||||
|
InvalidCommandError,
|
||||||
|
InvalidResponseError,
|
||||||
|
TcpTimeoutException,
|
||||||
|
)
|
||||||
from androidtv.adb_manager.adb_manager_sync import ADBPythonSync, PythonRSASigner
|
from androidtv.adb_manager.adb_manager_sync import ADBPythonSync, PythonRSASigner
|
||||||
from androidtv.setup_async import (
|
from androidtv.setup_async import (
|
||||||
AndroidTVAsync,
|
AndroidTVAsync,
|
||||||
|
@ -43,6 +50,18 @@ from .const import (
|
||||||
SIGNAL_CONFIG_ENTITY,
|
SIGNAL_CONFIG_ENTITY,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ADB_PYTHON_EXCEPTIONS: tuple = (
|
||||||
|
AdbTimeoutError,
|
||||||
|
BrokenPipeError,
|
||||||
|
ConnectionResetError,
|
||||||
|
ValueError,
|
||||||
|
InvalidChecksumError,
|
||||||
|
InvalidCommandError,
|
||||||
|
InvalidResponseError,
|
||||||
|
TcpTimeoutException,
|
||||||
|
)
|
||||||
|
ADB_TCP_EXCEPTIONS: tuple = (ConnectionResetError, RuntimeError)
|
||||||
|
|
||||||
PLATFORMS = [Platform.MEDIA_PLAYER]
|
PLATFORMS = [Platform.MEDIA_PLAYER]
|
||||||
RELOAD_OPTIONS = [CONF_STATE_DETECTION_RULES]
|
RELOAD_OPTIONS = [CONF_STATE_DETECTION_RULES]
|
||||||
|
|
||||||
|
@ -132,9 +151,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up Android TV platform."""
|
"""Set up Android TV platform."""
|
||||||
|
|
||||||
state_det_rules = entry.options.get(CONF_STATE_DETECTION_RULES)
|
state_det_rules = entry.options.get(CONF_STATE_DETECTION_RULES)
|
||||||
aftv, error_message = await async_connect_androidtv(
|
if CONF_ADB_SERVER_IP not in entry.data:
|
||||||
hass, entry.data, state_detection_rules=state_det_rules
|
exceptions = ADB_PYTHON_EXCEPTIONS
|
||||||
)
|
else:
|
||||||
|
exceptions = ADB_TCP_EXCEPTIONS
|
||||||
|
|
||||||
|
try:
|
||||||
|
aftv, error_message = await async_connect_androidtv(
|
||||||
|
hass, entry.data, state_detection_rules=state_det_rules
|
||||||
|
)
|
||||||
|
except exceptions as exc:
|
||||||
|
raise ConfigEntryNotReady(exc) from exc
|
||||||
|
|
||||||
if not aftv:
|
if not aftv:
|
||||||
raise ConfigEntryNotReady(error_message)
|
raise ConfigEntryNotReady(error_message)
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,6 @@ import functools
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Concatenate, ParamSpec, TypeVar
|
from typing import Any, Concatenate, ParamSpec, TypeVar
|
||||||
|
|
||||||
from adb_shell.exceptions import (
|
|
||||||
AdbTimeoutError,
|
|
||||||
InvalidChecksumError,
|
|
||||||
InvalidCommandError,
|
|
||||||
InvalidResponseError,
|
|
||||||
TcpTimeoutException,
|
|
||||||
)
|
|
||||||
from androidtv.constants import APPS, KEYS
|
from androidtv.constants import APPS, KEYS
|
||||||
from androidtv.exceptions import LockNotAcquiredException
|
from androidtv.exceptions import LockNotAcquiredException
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
@ -42,7 +35,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity import DeviceInfo
|
from homeassistant.helpers.entity import DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import get_androidtv_mac
|
from . import ADB_PYTHON_EXCEPTIONS, ADB_TCP_EXCEPTIONS, get_androidtv_mac
|
||||||
from .const import (
|
from .const import (
|
||||||
ANDROID_DEV,
|
ANDROID_DEV,
|
||||||
ANDROID_DEV_OPT,
|
ANDROID_DEV_OPT,
|
||||||
|
@ -252,19 +245,10 @@ class ADBDevice(MediaPlayerEntity):
|
||||||
# ADB exceptions to catch
|
# ADB exceptions to catch
|
||||||
if not aftv.adb_server_ip:
|
if not aftv.adb_server_ip:
|
||||||
# Using "adb_shell" (Python ADB implementation)
|
# Using "adb_shell" (Python ADB implementation)
|
||||||
self.exceptions = (
|
self.exceptions = ADB_PYTHON_EXCEPTIONS
|
||||||
AdbTimeoutError,
|
|
||||||
BrokenPipeError,
|
|
||||||
ConnectionResetError,
|
|
||||||
ValueError,
|
|
||||||
InvalidChecksumError,
|
|
||||||
InvalidCommandError,
|
|
||||||
InvalidResponseError,
|
|
||||||
TcpTimeoutException,
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
# Using "pure-python-adb" (communicate with ADB server)
|
# Using "pure-python-adb" (communicate with ADB server)
|
||||||
self.exceptions = (ConnectionResetError, RuntimeError)
|
self.exceptions = ADB_TCP_EXCEPTIONS
|
||||||
|
|
||||||
# Property attributes
|
# Property attributes
|
||||||
self._attr_extra_state_attributes = {
|
self._attr_extra_state_attributes = {
|
||||||
|
|
|
@ -111,7 +111,7 @@ def patch_connect(success):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def patch_shell(response=None, error=False, mac_eth=False):
|
def patch_shell(response=None, error=False, mac_eth=False, exc=None):
|
||||||
"""Mock the `AdbDeviceTcpAsyncFake.shell` and `DeviceAsyncFake.shell` methods."""
|
"""Mock the `AdbDeviceTcpAsyncFake.shell` and `DeviceAsyncFake.shell` methods."""
|
||||||
|
|
||||||
async def shell_success(self, cmd, *args, **kwargs):
|
async def shell_success(self, cmd, *args, **kwargs):
|
||||||
|
@ -128,7 +128,7 @@ def patch_shell(response=None, error=False, mac_eth=False):
|
||||||
async def shell_fail_python(self, cmd, *args, **kwargs):
|
async def shell_fail_python(self, cmd, *args, **kwargs):
|
||||||
"""Mock the `AdbDeviceTcpAsyncFake.shell` method when it fails."""
|
"""Mock the `AdbDeviceTcpAsyncFake.shell` method when it fails."""
|
||||||
self.shell_cmd = cmd
|
self.shell_cmd = cmd
|
||||||
raise ValueError
|
raise exc or ValueError
|
||||||
|
|
||||||
async def shell_fail_server(self, cmd):
|
async def shell_fail_server(self, cmd):
|
||||||
"""Mock the `DeviceAsyncFake.shell` method when it fails."""
|
"""Mock the `DeviceAsyncFake.shell` method when it fails."""
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import logging
|
import logging
|
||||||
from unittest.mock import Mock, patch
|
from unittest.mock import Mock, patch
|
||||||
|
|
||||||
|
from adb_shell.exceptions import TcpTimeoutException as AdbShellTimeoutException
|
||||||
from androidtv.constants import APPS as ANDROIDTV_APPS, KEYS
|
from androidtv.constants import APPS as ANDROIDTV_APPS, KEYS
|
||||||
from androidtv.exceptions import LockNotAcquiredException
|
from androidtv.exceptions import LockNotAcquiredException
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -538,25 +539,28 @@ async def test_select_source_firetv(hass, source, expected_arg, method_patch):
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"config",
|
["config", "connect"],
|
||||||
[
|
[
|
||||||
CONFIG_ANDROIDTV_DEFAULT,
|
(CONFIG_ANDROIDTV_DEFAULT, False),
|
||||||
CONFIG_FIRETV_DEFAULT,
|
(CONFIG_FIRETV_DEFAULT, False),
|
||||||
|
(CONFIG_ANDROIDTV_DEFAULT, True),
|
||||||
|
(CONFIG_FIRETV_DEFAULT, True),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_setup_fail(hass, config):
|
async def test_setup_fail(hass, config, connect):
|
||||||
"""Test that the entity is not created when the ADB connection is not established."""
|
"""Test that the entity is not created when the ADB connection is not established."""
|
||||||
patch_key, entity_id, config_entry = _setup(config)
|
patch_key, entity_id, config_entry = _setup(config)
|
||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
with patchers.patch_connect(False)[patch_key], patchers.patch_shell(
|
with patchers.patch_connect(connect)[patch_key], patchers.patch_shell(
|
||||||
SHELL_RESPONSE_OFF
|
SHELL_RESPONSE_OFF, error=True, exc=AdbShellTimeoutException
|
||||||
)[patch_key]:
|
)[patch_key]:
|
||||||
assert await hass.config_entries.async_setup(config_entry.entry_id) is False
|
assert await hass.config_entries.async_setup(config_entry.entry_id) is False
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
await async_update_entity(hass, entity_id)
|
await async_update_entity(hass, entity_id)
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
|
assert config_entry.state == ConfigEntryState.SETUP_RETRY
|
||||||
assert state is None
|
assert state is None
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue