Kodi specific service to call Kodi API methods ()

* Kodi specific services to call Kodi API methods

 - new service: `kodi_execute_addon` to run a Kodi Addon with optional parameters. Results of the Kodi API call, if any, are redirected in a Home Assistant event: `kodi_execute_addon_result`.
 - new service: `kodi_run_method` to run a Kodi JSONRPC API method with optional parameters. Results of the Kodi API call are redirected in a Home Assistant event: `kodi_run_method_result`.
 - Add descriptions in services.yaml.
 - Add `timeout` parameter to yaml config (needed to make slow queries to the JSONRPC API, default timeout is set to 5s).
 - Trigger events with the results of the Kodi API calls, with:
 ```
 event_data = {
   'result': api_call_results,
   'result_ok': boolean,
   'input': api_call_parameters,
   'entity_id': 'media_player.kodi'}
```

* no need to clean OrderedDicts; no need for the `kodi_execute_addon` service

* no need for the `kodi_execute_addon` service

* unused import

* naming changes
This commit is contained in:
Eugenio Panadero 2017-05-17 14:42:47 +02:00 committed by Adam Mills
parent 0e9728d94a
commit f7d25396a4
2 changed files with 51 additions and 4 deletions
homeassistant/components/media_player

View file

@ -24,7 +24,7 @@ from homeassistant.components.media_player import (
from homeassistant.const import (
STATE_IDLE, STATE_OFF, STATE_PAUSED, STATE_PLAYING, CONF_HOST, CONF_NAME,
CONF_PORT, CONF_SSL, CONF_PROXY_SSL, CONF_USERNAME, CONF_PASSWORD,
EVENT_HOMEASSISTANT_STOP)
CONF_TIMEOUT, EVENT_HOMEASSISTANT_STOP)
from homeassistant.core import callback
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
@ -34,6 +34,8 @@ REQUIREMENTS = ['jsonrpc-async==0.6', 'jsonrpc-websocket==0.5']
_LOGGER = logging.getLogger(__name__)
EVENT_KODI_CALL_METHOD_RESULT = 'kodi_call_method_result'
CONF_TCP_PORT = 'tcp_port'
CONF_TURN_OFF_ACTION = 'turn_off_action'
CONF_ENABLE_WEBSOCKET = 'enable_websocket'
@ -74,6 +76,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_TCP_PORT, default=DEFAULT_TCP_PORT): cv.port,
vol.Optional(CONF_PROXY_SSL, default=DEFAULT_PROXY_SSL): cv.boolean,
vol.Optional(CONF_TURN_OFF_ACTION, default=None): vol.In(TURN_OFF_ACTION),
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
vol.Inclusive(CONF_USERNAME, 'auth'): cv.string,
vol.Inclusive(CONF_PASSWORD, 'auth'): cv.string,
vol.Optional(CONF_ENABLE_WEBSOCKET, default=DEFAULT_ENABLE_WEBSOCKET):
@ -81,6 +84,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
})
SERVICE_ADD_MEDIA = 'kodi_add_to_playlist'
SERVICE_CALL_METHOD = 'kodi_call_method'
DATA_KODI = 'kodi'
@ -88,6 +92,7 @@ ATTR_MEDIA_TYPE = 'media_type'
ATTR_MEDIA_NAME = 'media_name'
ATTR_MEDIA_ARTIST_NAME = 'artist_name'
ATTR_MEDIA_ID = 'media_id'
ATTR_METHOD = 'method'
MEDIA_PLAYER_ADD_MEDIA_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({
vol.Required(ATTR_MEDIA_TYPE): cv.string,
@ -95,11 +100,17 @@ MEDIA_PLAYER_ADD_MEDIA_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({
vol.Optional(ATTR_MEDIA_NAME): cv.string,
vol.Optional(ATTR_MEDIA_ARTIST_NAME): cv.string,
})
MEDIA_PLAYER_CALL_METHOD_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({
vol.Required(ATTR_METHOD): cv.string,
}, extra=vol.ALLOW_EXTRA)
SERVICE_TO_METHOD = {
SERVICE_ADD_MEDIA: {
'method': 'async_add_media_to_playlist',
'schema': MEDIA_PLAYER_ADD_MEDIA_SCHEMA},
SERVICE_CALL_METHOD: {
'method': 'async_call_method',
'schema': MEDIA_PLAYER_CALL_METHOD_SCHEMA},
}
@ -127,7 +138,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
host=host, port=port, tcp_port=tcp_port, encryption=encryption,
username=config.get(CONF_USERNAME),
password=config.get(CONF_PASSWORD),
turn_off_action=config.get(CONF_TURN_OFF_ACTION), websocket=websocket)
turn_off_action=config.get(CONF_TURN_OFF_ACTION),
timeout=config.get(CONF_TIMEOUT), websocket=websocket)
hass.data[DATA_KODI].append(entity)
async_add_devices([entity], update_before_add=True)
@ -199,7 +211,7 @@ class KodiDevice(MediaPlayerDevice):
def __init__(self, hass, name, host, port, tcp_port, encryption=False,
username=None, password=None, turn_off_action=None,
websocket=True):
timeout=DEFAULT_TIMEOUT, websocket=True):
"""Initialize the Kodi device."""
import jsonrpc_async
import jsonrpc_websocket
@ -207,7 +219,7 @@ class KodiDevice(MediaPlayerDevice):
self._name = name
kwargs = {
'timeout': DEFAULT_TIMEOUT,
'timeout': timeout,
'session': async_get_clientsession(hass),
}
@ -678,6 +690,30 @@ class KodiDevice(MediaPlayerDevice):
yield from self.server.Player.SetShuffle(
{"playerid": self._players[0]['playerid'], "shuffle": shuffle})
@asyncio.coroutine
def async_call_method(self, method, **kwargs):
"""Run Kodi JSONRPC API method with params."""
import jsonrpc_base
_LOGGER.debug('Run API method "%s", kwargs=%s', method, kwargs)
result_ok = False
try:
result = yield from getattr(self.server, method)(**kwargs)
result_ok = True
except jsonrpc_base.jsonrpc.ProtocolError as exc:
result = exc.args[2]['error']
_LOGGER.error('Run API method %s.%s(%s) error: %s',
self.entity_id, method, kwargs, result)
if isinstance(result, dict):
event_data = {'entity_id': self.entity_id,
'result': result,
'result_ok': result_ok,
'input': {'method': method, 'params': kwargs}}
_LOGGER.debug('EVENT kodi_call_method_result: %s', event_data)
self.hass.bus.async_fire(EVENT_KODI_CALL_METHOD_RESULT,
event_data=event_data)
return result
@asyncio.coroutine
def async_add_media_to_playlist(
self, media_type, media_id=None, media_name='ALL', artist_name=''):

View file

@ -289,3 +289,14 @@ kodi_add_to_playlist:
artist_name:
description: Optional artist name for filtering media.
example: 'AC/DC'
kodi_call_method:
description: 'Call a Kodi JSONRPC API method with optional parameters. Results of the Kodi API call will be redirected in a Home Assistant event: `kodi_call_method_result`.'
fields:
entity_id:
description: Name(s) of the Kodi entities where to run the API method.
example: 'media_player.living_room_kodi'
method:
description: Name of the Kodi JSONRPC API method to be called.
example: 'VideoLibrary.GetRecentlyAddedEpisodes'