Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/alexxit/yandexdialogs

Компонент для управления Home Assistant через Яндекс.Диалоги
https://github.com/alexxit/yandexdialogs

home-assistant yandex-dialogs

Last synced: about 4 hours ago
JSON representation

Компонент для управления Home Assistant через Яндекс.Диалоги

Awesome Lists containing this project

README

        

# Яндекс.Диалоги для Home Assistant

[![](https://img.shields.io/badge/HACS-Custom-orange.svg)](https://github.com/custom-components/hacs)
![](https://img.shields.io/github/stars/AlexxIT/YandexDialogs?style=flat-square&logo=github)

Компонент позволяет управлять [Home Assistant](https://www.home-assistant.io/) из [Яндекс Алисы](https://yandex.ru/alice) через собственный навык в [Яндекс.Диалогах](https://dialogs.yandex.ru/developer).

С помощью Яндекс.Диалогов вы можете настроить реакцию Алисы на абсолютно любые фразы. А не только те, что заложили разработчики. Яндекс Алиса работает на колонках, мобильных приложениях Яндекса и на компьютере в браузере Яндекса.

Особенностью управления через Диалоги является необходимость называть имя навыка:

- Алиса, узнай у **Умного дома** температуру в спальне
- Алиса, попроси **Мой дом** включить Ютуб на телевизоре в зале
- Алиса, узнай у **Домашнего ассистента** когда было последнее движение у входной двери

Для начала диалога без использования имени навыка есть два метода:

- Создать сценарий Яндекса, например: если я скажу "включи мультики на телевизоре", умная колонка выполнит команду "скажи навыку умный дом включи мультики на ТВ"
- Начинать диалог из Home Assistant с помощью компонента [Yandex.Station](https://github.com/AlexxIT/YandexStation#%D0%B4%D0%B8%D0%B0%D0%BB%D0%BE%D0%B3-%D1%81-%D0%BA%D0%BE%D0%BB%D0%BE%D0%BD%D0%BA%D0%BE%D0%B9)

Для работы компонента нужен рабочий внешний доступ к вашему Home Assistant по протоколу HTTPS. Его можно получить через другой мой компонент - [Dataplicity](https://github.com/AlexxIT/Dataplicity).

Не стоит путать Яндекс.Диалоги с Умным домом Яндекса. Это разные технологии, не связанные между собой.

---

* [Установка](#установка)
* [Настройка](#настройка)
* [Использование](#использование)
* [Управление](#управление)
* [Управление через автоматизации на событиях](#управление-через-автоматизации-на-событиях)
* [Управление через Intent Script](#управление-через-intent-script)
* [Управление через python-скрипт](#управление-через-python-скрипт)
* [Настройка Интентов в Яндекс.Диалогах](#настройка-интентов-в-яндексдиалогах)
* [Пример калькулятора](#пример-калькулятора)
* [Пример тепературы в разных помещениях](#пример-тепературы-в-разных-помещениях)

## Установка

**Способ 1.** [HACS](https://hacs.xyz/) > Интеграции > 3 точки (правый верхний угол) > Пользовательские репозитории > URL: `AlexxIT/YandexDialogs`, Категория: Интеграция > Добавить > подождать > YandexDialogs > Установить

**Способ 2.** Вручную скопируйте папку `yandex_dialogs` из [latest release](https://github.com/AlexxIT/YandexDialogs/releases/latest) в директорию `/config/custom_components`.

## Настройка

**Способ 1.** GUI

> Настройки > Интеграции > Добавить интеграцию > **Yandex Dialogs**

Если интеграции нет в списке - очистите кэш браузера.

**Способ 2.** YAML

```yaml
yandex_dialogs:
```

## Использование

Если у вас уже работает компонент [YandexStation](https://github.com/AlexxIT/YandexStation) и есть внешний доступ по HTTPS - этот компонент может автоматически создать и настроить навык в Яндекс.Диалогах.

Для этого ещё раз добавьте интеграцию:

> Настройки > Интеграции > Добавить интеграцию > **Yandex Dialogs**

И укажите:

- аккаунт Яндекса, от имени которого создавать Диалог
- публичную HTTPS-ссылку на ваш сервер Home Assistant
- имя навыка (Яндекс требует имя из двух слов)

Компонент автоматически создаст новый приватный диалог, опубликует его и сохранит идентификатор вашего пользователя в настройки интеграции. Навык публикуется в течение нескольких минут!

По умолчанию приватный навык доступен только вашему пользователю. Но для дополнительной безопасности можно ограничить доступ только списку пользователей. Идентификаторы пользователей уникальны для связки **пользователь+навык** и выглядят примерно так: `ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0123456`. Если список пользователей пуст - дополнительная проверка выключена.

При необходимости вы можете создать несколько диалогов с разными именами.

**PS:** При желании можете самостоятельно создать приватный навык с Webhook на ваш Home Assistant: `https://myhome.duckdns.org/api/yandex_dialogs`

## Управление

Поддерживается обработка команд диалога разными способами:

- Управление через [автоматизации](https://www.home-assistant.io/docs/automation/) на событиях
- Управление через [Intent Script](https://www.home-assistant.io/integrations/intent_script/)
- Управление через python-скрипт

### Управление через автоматизации на событиях

**Внимание:** у вас несколько секунд, чтоб вызвать событие с текстовым результатом ответа.

Этот подход можно использовать в Node-RED.

При обращении к навыку создаётся событие `yandex_intent` с параметрами:

- `text` - произнесённая фраза
- `command` - фраза, почищенная от знаков препинания и числетельные преобразованы в числа
- `intent` - интент это обозначение "типовой" фразы. Например, для ответов "да" или "хорошо" здесь будет значение `YANDEX.CONFIRM`. При желании вы можете настраивать свои интенты (описано ниже)
- `session`, `user`, `application` - "хранилище" [состояний](https://yandex.ru/dev/dialogs/alice/doc/request.html#request__state-desc) диалога
- `...` - другие переменные, которые вы прописали в Интенте в Яндекс.Диалогах

Для ответа вы должны сами вызвать событие `yandex_intent_response` с параметрами:

- `text` - опциональный, текст ответа
- `tts` - опциональный, ответ в [формате TTS](https://yandex.ru/dev/dialogs/alice/doc/speech-tuning.html)
- `end_session`, опциональный, по умолчанию `True`, "выйти" из диалога после ответа
- `session`, `user`, `application` - опциональные, новое значение "хранилища" состояний. Состояния `session` и `application` не переносятся между разными шагами диалога автоматически!

Для ответа вы можете заполнить или `text` или `tts` в зависимости от того, нужно ли вам произнести ответ со [спецэффектами TTS](https://github.com/AlexxIT/YandexStation#%D1%81%D0%BF%D0%B5%D1%86%D1%8D%D1%84%D1%84%D0%B5%D0%BA%D1%82%D1%8B-%D0%B2-tts).

```yaml
automation:
- trigger:
platform: event
event_type: yandex_intent # это событие ОТ вашего навыка
event_data:
text: привет # проверяем точное совпадение с фразой "привет"
action:
event: yandex_intent_response # это наш ответ навыку, нужно уложиться в пару секунд
event_data:
text: "{{ ['слушаю', 'здесь я', 'на связи']|random }}"

- trigger:
platform: event
event_type: yandex_intent
event_data:
intent: calc # проверяем на совпадение с Интентом калькулятора
action:
- service: persistent_notification.create
data:
title: Яндекс Калькулятор
message: "{{ trigger.event.data.text }}"
- event: yandex_intent_response
event_data: # есть все переменные, как и в примере выше
text: >-
{% if trigger.event.data.action == 'плюс' %}
{{ trigger.event.data.x + trigger.event.data.y }}
{% elif trigger.event.data.action == 'минус' %}
{{ trigger.event.data.x - trigger.event.data.y }}
{% elif trigger.event.data.action == 'умножить на' %}
{{ trigger.event.data.x * trigger.event.data.y }}
{% elif trigger.event.data.action == 'разделить на' %}
{{ trigger.event.data.x / trigger.event.data.y }}
{% endif %}
```

**Управление продолжением диалога**

Фраза "Алиса, включи навык Умный дома" включит навык и навык будет ждать вашей команды.

Фраза "Алиса, спроси у Умного дома сколько градусов в зале" - вызовет ваш навык, получит ответ и тут же выйдет из него назад к Алисе.

Чтоб изменить это поведение, используйте параметр `end_session`. С ним вы можете либо продолжить разговор при фразе "Алиса спроси у Умного дома...". Либо прервать диалог в любом месте.

### Управление через Intent Script

Альтернативный способ управления диалогом. Более сложный и не рекомендуется к использованию.

Существует скрипт по умолчанию `yandex_default`. Он выполняется когда для фразы не совпал ни один Интент.

`action` опциональный. Он выполняется ДО генерации ответа и при желании может на него повлиять.

**Внимание:** у вашего скрипта пара секунд, чтоб вернуть ответ. Алиса дольше не ждёт. Если ваш скрипт выполняется дольше - запускайте его ассинхронно (читайте [документацию](https://www.home-assistant.io/integrations/intent_script/)).

Вам доступны переменные:
- `text` - произнесённая фраза
- `command` - фраза, почищенная от знаков препинания и числетельные преобразованы в числа
- `intent` - если фраза совпала, тут будет ID Интента из Яндекс.Диалогов
- `...` - другие переменные, которые вы прописали в Интенте в Яндекс.Диалогах

```yaml
intent_script:
yandex_default: # это скрипт по умолчанию
action: # действие опционально и должно уложиться в пару секунд
- service: persistent_notification.create
data:
title: Команда из Яндекса
message: "{{ text }}"
speech: # фраза для ответа, поддерживает шаблоны
text: >-
{% if text == 'привет' %}
{{ ['слушаю', 'здесь я', 'на связи']|random }}
{% elif text == 'какая температура в спальне' %}
Температура {{ states("sensor.temperature_bedroom")|round }} °C
{% else %}
Не могу выполнить: {{ text }}
{% endif %}

calc: # это Интент калькулятора (пример как настроить ниже)
action:
- service: persistent_notification.create
data:
title: Яндекс Калькулятор
message: "{{ text }}"
speech: # в нём распознались переменные action, x и y
text: >-
{% if action == 'плюс' %}
{{ x+y }}
{% elif action == 'минус' %}
{{ x-y }}
{% elif action == 'умножить на' %}
{{ x*y }}
{% elif action == 'разделить на' %}
{{ x/y }}
{% endif %}

temperature: # это Интент температуры в помещении (пример как настроить ниже)
speech:
text: >-
{% if room == 'в зале' %}
Температура в зале {{ states("sensor.temperature_hall")|round }} °C
{% elif room == 'в ванной' %}
Температура в ванной {{ states("sensor.temperature_bathroom")|round }} °C
{% elif room == 'на балконе' %}
Температура на балконе {{ states("sensor.temperature_balcony")|round }} °C
{% endif %}
```

### Управление через python-скрипт

- Python-код можно писать во внешнем файле или сразу в YAML
- Код из внешнего файла загружается при каждом вызове диалога (его можно закешировать при старте Hass)
- Можно установить внешние зависимости python через pip
- Синтаксис скрипта совместим с функциями [Yandex Cloud](https://yandex.ru/dev/dialogs/alice/doc/quickstart-programming.html)

```yaml
yandex_dialogs:
requirements: # можно установить внешние библиотеки python
- requests
file: dialogs.py # можно писать код в внемнем файле
cache: True # закешировать код внешнего файла (по умолчанию выключено)
source: |
def handler(event, context):
return {"response": {"text": "OK"}, "version": "1.0"}
```

Пример скрипта (подробнее в [документации](https://yandex.ru/dev/dialogs/alice/doc/response.html)):

```python
def make_response(event: dict, text: str, end_session=False) -> dict:
return {
"version": event["version"],
"session": event["session"],
"response": {"text": text, "end_session": end_session},
}

def handler(event: dict, context: dict) -> dict:
return make_response(event, "Ну привет!")
```

## Настройка Интентов в Яндекс.Диалогах

Платформа Яндекс.Диалогов позволяет гибко обрабатывать сказанные фразы через [Natural Language Processing](https://yandex.ru/dev/dialogs/alice/doc/nlu-docpage/) (NLU) от Яндекса.

Фраза, которую нужно распознать, называется Интентом. ID интента и все составляющие разобранной фразы прилетят в Home Assistant. И их можно использовать в автоматизациях.

При желании вы можете не пользоваться Интентами, а анализовать фразы в автоматизациях Home Assistant или Node-RED.

- `$room` - слово с долларом это переменная
- `[...]` - квадрытные скобки означают, что слова могут идти в любом порядке
- `(какая)?` - вопрос означает, что слова может не быть
- `%lemma` - означает режим сравнение без учёта формы слова (например "*включай свет*" приравнивается к "*включи свет*")

Полная [документация](https://yandex.ru/dev/dialogs/alice/doc/nlu-docpage/).

Интенты можно настраивать только после публикации навыка. Любые изменения в интентах требуют новой публикации (занимает пару минут).

![](assets/intents1.png)

### Пример калькулятора

![](assets/intents2.png)

```
root:
сколько будет $x $action $y
slots:
x:
source: $x
type: YANDEX.NUMBER
y:
source: $y
type: YANDEX.NUMBER
action:
source: $action
$x:
$YANDEX.NUMBER
$y:
$YANDEX.NUMBER
$action:
плюс | минус | умножить на | разделить на
```

### Пример тепературы в разных помещениях

![](assets/intents3.png)

```
root:
[(какая)? температура $room]
[сколько градусов $room]
slots:
room:
source: $room
$room:
в зале | в ванной | на балконе
```