1 """Base AndroidTV Entity."""
3 from __future__
import annotations
5 from collections.abc
import Awaitable, Callable, Coroutine
8 from typing
import Any, Concatenate
10 from androidtv.exceptions
import LockNotAcquiredException
26 ADB_PYTHON_EXCEPTIONS,
31 from .const
import DEVICE_ANDROIDTV, DOMAIN
33 PREFIX_ANDROIDTV =
"Android TV"
34 PREFIX_FIRETV =
"Fire TV"
36 _LOGGER = logging.getLogger(__name__)
38 type _FuncType[_T, **_P, _R] = Callable[Concatenate[_T, _P], Awaitable[_R]]
39 type _ReturnFuncType[_T, **_P, _R] = Callable[
40 Concatenate[_T, _P], Coroutine[Any, Any, _R |
None]
44 def adb_decorator[_ADBDeviceT: AndroidTVEntity, **_P, _R](
45 override_available: bool =
False,
46 ) -> Callable[[_FuncType[_ADBDeviceT, _P, _R]], _ReturnFuncType[_ADBDeviceT, _P, _R]]:
47 """Wrap ADB methods and catch exceptions.
49 Allows for overriding the available status of the ADB connection via the
50 `override_available` parameter.
54 func: _FuncType[_ADBDeviceT, _P, _R],
55 ) -> _ReturnFuncType[_ADBDeviceT, _P, _R]:
56 """Wrap the provided ADB method and catch exceptions."""
58 @functools.wraps(func)
59 async
def _adb_exception_catcher(
60 self: _ADBDeviceT, *args: _P.args, **kwargs: _P.kwargs
62 """Call an ADB-related method and catch exceptions."""
63 if not self.available
and not override_available:
67 return await func(self, *args, **kwargs)
68 except LockNotAcquiredException:
72 "ADB command %s not executed because the connection is"
78 except self.exceptions
as err:
82 "Failed to execute an ADB command. ADB connection re-"
83 "establishing attempt in the next update. Error: %s"
88 await self.aftv.adb_close()
89 self._attr_available =
False
91 except ServiceValidationError:
94 except Exception
as err:
100 "Unexpected exception executing an ADB command. ADB connection"
101 " re-establishing attempt in the next update. Error: %s"
106 await self.aftv.adb_close()
107 self._attr_available =
False
110 return _adb_exception_catcher
112 return _adb_decorator
116 """Defines a base AndroidTV entity."""
118 _attr_has_entity_name =
True
120 def __init__(self, entry: AndroidTVConfigEntry) ->
None:
121 """Initialize the AndroidTV base entity."""
122 self.
aftvaftv = entry.runtime_data.aftv
126 device_class = self.
aftvaftv.DEVICE_CLASS
128 PREFIX_ANDROIDTV
if device_class == DEVICE_ANDROIDTV
else PREFIX_FIRETV
131 device_name = entry.data.get(
132 CONF_NAME, f
"{device_type} {entry.data[CONF_HOST]}"
134 info = self.
aftvaftv.device_properties
135 model = info.get(ATTR_MODEL)
137 model=f
"{model} ({device_type})" if model
else device_type,
142 if manufacturer := info.get(ATTR_MANUFACTURER):
144 if sw_version := info.get(ATTR_SW_VERSION):
147 self.
_attr_device_info_attr_device_info[ATTR_CONNECTIONS] = {(CONNECTION_NETWORK_MAC, mac)}
150 if not self.
aftvaftv.adb_server_ip:
155 self.
exceptionsexceptions = ADB_TCP_EXCEPTIONS
None __init__(self, AndroidTVConfigEntry entry)
str|None get_androidtv_mac(dict[str, Any] dev_props)