Add 2 media_player services and 1 custom service to Squeezebox platform (#10969)

* Add 2 media_player services and 1 custom service to Squeezebox platform

* Fix pylint error

* Remove apostrophe in example

* Split method into command and parameters

* Fix Lint error
This commit is contained in:
Eric Pignet 2018-01-10 14:05:21 +11:00 committed by Adam Mills
parent cba55402b1
commit 92014bf1d1
2 changed files with 103 additions and 3 deletions

View file

@ -307,3 +307,16 @@ kodi_call_method:
method:
description: Name of the Kodi JSONRPC API method to be called.
example: 'VideoLibrary.GetRecentlyAddedEpisodes'
squeezebox_call_method:
description: 'Call a Squeezebox JSON/RPC API method.'
fields:
entity_id:
description: Name(s) of the Squeexebox entities where to run the API method.
example: 'media_player.squeezebox_radio'
command:
description: Name of the Squeezebox command.
example: 'playlist'
parameters:
description: Optional array of parameters to be appended to the command. See 'Command Line Interface' official help page from Logitech for details.
example: '["loadtracks", "track.titlesearch=highway to hell"]'

View file

@ -8,19 +8,22 @@ import logging
import asyncio
import urllib.parse
import json
import os
import aiohttp
import async_timeout
import voluptuous as vol
from homeassistant.config import load_yaml_config_file
from homeassistant.components.media_player import (
ATTR_MEDIA_ENQUEUE, SUPPORT_PLAY_MEDIA,
MEDIA_TYPE_MUSIC, SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, PLATFORM_SCHEMA,
SUPPORT_PREVIOUS_TRACK, SUPPORT_SEEK, SUPPORT_TURN_OFF, SUPPORT_TURN_ON,
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_PLAY, MediaPlayerDevice)
SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_PLAY, MediaPlayerDevice,
MEDIA_PLAYER_SCHEMA, DOMAIN, SUPPORT_SHUFFLE_SET, SUPPORT_CLEAR_PLAYLIST)
from homeassistant.const import (
CONF_HOST, CONF_PASSWORD, CONF_USERNAME, STATE_IDLE, STATE_OFF,
STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, CONF_PORT)
STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, CONF_PORT, ATTR_COMMAND)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.util.dt import utcnow
@ -33,7 +36,7 @@ TIMEOUT = 10
SUPPORT_SQUEEZEBOX = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | \
SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | \
SUPPORT_SEEK | SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_PLAY_MEDIA | \
SUPPORT_PLAY
SUPPORT_PLAY | SUPPORT_SHUFFLE_SET | SUPPORT_CLEAR_PLAYLIST
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
@ -42,12 +45,33 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_USERNAME): cv.string,
})
SERVICE_CALL_METHOD = 'squeezebox_call_method'
DATA_SQUEEZEBOX = 'squeexebox'
ATTR_PARAMETERS = 'parameters'
SQUEEZEBOX_CALL_METHOD_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({
vol.Required(ATTR_COMMAND): cv.string,
vol.Optional(ATTR_PARAMETERS):
vol.All(cv.ensure_list, vol.Length(min=1), [cv.string]),
})
SERVICE_TO_METHOD = {
SERVICE_CALL_METHOD: {
'method': 'async_call_method',
'schema': SQUEEZEBOX_CALL_METHOD_SCHEMA},
}
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the squeezebox platform."""
import socket
if DATA_SQUEEZEBOX not in hass.data:
hass.data[DATA_SQUEEZEBOX] = []
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
@ -74,8 +98,44 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
lms = LogitechMediaServer(hass, host, port, username, password)
players = yield from lms.create_players()
hass.data[DATA_SQUEEZEBOX].extend(players)
async_add_devices(players)
@asyncio.coroutine
def async_service_handler(service):
"""Map services to methods on MediaPlayerDevice."""
method = SERVICE_TO_METHOD.get(service.service)
if not method:
return
params = {key: value for key, value in service.data.items()
if key != 'entity_id'}
entity_ids = service.data.get('entity_id')
if entity_ids:
target_players = [player for player in hass.data[DATA_SQUEEZEBOX]
if player.entity_id in entity_ids]
else:
target_players = hass.data[DATA_SQUEEZEBOX]
update_tasks = []
for player in target_players:
yield from getattr(player, method['method'])(**params)
update_tasks.append(player.async_update_ha_state(True))
if update_tasks:
yield from asyncio.wait(update_tasks, loop=hass.loop)
descriptions = yield from hass.async_add_job(
load_yaml_config_file, os.path.join(
os.path.dirname(__file__), 'services.yaml'))
for service in SERVICE_TO_METHOD:
schema = SERVICE_TO_METHOD[service]['schema']
hass.services.async_register(
DOMAIN, service, async_service_handler,
description=descriptions.get(service), schema=schema)
return True
@ -305,6 +365,12 @@ class SqueezeBoxDevice(MediaPlayerDevice):
if 'album' in self._status:
return self._status['album']
@property
def shuffle(self):
"""Boolean if shuffle is enabled."""
if 'playlist_shuffle' in self._status:
return self._status['playlist_shuffle'] == 1
@property
def supported_features(self):
"""Flag media player features that are supported."""
@ -415,3 +481,24 @@ class SqueezeBoxDevice(MediaPlayerDevice):
def _add_uri_to_playlist(self, media_id):
"""Add a items to the existing playlist."""
return self.async_query('playlist', 'add', media_id)
def async_set_shuffle(self, shuffle):
"""Enable/disable shuffle mode."""
return self.async_query('playlist', 'shuffle', int(shuffle))
def async_clear_playlist(self):
"""Send the media player the command for clear playlist."""
return self.async_query('playlist', 'clear')
def async_call_method(self, command, parameters=None):
"""
Call Squeezebox JSON/RPC method.
Escaped optional parameters are added to the command to form the list
of positional parameters (p0, p1..., pN) passed to JSON/RPC server.
"""
all_params = [command]
if parameters:
for parameter in parameters:
all_params.append(urllib.parse.quote(parameter, safe=':='))
return self.async_query(*all_params)