Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions homeassistant/components/kodi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@
EVENT_HOMEASSISTANT_STOP,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession

from .const import (
CONF_WS_PORT,
DATA_CONNECTION,
DATA_KODI,
DATA_REMOVE_LISTENER,
DATA_VERSION,
DOMAIN,
)

Expand All @@ -48,13 +46,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
entry.data[CONF_SSL],
session=async_get_clientsession(hass),
)

kodi = Kodi(conn)

try:
await conn.connect()
kodi = Kodi(conn)
await kodi.ping()
raw_version = (await kodi.get_application_properties(["version"]))["version"]
except CannotConnectError as error:
raise ConfigEntryNotReady from error
except CannotConnectError:
pass
except InvalidAuthError as error:
_LOGGER.error(
"Login to %s failed: [%s]",
Expand All @@ -68,12 +66,10 @@ async def _close(event):

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] = {
DATA_CONNECTION: conn,
DATA_KODI: kodi,
DATA_REMOVE_LISTENER: remove_stop_listener,
DATA_VERSION: version,
}

for component in PLATFORMS:
Expand Down
1 change: 0 additions & 1 deletion homeassistant/components/kodi/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
DATA_CONNECTION = "connection"
DATA_KODI = "kodi"
DATA_REMOVE_LISTENER = "remove_listener"
DATA_VERSION = "version"

DEFAULT_PORT = 8080
DEFAULT_SSL = False
Expand Down
58 changes: 38 additions & 20 deletions homeassistant/components/kodi/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,18 @@
CONF_SSL,
CONF_TIMEOUT,
CONF_USERNAME,
EVENT_HOMEASSISTANT_STARTED,
STATE_IDLE,
STATE_OFF,
STATE_PAUSED,
STATE_PLAYING,
)
from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.core import CoreState, callback
from homeassistant.helpers import (
config_validation as cv,
device_registry,
entity_platform,
)
from homeassistant.helpers.event import async_track_time_interval
import homeassistant.util.dt as dt_util

Expand All @@ -63,7 +68,6 @@
CONF_WS_PORT,
DATA_CONNECTION,
DATA_KODI,
DATA_VERSION,
DEFAULT_PORT,
DEFAULT_SSL,
DEFAULT_TIMEOUT,
Expand Down Expand Up @@ -91,7 +95,7 @@
"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
MEDIA_TYPES = {
Expand Down Expand Up @@ -229,14 +233,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):

data = hass.data[DOMAIN][config_entry.entry_id]
connection = data[DATA_CONNECTION]
version = data[DATA_VERSION]
kodi = data[DATA_KODI]
name = config_entry.data[CONF_NAME]
uid = config_entry.unique_id
if uid is None:
uid = config_entry.entry_id

entity = KodiEntity(connection, kodi, name, uid, version)
entity = KodiEntity(connection, kodi, name, uid)
async_add_entities([entity])


Expand Down Expand Up @@ -264,13 +267,12 @@ async def wrapper(obj, *args, **kwargs):
class KodiEntity(MediaPlayerEntity):
"""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."""
self._connection = connection
self._kodi = kodi
self._name = name
self._unique_id = uid
self._version = version
self._players = None
self._properties = {}
self._item = {}
Expand Down Expand Up @@ -347,7 +349,6 @@ def device_info(self):
"identifiers": {(DOMAIN, self.unique_id)},
"name": self.name,
"manufacturer": "Kodi",
"sw_version": self._version,
}

@property
Expand All @@ -370,27 +371,43 @@ async def async_added_to_hass(self):
return

if self._connection.connected:
self._on_ws_connected()

self.async_on_remove(
async_track_time_interval(
self.hass,
self._async_connect_websocket_if_disconnected,
WEBSOCKET_WATCHDOG_INTERVAL,
await self._on_ws_connected()

async def start_watchdog(event=None):
"""Start websocket watchdog."""
await self._async_connect_websocket_if_disconnected()
self.async_on_remove(
async_track_time_interval(
self.hass,
self._async_connect_websocket_if_disconnected,
WEBSOCKET_WATCHDOG_INTERVAL,
)
)
)

@callback
def _on_ws_connected(self):
# If Home Assistant is already in a running state, start the watchdog
# 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."""
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)

async def _async_ws_connect(self):
"""Connect to Kodi via websocket protocol."""
try:
await self._connection.connect()
self._on_ws_connected()
await self._on_ws_connected()
except (jsonrpc_base.jsonrpc.TransportError, CannotConnectError):
_LOGGER.debug("Unable to connect to Kodi via websocket", exc_info=True)
await self._clear_connection(False)
Expand Down Expand Up @@ -426,6 +443,7 @@ def _register_ws_callbacks(self):
self._connection.server.System.OnRestart = self.async_on_quit
self._connection.server.System.OnSleep = self.async_on_quit

@cmd
async def async_update(self):
"""Retrieve latest state."""
if not self._connection.connected:
Expand Down