1 """Assist satellite Websocket API."""
4 from dataclasses
import asdict, replace
7 import voluptuous
as vol
16 from .connection_test
import CONNECTION_TEST_URL_BASE
21 AssistSatelliteEntityFeature,
23 from .entity
import AssistSatelliteEntity
25 CONNECTION_TEST_TIMEOUT = 30
30 """Register the websocket API."""
31 websocket_api.async_register_command(hass, websocket_intercept_wake_word)
32 websocket_api.async_register_command(hass, websocket_get_configuration)
33 websocket_api.async_register_command(hass, websocket_set_wake_words)
34 websocket_api.async_register_command(hass, websocket_test_connection)
37 @websocket_api.websocket_command(
{
vol.Required("type"):
"assist_satellite/intercept_wake_word",
38 vol.Required(
"entity_id"): cv.entity_domain(DOMAIN),
41 @websocket_api.require_admin
42 @websocket_api.async_response
48 """Intercept the next wake word from a satellite."""
49 satellite = hass.data[DATA_COMPONENT].
get_entity(msg[
"entity_id"])
51 connection.send_error(
52 msg[
"id"], websocket_api.ERR_NOT_FOUND,
"Entity not found"
56 async
def intercept_wake_word() -> None:
57 """Push an intercepted wake word to websocket."""
59 wake_word_phrase = await satellite.async_intercept_wake_word()
60 connection.send_message(
61 websocket_api.event_message(
63 {
"wake_word_phrase": wake_word_phrase},
66 except HomeAssistantError
as err:
67 connection.send_error(msg[
"id"],
"home_assistant_error",
str(err))
69 task = hass.async_create_task(intercept_wake_word(),
"intercept_wake_word")
70 connection.subscriptions[msg[
"id"]] = task.cancel
71 connection.send_message(websocket_api.result_message(msg[
"id"]))
75 @websocket_api.websocket_command(
{
vol.Required("type"):
"assist_satellite/get_configuration",
76 vol.Required(
"entity_id"): cv.entity_domain(DOMAIN),
84 """Get the current satellite configuration."""
85 satellite = hass.data[DATA_COMPONENT].
get_entity(msg[
"entity_id"])
87 connection.send_error(
88 msg[
"id"], websocket_api.ERR_NOT_FOUND,
"Entity not found"
92 config_dict = asdict(satellite.async_get_configuration())
93 config_dict[
"pipeline_entity_id"] = satellite.pipeline_entity_id
94 config_dict[
"vad_entity_id"] = satellite.vad_sensitivity_entity_id
96 connection.send_result(msg[
"id"], config_dict)
99 @websocket_api.websocket_command(
{
vol.Required("type"):
"assist_satellite/set_wake_words",
100 vol.Required(
"entity_id"): cv.entity_domain(DOMAIN),
101 vol.Required(
"wake_word_ids"): [str],
104 @websocket_api.require_admin
105 @websocket_api.async_response
111 """Set the active wake words for the satellite."""
112 satellite = hass.data[DATA_COMPONENT].
get_entity(msg[
"entity_id"])
113 if satellite
is None:
114 connection.send_error(
115 msg[
"id"], websocket_api.ERR_NOT_FOUND,
"Entity not found"
119 config = satellite.async_get_configuration()
122 actual_ids = msg[
"wake_word_ids"]
123 if len(actual_ids) > config.max_active_wake_words:
124 connection.send_error(
126 websocket_api.ERR_NOT_SUPPORTED,
127 f
"Maximum number of active wake words is {config.max_active_wake_words}",
132 available_ids = {ww.id
for ww
in config.available_wake_words}
133 for ww_id
in actual_ids:
134 if ww_id
not in available_ids:
135 connection.send_error(
137 websocket_api.ERR_NOT_SUPPORTED,
138 f
"Wake word id is not supported: {ww_id}",
142 await satellite.async_set_configuration(
143 replace(config, active_wake_words=actual_ids)
145 connection.send_result(msg[
"id"])
148 @websocket_api.websocket_command(
{
vol.Required("type"):
"assist_satellite/test_connection",
149 vol.Required(
"entity_id"): cv.entity_domain(DOMAIN),
152 @websocket_api.async_response
158 """Test the connection between the device and Home Assistant.
160 Send an announcement to the device with a special media id.
162 component: EntityComponent[AssistSatelliteEntity] = hass.data[DOMAIN]
163 satellite = component.get_entity(msg[
"entity_id"])
164 if satellite
is None:
165 connection.send_error(
166 msg[
"id"], websocket_api.ERR_NOT_FOUND,
"Entity not found"
169 if not (satellite.supported_features
or 0) & AssistSatelliteEntityFeature.ANNOUNCE:
170 connection.send_error(
172 websocket_api.ERR_NOT_SUPPORTED,
173 "Entity does not support announce",
178 connection_test_data = hass.data[CONNECTION_TEST_DATA]
179 connection_id = uuid_util.random_uuid_hex()
180 connection_test_event = asyncio.Event()
181 connection_test_data[connection_id] = connection_test_event
183 hass.async_create_background_task(
184 satellite.async_internal_announce(
185 media_id=f
"{CONNECTION_TEST_URL_BASE}/{connection_id}"
187 f
"assist_satellite_connection_test_{msg['entity_id']}",
191 async
with asyncio.timeout(CONNECTION_TEST_TIMEOUT):
192 await connection_test_event.wait()
193 connection.send_result(msg[
"id"], {
"status":
"success"})
195 connection.send_result(msg[
"id"], {
"status":
"timeout"})
197 connection_test_data.pop(connection_id,
None)
198
None async_register_websocket_api(HomeAssistant hass)
None websocket_set_wake_words(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
None websocket_get_configuration(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
None websocket_intercept_wake_word(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
None websocket_test_connection(HomeAssistant hass, websocket_api.connection.ActiveConnection connection, dict[str, Any] msg)
CalendarEntity get_entity(HomeAssistant hass, str entity_id)