Яндекс: умный дом по-взрослому

в 20:48, , рубрики: javascript, node-red, node.js, wiren board, zigbee, автоматизация, алиса, голосовое управление, голосовой помощник, Разработка под Linux, умный дом, яндекc, Яндекс API

Яндекс: умный дом по-взрослому - 1

Недавно компания Яндекс запустила свою систему «умного дома». Нам предлагают купить недорогие работающие по Wi-Fi устройства: адаптер в розетку, лампочку и ИК пульт. Интересно, что у разработчиков «умных» устройств появилась возможность создать свои навыки «умного дома», это позволит подключить девайсы к системе Яндекса и управлять ими голосом через Алису. В списках навыков появляется всё больше новых брендов. Алиса прекрасно понимает русскую речь, что делает ее безусловным лидером среди голосовых ассистентов на российском рынке.
Однако, не всё так гладко…

Первый минус: в основном, все предложенные системы — «облачные». Их надежность порой вызывает сомнения, так как их работоспособность на прямую зависит от качества соединения с серверами производителя. А при отключении интернета устройства вовсе превращаются в “тыкву”.
Второй минус: система сценариев. Немаловажная часть умного дома — сценарии. И тут они очень примитивные: Если “фраза такая-то”, то включить “устройство такое то”. Для моего умного дома этого оказалось слишком мало.
Минусы на этом не заканчиваются, но остальное связанно скорее с незрелостью системы. Команда разработчиков Яндекса продолжает активно добавлять различные фичи, а баги — править, за что им большое спасибо!
Изучив документацию, я решил создать навык Яндекс УД и подключить к нему контроллер умного дома. Это позволит не зависеть от облачных серверов, реализовывать любые сценарии локально на контроллере и при этом управлять системой голосом через Алису. Для этого я написал плагин “yandex2mqtt” на Node.js.

Немного теории

— Алиса, включи свет.
После этой фразы происходит магия и включается свет. Но что же за кулисами? Давайте разбираться, как всё это работает.
Яндекс-станция, услышав знакомую команду, отправляет данные на сервер Яндекса, которому мы заранее указали адрес нашего контроллера. Сервер обрабатывает информацию и перенаправляет ее на контроллер в виде Post-запроса. На контроллере промежуточный API (в нашем случае это плагин yandex2mqtt) обрабатывает запрос и перенаправляет его в MQTT топик. Дальше происходит обработка сценария в программе Node-Red.
Node-Red решает, что делать дальше. Если это предусмотрено сценарием, он посылает команду на включение света в соответствующий топик MQTT. Драйвер wb-mqtt-serial реагирует, посылая команду по Modbus на релейный модуль, тот переключает реле. И наконец-то включается свет! Да, путь не близкий, однако для пользователя проходят считанные доли секунд.

Давайте посмотрим на плагин yandex2mqtt поближе. Первое, что требует Яндекс для работы навыка, — oAuth сервис для связки аккаунтов в приложении Яндекс. После того как Яндекс получит токен авторизации от oAuth сервиса, он запрашивает список устройств. Плагин yandex2mqtt отдает в ответ список устройств со всеми свойствами в json формате. Затем они появляются в списке доступных для управления устройств (в так называемом квазаре). Теперь, если скомандовать Алисе включить какое-то устройство из списка, Яндекс пошлёт Post запрос с данными устройства, которое он хочет включить, на контроллер. В ответ плагин подтверждает включение и записывает новое состояние в mqtt топик, указанный в настройках все того же плагина. Если же устройство изменило свой статус без участия Яндекса, то плагин, увидев новые данные в mqtt топике, отправит их Яндексу при запросе статуса, который сейчас происходит, только если зайти в само устройство в квазаре. В иных случаях Яндекс не опрашивает статусы.
Теперь расскажу о некоторых свойствах устройств Яндекс УД.

Тип устройств:

Для правильного отображения в “квазаре” и более точного определения команд Алисой Яндекс предлагает присваивать устройствам разные типы. Всего типов 10:

  • devices.types.light — Любой светильник, люстра, лампочка итд.
  • devices.types.socket — Розетка
  • devices.types.switch — Переключатель
  • devices.types.thermostat — Термостат
  • devices.types.thermostat.ac — Кондиционер
  • devices.types.media_device — Медиа устройство
  • devices.types.media_device.tv — Телевизор
  • devices.types.cooking — Кухонная техника
  • devices.types.cooking.kettle — Чайник
  • devices.types.other — Всё остальное, что не подошло под предыдущие пункты.

