mirror of
https://github.com/home-assistant/core.git
synced 2025-07-20 03:37:07 +00:00
Add description to tts and notify services (#46764)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com> Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
parent
ea4bbd771f
commit
afa91e886b
@ -118,7 +118,7 @@ play_media:
|
|||||||
media_content_type:
|
media_content_type:
|
||||||
name: Content type
|
name: Content type
|
||||||
description:
|
description:
|
||||||
The type of the content to play. Must be one of image, music, tvshow,
|
The type of the content to play. Like image, music, tvshow,
|
||||||
video, episode, channel or playlist.
|
video, episode, channel or playlist.
|
||||||
required: true
|
required: true
|
||||||
example: "music"
|
example: "music"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional, cast
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -12,10 +12,12 @@ from homeassistant.core import ServiceCall
|
|||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import config_per_platform, discovery
|
from homeassistant.helpers import config_per_platform, discovery
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.helpers.service import async_set_service_schema
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import async_get_integration, bind_hass
|
||||||
from homeassistant.setup import async_prepare_setup_platform
|
from homeassistant.setup import async_prepare_setup_platform
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
from homeassistant.util.yaml import load_yaml
|
||||||
|
|
||||||
# mypy: allow-untyped-defs, no-check-untyped-defs
|
# mypy: allow-untyped-defs, no-check-untyped-defs
|
||||||
|
|
||||||
@ -41,6 +43,9 @@ SERVICE_PERSISTENT_NOTIFICATION = "persistent_notification"
|
|||||||
|
|
||||||
NOTIFY_SERVICES = "notify_services"
|
NOTIFY_SERVICES = "notify_services"
|
||||||
|
|
||||||
|
CONF_DESCRIPTION = "description"
|
||||||
|
CONF_FIELDS = "fields"
|
||||||
|
|
||||||
PLATFORM_SCHEMA = vol.Schema(
|
PLATFORM_SCHEMA = vol.Schema(
|
||||||
{vol.Required(CONF_PLATFORM): cv.string, vol.Optional(CONF_NAME): cv.string},
|
{vol.Required(CONF_PLATFORM): cv.string, vol.Optional(CONF_NAME): cv.string},
|
||||||
extra=vol.ALLOW_EXTRA,
|
extra=vol.ALLOW_EXTRA,
|
||||||
@ -161,6 +166,13 @@ class BaseNotificationService:
|
|||||||
self._target_service_name_prefix = target_service_name_prefix
|
self._target_service_name_prefix = target_service_name_prefix
|
||||||
self.registered_targets = {}
|
self.registered_targets = {}
|
||||||
|
|
||||||
|
# Load service descriptions from notify/services.yaml
|
||||||
|
integration = await async_get_integration(hass, DOMAIN)
|
||||||
|
services_yaml = integration.file_path / "services.yaml"
|
||||||
|
self.services_dict = cast(
|
||||||
|
dict, await hass.async_add_executor_job(load_yaml, str(services_yaml))
|
||||||
|
)
|
||||||
|
|
||||||
async def async_register_services(self) -> None:
|
async def async_register_services(self) -> None:
|
||||||
"""Create or update the notify services."""
|
"""Create or update the notify services."""
|
||||||
assert self.hass
|
assert self.hass
|
||||||
@ -185,6 +197,13 @@ class BaseNotificationService:
|
|||||||
self._async_notify_message_service,
|
self._async_notify_message_service,
|
||||||
schema=NOTIFY_SERVICE_SCHEMA,
|
schema=NOTIFY_SERVICE_SCHEMA,
|
||||||
)
|
)
|
||||||
|
# Register the service description
|
||||||
|
service_desc = {
|
||||||
|
CONF_NAME: f"Send a notification via {target_name}",
|
||||||
|
CONF_DESCRIPTION: f"Sends a notification message using the {target_name} integration.",
|
||||||
|
CONF_FIELDS: self.services_dict[SERVICE_NOTIFY][CONF_FIELDS],
|
||||||
|
}
|
||||||
|
async_set_service_schema(self.hass, DOMAIN, target_name, service_desc)
|
||||||
|
|
||||||
for stale_target_name in stale_targets:
|
for stale_target_name in stale_targets:
|
||||||
del self.registered_targets[stale_target_name]
|
del self.registered_targets[stale_target_name]
|
||||||
@ -203,6 +222,14 @@ class BaseNotificationService:
|
|||||||
schema=NOTIFY_SERVICE_SCHEMA,
|
schema=NOTIFY_SERVICE_SCHEMA,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Register the service description
|
||||||
|
service_desc = {
|
||||||
|
CONF_NAME: f"Send a notification with {self._service_name}",
|
||||||
|
CONF_DESCRIPTION: f"Sends a notification message using the {self._service_name} service.",
|
||||||
|
CONF_FIELDS: self.services_dict[SERVICE_NOTIFY][CONF_FIELDS],
|
||||||
|
}
|
||||||
|
async_set_service_schema(self.hass, DOMAIN, self._service_name, service_desc)
|
||||||
|
|
||||||
async def async_unregister_services(self) -> None:
|
async def async_unregister_services(self) -> None:
|
||||||
"""Unregister the notify services."""
|
"""Unregister the notify services."""
|
||||||
assert self.hass
|
assert self.hass
|
||||||
|
@ -1,22 +1,37 @@
|
|||||||
# Describes the format for available notification services
|
# Describes the format for available notification services
|
||||||
|
|
||||||
notify:
|
notify:
|
||||||
description: Send a notification.
|
name: Send a notification
|
||||||
|
description: Sends a notification message to selected notify platforms.
|
||||||
fields:
|
fields:
|
||||||
message:
|
message:
|
||||||
|
name: Message
|
||||||
description: Message body of the notification.
|
description: Message body of the notification.
|
||||||
example: The garage door has been open for 10 minutes.
|
example: The garage door has been open for 10 minutes.
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
title:
|
title:
|
||||||
|
name: Title
|
||||||
description: Optional title for your notification.
|
description: Optional title for your notification.
|
||||||
example: "Your Garage Door Friend"
|
example: "Your Garage Door Friend"
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
target:
|
target:
|
||||||
description: An array of targets to send the notification to. Optional depending on the platform.
|
description:
|
||||||
|
An array of targets to send the notification to. Optional depending on
|
||||||
|
the platform.
|
||||||
example: platform specific
|
example: platform specific
|
||||||
data:
|
data:
|
||||||
description: Extended information for notification. Optional depending on the platform.
|
name: Data
|
||||||
|
description:
|
||||||
|
Extended information for notification. Optional depending on the
|
||||||
|
platform.
|
||||||
example: platform specific
|
example: platform specific
|
||||||
|
selector:
|
||||||
|
object:
|
||||||
|
|
||||||
persistent_notification:
|
persistent_notification:
|
||||||
|
name: Send a persistent notification
|
||||||
description: Sends a notification to the visible in the front-end.
|
description: Sends a notification to the visible in the front-end.
|
||||||
fields:
|
fields:
|
||||||
message:
|
message:
|
||||||
@ -27,10 +42,16 @@ persistent_notification:
|
|||||||
example: "Your Garage Door Friend"
|
example: "Your Garage Door Friend"
|
||||||
|
|
||||||
apns_register:
|
apns_register:
|
||||||
description: Registers a device to receive push notifications.
|
name: Register APNS device
|
||||||
|
description:
|
||||||
|
Registers a device to receive push notifications via APNS (Apple Push
|
||||||
|
Notification Service).
|
||||||
fields:
|
fields:
|
||||||
push_id:
|
push_id:
|
||||||
description: The device token, a 64 character hex string (256 bits). The device token is provided to you by your client app, which receives the token after registering itself with the remote notification service.
|
description:
|
||||||
|
The device token, a 64 character hex string (256 bits). The device token
|
||||||
|
is provided to you by your client app, which receives the token after
|
||||||
|
registering itself with the remote notification service.
|
||||||
example: "72f2a8633655c5ce574fdc9b2b34ff8abdfc3b739b6ceb7a9ff06c1cbbf99f62"
|
example: "72f2a8633655c5ce574fdc9b2b34ff8abdfc3b739b6ceb7a9ff06c1cbbf99f62"
|
||||||
name:
|
name:
|
||||||
description: A friendly name for the device (optional).
|
description: A friendly name for the device (optional).
|
||||||
|
@ -7,7 +7,7 @@ import logging
|
|||||||
import mimetypes
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Optional, cast
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
import mutagen
|
import mutagen
|
||||||
@ -24,6 +24,7 @@ from homeassistant.components.media_player.const import (
|
|||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
|
CONF_NAME,
|
||||||
CONF_PLATFORM,
|
CONF_PLATFORM,
|
||||||
HTTP_BAD_REQUEST,
|
HTTP_BAD_REQUEST,
|
||||||
HTTP_NOT_FOUND,
|
HTTP_NOT_FOUND,
|
||||||
@ -33,8 +34,11 @@ from homeassistant.exceptions import HomeAssistantError
|
|||||||
from homeassistant.helpers import config_per_platform, discovery
|
from homeassistant.helpers import config_per_platform, discovery
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.network import get_url
|
from homeassistant.helpers.network import get_url
|
||||||
|
from homeassistant.helpers.service import async_set_service_schema
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
from homeassistant.loader import async_get_integration
|
||||||
from homeassistant.setup import async_prepare_setup_platform
|
from homeassistant.setup import async_prepare_setup_platform
|
||||||
|
from homeassistant.util.yaml import load_yaml
|
||||||
|
|
||||||
# mypy: allow-untyped-defs, no-check-untyped-defs
|
# mypy: allow-untyped-defs, no-check-untyped-defs
|
||||||
|
|
||||||
@ -55,6 +59,9 @@ CONF_LANG = "language"
|
|||||||
CONF_SERVICE_NAME = "service_name"
|
CONF_SERVICE_NAME = "service_name"
|
||||||
CONF_TIME_MEMORY = "time_memory"
|
CONF_TIME_MEMORY = "time_memory"
|
||||||
|
|
||||||
|
CONF_DESCRIPTION = "description"
|
||||||
|
CONF_FIELDS = "fields"
|
||||||
|
|
||||||
DEFAULT_CACHE = True
|
DEFAULT_CACHE = True
|
||||||
DEFAULT_CACHE_DIR = "tts"
|
DEFAULT_CACHE_DIR = "tts"
|
||||||
DEFAULT_TIME_MEMORY = 300
|
DEFAULT_TIME_MEMORY = 300
|
||||||
@ -127,6 +134,13 @@ async def async_setup(hass, config):
|
|||||||
hass.http.register_view(TextToSpeechView(tts))
|
hass.http.register_view(TextToSpeechView(tts))
|
||||||
hass.http.register_view(TextToSpeechUrlView(tts))
|
hass.http.register_view(TextToSpeechUrlView(tts))
|
||||||
|
|
||||||
|
# Load service descriptions from tts/services.yaml
|
||||||
|
integration = await async_get_integration(hass, DOMAIN)
|
||||||
|
services_yaml = integration.file_path / "services.yaml"
|
||||||
|
services_dict = cast(
|
||||||
|
dict, await hass.async_add_executor_job(load_yaml, str(services_yaml))
|
||||||
|
)
|
||||||
|
|
||||||
async def async_setup_platform(p_type, p_config=None, discovery_info=None):
|
async def async_setup_platform(p_type, p_config=None, discovery_info=None):
|
||||||
"""Set up a TTS platform."""
|
"""Set up a TTS platform."""
|
||||||
if p_config is None:
|
if p_config is None:
|
||||||
@ -193,6 +207,14 @@ async def async_setup(hass, config):
|
|||||||
DOMAIN, service_name, async_say_handle, schema=SCHEMA_SERVICE_SAY
|
DOMAIN, service_name, async_say_handle, schema=SCHEMA_SERVICE_SAY
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Register the service description
|
||||||
|
service_desc = {
|
||||||
|
CONF_NAME: "Say an TTS message with {p_type}",
|
||||||
|
CONF_DESCRIPTION: f"Say something using text-to-speech on a media player with {p_type}.",
|
||||||
|
CONF_FIELDS: services_dict[SERVICE_SAY][CONF_FIELDS],
|
||||||
|
}
|
||||||
|
async_set_service_schema(hass, DOMAIN, service_name, service_desc)
|
||||||
|
|
||||||
setup_tasks = [
|
setup_tasks = [
|
||||||
asyncio.create_task(async_setup_platform(p_type, p_config))
|
asyncio.create_task(async_setup_platform(p_type, p_config))
|
||||||
for p_type, p_config in config_per_platform(config, DOMAIN)
|
for p_type, p_config in config_per_platform(config, DOMAIN)
|
||||||
|
@ -1,23 +1,43 @@
|
|||||||
# Describes the format for available TTS services
|
# Describes the format for available TTS services
|
||||||
|
|
||||||
say:
|
say:
|
||||||
description: Say some things on a media player.
|
name: Say an TTS message
|
||||||
|
description: Say something using text-to-speech on a media player.
|
||||||
fields:
|
fields:
|
||||||
entity_id:
|
entity_id:
|
||||||
|
name: Entity
|
||||||
description: Name(s) of media player entities.
|
description: Name(s) of media player entities.
|
||||||
example: "media_player.floor"
|
example: "media_player.floor"
|
||||||
|
required: true
|
||||||
|
selector:
|
||||||
|
entity:
|
||||||
|
domain: media_player
|
||||||
message:
|
message:
|
||||||
|
name: Message
|
||||||
description: Text to speak on devices.
|
description: Text to speak on devices.
|
||||||
example: "My name is hanna"
|
example: "My name is hanna"
|
||||||
|
required: true
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
cache:
|
cache:
|
||||||
|
name: Cache
|
||||||
description: Control file cache of this message.
|
description: Control file cache of this message.
|
||||||
example: "true"
|
example: "true"
|
||||||
|
default: false
|
||||||
|
selector:
|
||||||
|
boolean:
|
||||||
language:
|
language:
|
||||||
|
name: Language
|
||||||
description: Language to use for speech generation.
|
description: Language to use for speech generation.
|
||||||
example: "ru"
|
example: "ru"
|
||||||
|
selector:
|
||||||
|
text:
|
||||||
options:
|
options:
|
||||||
description: A dictionary containing platform-specific options. Optional depending on the platform.
|
description:
|
||||||
|
A dictionary containing platform-specific options. Optional depending on
|
||||||
|
the platform.
|
||||||
example: platform specific
|
example: platform specific
|
||||||
|
|
||||||
clear_cache:
|
clear_cache:
|
||||||
description: Remove cache files and RAM cache.
|
name: Clear TTS cache
|
||||||
|
description: Remove all text-to-speech cache files and RAM cache.
|
||||||
|
@ -478,6 +478,9 @@ def async_set_service_schema(
|
|||||||
"fields": schema.get("fields", {}),
|
"fields": schema.get("fields", {}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if "target" in schema:
|
||||||
|
description["target"] = schema["target"]
|
||||||
|
|
||||||
hass.data[SERVICE_DESCRIPTION_CACHE][f"{domain}.{service}"] = description
|
hass.data[SERVICE_DESCRIPTION_CACHE][f"{domain}.{service}"] = description
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user