mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 17:57:55 +00:00
Bugfix voicerss post api (#5021)
* Bugfix voicerss post api * fix unittest * Add cache to service description
This commit is contained in:
parent
b170f4c399
commit
25469dd8ee
@ -3,12 +3,16 @@ say:
|
|||||||
|
|
||||||
fields:
|
fields:
|
||||||
entity_id:
|
entity_id:
|
||||||
description: Name(s) of media player entities
|
description: Name(s) of media player entities.
|
||||||
example: 'media_player.floor'
|
example: 'media_player.floor'
|
||||||
|
|
||||||
message:
|
message:
|
||||||
description: Text to speak on devices
|
description: Text to speak on devices.
|
||||||
example: 'My name is hanna'
|
example: 'My name is hanna'
|
||||||
|
|
||||||
|
cache:
|
||||||
|
description: Control file cache of this message.
|
||||||
|
example: 'true'
|
||||||
|
|
||||||
clear_cache:
|
clear_cache:
|
||||||
description: Remove cache files and RAM cache.
|
description: Remove cache files and RAM cache.
|
||||||
|
@ -21,6 +21,18 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
VOICERSS_API_URL = "https://api.voicerss.org/"
|
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 = [
|
SUPPORT_LANGUAGES = [
|
||||||
'ca-es', 'zh-cn', 'zh-hk', 'zh-tw', 'da-dk', 'nl-nl', 'en-au', 'en-ca',
|
'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',
|
'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.hass = hass
|
||||||
self.extension = conf.get(CONF_CODEC)
|
self.extension = conf.get(CONF_CODEC)
|
||||||
|
|
||||||
self.params = {
|
self.form_data = {
|
||||||
'key': conf.get(CONF_API_KEY),
|
'key': conf.get(CONF_API_KEY),
|
||||||
'hl': conf.get(CONF_LANG),
|
'hl': conf.get(CONF_LANG),
|
||||||
'c': (conf.get(CONF_CODEC)).upper(),
|
'c': (conf.get(CONF_CODEC)).upper(),
|
||||||
@ -94,21 +106,28 @@ class VoiceRSSProvider(Provider):
|
|||||||
def async_get_tts_audio(self, message):
|
def async_get_tts_audio(self, message):
|
||||||
"""Load TTS from voicerss."""
|
"""Load TTS from voicerss."""
|
||||||
websession = async_get_clientsession(self.hass)
|
websession = async_get_clientsession(self.hass)
|
||||||
|
form_data = self.form_data.copy()
|
||||||
|
|
||||||
|
form_data['src'] = message
|
||||||
|
|
||||||
request = None
|
request = None
|
||||||
try:
|
try:
|
||||||
with async_timeout.timeout(10, loop=self.hass.loop):
|
with async_timeout.timeout(10, loop=self.hass.loop):
|
||||||
request = yield from websession.post(
|
request = yield from websession.post(
|
||||||
VOICERSS_API_URL, params=self.params,
|
VOICERSS_API_URL, data=form_data
|
||||||
data=bytes(message, 'utf-8')
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if request.status != 200:
|
if request.status != 200:
|
||||||
_LOGGER.error("Error %d on load url %s",
|
_LOGGER.error("Error %d on load url %s.",
|
||||||
request.status, request.url)
|
request.status, request.url)
|
||||||
return (None, None)
|
return (None, None)
|
||||||
data = yield from request.read()
|
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):
|
except (asyncio.TimeoutError, aiohttp.errors.ClientError):
|
||||||
_LOGGER.error("Timeout for voicerss api.")
|
_LOGGER.error("Timeout for voicerss api.")
|
||||||
return (None, None)
|
return (None, None)
|
||||||
|
@ -20,11 +20,12 @@ class TestTTSVoiceRSSPlatform(object):
|
|||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
|
|
||||||
self.url = "https://api.voicerss.org/"
|
self.url = "https://api.voicerss.org/"
|
||||||
self.url_param = {
|
self.form_data = {
|
||||||
'key': '1234567xx',
|
'key': '1234567xx',
|
||||||
'hl': 'en-us',
|
'hl': 'en-us',
|
||||||
'c': 'MP3',
|
'c': 'MP3',
|
||||||
'f': '8khz_8bit_mono',
|
'f': '8khz_8bit_mono',
|
||||||
|
'src': "I person is on front of your door.",
|
||||||
}
|
}
|
||||||
|
|
||||||
def teardown_method(self):
|
def teardown_method(self):
|
||||||
@ -63,7 +64,7 @@ class TestTTSVoiceRSSPlatform(object):
|
|||||||
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
|
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
|
||||||
|
|
||||||
aioclient_mock.post(
|
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 = {
|
config = {
|
||||||
tts.DOMAIN: {
|
tts.DOMAIN: {
|
||||||
@ -82,15 +83,16 @@ class TestTTSVoiceRSSPlatform(object):
|
|||||||
|
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
assert len(aioclient_mock.mock_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
|
assert calls[0].data[ATTR_MEDIA_CONTENT_ID].find(".mp3") != -1
|
||||||
|
|
||||||
def test_service_say_german(self, aioclient_mock):
|
def test_service_say_german(self, aioclient_mock):
|
||||||
"""Test service call say with german code."""
|
"""Test service call say with german code."""
|
||||||
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
|
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(
|
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 = {
|
config = {
|
||||||
tts.DOMAIN: {
|
tts.DOMAIN: {
|
||||||
@ -110,13 +112,14 @@ class TestTTSVoiceRSSPlatform(object):
|
|||||||
|
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
assert len(aioclient_mock.mock_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):
|
def test_service_say_error(self, aioclient_mock):
|
||||||
"""Test service call say with http response 400."""
|
"""Test service call say with http response 400."""
|
||||||
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
|
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
|
||||||
|
|
||||||
aioclient_mock.post(
|
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 = {
|
config = {
|
||||||
tts.DOMAIN: {
|
tts.DOMAIN: {
|
||||||
@ -135,13 +138,14 @@ class TestTTSVoiceRSSPlatform(object):
|
|||||||
|
|
||||||
assert len(calls) == 0
|
assert len(calls) == 0
|
||||||
assert len(aioclient_mock.mock_calls) == 1
|
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):
|
def test_service_say_timeout(self, aioclient_mock):
|
||||||
"""Test service call say with http timeout."""
|
"""Test service call say with http timeout."""
|
||||||
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
|
calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA)
|
||||||
|
|
||||||
aioclient_mock.post(
|
aioclient_mock.post(
|
||||||
self.url, params=self.url_param, exc=asyncio.TimeoutError())
|
self.url, data=self.form_data, exc=asyncio.TimeoutError())
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
tts.DOMAIN: {
|
tts.DOMAIN: {
|
||||||
@ -160,3 +164,32 @@ class TestTTSVoiceRSSPlatform(object):
|
|||||||
|
|
||||||
assert len(calls) == 0
|
assert len(calls) == 0
|
||||||
assert len(aioclient_mock.mock_calls) == 1
|
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user