IoBroker. Пытаемся подружиться с Алисой

25 января 2020, 07:35

В статье разберем альтернативный вариант интеграции голосового ассистента Алиса и IoBroker, через протокол MQTT. Этот вариант подойдет тем, кто не хочет или не может, по личным причинам, использовать адаптер IoBroker.IoT.

Для этого понадобится:

  • Домен.
  • Nginx Proxy Manager.
  • SSL сертификат для домена.
  • Плагин yndex2mqtt.
  • Навыки Yandex Умный дом.
  • Немного скриптов на JS (Blokly).
  • Чуть-чуть знаний и магии.

Домен

В идеале, надо иметь белый IP адрес и купить домен, но можно обойтись DDNS.

В моем случае, был задействован VPS на Aruba Cloud (белый IP, место для размещения Nginx Proxy Manager и плагина yandex2mqtt). Но можно обойтись и другими вариантами, например, если ваш провайдер дает белый IP и вы планируете развернуть proxy на том же сервере, где крутится IoBroker.

Свой домен я регистрировал через хостинг Timeweb. Год стоит от 99 рублей (цена будет зависеть от выбранного домена и действующей акции).

Там же добавил поддомены proxy.мойдомен.ru и alice.мойдомен.ru, эта услуга к домену прилагается обычно бесплатно. Также не забываем на своем хостинге настроить DNS на созданные поддомены.

Nginx Proxy Manager

Разворачивается очень просто в Docker по инструкции, с помощью Docker Compose. Если еще не установлен, то вот инструкция. В результате должно получиться что-то типа такого:

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

Алиса не будет работать с самоподписанными сертификатами. Выходы следующие:

  • Купить SSL сертификат для поддомена alice.мойдомен.ru.
  • Воспользоваться Let's Encrypt.
Let's Encrypt сертификат можно самостоятельно получить с помощью небольшого приложения Сertbot. Инструкции есть в интернете. Полученные ключи понадобятся для настройки yandex2mqtt.

Также можно дополнительно получить сертификаты для любых своих поддоменов, но чуть более простым путем. Для этого используем уже установленный Nginx Proxy Manager. Например, для Proxy.

Вводим имя своего поддомена, белый IP, с которого он будет доступен и порт админ панели (указывался в файле конфигурации Nginx Proxy Manager).

Дальше на вкладке SSL указываются все необходимые данные для получения сертификата.

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

 yndex2mqtt

Установка несложная, по инструкции. При настройке плагина в файле config.js не забыть указать пути к ключам своего SSL сертификата, порт для https, настройки вашего mqtt брокера (должен быть доступен из интернета через белый IP).