Умение (capability)

Также у каждого устройства должно быть минимум одно умение (capability).
Всего у Яндекс УД есть 5 типов умений. Каждое умение имеет разную функцию (instance), а некоторые умения имеют несколько таких функций, что добавляет гибкости при настройке устройств.

Сapabilities:

1. devices.capabilities.on_off — Включение и выключение.
instance:

  • on

2. devices.capabilities.color_setting — Управление цветом.
instance:

  • rgb
  • hsv
  • temperature_k

3. devices.capabilities.mode — Переключение режимов.
instance:

  • thermostat
  • fan_speed

4. devices.capabilities.range — Управление диапазоном.
instance:

  • brightness
  • temperature
  • volume
  • channel

5. devices.capabilities.toggle — Выключение звука.

instance:

  • mute

При правильной комбинации всех свойств устройства Алиса без проблем понимает все отданные ей команды по управлению Умным домом. Тут, конечно, есть некие трудности с комбинированием умений. В документации явно не указано, какие умения можно комбинировать, а какие нельзя. Но с этим нам поможет “метод научного тыка”.
Так, к примеру, я выяснил, что кондиционер содержит четыре умения:

Тип устройства:
devices.types.thermostat.ac

Тип умения:
devices.capabilities.on_off
instance:

  • on

devices.capabilities.range
instance:

  • temperature

devices.capabilities.mode
instance:

  • thermostat

devices.capabilities.mode
instance:

  • fan_speed

Остальные свойства описывать не буду, там всё довольно просто.

Чтобы всё заработало, требуется:

  • Контроллер
  • Любой домен
  • SSL сертификат
  • Node.js
  • Плагин yandex2mqtt
  • MQTT брокер
  • Node-red

Контроллер

Моя “умная” квартира управляется контроллером Wiren Board 6. Но можно использовать любой другой контроллер на линуксе, который потянет Node.js и Node-Red. Например, Raspberry pi или ПК.

Домен

Желательно, конечно, иметь белый IP адрес и купить домен, но это необязательно. Можно использовать DDNS — например, www.noip.com.
Тут всё просто: регистрируемся, создаем бесплатный хостнейм, вписываем свой IP адрес. У некоторых роутеров есть специальная настройка DDNS, куда можно вписать данные noip.com. Роутер будет автоматически отправлять IP адрес при его смене. Если такой настройки в роутере нет, можно установить программу noip на контроллер и добавить её в автозапуск. Программа будет делать ровно то же самое, что и роутер со специальной настройкой DDNS — обновлять Ваш ip адрес в базе noip.com
Таким образом, мы имеем статический адрес, который перенаправляет все запросы на наш контроллер.

Порты 443 и 80

Сейчас почти у каждого человека дома есть роутер. Помимо очевидных его функций, он также является барьером для локальной сети от нежелательных гостей извне. Но в определённых случаях нам требуется доступ к внутренней сети снаружи. Производители роутеров это предусмотрели и добавили функцию NAT (Network Address Translation).
Момент настройки роутера я расписывать не стану, так как он разный для каждого производителя. Как это сделать, читайте в инструкции к Вашему роутеру. Ключевые слова для гугления: Port Forwarding, Port Mapping, NAT.
Необходимо пробросить порт для доступа к yandex2mqtt (может быть любой, я выбрал 443) и 80 порт (нужен только для получения SSL сертификата. После получения сертификата 80 порт можно закрыть).

SSL-сертификат

Сразу расставим все точки над «и»: самоподписанные сертификаты работать не будут.
Большинство регистраторов доменов (например, reg.ru) дарят своим клиентам бесплатные SSL-сертификаты для основного домена (www.yourdomain.ru). Если вы купили домен специально для Алисы, то Вы можете воспользоваться предоставленным SSL-сертификатом.
Если же собственного домена Вы не имеете, либо для Алисы у Вас выделен другой поддомен (например, alice.yourdomain.ru), то нужно получить сертификат на этот поддомен, либо на адрес, предоставленный DDNS-службой.
Для этого предлагаю воспользоваться бесплатной услугой получения SSL-сертификата от letsencrypt.org.
Для получения сертификата необходимо установить программу certbot, запустить и указать все данные, которые она запросит. При этом должен быть свободен и доступен снаружи порт 80. Я советую внимательно изучить инструкцию от letsencrypt.

