Таймеры, несколько команд устройству, TTS (NodeJS): различия между версиями
Нет описания правки |
Нет описания правки |
||
| (не показано 14 промежуточных версий 3 участников) | |||
| Строка 5: | Строка 5: | ||
{{Hands}} | {{Hands}} | ||
<pre class="red"> | |||
13.10.2020 Появилась частичная поддержка таймеров "из коробки". Яндекс реализовал таймеры для включения/выключения устройств. | |||
</pre> | |||
Соответствующая новость была размещена в телеграм канале "[https://t.me/yandexdb/413 Около Яндекс.станции]". | |||
Таймеры для сценариев пока отсутствуют и нет поддержки расписания. | |||
<pre class="red"> | |||
21.01.2021 Появилась поддержка таймеров для сценариев и расписания для них же. | |||
</pre> | |||
Соответствующая новость была размещена в телеграм канале "[https://t.me/yandexdb/456 Около Яндекс.станции]". | |||
| Строка 18: | Строка 29: | ||
* Выключи люстру '''и''' включи телевизор | * Выключи люстру '''и''' включи телевизор | ||
* Включи аквариум '''и''' телевизор '''и''' выключи люстру | * Включи аквариум '''и''' телевизор '''и''' выключи люстру | ||
Выполнять сценарии в определенное время. Примеры: | |||
* Добавить таймер включи ночную громкость в 23 часа | * Добавить таймер включи ночную громкость в 23 часа | ||
* Добавить таймер включи утреннюю громкость в 8 часов | * Добавить таймер включи утреннюю громкость в 8 часов | ||
* Выключи телевизор через 15 минут | |||
Нам понадобятся: | Нам понадобятся: | ||
* Сервер/хостинг с поддержкой [https://nodejs.org/ NodeJS], и | * Сервер/хостинг с поддержкой [https://nodejs.org/ NodeJS] (из бесплатных вариантов [https://yandex.ru/blog/dialogs/navyki-alisy-teper-mozhno-razmeschat-v-yandeks-oblake-besplatno-i-prosto Yandex Cloud Functions], но с ограничением по функционалу ''(без таймеров)'' или [https://www.oracle.com/ru/cloud/free/ Oracle Cloud Free Tier] ''(в чате писали что поднимали там nodejs)''), и | ||
* Этот [https://github.com/subnetsRU/alice-command-skill/blob/master/index.js полезный скрипт], который является навыком для Алисы. | * Этот [https://github.com/subnetsRU/alice-command-skill/blob/master/index.js полезный скрипт], который является навыком для Алисы. | ||
Наши действия: | Наши действия: | ||
| Строка 31: | Строка 43: | ||
* Устанавливаем и запускаем скрипт alice-command-skill (код навыка) на сервере/хостинге; | * Устанавливаем и запускаем скрипт alice-command-skill (код навыка) на сервере/хостинге; | ||
* Создаём нужные нам сценарии умного дома в приложении Яндекс; | * Создаём нужные нам сценарии умного дома в приложении Яндекс; | ||
* Наслаждаемся. | * Наслаждаемся новым, недоступным пока в Умном Доме Яндекс, функционалом. | ||
== Установка скрипта == | == Установка скрипта == | ||
| Строка 45: | Строка 57: | ||
Можно переходить к настройке. Правке файла с настройками - config.js. | Можно переходить к настройке. Правке файла с настройками - config.js. | ||
После чего запустите навык: | |||
<pre> | |||
# npm start | |||
</pre> | |||
== Настройка == | == Настройка == | ||
| Строка 58: | Строка 74: | ||
Создаём свой навык в [https://dialogs.yandex.ru/developer dialogs.yandex.ru] ([https://yandex.ru/dev/dialogs/alice/doc/protocol-docpage/ документация]): | Создаём свой навык в [https://dialogs.yandex.ru/developer dialogs.yandex.ru] ([https://yandex.ru/dev/dialogs/alice/doc/protocol-docpage/ документация]): | ||
# Задаём имя навыка (как будем к нему обращаться, в моём примере навык называется "дом вируса", у вас будет своё название); | # Задаём имя навыка (как будем к нему обращаться, в моём примере навык называется "''дом вируса''", у вас будет своё название); | ||
# В ''Webhook URL'' - имя домена или IP-адрес, где расположен скрипт ''alice-command-skill'', и порт (указан в ''config.js'', по умолчанию 8443); | # В ''Webhook URL'' - имя домена или IP-адрес, где расположен скрипт ''alice-command-skill'', и порт (указан в ''config.js'', по умолчанию 8443); | ||
# Указываем, что навык приватный! | # Указываем, что навык '''приватный'''! | ||
# Заполняем остальные обязательные поля; | # Заполняем остальные обязательные поля; | ||
# Отправляем навык на модерацию, ждём размещения в каталоге (вам придёт письмо-оповещение). | # Отправляем навык на модерацию, ждём размещения в каталоге (вам придёт письмо-оповещение). | ||
* Добавляем необходимую информацию в config.js; | * Добавляем необходимую информацию в config.js: | ||
* Куда логировать: | |||
<p class="tocopy">log: { | |||
<br> type: 'cli', //cli - логировать только в консоль; log - логировать только в файл; all - логировать в консоль и файл; | |||
<br> file: 'acs.log', //название файла с логами, по умолчанию acs.log | |||
<br>}, | |||
</p> | |||
* Указываем путь до SSL сертификата и его ключа: | * Указываем путь до SSL сертификата и его ключа: | ||
<p class="tocopy">ssl: { | <p class="tocopy">ssl: { | ||
| Строка 72: | Строка 94: | ||
</p> | </p> | ||
<pre class="red"> | |||
Самоподписанные сертификаты с 2021 года полностью исключены. | |||
Валидный сертификат можно бесплатно получить на https://www.sslforfree.com/ или https://letsencrypt.org/ru/ | |||
</pre> | |||
* Указываем порт, на котором будут ожидаться запросы от яндекс диалогов и который мы указали в ''Webhook URL'', например: <span class="tocopy">port: 8443,</span> | |||
* Для авторизации в Яндекс необходимо задать параметры или login и pass или cookie. | |||
** Для того, чтобы ваш логин и пароль от вашего Яндекс аккаунта не был указан в config.js в явном виде, необходимо выполнить: | |||
<pre> | |||
# npm start auth | |||
</pre> | |||
После чего вам будет предложено ввести логин и пароль от вашего Яндекс аккаунта: | |||
<pre> | |||
Yandex login ? my-Yandex-login | |||
Yandex password ? my-secret-password | |||
Login for config.js: bXktWWFuZGV4LWxvZ2lu | |||
Pass for config.js: bXktc2VjcmV0LXBhc3N3b3Jk | |||
</pre> | |||
После чего полученные значения можно внести в config.js: | |||
<pre> | |||
login: 'bXktWWFuZGV4LWxvZ2lu', | |||
pass: 'bXktc2VjcmV0LXBhc3N3b3Jk', | |||
</pre> | |||
Отвечаю на немые вопросы: | |||
* введенные вами логин и пароль никуда не отправляются и разработчику данного скрипта они и даром не нужны, даже если будете просить взять - не возьму; | |||
* да, такой способ защиты ваших данных является защитой, как говорят, от дурака и не сокроют эти данные от опытных пользователей, если вы покажете ''config.js'' кому-то. В любом случае одним только взглядом в ''config.js'' логина и пароля не узнать и именно этого я пытался достичь; | |||
* Значение параметра "cookie" можно взять так: | * Значение параметра "cookie" (''если не указаны параметры login и pass'') можно взять так: | ||
** Открываем консоль браузера (F12, вкладка "Network") | ** Открываем консоль браузера (F12, вкладка "Network") | ||
** Заходим, к примеру, в [https://iot.quasar.yandex.ru/m/user/devices квазар] | ** Заходим, к примеру, в [https://iot.quasar.yandex.ru/m/user/devices квазар] | ||
| Строка 84: | Строка 128: | ||
** Копируем из Request Headers часть строки после "Cookie": | ** Копируем из Request Headers часть строки после "Cookie": | ||
cookie: 'yandexuid=XXXXXXXXXXXXXXXXXX;uniqueuid=YYYYYYYYYYYYYYYYYYY;ну и так далее...', | cookie: 'yandexuid=XXXXXXXXXXXXXXXXXX;uniqueuid=YYYYYYYYYYYYYYYYYYY;ну и так далее...', | ||
Учтите, что cookie могут устареть и вам придется повторить операцию и обновить значение параметра "cookie". | |||
Если заданы логин и пароль, то параметр "cookie", при успешной авторизации в Яндекс, будет заполнен автоматически. | |||
* Находим идентификатор Яндекс.Станции, которая будет отвечать на команды. Этот ID можно увидеть на [https://iot.quasar.yandex.ru/m/user/devices странице с устройствами]. | * Находим идентификатор Яндекс.Станции, которая будет отвечать на команды. Этот ID можно увидеть на [https://iot.quasar.yandex.ru/m/user/devices странице с устройствами]. | ||
* Укажем | * Укажем ID яндекс.станции в ''config'' (это только пример! У вас будет другое значение): | ||
speaker: '2077cfa6-2365-4ed4-97d5-4b46895762af', | speaker: '2077cfa6-2365-4ed4-97d5-4b46895762af', | ||
* Задаём каким устройствам/пользователям разрешено использовать наш навык: | |||
<pre> | <pre> | ||
auth:{ | auth:{ | ||
| Строка 99: | Строка 146: | ||
Их вы сможете узнать когда выполните своё первое обращение к навыку. Будет отображено в консоли (где вы запустили навык) в ''incoming JSON'', который отображает весь пришедший в навык запрос от Яндекс.Диалогов, где: | Их вы сможете узнать когда выполните своё первое обращение к навыку. Будет отображено в консоли (где вы запустили навык) в ''incoming JSON'', который отображает весь пришедший в навык запрос от Яндекс.Диалогов, где: | ||
* '''user.user_id''' - '''идентификатор пользователя''' Яндекса, единый для всех приложений и устройств пользователя. Присутствует только, когда пользователь выполнил вход в аккаунт '''Яндекс''' на устройстве. Никогда не изменяется. | * ''user_id'' это '''user.user_id''' из запроса к навыку - '''идентификатор пользователя''' Яндекса, единый для всех приложений и устройств пользователя. Присутствует только, когда пользователь выполнил вход в аккаунт '''Яндекс''' на устройстве. Никогда не изменяется. | ||
* '''application.application_id''' - '''идентификатор экземпляра приложения''', в котором пользователь общается с Алисой. Присутствует всегда, но может изменяться (например, если переустановите приложение). | * ''application'' это '''application.application_id''' из запроса к навыку - '''идентификатор экземпляра приложения''' (браузер или мобильное приложение), в котором пользователь общается с Алисой. Присутствует всегда, но может изменяться (например, если переустановите приложение). | ||
Поясню по user_id и application. | Поясню по ''user_id'' и ''application''. | ||
Ситуация 1: | Ситуация 1: | ||
* берём смартфон | * берём смартфон | ||
* открываем приложение/браузер яндекс | * открываем приложение/браузер яндекс | ||
* обращаемся к Алисе: "Алиса, попроси | * обращаемся к Алисе: "Алиса, попроси <НАЗВАНИЕ НАВЫКА> помощь" | ||
В этой ситуации в ''incoming JSON'' вы увидите наличие только <b class="green">application.application_id</b>, а <b class="red">user.user_id</b> будет отсутствовать | В этой ситуации в ''incoming JSON'' вы увидите наличие только <b class="green">application.application_id</b>, а <b class="red">user.user_id</b> будет отсутствовать | ||
| Строка 114: | Строка 161: | ||
* открываем приложение/браузер яндекс | * открываем приложение/браузер яндекс | ||
* '''авторизуемся в приложении/браузере яндекс -> [https://passport.yandex.ru/ passport.yandex.ru]''' | * '''авторизуемся в приложении/браузере яндекс -> [https://passport.yandex.ru/ passport.yandex.ru]''' | ||
* обращаемся к Алисе: "Алиса, попроси | * обращаемся к Алисе: "Алиса, попроси <НАЗВАНИЕ НАВЫКА> помощь" | ||
* в ''incoming JSON'' вы увидите наличие <b class="green">application.application_id</b> и <b class="green">user.user_id</b> | * в ''incoming JSON'' вы увидите наличие <b class="green">application.application_id</b> и <b class="green">user.user_id</b> | ||
Если в "ситуация 2" использовать ещё один смартфон, то вы увидите, что ''application.application_id'' будет отличаться, а ''user.user_id'' нет. | |||
Если вы хотите дать возможность управления нескольким устройствам/пользователям, то их можно перечислить через запятую. Пример: | Если вы хотите дать возможность управления нескольким устройствам/пользователям, то их можно перечислить через запятую. Пример: | ||
| Строка 125: | Строка 174: | ||
</pre> | </pre> | ||
Навык производит аутентификацию по любому из этих параметров. Требуется хотя бы одно совпадение. | |||
Задайте интенты (слова на которые будет реагировать навык). | *Задайте интенты (слова на которые будет реагировать навык). | ||
* help - фразы для воспроизведения фраз команды "помощь". | ** help - фразы для воспроизведения фраз команды "помощь". | ||
* enable - слова, которые будут означать команду для сценариев включения | ** enable - слова, которые будут означать команду для сценариев включения | ||
* disable - слова, которые будут означать команду для сценариев выключения | ** disable - слова, которые будут означать команду для сценариев выключения | ||
* timers - слова, которые будут означать команду для работы с таймерами | ** timers - слова, которые будут означать команду для работы с таймерами | ||
* action_add - слова, которые будут означать команду для добавления (например таймера) | ** action_add - слова, которые будут означать команду для добавления (например таймера) | ||
* action_del - слова, которые будут означать команду для удаления (например таймера) | ** action_del - слова, которые будут означать команду для удаления (например таймера) | ||
<pre> | <pre> | ||
| Строка 146: | Строка 196: | ||
</pre> | </pre> | ||
* Задаём с какой периодичностью обрабатывать таймеры: | |||
<pre> | <pre> | ||
timer_period: 5, | timer_period: 5, | ||
</pre> | </pre> | ||
Значение | '''Значение''' указывается '''в минутах'''. По умолчанию 5 минут. | ||
== Выполнение нескольких сценариев за одну команду == | |||
Создадим сценарии, которые мы и собираемся выполнять. | |||
Сделать это можно как в приложении Яндекса ([https://mobile.yandex.ru/apps/android/search/ Android], [https://mobile.yandex.ru/apps/iphone/search/ IOS]), так и в [https://yandex.ru/quasar web-интерфейсе квазара]. | Сделать это можно как в приложении Яндекса ([https://mobile.yandex.ru/apps/android/search/ Android], [https://mobile.yandex.ru/apps/iphone/search/ IOS]), так и в [https://yandex.ru/quasar web-интерфейсе квазара]. | ||
| Строка 184: | Строка 235: | ||
} | } | ||
}, | }, | ||
</pre> | </pre> | ||
| Строка 199: | Строка 245: | ||
== Таймеры == | == Таймеры == | ||
Рассмотрим | Рассмотрим на примере самой частой хотелки - автоматическое понижение/повышение уровня громкости станции в зависимости от времени. Для достижения этой цели потребуется: | ||
1. Создать сценарий для понижения громкости: | 1. Создать сценарий для понижения громкости: | ||
| Строка 222: | Строка 268: | ||
4. Перезапустить навык, т.к. вносились изменения в config.js. | 4. Перезапустить навык, т.к. вносились изменения в config.js. | ||
Теперь говорим Алисе, например: | |||
* "''попроси <НАЗВАНИЕ НАВЫКА> добавить таймер включи ночную громкость в 23 часа''" навык добавит таймер для ежедневного выполнения сценария "''Включи ночную громкость''" в 23 часа, что, в свою очередь, приведет к ежедневной автоматической установке громкости станции на 2 в 23 часа. | * "''попроси <НАЗВАНИЕ НАВЫКА> добавить таймер включи ночную громкость в 23 часа''" - навык добавит таймер для ежедневного выполнения сценария "''Включи ночную громкость''" в 23 часа, что, в свою очередь, приведет к ежедневной автоматической установке громкости станции на 2 в 23 часа. | ||
* "''попроси <НАЗВАНИЕ НАВЫКА> добавить таймер включи утреннюю громкость в 8 часов''" навык добавит таймер для ежедневного выполнения сценария "''Включи утреннюю громкость''" в 8 часов, что, в свою очередь, приведет к ежедневной автоматической установке громкости станции на 5 в 8-мь утра. | * "''попроси <НАЗВАНИЕ НАВЫКА> добавить таймер включи утреннюю громкость в 8 часов''" - навык добавит таймер для ежедневного выполнения сценария "''Включи утреннюю громкость''" в 8 часов, что, в свою очередь, приведет к ежедневной автоматической установке громкости станции на 5 в 8-мь утра. | ||
Созданные вами таймеры навык будет сохранять в файле timers.json. Пример: | Созданные вами таймеры навык будет сохранять в файле ''timers.json''. Пример содержимого файла: | ||
<pre> | <pre> | ||
[ | [ | ||
| Строка 243: | Строка 289: | ||
"hour":"8", | "hour":"8", | ||
"min":"15", | "min":"15", | ||
}, | |||
{ | |||
"name":"телевизор", | |||
"action":"disable", | |||
"id":"3a5550951-c640-468b-a0cc-db5d81dbbe7c", | |||
"once":"1594561800", | |||
} | } | ||
] | ] | ||
| Строка 250: | Строка 302: | ||
* "name" и "action" - для понимания, что это за таймер | * "name" и "action" - для понимания, что это за таймер | ||
* "id" - ID выполняемого сценария | * "id" - ID выполняемого сценария | ||
* "days" - дни, по которым будет выполняться сценарий. В Javascript воскресенье это нулевой день. | * "days" - дни, по которым будет выполняться сценарий. В Javascript воскресенье это нулевой день, а суббота 6. | ||
* "hour" - час, в который будет выполняться сценарий. Если минуты не | * "hour" - час, в который будет выполняться сценарий. | ||
* " | * "min" - минуты, когда будет выполняться сценарий. Если минуты не указаны, то это означает ноль минут. | ||
* "once" - признак одноразового сценария, который будет выполнен в указанное в параметре время (unixtime). | |||
Шаблоны команд, которые нужно использовать для добавления таймера: | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' добавить таймер ''<ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ>'' в ''X'' часов - запуск ежедневно в X часов ровно. | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' добавить таймер ''<ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ>'' в ''X'' часов Y минут - запуск ежедневно в X часов Y минут. | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' добавить таймер ''<ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ>'' по будням в ''X'' часов - запуск по будням в X часов ровно. | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' добавить таймер ''<ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ>'' по выходным в ''X'' часов Y минут - запуск по выходным в X часов Y минут. | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' добавить таймер ''<ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ>'' в ''<НАЗВАНИЕ ДНЯ (или дней) НЕДЕЛИ>'' в ''X'' часов - запуск по перечисленным дням в X часов ровно. | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' добавить таймер ''<ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ>'' через ''Y'' минут - одноразовый запуск через Y минут. | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' добавить таймер ''<ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ>'' через ''X'' часов ''Y'' минут - одноразовый запуск через X часов Y минут. | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' ''<ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ>'' через ''Y'' минут - одноразовый запуск Y минут. | |||
Примеры установки таймеров согласно шаблонам: | |||
* | * попроси дом вируса добавить таймер включи лампу в 21 час | ||
* | * попроси дом вируса добавить таймер выключи люстру в 21 час 10 минут | ||
* | * попроси дом вируса добавить таймер включи коридор по будням в 8 часов | ||
* | * попроси дом вируса добавить таймер выключи коридор по будням в 8 часов 10 минут | ||
* попроси дом вируса добавить таймер выключи телевизор по понедельникам средам пятницам в 22 часа | |||
* попроси дом вируса добавить таймер включи аквариум в субботу в 9 часов 15 минут | |||
* попроси дом вируса добавить таймер выключи аквариум через 4 часа 30 минут | |||
* попроси дом вируса добавить таймер выключи телевизор через 15 минут | |||
* попроси дом вируса выключить телевизор через 5 минут | |||
Команда для удаления таймера аналогична добавлению, но вместо "добавить" нужно произнести "удалить". Ну или просто удалить таймер вручную - отредактировав файл timers.json. | Команда для удаления таймера аналогична его добавлению, но вместо "''добавить''" нужно произнести "''удалить''". Ну или просто удалить таймер вручную - отредактировав файл timers.json. | ||
Одноразовый таймер удаляется сразу после его исполнения. | |||
Узнать какие таймеры установлены можно командами: | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' список таймеров | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' какие установлены таймеры | |||
После правки ''timers.json'' навык перезапускать '''НЕ''' надо. Файл ''timers.json'' будет перечитан автоматически при следующей обработке таймеров, которая производится каждые X минут (где X это значение указанное вами в ''timer_period'' в ''config.js''). | |||
== Послесловие == | == Послесловие == | ||
Если возникают проблемы с выполнением сценария, то необходимо включить логи и смотреть, что происходит при выполнении сценария, по ним. | |||
Для быстрого понимания можно воспользоваться командой: | |||
* попроси ''<НАЗВАНИЕ НАВЫКА>'' отчёт | |||
Навык зачитает статус крайнего выполненного сценария. Так статус "200" - все ОК. Статус "403" или "302" - проблема с авторизацией. | |||
| Строка 276: | Строка 349: | ||
[[Файл:Text_morecommand_tts_nodeJS.mp4]] | [[Файл:Text_morecommand_tts_nodeJS.mp4]] | ||
После внесения изменений в | '''Внимание''': После внесения изменений в файл '''config.js''' (настройки навыка) необходимо перезапускать скрипт навыка. | ||
С автором статьи можно связаться в телеграм: [https://t.me/VirusNet @VirusNet]. | С автором статьи можно связаться в телеграм: [https://t.me/VirusNet @VirusNet]. | ||
[[Category: Умный дом]] | |||
[[Category:Умный дом]] | |||
Текущая версия от 06:42, 4 июня 2021
Телефон вызова экстренных служб - 112.
13.10.2020 Появилась частичная поддержка таймеров "из коробки". Яндекс реализовал таймеры для включения/выключения устройств.
Соответствующая новость была размещена в телеграм канале "Около Яндекс.станции". Таймеры для сценариев пока отсутствуют и нет поддержки расписания.
21.01.2021 Появилась поддержка таймеров для сценариев и расписания для них же.
Соответствующая новость была размещена в телеграм канале "Около Яндекс.станции".
Постановка задачи
По мотивам статьи Алиса, таймеры, TTS и Node-RED, идея работы навыка взята здесь.
Необходима возможность выполнения нескольких сценариев за одну команду для Алисы, а так же возможность указать время выполнения сценария (таймер), не требуя Node-RED.
Выполнять составные команды. Примеры:
- Включи люстру и телевизор
- Выключи люстру и включи телевизор
- Включи аквариум и телевизор и выключи люстру
Выполнять сценарии в определенное время. Примеры:
- Добавить таймер включи ночную громкость в 23 часа
- Добавить таймер включи утреннюю громкость в 8 часов
- Выключи телевизор через 15 минут
Нам понадобятся:
- Сервер/хостинг с поддержкой NodeJS (из бесплатных вариантов Yandex Cloud Functions, но с ограничением по функционалу (без таймеров) или Oracle Cloud Free Tier (в чате писали что поднимали там nodejs)), и
- Этот полезный скрипт, который является навыком для Алисы.
Наши действия:
- Создаём обычный приватный диалог (навык);
- Устанавливаем и запускаем скрипт alice-command-skill (код навыка) на сервере/хостинге;
- Создаём нужные нам сценарии умного дома в приложении Яндекс;
- Наслаждаемся новым, недоступным пока в Умном Доме Яндекс, функционалом.
Установка скрипта
На сервере/хостинге выполняем три простых команды (в каждую из строк можно кликнуть мышью и скопировать нужный текст)
- git clone https://github.com/subnetsRU/alice-command-skill.git
- cd alice-command-skill
- npm install
Можно переходить к настройке. Правке файла с настройками - config.js.
После чего запустите навык:
# npm start
Настройка




Если вы пользуетесь браузером Chrome, то для удобства чтения JSON (вам это понадобится, будет присутствовать ниже) на страницах можно использовать плагин JSON Formatter. Если у вас другой браузер, то вы можете найти похожий плагин и для него.
Создаём свой навык в dialogs.yandex.ru (документация):
- Задаём имя навыка (как будем к нему обращаться, в моём примере навык называется "дом вируса", у вас будет своё название);
- В Webhook URL - имя домена или IP-адрес, где расположен скрипт alice-command-skill, и порт (указан в config.js, по умолчанию 8443);
- Указываем, что навык приватный!
- Заполняем остальные обязательные поля;
- Отправляем навык на модерацию, ждём размещения в каталоге (вам придёт письмо-оповещение).
- Добавляем необходимую информацию в config.js:
- Куда логировать:
log: {
type: 'cli', //cli - логировать только в консоль; log - логировать только в файл; all - логировать в консоль и файл;
file: 'acs.log', //название файла с логами, по умолчанию acs.log
},
- Указываем путь до SSL сертификата и его ключа:
ssl: {
crt: '/path/to/ssl.crt', //путь до файла с SSL сертификатом
key: '/path/to/ssl.key', //путь до файла с ключом от SSL сертификата
},
Самоподписанные сертификаты с 2021 года полностью исключены. Валидный сертификат можно бесплатно получить на https://www.sslforfree.com/ или https://letsencrypt.org/ru/
- Указываем порт, на котором будут ожидаться запросы от яндекс диалогов и который мы указали в Webhook URL, например: port: 8443,
- Для авторизации в Яндекс необходимо задать параметры или login и pass или cookie.
- Для того, чтобы ваш логин и пароль от вашего Яндекс аккаунта не был указан в config.js в явном виде, необходимо выполнить:
# npm start auth
После чего вам будет предложено ввести логин и пароль от вашего Яндекс аккаунта:
Yandex login ? my-Yandex-login Yandex password ? my-secret-password Login for config.js: bXktWWFuZGV4LWxvZ2lu Pass for config.js: bXktc2VjcmV0LXBhc3N3b3Jk
После чего полученные значения можно внести в config.js:
login: 'bXktWWFuZGV4LWxvZ2lu',
pass: 'bXktc2VjcmV0LXBhc3N3b3Jk',
Отвечаю на немые вопросы:
- введенные вами логин и пароль никуда не отправляются и разработчику данного скрипта они и даром не нужны, даже если будете просить взять - не возьму;
- да, такой способ защиты ваших данных является защитой, как говорят, от дурака и не сокроют эти данные от опытных пользователей, если вы покажете config.js кому-то. В любом случае одним только взглядом в config.js логина и пароля не узнать и именно этого я пытался достичь;
- Значение параметра "cookie" (если не указаны параметры login и pass) можно взять так:
- Открываем консоль браузера (F12, вкладка "Network")
- Заходим, к примеру, в квазар
- Щёлкаем на запрос в консоли
- Копируем из Request Headers часть строки после "Cookie":
cookie: 'yandexuid=XXXXXXXXXXXXXXXXXX;uniqueuid=YYYYYYYYYYYYYYYYYYY;ну и так далее...',
Учтите, что cookie могут устареть и вам придется повторить операцию и обновить значение параметра "cookie".
Если заданы логин и пароль, то параметр "cookie", при успешной авторизации в Яндекс, будет заполнен автоматически.
- Находим идентификатор Яндекс.Станции, которая будет отвечать на команды. Этот ID можно увидеть на странице с устройствами.
- Укажем ID яндекс.станции в config (это только пример! У вас будет другое значение):
speaker: '2077cfa6-2365-4ed4-97d5-4b46895762af',
- Задаём каким устройствам/пользователям разрешено использовать наш навык:
auth:{
user_id: ['BBD3793D182F7C1842F0F1B99B9FE39DFA3E26557C99B7CDE2CAE116A3170301'],
application: ['BBD3793D182F7C1842F0F1B99B9FE39DFA3E26557C99B7CDE2CAE116A3170301'],
},
Их вы сможете узнать когда выполните своё первое обращение к навыку. Будет отображено в консоли (где вы запустили навык) в incoming JSON, который отображает весь пришедший в навык запрос от Яндекс.Диалогов, где:
- user_id это user.user_id из запроса к навыку - идентификатор пользователя Яндекса, единый для всех приложений и устройств пользователя. Присутствует только, когда пользователь выполнил вход в аккаунт Яндекс на устройстве. Никогда не изменяется.
- application это application.application_id из запроса к навыку - идентификатор экземпляра приложения (браузер или мобильное приложение), в котором пользователь общается с Алисой. Присутствует всегда, но может изменяться (например, если переустановите приложение).
Поясню по user_id и application.
Ситуация 1:
- берём смартфон
- открываем приложение/браузер яндекс
- обращаемся к Алисе: "Алиса, попроси <НАЗВАНИЕ НАВЫКА> помощь"
В этой ситуации в incoming JSON вы увидите наличие только application.application_id, а user.user_id будет отсутствовать
Ситуация 2:
- берём смартфон
- открываем приложение/браузер яндекс
- авторизуемся в приложении/браузере яндекс -> passport.yandex.ru
- обращаемся к Алисе: "Алиса, попроси <НАЗВАНИЕ НАВЫКА> помощь"
- в incoming JSON вы увидите наличие application.application_id и user.user_id
Если в "ситуация 2" использовать ещё один смартфон, то вы увидите, что application.application_id будет отличаться, а user.user_id нет.
Если вы хотите дать возможность управления нескольким устройствам/пользователям, то их можно перечислить через запятую. Пример:
auth:{
user_id: ['BBD3793D182F7C1842F0F1B99B9FE39DFA3E26557C99B7CDE2CAE116A3170301','28D27CB412CAA0AB39DDBD9A6974BE2BCD75362DEFC9C7DE92799D8825EA5399'],
application: ['BBD3793D182F7C1842F0F1B99B9FE39DFA3E26557C99B7CDE2CAE116A3170301','8E73021EA84D8432C264A6D75C30F2A654C22D3FCEB22D8BAAD30A807110FD0E'],
},
Навык производит аутентификацию по любому из этих параметров. Требуется хотя бы одно совпадение.
- Задайте интенты (слова на которые будет реагировать навык).
- help - фразы для воспроизведения фраз команды "помощь".
- enable - слова, которые будут означать команду для сценариев включения
- disable - слова, которые будут означать команду для сценариев выключения
- timers - слова, которые будут означать команду для работы с таймерами
- action_add - слова, которые будут означать команду для добавления (например таймера)
- action_del - слова, которые будут означать команду для удаления (например таймера)
intents: {
help: ['справка', 'помощь', 'что ты умеешь'],
enable: ['включи','включить'],
disable: ['выключи','выключить']
timers: ['таймер'],
action_add: ['добавить','добавь'],
action_del: ['удалить','удали'],
},
- Задаём с какой периодичностью обрабатывать таймеры:
timer_period: 5,
Значение указывается в минутах. По умолчанию 5 минут.
Выполнение нескольких сценариев за одну команду
Создадим сценарии, которые мы и собираемся выполнять. Сделать это можно как в приложении Яндекса (Android, IOS), так и в web-интерфейсе квазара.
Покажу на примере. Создаем сценарий на включение люстры:

По образу и подобию люстры создаём такой же сценарий, но для лампы.
Создаем сценарий для выполнения двух сценариев:

Открываем страницу с JSON по сценариям находим ID созданных сценариев "Включи люстру" и "Включи лампу" (включением лампы и люстры).
В вносим их в config.js в scenarios -> enable.
Где искать ID у сценария показано на скриншоте:

Аналогично вы можете поступить и со сценариями для выключения, создав сценарии "Выключи люстру" и "Выключи лампу", а затем добавить их в config.js в scenarios -> disable.
scenarios: {
enable: { //сценарии на включение
'люстру': '49c84e35-d1f3-4f8b-bc26-fe1ddd383d3f', //сценарий: включи люстру
'лампу': '0f70f28e-6b09-4876-8846-d34449dddc9e', //сценарий: включи лампу
},
disable:{ //сценарии на выключение
'люстру': '1e3d27e6-1731-4461-bbe0-e3ed75e41ed5', //сценарий: выключи люстру
'лампу': '212bc2b7-57db-4f79-a896-aff933b0e433', //сценарий: выключи лампу
}
},
Исходя из примера когда вы скажете Алисе "Включай люстру и лампу" навык запустит два сценария "Включи люстру" и "Включи лампу", что, в свою очередь, приведет к включению устройств "люстра" и "лампа" в вашем Умном Доме.
Далее Вы можете комбинировать, создав сценарии, например:
- Выключи люстру и включи лампу
- Включи люстру и выключи лампу
Таймеры
Рассмотрим на примере самой частой хотелки - автоматическое понижение/повышение уровня громкости станции в зависимости от времени. Для достижения этой цели потребуется:
1. Создать сценарий для понижения громкости:

2. Создать сценарий для повышения громкости:

3. Открыть страницу с JSON по сценариям и найти ID созданных сценариев:
- "Включи ночную громкость"
- "Включи утреннюю громкость"
Копируем ID и вносим их в config.js в scenarios -> enable.
scenarios: {
enable: { //сценарии на включение
'ночную громкость': 'd9c96931-03d5-41a3-90d0-e930ff9c0994',
'утреннюю громкость': '39094cf9-9040-4cb9-ba07-b2a669225fa5',
},
},
4. Перезапустить навык, т.к. вносились изменения в config.js.
Теперь говорим Алисе, например:
- "попроси <НАЗВАНИЕ НАВЫКА> добавить таймер включи ночную громкость в 23 часа" - навык добавит таймер для ежедневного выполнения сценария "Включи ночную громкость" в 23 часа, что, в свою очередь, приведет к ежедневной автоматической установке громкости станции на 2 в 23 часа.
- "попроси <НАЗВАНИЕ НАВЫКА> добавить таймер включи утреннюю громкость в 8 часов" - навык добавит таймер для ежедневного выполнения сценария "Включи утреннюю громкость" в 8 часов, что, в свою очередь, приведет к ежедневной автоматической установке громкости станции на 5 в 8-мь утра.
Созданные вами таймеры навык будет сохранять в файле timers.json. Пример содержимого файла:
[
{
"name":"ночную громкость",
"action":"enable",
"id":"d9c96931-03d5-41a3-90d0-e930ff9c0994",
"days":[0,1,2,3,4,5,6],
"hour":"23"
},
{
"name":"утреннюю громкость",
"action":"enable",
"id":"39094cf9-9040-4cb9-ba07-b2a669225fa5",
"days":[0,1,2,3,4,5,6],
"hour":"8",
"min":"15",
},
{
"name":"телевизор",
"action":"disable",
"id":"3a5550951-c640-468b-a0cc-db5d81dbbe7c",
"once":"1594561800",
}
]
Где:
- "name" и "action" - для понимания, что это за таймер
- "id" - ID выполняемого сценария
- "days" - дни, по которым будет выполняться сценарий. В Javascript воскресенье это нулевой день, а суббота 6.
- "hour" - час, в который будет выполняться сценарий.
- "min" - минуты, когда будет выполняться сценарий. Если минуты не указаны, то это означает ноль минут.
- "once" - признак одноразового сценария, который будет выполнен в указанное в параметре время (unixtime).
Шаблоны команд, которые нужно использовать для добавления таймера:
- попроси <НАЗВАНИЕ НАВЫКА> добавить таймер <ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ> в X часов - запуск ежедневно в X часов ровно.
- попроси <НАЗВАНИЕ НАВЫКА> добавить таймер <ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ> в X часов Y минут - запуск ежедневно в X часов Y минут.
- попроси <НАЗВАНИЕ НАВЫКА> добавить таймер <ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ> по будням в X часов - запуск по будням в X часов ровно.
- попроси <НАЗВАНИЕ НАВЫКА> добавить таймер <ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ> по выходным в X часов Y минут - запуск по выходным в X часов Y минут.
- попроси <НАЗВАНИЕ НАВЫКА> добавить таймер <ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ> в <НАЗВАНИЕ ДНЯ (или дней) НЕДЕЛИ> в X часов - запуск по перечисленным дням в X часов ровно.
- попроси <НАЗВАНИЕ НАВЫКА> добавить таймер <ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ> через Y минут - одноразовый запуск через Y минут.
- попроси <НАЗВАНИЕ НАВЫКА> добавить таймер <ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ> через X часов Y минут - одноразовый запуск через X часов Y минут.
- попроси <НАЗВАНИЕ НАВЫКА> <ДЕЙСТВИЕ> <НАЗВАНИЕ СЦЕНАРИЯ> через Y минут - одноразовый запуск Y минут.
Примеры установки таймеров согласно шаблонам:
- попроси дом вируса добавить таймер включи лампу в 21 час
- попроси дом вируса добавить таймер выключи люстру в 21 час 10 минут
- попроси дом вируса добавить таймер включи коридор по будням в 8 часов
- попроси дом вируса добавить таймер выключи коридор по будням в 8 часов 10 минут
- попроси дом вируса добавить таймер выключи телевизор по понедельникам средам пятницам в 22 часа
- попроси дом вируса добавить таймер включи аквариум в субботу в 9 часов 15 минут
- попроси дом вируса добавить таймер выключи аквариум через 4 часа 30 минут
- попроси дом вируса добавить таймер выключи телевизор через 15 минут
- попроси дом вируса выключить телевизор через 5 минут
Команда для удаления таймера аналогична его добавлению, но вместо "добавить" нужно произнести "удалить". Ну или просто удалить таймер вручную - отредактировав файл timers.json.
Одноразовый таймер удаляется сразу после его исполнения.
Узнать какие таймеры установлены можно командами:
- попроси <НАЗВАНИЕ НАВЫКА> список таймеров
- попроси <НАЗВАНИЕ НАВЫКА> какие установлены таймеры
После правки timers.json навык перезапускать НЕ надо. Файл timers.json будет перечитан автоматически при следующей обработке таймеров, которая производится каждые X минут (где X это значение указанное вами в timer_period в config.js).
Послесловие
Если возникают проблемы с выполнением сценария, то необходимо включить логи и смотреть, что происходит при выполнении сценария, по ним. Для быстрого понимания можно воспользоваться командой:
- попроси <НАЗВАНИЕ НАВЫКА> отчёт
Навык зачитает статус крайнего выполненного сценария. Так статус "200" - все ОК. Статус "403" или "302" - проблема с авторизацией.
Видеодемонстрация работы навыка:
Внимание: После внесения изменений в файл config.js (настройки навыка) необходимо перезапускать скрипт навыка.
С автором статьи можно связаться в телеграм: @VirusNet.