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

rsl_lmpzna0pj3o9ahxzsawpsn0.png

Недавно компания Яндекс запустила свою систему «умного дома». Нам предлагают купить недорогие работающие по 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:

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:

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

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

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


devices.capabilities.range
instance:

  • temperature


devices.capabilities.mode
instance:

  • thermostat


devices.capabilities.mode
instance:

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

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

  • Контроллер
  • Любой домен
  • 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
mngfsiaatuo6txsrtc6wyyz4v_o.png

2. Вам предлагают прочесть пользовательские соглашения. Если вы со всем согласны, просто введите «A», что означает Agree, то есть согласен.
y8zztosybjouwmncxuawmbq-55c.png

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

4. Введите свой домен, на который хотите получить сертификат (можно ввести тот, что мы получили в noip ранее). Тут я привожу пример ошибочного ввода. Префикс http:// вводить не нужно.
mtbjpyenb63jqv3gvtd_oyh9qze.png
Если Вы всё сделали правильно, то увидите следующее:
ug7ckfuvos8bkgfgzvaepqvu48s.png
Значит, сертификат успешно получен. Запомните путь к сертификату и ключу, он потребуется при настройке плагина 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

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

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


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


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


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

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

Node-Red

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

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

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

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


3tmnqhsdi1vnkdd_wr4ucnsvusc.jpeg

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.
evp8zn84umdssgxcecq9rmosgm8.jpeg
Икеевская лампочка подключена через плагин zigbee2mqtt, поэтому в mqtt топик лампочки для управления нужно отправлять json. Для этого между виртуальным девайсом WB и mqtt топиком лампочки вставим простую функцию.
y1e69hfghaemcayotpvugppiqz8.jpeg
Нажимаем Deploy. Проверяем.

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

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

© Habrahabr.ru