Предисловие
Статья по факту сумбурная, изобилует рассуждениями и наблюдениями автора, и по сути, в ней больше разъяснений о том, как интегрировать dialogflow. На создание статьи сподвиг перевод LMSControl на русский язык и его управление с Алисой.
Что хотелось бы...
На данный момент Яндекс, как в прочем и google, не обладают функционалом по получению данных в своих голосовых помощниках с ваших датчиков и сенсоров из home asisstant. Ниже описанным методом мы можем спрашивать у Алисы (гугла) к примеру, какая температура в комнате, кто из person где находится, можем попросить Алису скачать фильм в вашу библиотеку Plex, запрашивать состояние сущностей и многое другое, в том числе, и управлять сущностями ha. Сразу хочу отметить имеющиеся на данный момент минусы. Запрос идет через одно, а то и два (три) облака, что вызывает некоторую задержку в ответе. Взаимодействие ведется через Ваш приватный навык в яндекс.диалогах. Что заставляет делать лишние телодвижения в виде вызова своего навыка, что, в свою очередь, можно обойти созданием сценария в квазаре. Но тогда вы должны точно формулировать запрос так, как он указан в сценарии (и чего не нужно делать при вызове навыка, об этом ниже).
Что необходимо иметь перед дальнейшей настройкой
Доступ к Вашему home asisstant из внешней сети. С доступом по SSL.Аккаунт google (для создания диалога Dialogflow, при желании колонка гугла, на которой все это также должно работать).Аккаунт Яндекс и колонка с Алисой.
Что будем использовать (пункты к выполнению)
Созданный Вами проект на Dialogflow. Это сервис, позволяющий создавать чат-ботов для разных платформ и языков на разных устройствах.Интеграцию Dialogflow в HA. Для связки гугловского Dialogflow с Вашим Яндекс.Диалогом понадобится очередное облако, в виде проекта Dialogflower.com.Созданный Вами навык Алисы на Яндекс.Диалогах (модерация может занимать до 3-х дней).
Приступим
Пункт 1. Переходим по ссылке на сайт Dialogflow, заходим под Вашим Google аккаунтом. В меню слева создаем нового агента, нажимая Create new agent. В самом верху даем имя агенту, в моем случае - HA. Меняем DEFAULT LANGUAGE на Russian-RU, а DEFAULT TIME ZONE меняем на Вашу временную зону. Жмем вверху синюю кнопку Save и ждем сохранения. Переходим в меню слева Intents. Видим два интента:
- Ответ приветствие по умолчанию - Default Welcome Intent.
- И ответ, когда не найдено сопоставление вашему запросу - Default Fallback Intent.
Привет привет;И снова здравствуйте;Хай и т.д.
После добавления, жмем сохранить. Тоже самое делаем с Default Fallback Intent. Добавляем в Responses наши ответы:А вот это не совсем понятно;Вот эта последняя фраза мне не ясна;Не совсем понимаю, о чём ты.
После добавления жмем сохранить. Это необходимо для того, чтобы понимать, что диалог работает корректно, в случае не восприятия вашего запроса.
Теперь добавляем наш новый интент, будем спрашивать температуру в системе отопления с датчика esphome, примотанному к трубе (другими пока не обзавелся).
Жмем плюс напротив Intents. Заполняем поля (придумываем на английском). Имя сверху - Temp. Заполняем Training phrases нашими запросами (жмем Add Training phrases).
Какая температура в системе отопления?;Какая температура отопления?;Сколько градусов в котле?
В самом низу в графе Fulfillment выставляем переключатель Enable webhook call for this intent на вкл.
Чуть выше в графе Responses обязательно выставляем переключатель Set this intent as end of conversation на вкл.
Это позволит сразу выходить из навыка после получения ответа.
(Если этого не сделать, то Алиса будет помнить, что вы запустили навык и теперь будет ожидать следующей команды от вас, и, скажем, запрос "включи музыку" не обработает, т.к. ваш навык настроен не на это. Лечится просьбой "Алиса хватит". )
Поднимаемся выше и заполняем в том же окне Action and parameters (жмем Add Action and parameters). Тут мы указываем Action в поле Enter name action. Вносим Temperature. При запросе "Какая температура в системе отопления" dialogflow вызовет Action Temperature, сопоставленный с Вашим конфигом. Пример конфига ниже.
(Сейчас нет смысла его добавлять, мы сделаем это позже, а сейчас работаем с dialogflow).
dialogflow: intent_script: Temperature: speech: text: Температура отопления {{ states('sensor.sonoff_mini_warm_floor_temperature') }} градус по цельсию
Вот почему action в интенте запроса температуры в dialogflow будет иметь имя Temperature, по аналогии с yaml конфигом. Далее Жмем сверху синюю кнопку Save и сохраняем интент.
В дальнейшем, при добавлении новых запросов, в dialogflow нужно лишь создать новый интент с вашими запросами.
Пункт 2. Для этого добавим интеграцию dialogflow. Через Ваш веб интерфейс HA. Настройки, интеграция, плюсик в углу. Ищем dialogflow и получаем токен, копируем и сохраняем себе (советую сохранить его отдельно, так как вы его тут видите последний раз, возможно, он измениться при удалении и добавлении вновь).
На странице dialogflow переходим в меню слева Fulfillment. Включаем Webhook. И вставляем в url наш токен полученный чуть выше. Прокручиваем вниз до синей кнопки Save. Сохраняем.
Теперь закидываем в конфиг вашего ha настройки с ответами на ваши запросы. Код уже приводил выше.
dialogflow: #включаем поддержку dialogflow (возможно интеграция уже сделала это за нас, но у меня так) intent_script: # тут объявляем и пишем интент скрип Temperature: # название должно совпадать с тем что указанно будет в dialogflow в вашем интенте в поле action speech: text: Температура отопления {{ states('sensor.sonoff_mini_warm_floor_temperature') }} градус # Текст с вашим ответом, тут можете использовать шаблоны да бы разнообразить жизнь. # action: # - service: notify.pushbullet # data_template: # message: Кто-то спросил про отопление
Теперь вы можете протестировать и убедиться, что связь с dialogflow работает. Для этого на сайте вашего проекта dialogflow в правом верхнем углу есть тестирование работоспособности. Можно внести в текстовое поле любую фразу из тех, которые мы добавляли в интент. Вставляем, к примеру, "Сколько градусов в котле" жмем энтер и получаем ответ чуть ниже, что-то вроде "Температура отопления 40.1 градус". Также для теста можно использовать микрофон, кнопочка рядом. Протестируйте систему и с неправильными запросами "Какой из телевизоров включен?". Вы должны получить ответ из вашего списка "Default Fallback Intent", типа "Можешь сказать то же самое другими словами?"(примечательно, что dialogflow на запрос "как оно" отвечает "Отлично, спасибо что интересуешься", но такого в интентах мы не заводили).
Для Алисы же нужно создать приватный диалог. И связать его с нашим агентом в dialogflow.
в поле "Вставьте его здесь". Жмете "Получите OAuth токен и укажите его здесь" и вас перебросит в Яндекс, копируем токен с белого экрана и возвращаемся на dialogflower.com. Вставляем.
После нажатия готово, вы получите url с вебхуком для навыка Алисы. Копируем его в буфер и не теряем.
- Добавляем иконку (любую картинку, масштабируется);
- Имя навыка - несколько слов, в моем случае "кластер двенадцать";
Активационное имя - заполняем сколнениями имени навыка "кластера двенадцать";
- Заполняем примеры запросов выпадающими списками: "Запусти навык" "кластер двенадцать" , "Спроси у" "кластера двенадцать" далее текстом "какая температура отопления";
- Обязательно ставим галочку Приватность, не показывать в диалоге;
- Backend выставляем Webhook url и вставляем из буфера url с вебхуком, полученным от dialogflower.com в конце третьего пункта.
- Описание и Заметки для модератора указываем что-то вроде "Для личного пользования, управление Умным Домом".
(Сразу говорю о том, что с полями активации придётся поиграться).
Также можно изменить голос в навыке на другой, чтобы вы понимали, что сейчас работает - нативная Алиса или ваш навык. Я оставил голос Алисы, как то эстетичнее.
Сохраняем и отправляем на модерацию, она, как правило, занимает пару дней. Возможно, вам вернут навык и укажут на ошибки в полях, тогда исправьте их и отправьте снова. После модерации вы должны опубликовать диалог (кнопка появится там же, где кнопка "на модерацию"). Не пугайтесь слова "опубликовать" - навык приватный и другим не доступен, но он не заработает с вашими колонками без публикации. У меня публикация заняла несколько часов.
Нюансы и отладка
На вкладке тестирование в Яндекс.диалогах вы можете в текстовом поле опробовать работу ваших диалогов. Все те фразы, что вы добавляли в dialogflow, теперь работают тут. После опубликования навыка, диалоги будут доступны к вызову через имя вашего навыка.
Спросите у Алисы в колонке или станции "Спроси кластер двенадцать какая температура отопления" и вы услышите ответ. Сократить запрос до более внятного можно через создание сценария в квазаре (уд яндекса в телефоне). Где на запрос "какая температура отопления" вы ставите запрос к колонке "Спроси кластер двенадцать какая температура отопления".
Минус использования сценариев есть. Вы теряете разнообразие запросов. Запрос сводится к тому, который указан в сценарии.
Также в сценарии нельзя передать параметр. Например, "Алиса скачай Титаник" (данный пример ниже).
Вот еще пару примеров, которые я сделал на пробу.
Первый пример: Спрашиваешь, кто где находится, Алиса отвечает.
intent_script: # Temperature: # speech: # text: Температура отопления {{ states('sensor.sonoff_mini_warm_floor_temperature') }} градус по цельсию WhereAreWeIntent: speech: text: > {% for state in states.person -%} {%- if loop.first %}{% elif loop.last %}а {% else %}{% endif -%} {%- if state.state_with_unit == "Работа" %}{{ state.name | lower }} {{"на работе "}}{%- endif %} {%- if state.state_with_unit == "home" %}{{ state.name | lower }} {{"дома "}}{%- endif %} {%- if state.state_with_unit == "not_home" %}{{ state.name | lower }}{{" не дома "}}{%- endif %} {%- if state.state_with_unit == "Школа" %}{{ state.name | lower }}{{" в школе "}}{%- endif %} {%- endfor %}.
Добавив новый интент в уже имеющемся dialogflow с action WhereAreWeIntent и обучив его запросами, вы сможете спрашивать у Алисы, кто из семьи где находится, если используете персоны и девайстрекеры в ха (шаблоны писать не мастер, но работает прикольно).
А вот второй пример. Я также настроил интеграцию с сервисом OMBI (вкратце - это вебморда для автоматического скачивания фильмов и сериалов с использованием jackett, sonarr, radarr и Plex. Объедение этих сервисов требует отдельного разговора и не относится к теме УД).
Теперь можно попросить "Алиса, скачай голый пистолет", вуаля, фильм в поиске и скоро будет доступен в вашем сервере PLEX.
Пример конфига HA:
intent_script: Dlmovie: speech: text: Хорошо, попробую найти и скачать {{ movie }} action: - service: ombi.submit_movie_request data_template: name: "{{ movie }}"
В dialogflow добавляем новый интент, например, DownloadMovie.
Заполняем action - Dlmovie (тут, опять же, внимательно берем имя, как в конфиге ha).
Для передачи названия фильма в ha, добавим параметр в графе Action and parametrs.
- Заполняем PARAMETER NAME - movie;
- Ставим галку REQUIRED;
- ENTITY из выпадающего списка выберете @sys.any;
- VALVE вписываем $movie.
- Включаем Set this intent as end of conversation (если хотим закрывать диалог после запроса):
Включаем Enable webhook call for this intent.
Далее, заполняем чуть выше Training phrases.
- Поставь на закачку титаник;
- Скачай робокоп 2.
Теперь в каждой строке выделяем имя фильма и в выпадающем списке выбрать @sys.any:movie.
Послесловие
В статье не затронут такой момент, как диалог в контексте типа "Алиса, какая температура?", Алиса будет уточнять "В какой комнате?" (в контексте вопроса), вы уточните "В спальне", получите ответ "В спальне 25". Это все позволяет сделать dialogflow, но я пока не разобрался.
З.Ы. Можно было бы еще рассказать о том, как выпустить тестовое приложение для гугла. Сейчас можно вызывать ваше "приложение" (по аналогии со сценариями алисы) в гугле, но имя "приложение" должно состоять из не менее, чем трех слов. У меня это "Мои сенсоры и датчики". Итого, запрос будет звучать так: "ОК Гугл, спроси Мои сенсоры и датчики какая температура отопления". Что очень длинно.
Гугл ассистент только что добавил работу "Программ" (по аналогии со сценариями Алисы), но русский язык еще не поддерживается. После поддержки русского, запросы можно будет сокращать по аналогии с Алисой. Но это уже совсем другая история, т.к. у меня нет google mini.
Полезная статья=)
Для того чтобы добавить новый запрос, нужно создать новый интент в существующем агенте, далее шаги 3 и 4?
Нет. Грубо говоря 1 и 2 шаг. Добавить новый интент в dialogflow. И новый action скрипт в конфиг ха. Яндекс диалог трогать, модерировать и публиковать заново не нужно.
Спасибо! а то я испугался уже) Отличная замена TTS. Жаль только, что колонки заказал для малины..
"Минус использования сценариев есть. Вы теряете разнообразие запросов. Запрос сводится к тому, который указан в сценарии. "
Этот минус легко обойти. Нужно создать необходимое количество сценариев, вызывающих одну и ту же фразу...
Не совсем понятно как это реализовать: Где на запрос "какая температура отопления" вы ставите запрос к колонке "Спроси кластер двенадцать какая температура отопления". При создании сценария, вбиваю фразу, тут все ОК, а дальше можно выбрать только устройство, вписать другую фразу нет возможности.
Или этот способ работает только через колонку?
Интересно, а можно ли таким образом сделать односторонний TTS с Я.Станцией? То есть, вызов сервиса со стороны HA спровоцирует какую-нибудь фразу на колонке.
Например: "Кто-то позвонил в дверь" или "В увлажнителе закончилась вода".
Очень не хватает этой фичи у Станции. Остальные колонки давно такое умеют.
К сожалению пока никак. Поставьте рядом умеющую колонку. Пусть она тихо спрашивает Алису. А та уже орет что нужно в ответ))) шутка
Вообще никаких проблем. Автоматизация на любой эвент и будет говорить что-угодно. Вот https://github.com/AlexxIT/YandexStation">компонент.
Вообще не смог понять смысл костылей этой статьи. Зачем к Яндексу прикручивать компонент Гугла...
Увы, у меня Станция Мини, там этот компонент не поддерживается :(
обещали вот-вот пробросить...
Вы с разрабами общались? Или откуда дровишки?
Уже поддерживается
Например так:
intent_script:
temperature_living:
speech:
text: >
{% set plural_form = ['градус','градуса','градусов'] %}
{% set plural_num = states('sensor.temperature')|int %}
Температура в гостинной {{ plural_num }} {%if((plural_num-plural_num%10)%100!=10)%}{%if plural_num%10==1%}{{plural_form[0]}}{%elif plural_num%10>=2 and plural_num%10<=4%}{{plural_form[1]}}{%else%}{{plural_form[2]}}{%endif%}{%else%}{{plural_form[2]}}{%endif%}
Ответы будут такие:
Температура в гостинной 21 градус
Температура в гостинной 22 градуса
Температура в гостинной 25 градусов
Или просто поставить такой компонент. Правда некоторые пользователи говорят, что не всегда грузится. У себя не могу отловить эту проблему :(
https://github.com/AlexxIT/MorphNumbers">https://github.com/AlexxIT/MorphNumbers
А можно просто значок °C использовать