Установка и настройка certbot

apt-get update
apt-get install certbot

Останавливаем сервисы watchdog и nginx.

service watchdog stop
service nginx stop

Пробрасываем 80 порт в роутере.

Запускаем программу certbot:

certbot certonly --standalone

После запуска программа задаст несколько простых вопросов

1. Ваш e-mail. Просто введите адрес и нажмите enter
Яндекс: умный дом по-взрослому - 2

2. Вам предлагают прочесть пользовательские соглашения. Если вы со всем согласны, просто введите “A”, что означает Agree, то есть согласен.
Яндекс: умный дом по-взрослому - 3

3. Программа просит разрешения на отправку Вашего адреса электронной почты разработчикам. Введите N.
Яндекс: умный дом по-взрослому - 4

4. Введите свой домен, на который хотите получить сертификат (можно ввести тот, что мы получили в noip ранее). Тут я привожу пример ошибочного ввода. Префикс http:// вводить не нужно.
Яндекс: умный дом по-взрослому - 5
Если Вы всё сделали правильно, то увидите следующее:
Яндекс: умный дом по-взрослому - 6
Значит, сертификат успешно получен. Запомните путь к сертификату и ключу, он потребуется при настройке плагина yandex2mqtt. Для безопасности закройте 80 порт в настройках роутера, он больше не пригодится.

Включаем сервисы watchdog и nginx.

service nginx start
service watchdog start

Сертификат от letsencrypt выдаётся на 3 месяца. Не забывайте обновлять.

Node.js и плагин yandex2mqtt

Установка

Настраиваем репозиторий node.js

curl -sL https://deb.nodesource.com/setup_10.x | bash -

Далее устанавливаем или обновляем все необходимые компоненты

apt-get install -y nodejs git make g++ gcc build-essential

После успешной установки копируем репозиторий yandex2mqtt на контроллер.

git clone https://github.com/munrexio/yandex2mqtt.git /mnt/data/root/yandex2mqtt

Задаём права.

chown -R root:root /mnt/data/root/yandex2mqtt

Заходим в папку.

cd /mnt/data/root/yandex2mqtt

Запускаем установку.

npm install

Установка завершена.

Автозапуск

Cоздайте юнит systemd:
Перейдите в папку /etc/systemd/system/ на контроллере и создайте файл с названием yandex2mqtt.service. Скопируйте в него следующее:

[Unit]
Description=yandex2mqtt
After=network.target

[Service]
ExecStart=/usr/bin/npm start
WorkingDirectory=/mnt/data/root/yandex2mqtt
StandardOutput=inherit
StandardError=inherit
Restart=always
User=root

[Install]
WantedBy=multi-user.target

После этого сохраните изменения и закройте файл.
Для включения юнита введите в консоль команду:

systemctl enable yandex2mqtt.service

Теперь можно запускать и останавливать плагин командами

service yandex2mqtt start
service yandex2mqtt stop
service yandex2mqtt restart

Настройка:

Все необходимые настройки плагина находятся в файле /mnt/data/root/yandex2mqtt/config.js
Отредактируйте этот файл в соответствии с Вашими параметрами.
SSL-сертификат обязательно должен быть fullchain.
После настройки запустите yandex2mqtt командой:

service yandex2mqtt start

После настройки и запуска моста советую проверить сертификат на сайте www.sslshopper.com/ssl-checker.html

Просто введите свой домен, который собираетесь использовать для доступа к Алисе. Для корректной работы сертификат должен пройти все проверки. Иначе ничего не заработает.

Навык Яндекс УД

Создание навыка

1. Перейти на страницу dialogs.yandex.ru/developer
2. Залогиньтесь под своим аккаунтом.
3. Нажать “создать диалог”
4. Выбрать пункт “Умный дом”
5. Ввести обязательные параметры:

  • Название — Любое название.
  • Endpoint URL — адрес типа вашдомен/provider , где вместо “вашдомен” адрес из noip или ваш домен, для которого получен ssl-сертификат.

Яндекс: умный дом по-взрослому - 7

  • Приватность — выбрать “Не показывать в каталоге” (Обязательно! Иначе навык не пройдет мгновенную модерацию)
  • Имя и Email разработчика — указать Ваши данные.
  • Описание — любой текст
  • Иконка — любая иконка.

