mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Fix kodi media_player unavailable at start (#41714)
This commit is contained in:
parent
6a5546afc1
commit
212fb572e1
@ -15,7 +15,6 @@ from homeassistant.const import (
|
|||||||
EVENT_HOMEASSISTANT_STOP,
|
EVENT_HOMEASSISTANT_STOP,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
@ -23,7 +22,6 @@ from .const import (
|
|||||||
DATA_CONNECTION,
|
DATA_CONNECTION,
|
||||||
DATA_KODI,
|
DATA_KODI,
|
||||||
DATA_REMOVE_LISTENER,
|
DATA_REMOVE_LISTENER,
|
||||||
DATA_VERSION,
|
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,13 +46,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
entry.data[CONF_SSL],
|
entry.data[CONF_SSL],
|
||||||
session=async_get_clientsession(hass),
|
session=async_get_clientsession(hass),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
kodi = Kodi(conn)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await conn.connect()
|
await conn.connect()
|
||||||
kodi = Kodi(conn)
|
except CannotConnectError:
|
||||||
await kodi.ping()
|
pass
|
||||||
raw_version = (await kodi.get_application_properties(["version"]))["version"]
|
|
||||||
except CannotConnectError as error:
|
|
||||||
raise ConfigEntryNotReady from error
|
|
||||||
except InvalidAuthError as error:
|
except InvalidAuthError as error:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Login to %s failed: [%s]",
|
"Login to %s failed: [%s]",
|
||||||
@ -68,12 +66,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
|
|
||||||
remove_stop_listener = hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _close)
|
remove_stop_listener = hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, _close)
|
||||||
|
|
||||||
version = f"{raw_version['major']}.{raw_version['minor']}"
|
|
||||||
hass.data[DOMAIN][entry.entry_id] = {
|
hass.data[DOMAIN][entry.entry_id] = {
|
||||||
DATA_CONNECTION: conn,
|
DATA_CONNECTION: conn,
|
||||||
DATA_KODI: kodi,
|
DATA_KODI: kodi,
|
||||||
DATA_REMOVE_LISTENER: remove_stop_listener,
|
DATA_REMOVE_LISTENER: remove_stop_listener,
|
||||||
DATA_VERSION: version,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for component in PLATFORMS:
|
for component in PLATFORMS:
|
||||||
|
@ -6,7 +6,6 @@ CONF_WS_PORT = "ws_port"
|
|||||||
DATA_CONNECTION = "connection"
|
DATA_CONNECTION = "connection"
|
||||||
DATA_KODI = "kodi"
|
DATA_KODI = "kodi"
|
||||||
DATA_REMOVE_LISTENER = "remove_listener"
|
DATA_REMOVE_LISTENER = "remove_listener"
|
||||||
DATA_VERSION = "version"
|
|
||||||
|
|
||||||
DEFAULT_PORT = 8080
|
DEFAULT_PORT = 8080
|
||||||
DEFAULT_SSL = False
|
DEFAULT_SSL = False
|
||||||
|
@ -48,13 +48,18 @@ from homeassistant.const import (
|
|||||||
CONF_SSL,
|
CONF_SSL,
|
||||||
CONF_TIMEOUT,
|
CONF_TIMEOUT,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
|
EVENT_HOMEASSISTANT_STARTED,
|
||||||
STATE_IDLE,
|
STATE_IDLE,
|
||||||
STATE_OFF,
|
STATE_OFF,
|
||||||
STATE_PAUSED,
|
STATE_PAUSED,
|
||||||
STATE_PLAYING,
|
STATE_PLAYING,
|
||||||
)
|
)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import CoreState, callback
|
||||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
from homeassistant.helpers import (
|
||||||
|
config_validation as cv,
|
||||||
|
device_registry,
|
||||||
|
entity_platform,
|
||||||
|
)
|
||||||
from homeassistant.helpers.event import async_track_time_interval
|
from homeassistant.helpers.event import async_track_time_interval
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
@ -63,7 +68,6 @@ from .const import (
|
|||||||
CONF_WS_PORT,
|
CONF_WS_PORT,
|
||||||
DATA_CONNECTION,
|
DATA_CONNECTION,
|
||||||
DATA_KODI,
|
DATA_KODI,
|
||||||
DATA_VERSION,
|
|
||||||
DEFAULT_PORT,
|
DEFAULT_PORT,
|
||||||
DEFAULT_SSL,
|
DEFAULT_SSL,
|
||||||
DEFAULT_TIMEOUT,
|
DEFAULT_TIMEOUT,
|
||||||
@ -91,7 +95,7 @@ DEPRECATED_TURN_OFF_ACTIONS = {
|
|||||||
"shutdown": "System.Shutdown",
|
"shutdown": "System.Shutdown",
|
||||||
}
|
}
|
||||||
|
|
||||||
WEBSOCKET_WATCHDOG_INTERVAL = timedelta(minutes=3)
|
WEBSOCKET_WATCHDOG_INTERVAL = timedelta(seconds=10)
|
||||||
|
|
||||||
# https://github.com/xbmc/xbmc/blob/master/xbmc/media/MediaType.h
|
# https://github.com/xbmc/xbmc/blob/master/xbmc/media/MediaType.h
|
||||||
MEDIA_TYPES = {
|
MEDIA_TYPES = {
|
||||||
@ -229,14 +233,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
|
|
||||||
data = hass.data[DOMAIN][config_entry.entry_id]
|
data = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
connection = data[DATA_CONNECTION]
|
connection = data[DATA_CONNECTION]
|
||||||
version = data[DATA_VERSION]
|
|
||||||
kodi = data[DATA_KODI]
|
kodi = data[DATA_KODI]
|
||||||
name = config_entry.data[CONF_NAME]
|
name = config_entry.data[CONF_NAME]
|
||||||
uid = config_entry.unique_id
|
uid = config_entry.unique_id
|
||||||
if uid is None:
|
if uid is None:
|
||||||
uid = config_entry.entry_id
|
uid = config_entry.entry_id
|
||||||
|
|
||||||
entity = KodiEntity(connection, kodi, name, uid, version)
|
entity = KodiEntity(connection, kodi, name, uid)
|
||||||
async_add_entities([entity])
|
async_add_entities([entity])
|
||||||
|
|
||||||
|
|
||||||
@ -264,13 +267,12 @@ def cmd(func):
|
|||||||
class KodiEntity(MediaPlayerEntity):
|
class KodiEntity(MediaPlayerEntity):
|
||||||
"""Representation of a XBMC/Kodi device."""
|
"""Representation of a XBMC/Kodi device."""
|
||||||
|
|
||||||
def __init__(self, connection, kodi, name, uid, version):
|
def __init__(self, connection, kodi, name, uid):
|
||||||
"""Initialize the Kodi entity."""
|
"""Initialize the Kodi entity."""
|
||||||
self._connection = connection
|
self._connection = connection
|
||||||
self._kodi = kodi
|
self._kodi = kodi
|
||||||
self._name = name
|
self._name = name
|
||||||
self._unique_id = uid
|
self._unique_id = uid
|
||||||
self._version = version
|
|
||||||
self._players = None
|
self._players = None
|
||||||
self._properties = {}
|
self._properties = {}
|
||||||
self._item = {}
|
self._item = {}
|
||||||
@ -347,7 +349,6 @@ class KodiEntity(MediaPlayerEntity):
|
|||||||
"identifiers": {(DOMAIN, self.unique_id)},
|
"identifiers": {(DOMAIN, self.unique_id)},
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
"manufacturer": "Kodi",
|
"manufacturer": "Kodi",
|
||||||
"sw_version": self._version,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -370,27 +371,43 @@ class KodiEntity(MediaPlayerEntity):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if self._connection.connected:
|
if self._connection.connected:
|
||||||
self._on_ws_connected()
|
await self._on_ws_connected()
|
||||||
|
|
||||||
self.async_on_remove(
|
async def start_watchdog(event=None):
|
||||||
async_track_time_interval(
|
"""Start websocket watchdog."""
|
||||||
self.hass,
|
await self._async_connect_websocket_if_disconnected()
|
||||||
self._async_connect_websocket_if_disconnected,
|
self.async_on_remove(
|
||||||
WEBSOCKET_WATCHDOG_INTERVAL,
|
async_track_time_interval(
|
||||||
|
self.hass,
|
||||||
|
self._async_connect_websocket_if_disconnected,
|
||||||
|
WEBSOCKET_WATCHDOG_INTERVAL,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
@callback
|
# If Home Assistant is already in a running state, start the watchdog
|
||||||
def _on_ws_connected(self):
|
# immediately, else trigger it after Home Assistant has finished starting.
|
||||||
|
if self.hass.state == CoreState.running:
|
||||||
|
await start_watchdog()
|
||||||
|
else:
|
||||||
|
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, start_watchdog)
|
||||||
|
|
||||||
|
async def _on_ws_connected(self):
|
||||||
"""Call after ws is connected."""
|
"""Call after ws is connected."""
|
||||||
self._register_ws_callbacks()
|
self._register_ws_callbacks()
|
||||||
|
|
||||||
|
version = (await self._kodi.get_application_properties(["version"]))["version"]
|
||||||
|
sw_version = f"{version['major']}.{version['minor']}"
|
||||||
|
dev_reg = await device_registry.async_get_registry(self.hass)
|
||||||
|
device = dev_reg.async_get_device({(DOMAIN, self.unique_id)}, [])
|
||||||
|
dev_reg.async_update_device(device.id, sw_version=sw_version)
|
||||||
|
|
||||||
self.async_schedule_update_ha_state(True)
|
self.async_schedule_update_ha_state(True)
|
||||||
|
|
||||||
async def _async_ws_connect(self):
|
async def _async_ws_connect(self):
|
||||||
"""Connect to Kodi via websocket protocol."""
|
"""Connect to Kodi via websocket protocol."""
|
||||||
try:
|
try:
|
||||||
await self._connection.connect()
|
await self._connection.connect()
|
||||||
self._on_ws_connected()
|
await self._on_ws_connected()
|
||||||
except (jsonrpc_base.jsonrpc.TransportError, CannotConnectError):
|
except (jsonrpc_base.jsonrpc.TransportError, CannotConnectError):
|
||||||
_LOGGER.debug("Unable to connect to Kodi via websocket", exc_info=True)
|
_LOGGER.debug("Unable to connect to Kodi via websocket", exc_info=True)
|
||||||
await self._clear_connection(False)
|
await self._clear_connection(False)
|
||||||
@ -426,6 +443,7 @@ class KodiEntity(MediaPlayerEntity):
|
|||||||
self._connection.server.System.OnRestart = self.async_on_quit
|
self._connection.server.System.OnRestart = self.async_on_quit
|
||||||
self._connection.server.System.OnSleep = self.async_on_quit
|
self._connection.server.System.OnSleep = self.async_on_quit
|
||||||
|
|
||||||
|
@cmd
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
"""Retrieve latest state."""
|
"""Retrieve latest state."""
|
||||||
if not self._connection.connected:
|
if not self._connection.connected:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user