Bugfix voicerss post api (#5021)

* Bugfix voicerss post api

* fix unittest

* Add cache to service description
This commit is contained in:
Pascal Vizeli 2016-12-21 10:22:12 +01:00 committed by pvizeli
parent 61fc4ca8fe
commit 35b4da0aa2
3 changed files with 68 additions and 12 deletions

View file

@ -3,12 +3,16 @@ say:
fields:
entity_id:
description: Name(s) of media player entities
description: Name(s) of media player entities.
example: 'media_player.floor'
message:
description: Text to speak on devices
description: Text to speak on devices.
example: 'My name is hanna'
cache:
description: Control file cache of this message.
example: 'true'
clear_cache:
description: Remove cache files and RAM cache.

View file

@ -21,6 +21,18 @@ _LOGGER = logging.getLogger(__name__)
VOICERSS_API_URL = "https://api.voicerss.org/"
ERROR_MSG = [
b'Error description',
b'The subscription is expired or requests count limitation is exceeded!',
b'The request content length is too large!',
b'The language does not support!',
b'The language is not specified!',
b'The text is not specified!',
b'The API key is not available!',
b'The API key is not specified!',
b'The subscription does not support SSML!',
]
SUPPORT_LANGUAGES = [
'ca-es', 'zh-cn', 'zh-hk', 'zh-tw', 'da-dk', 'nl-nl', 'en-au', 'en-ca',
'en-gb', 'en-in', 'en-us', 'fi-fi', 'fr-ca', 'fr-fr', 'de-de', 'it-it',
@ -83,7 +95,7 @@ class VoiceRSSProvider(Provider):
self.hass = hass
self.extension = conf.get(CONF_CODEC)
self.params = {
self.form_data = {
'key': conf.get(CONF_API_KEY),
'hl': conf.get(CONF_LANG),
'c': (conf.get(CONF_CODEC)).upper(),
@ -94,21 +106,28 @@ class VoiceRSSProvider(Provider):
def async_get_tts_audio(self, message):
"""Load TTS from voicerss."""
websession = async_get_clientsession(self.hass)
form_data = self.form_data.copy()
form_data['src'] = message
request = None
try:
with async_timeout.timeout(10, loop=self.hass.loop):
request = yield from websession.post(
VOICERSS_API_URL, params=self.params,
data=bytes(message, 'utf-8')
VOICERSS_API_URL, data=form_data
)
if request.status != 200:
_LOGGER.error("Error %d on load url %s",
_LOGGER.error("Error %d on load url %s.",
request.status, request.url)
return (None, None)
data = yield from request.read()
if data in ERROR_MSG:
_LOGGER.error(
"Error receive %s from voicerss.", str(data, 'utf-8'))
return (None, None)
except (asyncio.TimeoutError, aiohttp.errors.ClientError):
_LOGGER.error("Timeout for voicerss api.")
return (None, None)

View file

@ -20,11 +20,12 @@ class TestTTSVoiceRSSPlatform(object):
self.hass = get_test_home_assistant()
self.url = "https://api.voicerss.org/"
self.url_param = {
self.form_data = {
'key': '1234567xx',
'hl': 'en-us',
'c': 'MP3',
'f': '8khz_8bit_mono',
'src': "I person is on front of your door.",
}
def teardown_method(self):
@ -63,7 +64,7 @@ class TestTTSVoiceRSSPlatform(object):
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
aioclient_mock.post(
self.url, params=self.url_param, status=200, content=b'test')
self.url, data=self.form_data, status=200, content=b'test')
config = {
tts.DOMAIN: {
@ -82,15 +83,16 @@ class TestTTSVoiceRSSPlatform(object):
assert len(calls) == 1
assert len(aioclient_mock.mock_calls) == 1
assert aioclient_mock.mock_calls[0][2] == self.form_data
assert calls[0].data[ATTR_MEDIA_CONTENT_ID].find(".mp3") != -1
def test_service_say_german(self, aioclient_mock):
"""Test service call say with german code."""
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
self.url_param['hl'] = 'de-de'
self.form_data['hl'] = 'de-de'
aioclient_mock.post(
self.url, params=self.url_param, status=200, content=b'test')
self.url, data=self.form_data, status=200, content=b'test')
config = {
tts.DOMAIN: {
@ -110,13 +112,14 @@ class TestTTSVoiceRSSPlatform(object):
assert len(calls) == 1
assert len(aioclient_mock.mock_calls) == 1
assert aioclient_mock.mock_calls[0][2] == self.form_data
def test_service_say_error(self, aioclient_mock):
"""Test service call say with http response 400."""
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
aioclient_mock.post(
self.url, params=self.url_param, status=400, content=b'test')
self.url, data=self.form_data, status=400, content=b'test')
config = {
tts.DOMAIN: {
@ -135,13 +138,14 @@ class TestTTSVoiceRSSPlatform(object):
assert len(calls) == 0
assert len(aioclient_mock.mock_calls) == 1
assert aioclient_mock.mock_calls[0][2] == self.form_data
def test_service_say_timeout(self, aioclient_mock):
"""Test service call say with http timeout."""
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
aioclient_mock.post(
self.url, params=self.url_param, exc=asyncio.TimeoutError())
self.url, data=self.form_data, exc=asyncio.TimeoutError())
config = {
tts.DOMAIN: {
@ -160,3 +164,32 @@ class TestTTSVoiceRSSPlatform(object):
assert len(calls) == 0
assert len(aioclient_mock.mock_calls) == 1
assert aioclient_mock.mock_calls[0][2] == self.form_data
def test_service_say_error_msg(self, aioclient_mock):
"""Test service call say with http error api message."""
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
aioclient_mock.post(
self.url, data=self.form_data, status=200,
content=b'The subscription does not support SSML!'
)
config = {
tts.DOMAIN: {
'platform': 'voicerss',
'api_key': '1234567xx',
}
}
with assert_setup_component(1, tts.DOMAIN):
setup_component(self.hass, tts.DOMAIN, config)
self.hass.services.call(tts.DOMAIN, 'voicerss_say', {
tts.ATTR_MESSAGE: "I person is on front of your door.",
})
self.hass.block_till_done()
assert len(calls) == 0
assert len(aioclient_mock.mock_calls) == 1
assert aioclient_mock.mock_calls[0][2] == self.form_data