module.exports = {

    mqtt: {
        host: '192.168.1.5',
        port: 1883,
        user: 'admin',
        password: 'admin'
    },

    https: {
        privateKey: '/etc/letsencrypt/live/alice.мойдомен.ru/privkey.pem',
        certificate: '/etc/letsencrypt/live/alice.мойдомен.ru/fullchain.pem',
        port: 443
    },

При первоначальной настройке рекомендую оставить без изменения раздел devices, это облегчит создание навыка.

Навыки Yandex Умный дом

Надо выполнить следующие пункты:

  • Перейти на страницу dialogs.yandex.ru/developer.
  • Залогиниться под своим аккаунтом.
  • Нажать "создать диалог".
  • Выбрать пункт "Умный дом".
  • Ввести необходимые параметры.
  • Связать аккаунты.
  • Сохранить навык.
  • Нажать "На модерацию".
  • Нажать "Опубликовать".

Более подробно расписано в статьях раз и два. Если все сделано правильно, результат будет похож на это:

В IoBroker появятся объекты, описанные в config.js плагина yndex2mqtt.

Если получилось с базовыми устройствами, можно начать пробовать создавать свои устройства. Все доступные варианты описаны в документации Yandex.

Очень удобно тестировать добавленные устройства сразу в личном кабинете, в правой части есть лог запросов, в котором можно увидеть и понять проблемные места (криво описали устройство в devices).

Решение возможных проблем описано в конце инструкции.

Дополнительно добавлю, что если не получается обновить устройства, то надо выполнить следующие действия:

  1. В config.js задать новый clientId.
  2. Перезапустить yandex2mqtt.
  3. Повторно добавить устройства в Умный дом.

Удалять добавленные устройства можно так:

Настраиваем IoBroker 

Созданные mqtt топики в IoBroker красиво меняются по командам Алисы, пора добавить логики и связать с реальными устройствами. Я для этого использую JS и Aliases.

Самый простой пример управление светом:

on({id: 'mqtt.0.devices.yandex.controls.bedlightwhite.on', change: "any"}, function (obj) {
  var value = obj.state.val;
  // Проверка на подтверждение команды
  if (value)  setState('javascript.0.Bedroom.RGB.white'/*Bedroom RGB white*/, true, true);
  if (!value)  setState('javascript.0.Bedroom.RGB.white'/*Bedroom RGB white*/, false, true);
});

Посложнее. Настройка управления MPD сервером с помощью адаптера MPD

config.js

// ________ Спальня. MPD ___________//
        {
            name: 'Плеер',
            room: 'Спальня',
            type: 'devices.types.media_device',
            mqtt: [
                 {
                    type: 'on',
                    set: '/devices/yandex/controls/bedroom/mpd/power/on',
                    stat: '/devices/yandex/controls/bedroom/mpd/power'
                },
                {
                    type: 'mute',
                    set: '/devices/yandex/controls/bedroom/mpd/muteon/on',
                    stat: '/devices/yandex/controls/bedroom/mpd/muteon'
                },
{
                    type: 'pause',
                    set: '/devices/yandex/controls/bedroom/mpd/pauseon/on',
                    stat: '/devices/yandex/controls/bedroom/mpd/pauseon'
                },
                {
                    type: 'volume',
                    set: '/devices/yandex/controls/bedroom/mpd/volumeon/on',
                    stat: '/devices/yandex/controls/bedroom/mpd/volumeon'
                },
            ],
            capabilities: [
                {
                    type: 'devices.capabilities.on_off',
                    retrievable: true,
                    state: {
                        instance: 'on',
                        value: false
                    }
                },
                {
                    type: 'devices.capabilities.toggle',
                    retrievable: true,
                    parameters: {
                        instance: 'mute'
                    },
                    state: {
                        instance: 'mute',
                        value: false
                    },
                },
{
                    type: 'devices.capabilities.toggle',
                    retrievable: true,
                    parameters: {
                        instance: 'pause'
                    },
                    state: {
                        instance: 'pause',
                        value: false
                    },
                },
                {
                    type: 'devices.capabilities.range',
                    retrievable: true,

                    parameters: {
                        instance: 'volume',
                        range: {
                            min: 0,
                            max: 100,
                            precision: 1
                        }
                    },
                    state: {
                        instance: 'volume',
                        value: 10,
                    },
                },
            ]
        },
    //_________конец второго устройства_________//
// вкл/выкл
on({id: 'mqtt.0.devices.yandex.controls.bedroom.mpd.power.on'/*/devices/yandex/controls/bedroom/mpd/power/on*/, change: "any"}, function (obj) {
    var value = obj.state.val;
    // Проверка на подтверждение команды
    if (value) {
        setState("mpd.0.play"/*Controlling playback play*/,true); // включить музыку
        setState("mpd.0.volume"/*volume*/, getState('mqtt.0.devices.yandex.controls.bedroom.mpd.volumeon.on'));
    }
    if (!value) setState("mpd.0.stop"/*Controlling playback stop*/, true); // выключить музыку
});

// без звука
on({id: 'mqtt.0.devices.yandex.controls.bedroom.mpd.muteon.on'/*/devices/yandex/controls/bedroom/mpd/muteon/on*/, change: "any"}, function (obj) {
    var value = obj.state.val;
    // Проверка на подтверждение команды
    if (value)  setState("mpd.0.mute", true);
    if (!value) setState("mpd.0.mute", false);
});

// пауза
on({id: 'mqtt.0.devices.yandex.controls.bedroom.mpd.pauseon.on'/*/devices/yandex/controls/bedroom/mpd/pauseon/on*/, change: "any"}, function (obj) {
    var value = obj.state.val;
    // Проверка на подтверждение команды
    if (value)  setState("mpd.0.pause", true);
    if (!value) setState("mpd.0.pause", false);
});

// громкость
on({id: 'mqtt.0.devices.yandex.controls.bedroom.mpd.volumeon.on'/*/devices/yandex/controls/bedroom/mpd/volumeon/on*/, change: "any"}, function (obj) {
    var value = obj.state.val;
    setState("mpd.0.volume", value);
});

Результат:

В планах добавить переключение каналов.

И, напоследок, покажу свой вариант реализации управления RGB лентой. Устройство самодельное, имеет 4 канала управления цветами RGBW, которые задаются числом в 4 байта HEX, например, красный цвет "FF000000" или желтый "FF140000". 

Кроме передачи цвета, я хотел еще через Алису менять яркость цвета. Алиса передает яркость в процентах от 0 %до 100%. Но как менять яркость цвета, заданного в RGB?

Изыскания привели меня к тому, что цвет RGB необходимо конвертировать в HSV (англ. Hue, Saturation, Value — тон, насыщенность, значение), где Value и есть необходимая яркость. Дальнейший поиск привел к npm пакету color-convert, который дает возможность удобно конвертировать в любые форматы.

Для удобства работы, ленту описал через недавно добавленную фичу псевдонимов Alias.

{
  "_id": "alias.0.Bedroom.Polka.BRIGHTNESS",
  "native": {},
  "type": "state",
  "common": {
    "alias": {
      "id": "mqtt.0.devices.yandex.controls.bedlight1brightness.on"
    },
    "name": "BRIGHTNESS",
    "type": "number",
    "min": 0,
    "max": 100,
    "role": "level.brightness"
  },
  "from": "system.adapter.admin.0",
  "user": "system.user.admin",
  "ts": 1579365958198,
  "acl": {
    "object": 1636,
    "state": 1636,
    "owner": "system.user.admin",
    "ownerGroup": "system.group.administrator"
  }
}
{
  "_id": "alias.0.Bedroom.Polka.RGB",
  "common": {
    "name": "RGB",
    "role": "level.color.rgb",
    "type": "string",
    "read": true,
    "write": true,
    "alias": {
      "id": "mysensors.0.70.1_RGBW_LIGHT.V_RGBW"
    }
  },
  "native": {},
  "type": "state",
  "from": "system.adapter.admin.0",
  "user": "system.user.admin",
  "ts": 1579365889870,
  "acl": {
    "object": 1636,
    "state": 1636,
    "owner": "system.user.admin",
    "ownerGroup": "system.group.administrator"
  }
}

И скрипт, который корректно связывает команды Алисы с RGB контроллером. 

Алиса передает цвет RGB числом в три байта, в скрипте добавляю четвертый байт для белого цвета RGBColor "00".

// Преобразуем число от Алисы в строку для RGB полки
on({id: 'mqtt.0.devices.yandex.controls.bedlight1rgb.on', change: 'any'}, function (obj) {
    let tmp = Number(obj.state.val).toString(16);
    tmp = String(tmp)   "00";
    setState('alias.0.Bedroom.Polka.RGB'/*Rgb*/, tmp);
});

// Команда от Алисы вкл/выкл
on({id: 'mqtt.0.devices.yandex.controls.bedlight1.on', change: 'any'}, function (obj) {
    if (obj.state.val === 0){
        setState('alias.0.Bedroom.Polka.RGB'/*Rgb*/, "00000000");
    } else {
        // восстаналвиваем предыдущее значение при включении
        let tmp = Number(getState('mqtt.0.devices.yandex.controls.bedlight1rgb.on').val).toString(16);
        tmp = String(tmp)   "00";
        setState('alias.0.Bedroom.Polka.RGB'/*Rgb*/, tmp);
    }
});

// Команда от Алисы изменение яркости
on({id: 'alias.0.Bedroom.Polka.BRIGHTNESS'/*Brightness*/, change: 'any'}, function (obj) {
    var convert = require('color-convert');
    let hsv = convert.hex.hsv(getState('alias.0.Bedroom.Polka.RGB').val);
    hsv[2] = obj.state.val; // меняем яркость
    let rgbHEX = convert.hsv.hex(hsv)   "00";
    setState('alias.0.Bedroom.Polka.RGB'/*Rgb*/, rgbHEX);
});

На этом пока заканчиваю. Если будут вопросы, то задавайте тут или в Telegram.


Все новости мира умных домов - t.me/SprutAI_News или Instagram
Остались вопросы? Мы в Telegram - @Soprut

Хочешь умный дом но нет времени разбираться?
Посмотри примеры работ и выбери себе интегратора.
К списку статей

Устройства в материале

Яндекс.Станция

Производитель: Яндекс

Скидки для сообщества

Интернет-магазин yourhomekit.ru

+7 914 550-51-11
Промокод:
SPRUT-BLG
Размер скидки:
8%
Cамый большой ассортимент в России аксессуаров Apple HomeKit

Тематические чаты

Похожие статьи

17 декабря 2019, 17:49
Универсальный привод для автоматического удаленного открытия окон с простой интеграцией в умные дома.
20 октября 2018, 22:57
Теоретические основы протокола MQTT и описание того, как он работает и для чего используется
18 февраля 2020, 17:06
В данной статье описывается сборка слаботочного эл. щита на базе Wiren Board 6, а так же силового щита для небольшой квартиры.
29 октября 2019, 07:59
Умный домофон на базе nodeMCU с прошивкой ESPHome.
15 июня 2018, 12:13
Охранная система в гараж на ESP8266 с интеграцией в Apple HomeKit
01 октября 2019, 07:07
"У всякого в умном дому неведомо никому" (с) Народная мудрость
03 апреля 2019, 04:29
Разбираем простейшую задачу по электрическому подключению светодиодной ленты к источнику питания и управлению через Умный дом.
04 апреля 2019, 08:22
Личная жизнь мешает увлечению "умным домом"? Есть решение!
08 апреля 2020, 11:32
Голосовые уведомления через Xiaomi Gateway, Home Assistant и HomeKit. Пример реализации, кейсы применения.
09 января 2019, 17:34
Небольшая статья о том, зачем нужна малина, почему автоматизации в HomeKit это не очень хорошо и чем USB стик лучше отдельного шлюза.