Обмен данными при голосовых запросах в Canvas App
По умолчанию голосовые команды, передаются в сценарий запущенного смартапа.
Схема обработки голосовой команды на примере демо-приложения:
Стандартные команды навигации не передаются в сценарий.
Описание обработки голосовой команды:
Пользователь произносит команду «Напомнить купить карандаши».
Ассистент запрашивает данные об экране приложения (состояние фронтенда) с помощью метода
getState()
.Данные передаются в объекте AssistantAppState, который хранится на фронтенде в ожидании запроса
getState()
.Фронтенд должен вернуть данные в течение 200 мс, в противном случае сценарий получит устаревшие данные или пустой объект, если данные отсутствуют.
Ассистент передает запрос
MESSAGE_TO_SKILL
в сценарий смартапа.Данные о состоянии приложения передаются в поле
payload.meta.state.<имя_состояния_из_системного_хранилища>
, а разбор реплики пользователя в полеpayload.message
.Сценарий обрабатывает сообщение и возвращает ассистенту объект с описанием ответа ассистента.
/src/scenario/scenario.tsAddNote: {
match: regexp(/^(записать|напомнить|добавить запись) (?<note>.+)$/i),
handle: addNote,
},Сценарий вызывает обработчик
AddNote
:/src/scenario/handlers.tsexport const addNote: SaluteHandler<SaluteRequest<NoteVariable>> = ({ req, res }) => {
const { note } = req.variables;
res.appendCommand<AddNoteCommand>({ type: 'add_note', payload: { note } });
res.appendSuggestions(['Запиши купить молоко', 'Добавь запись помыть машину']);
res.setPronounceText('Добавлено');
res.appendBubble('Добавлено');
res.setAutoListening(true);
};Обработчик добавляет к ответу
ANSWER_TO_USER
команду типаsmart_app_data
с данными, которые надо отобразить на фронтенде:{
"command": {
"type": "smart_app_data",
"action": {
"type": "add_note",
"payload": "купить карандаши"
}
}
}Сценарий передает ответ ассистенту.
Ассистент разбирает ответ
ANSWER_TO_USER
и передает данные в ОС, которая передает их на фронтенд.Фронтенд использует метод
assistant.on('data', dataHandler);
в файлеsrc/utils/assistant.ts
чтобы обработать сообщение от ОС.Метод использует обработчик
dataHandler
, логика которого меняется в зависимости от типа команды:/src/utils/assistant.tsexport const dataHandler = (command: AssistantClientCustomizedCommand<AssistantSmartAppData>) => {
let navigation: AssistantNavigationCommand['navigation'] | undefined;
switch (command.type) {
// Обработка голоса ассистента
case 'character':
if (Router.router) {
replaceRouterCharacter(command.character.id);
} else {
waitForRouter().then(() => replaceRouterCharacter(command.character.id));
}
break;
// Обработка навигационной команды
case 'navigation':
navigation = (command as AssistantNavigationCommand).navigation;
break;
// Обработка коанды smart_app_data, которая содержит данные о записи
case 'smart_app_data':
smartAppDataHandler(command.smart_app_data);
break;
default:
break;
}
// Обработка навигационных команд
if (navigation) {
switch (navigation.command) {
case 'UP':
window.scrollTo(0, window.scrollY - 500);
break;
case 'DOWN':
window.scrollTo(0, window.scrollY + 500);
break;
default:
break;
}
}
};Ассистент сообщает пользователю об успешном добавлении элемента списка:
/src/scenario/handlers.ts// Обработчик addNote
// Задает реплику, которую нужно произнести
res.setPronounceText('Добавлено');
// Задает текст сообщения в чате
res.appendBubble('Добавлено');Добавление элемента списка и оповещение пользователя выполняются параллельно.
В результате в интерфейсе смартапа появляется новая запись.
По такой же схеме работают текстовые команды пользователя в чате с ассистентом.