Яндекс: умный дом по-взрослому - 8
6. Связка аккаунтов:
Яндекс: умный дом по-взрослому - 9
Нажать “добавить новую”

  • Первые два пункта — указываем данные из config.js / clients :

1. Идентификатор приложения — clientId
2. Секрет приложения — clientSecret

Яндекс: умный дом по-взрослому - 10
7. Сохранить навык
Яндекс: умный дом по-взрослому - 11
8. Нажать “На модерацию”
Яндекс: умный дом по-взрослому - 12
9. Нажать “Опубликовать”
Яндекс: умный дом по-взрослому - 13

Добавление устройств в Яндекс УД.

1. Зайти в приложение Яндекс на телефоне
Яндекс: умный дом по-взрослому - 14
2. В меню выбрать Устройства/Умный дом
Яндекс: умный дом по-взрослому - 15
3. Нажать “Добавить устройство”
Яндекс: умный дом по-взрослому - 16
4. Выбрать свой навык
Яндекс: умный дом по-взрослому - 17
5. Нажать “Объединить аккаунты”
Яндекс: умный дом по-взрослому - 18
6. Откроется страница авторизации
Ввести логин и пароль (задается в файле config.js в блоке users)
Яндекс: умный дом по-взрослому - 19
7. Нажать “Разрешить”.
Яндекс: умный дом по-взрослому - 20
8. Нажать “Обновить список устройств”
Яндекс: умный дом по-взрослому - 21

Теперь Алисе можно отдавать команды для управления добавленными устройствами. В указанные mqtt топики будут приходить соответствующие команды.

Осталось привязать к этим топикам какие-то действия.

Node-Red

Для системы автоматизации был выбран Node-Red. Это отличный инструмент визуального программирования. Процедуру установки и настройки можно подсмотреть тут.

Процесс настройки и автоматизации умного дома потянет на целую статью, а то и две. Да и таких статей уже много. Вместо этого — небольшой пример использования плагина, как включить лампочку голосом.

Для удобства на контроллере Wiren Board 6 в веб интерфейсе создаем виртуальное устройство.
В движок правил wb-rules нужно вписать

defineVirtualDevice("yandex", {
    title: "yandex controls",
    cells: {
        light1: {
            type: "switch",
            value: false
        },
    }
});


Яндекс: умный дом по-взрослому - 22

MQTT топики этого виртуального устройства впишем в config.js на тип умения “on” устройства “Свет”:

 devices: [
    //_______________ Начало устройства ______________//
{
            name: 'Свет',
            room: 'Комната',
            type: 'devices.types.light',
            mqtt: [
                 {
                    type: 'on',
                    set: '/devices/yandex/controls/light1/on', // топик управления
                    stat: '/devices/yandex/controls/light1'     // топик статуса
                },
            ],
            capabilities: [
                {
                    type: 'devices.capabilities.on_off',
                    retrievable: true,
                    state: {
                        instance: 'on',
                        value: true
                    }
                },
            ]
        },
    //_______________ Конец устройства _______________//    
    ]

Теперь при фразе “Алиса, включи/выключи Свет” переключается виртуальное устройство.

Перейдем в Node-Red, который установили по инструкции.
Для удобной работы с Wiren Board 6 также можно использовать дополнительную “ноду” node-red-contrib-wirenboard.
В контроллер поставлен модуль расширения WBE2R-R-ZIGBEE, что позволило подключиться к “Икеевской” умной лампочке серии ТРОДФРИ по ZigBee-протоколу.

Теперь дело за малым. Закинуть несколько блоков в рабочее поле Node-Red, соединить “ниточками” и нажать Deploy.
Яндекс: умный дом по-взрослому - 23
Икеевская лампочка подключена через плагин zigbee2mqtt, поэтому в mqtt топик лампочки для управления нужно отправлять json. Для этого между виртуальным девайсом WB и mqtt топиком лампочки вставим простую функцию.
Яндекс: умный дом по-взрослому - 24
Нажимаем Deploy. Проверяем.

Алиса, включи Свет!

Итак, сегодня мы научились подключать Алису к системе автоматизации. Возможно в некоторых случаях это слишком сложно, проще купить обычную wi-fi лампочку, и этого хватит. Но если Вы задумали собрать себе по-настоящему умный дом, то простыми способами тут не обойтись. А стоит оно того или нет, каждый решит сам. Спасибо за внимание!

Автор: Ян Янин

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js