Беспроводные устройства Xiaomi в умном доме ioBroker

в 17:29, , рубрики: diy или сделай сам, ioBroker, javascript, zigbee, Блог компании ioBroker, Интернет вещей, умный дом

Приветствую всех любителей домашней автоматизации. Решил поделиться опытом использования беспроводных Xiaomi устройств с интерфейсом ZigBee. Я, честно говоря, против применения любых беспроводных устройств в любой автоматизации, от серьезных АСУТП больших объектов до малой автоматики типа охранно-пожарной сигнализации или умного дома, но… Решения Xiaomi подкупили дешевизной, доступностью, отличным дизайном и множеством положительных отзывов от пользователей, решил попробовать.

Этот пост следует воспринимать, как пошаговую инструкцию для интеграции ZigBee устройств в инфраструктуру умного дома. Описанное здесь ни в коем случае не является аксиомой и можно найти много других способов подключения ZigBee устройств. Если всё же пропускать детальное описание, то можно составить впечатление о сложности или легкости объединения устройств от разных производителей в одну локальную платформу на примере ZigBee и ioBroker (о нём чуть позже). Я расскажу в этой статье, как подключить устройства к умному дому, отобразить информацию с них на планшете или просто в браузере и отправить сообщения через телеграм о смене состояния устройств. Если я вас заинтересовал, то прошу под кат.

По замыслу производителя Xiaomi, пользователи должны использовать родное приложение с облачным подключением и Wi-Fi шлюз для устройств ZigBee. Однако уже давно известен способ активации режима разработчика в приложении для получения управляющего токена. Таким образом внутри локальной сети можно общаться со шлюзом, что и позволяет проделать драйвер mihome, который идет в составе ioBroker.

ioBroker — это открытая платформа для IoT, в том числе для построения систем типа «умный дом». Что такое ioBroker можно почитать в предыдущей статье.

Сейчас мой умный дом «крутится» на ARM-плате Cubietruck с некоторым «обвесом» в виде жесткого диска на 80Гб, аккумуляторной батарей на 5000мАч, USB-мастера сети 1-wire, USB-RS485 преобразователя для опроса устройств по протоколу modbus. ОС Armbian установлена на жесткий диск с переносом корневого раздела, на карте памяти microSD остался только загрузчик.

Своё знакомство с беспроводными устройствами Xiaomi я начал с покупки датчиков температуры и влажности. На тот момент была единственная возможность их интеграции — драйвер mihome, который упоминался выше.

Драйвер mihome

Добавить драйвер в систему очень просто, нужно кликнуть на кнопке “+” в списке доступных драйверов и наблюдать процесс установки.

Беспроводные устройства Xiaomi в умном доме ioBroker - 1

Установку и первоначальную настройку родного Android-приложения Mi Home описывать не буду, можно посмотреть на странице github драйвера или в интернете. Итак, режим разработчика активирован, токен получен, настраиваем адаптер mihome, сохраняем и запускаем, если он не был запущен.

Беспроводные устройства Xiaomi в умном доме ioBroker - 2

В дереве объектов должен появиться шлюз Xiaomi и подключенные в приложении Mi Home устройства.

Беспроводные устройства Xiaomi в умном доме ioBroker - 3

Далее можно настроить только что созданные объекты. К примеру, хранение истории датчиков температуры и влажности. Я использую для исторических данных драйвер SQL с настройкой на БД SQLite.

Беспроводные устройства Xiaomi в умном доме ioBroker - 4

Настройка хранения истории переменной производится в окне объектов системы: нужно в иерархии объектов добраться до самой переменной и нажать справа кнопку с гаечным ключом. На вкладке «Настройки» у меня по сенсорам активировано хранение истории — только изменения переменной.

Другие настройки:

  • минимальный интервал 10 секунд — если переменная будет изменяться чаще, то запись в БД будет игнорироваться
  • запись значений каждые 300 секунд (5 минут) — если переменная не изменяется более 5 минут, в БД все равно запишется текущее значение
  • тип значения — число
  • срок хранения — 1 год

Беспроводные устройства Xiaomi в умном доме ioBroker - 5

Добавление новых устройств происходит через родное приложение. Т.е. надо осуществить сопряжение нового девайса со шлюзом согласно прилагаемой инструкции и после этого он автоматически появится в списке объектов ioBroker.

Драйвер zigbee

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

Один из активных пользователей платформы ioBroker нашел в интернете библиотеку zigbee-shepherd на node.js, в которой было упоминание о подключении устройств Xiaomi. На её базе был написан драйвер для ioBroker, причем автор этого драйвера не ограничился только устройствами Xiaomi, список поддерживаемых устройств постоянно дополняется и доступен на github странице проекта.

В качестве координатора сети предполагается использовать недорогие готовые устройства на базе чипов CC25хх от TI. Можно купить готовые ZigBee-модули как с подключением по USB и встроенной антенной, так и модели подороже-посерьезнее: с внешней антенной, усилителем, подключением через UART.

Для работы с драйвером, надо только сменить прошивку. Таким образом получается, что для работы этого драйвера не нужен дорогостоящий шлюз, не нужны сети Wi-Fi. «Точкой входа» является координатор — устройство на базе чипа СС25хх со специальной прошивкой. Через координатор происходит непосредственное общение zigbee-устройств и системы «Умный дом», а также привязка новых устройств.

В качестве координатора я использую готовую плату на базе чипа СС2530 с внешней антенной, которую подключил к серверу через UART.

Для прошивки устройства был куплен специальный дебагер SmartRF04EB, порт microUSB которого я подключил к компьютеру, а модуль ZigBee подключил с помощью проводков для отладки по схеме:

СС2530 Плата SmartRF04EB
P22 DC
P21 DD
RST RESET
GND GND
VCC 3.3V

Беспроводные устройства Xiaomi в умном доме ioBroker - 6

На странице github проекта качаем прошивку (именно для этого устройства файл называется CC2530ZNP-Pro-Secure_LinkKeyJoin.hex) и программу для прошивки (flash-programmer), после установки которой в систему добавляются нужные драйвера.
При подключении платы-дебагера в USB-порт компьютера в программе сразу отобразится подключенное устройство. Нужно только указать путь к файлу-прошивке и нажать кнопку “Perform Actions”

Беспроводные устройства Xiaomi в умном доме ioBroker - 7

ZigBee-модуль портами P03 (Rx) и Р02 (Tx) подключен в UART4 (в ОС как ttyS4) платы cubietruck, питание 3V3, GND взял на соседних pin. Для устойчивой работы еще надо порты P20, P4, P5 самого координатора подтянуть к земле. Как писал выше, я использую ОС Armbian, порт UART активируется очень просто, с помощью команды armbian-config в разделе SystemHardware нужно активировать нужный порт и перезагрузить систему.

Беспроводные устройства Xiaomi в умном доме ioBroker - 8

Драйвер zigbee добавляется из админки одним кликом.

Беспроводные устройства Xiaomi в умном доме ioBroker - 9

В моем случае координатор подключен в порт /dev/ttyS4 (как писал выше), указываем его в настройках.

Беспроводные устройства Xiaomi в умном доме ioBroker - 10

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

Итак, для примера добавим кнопку Xiaomi (серия Mijia), для этого нажимаем зеленую кнопку в настройках драйвера и, следуя инструкции, сначала зажимаем кнопку сопряжения на тыльной стороне скрепкой, пока не начнет мигать светодиод, затем кликаем этой кнопкой примерно раз в 2 секунды, видим прогресс сопряжения.

Беспроводные устройства Xiaomi в умном доме ioBroker - 11

Квартира у меня не большая, со всеми устройствами связь стабильная, даже с датчиком открытия двери на лестничной площадке (ЖБ стена в 100мм и расстояние 5м по прямой). Проблемы начались, когда я решил добавить датчик температуры и влажности уличного воздуха, который установил на наружней стене дома со стороны утепленной лоджии. Сигнал слабого датчика, который к тому же находился на улице, не добивал до шкафа автоматики. Решить проблему можно просто — надо добавить роутер в состав сети ZigBee и расположить его ближе к датчику. Некоторые беспроводные устройства, к примеру, розетка Xiaomi могут работать в качестве роутера, но у меня не было подобных устройств. Покупать дорогую розетку или управляемую лампочку только для “проброса” данных от датчика на улице я не хотел. Как оказалось, для тех же оконечных девайсов на базе чипа СС25хх есть специальная прошивка, которая позволяет их использовать как роутер в системе. В итоге я добавил роутер на базе чипа СС2531 с подключением USB. Подробно на процессе прошивки останавливаться не буду, схему и сам файл прошивки можно найти на странице github проекта.

Так как по сути, общение с модулем через USB-порт не происходит, я его временно включил в зарядку с USB-портом и вставил в розетку на кухне. В ближайшем будущем планирую расположить стационарно в нормальном корпусе на лоджии и с нормальным питанием от домашнего ИБП.

Беспроводные устройства Xiaomi в умном доме ioBroker - 12

Процесс добавления роутера в систему прост: нажимаем кнопку сопряжения в драйвере и на включенном роутере несколько раз нажимаем кнопку S2, пока устройства не соединятся.

Беспроводные устройства Xiaomi в умном доме ioBroker - 13

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

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

Беспроводные устройства Xiaomi в умном доме ioBroker - 14

Убедимся что датчик правильно подключился — посмотрим карту сети.

Беспроводные устройства Xiaomi в умном доме ioBroker - 15

На карте показаны линии сопряжения устройств с указанием качества сигнала между сегментами сети. Как писал выше, у меня небольшая однушка 35 кв.м., поэтому карта довольно скромная. С разрешения других пользователей, опубликую возможные варианты с картой побольше.

Беспроводные устройства Xiaomi в умном доме ioBroker - 16

Беспроводные устройства Xiaomi в умном доме ioBroker - 17

Беспроводные устройства Xiaomi в умном доме ioBroker - 18

Функционал некоторых устройств Xiaomi через этот адаптер даже немного больше, чем через родное приложение и драйвер mihome. В будущем хочу расширить немного сеть и попробовать новые устройства, в частности умный привод для штор и сенсор-кубик.

Драйвер Material

Данные мы получили, исполнительные механизмы привязали, что теперь с ними делать? Для начала давайте отобразим в красивом интерфейсе. У меня есть большой проект в драйвере VIS, который существует в нескольких версиях под разные разрешения, но там материала достаточно на отдельную статью. Возможно она будет следующей.

Для простого и быстрого вывода на экран данных и управления различными устройствами, я использую драйвер material. Установка как обычно в пару кликов. Плитки интерфейса отображают данные исходя из настроек категорий, которые добавляются в одноименном окне админки интерфейса. Список категорий ограничен только фантазией, я использую схему «комната-функция», по ним и происходит группировка. Добавил все комнаты (кухня, коридор, комната, балкон и т.п.) и функции (освещение, датчики, системные и т.п.).

Беспроводные устройства Xiaomi в умном доме ioBroker - 19

Теперь в окне настройки объектов системы, нужно для переменных, которые будут выводиться на экран, указать комнату, функцию и назначить роль (для правильного отображения). Пример — комнатный настенный датчик температуры и влажности Xiaomi, подключенный через Bluetooth.

Беспроводные устройства Xiaomi в умном доме ioBroker - 20

Исходя из этих настроек, плитка будет выводить на экран данные, подтянется иконка, и у объектов определенного типа будет доступно управление.

Пример 1. Вывод всей информации по одной категории — функции. Освещение во всей квартире.

Беспроводные устройства Xiaomi в умном доме ioBroker - 21

Пример 2. Вывод всей информации по комнате — Ванная комната.

Беспроводные устройства Xiaomi в умном доме ioBroker - 22

Пример 3. Вольтаж и уровень разряда батарей всех беспроводных устройств Xiaomi.

Беспроводные устройства Xiaomi в умном доме ioBroker - 23

Этот драйвер у меня работает для локального управления системой с мобильного телефона, стационарного планшета на стене. Иногда я подключаюсь через VPN. Для управления и просмотра состояний удаленно, получения уведомлений, я использую драйвер telegram.

Драйвер Telegram

Установку уже описывать не буду, сразу пробежимся по настройкам. Я использую режим работы через периодический опрос (по-умолчанию 300мс) и соединение через прокси-сервер. Чтобы получить token, нужно немного «пообщаться» с создателем ботов — BotFather. Процесс простой — находите поиском этого бота, даете команду на создание нового, указываете его уникальное имя и ключ ваш, указываем его в настройках драйвера и, для безопасности, обязательно указываем пароль «приветствия». Его ваш бот будет спрашивать при общении с новым пользователем.

Беспроводные устройства Xiaomi в умном доме ioBroker - 24

Теперь нужно настроить кейсы общения через бота. Для этого можно использовать драйвер text2command или JavaScript. Так исторически сложилось, что я использую JavaScript как в виде текста, так и блоками Blockly. Установка драйвера JS не должна вызвать трудностей, настройка в данном кейсе не нужна. После установки и запуска нужно включить отображение меню для создания и редактирования скриптов.

Беспроводные устройства Xiaomi в умном доме ioBroker - 25

Пример 1. Оповещения.

Для начала давайте попробуем отправить уведомление об открытии, к примеру, входной двери. У меня стоит датчик-геркон беспроводной Xiaomi на входной двери. Мониторю как жена гуляет с мелким пока я на работе. Создадим новый скрипт в группе common.

Беспроводные устройства Xiaomi в умном доме ioBroker - 26

Укажем что будет «рисовать» в blockly и назовем «telegram_bot».

Беспроводные устройства Xiaomi в умном доме ioBroker - 27

В группе «События» возьмем блок реакции на изменение переменной и перетащим на рабочее поле.

Беспроводные устройства Xiaomi в умном доме ioBroker - 28

Далее выберем ID объекта на который подписываемся, вставим проверку объекта через «если» — «иначе если» на значение true/false. В итоге должно получится примерно следующее.

Беспроводные устройства Xiaomi в умном доме ioBroker - 29

Отлично, теперь бежим, открываем дверь — закрываем дверь и видим сообщения в telegram.

Беспроводные устройства Xiaomi в умном доме ioBroker - 30

Пример 2. Управление освещением через меню.
Пример посложнее, сделаем управление освещением кнопками меню в telegram. Здесь уже придется немного покодить, т.е. при создании скрипта нужно выбрать JS. Задача примерно такая: сделать кнопки в виде меню с выводом статуса светильников сразу в текст подписи кнопок. Еще постараться сделать так, чтобы при нажатии на кнопку, состояние освещения инвертировалось и статус тут же обновлялся в тексте кнопки появлением/исчезновением лампочки. Плюс к тому, если меню уже запущено и вручную клавишей включили/выключили свет, нужно чтобы меню также обновлялось со статусами светильников.

Код примерно следующий у меня получился:

//Подписи кнопок меню и ID каналов управления освещением
const LIGHT1 = 'Комн ночн',     CH_LIGHT1 = 'mqtt.0.PLC55_Lighting.lighting.MainRoom_main1';
const LIGHT2 = 'Комн осн',      CH_LIGHT2 = 'mqtt.0.PLC55_Lighting.lighting.MainRoom_main2';
const LIGHT3 = 'Комн подсв',    CH_LIGHT3 = 'mqtt.0.PLC55_Lighting.lighting.MainRoom_sec';
const LIGHT4 = 'Кух свет',      CH_LIGHT4 = 'mqtt.0.PLC55_Lighting.lighting.Kitchen_main';
const LIGHT5 = 'Кух подсв1',    CH_LIGHT5 = 'mqtt.0.PLC55_Lighting.lighting.Kitchen_sec_top';
const LIGHT6 = 'Кух подсв2',    CH_LIGHT6 = 'mqtt.0.PLC55_Lighting.lighting.Kitchen_sec_bottom';
const LIGHT7 = 'Ванна осн',     CH_LIGHT7 = 'mqtt.0.PLC55_Lighting.lighting.BathRoom_main';
const LIGHT8 = 'Кор осн',       CH_LIGHT8 = 'mqtt.0.PLC55_Lighting.lighting.Hall_main';
const LIGHT9 = 'Балкон осн',    CH_LIGHT9 = 'mqtt.0.PLC55_Lighting.lighting.Balcon_main';

//Отправка самого меню в телеграм
function sendLightMenu(message_text) {
    //Получаем текущее состояние светильников
    var l1 = getState(CH_LIGHT1).val ? '' : '';
    var l2 = getState(CH_LIGHT2).val ? '' : '';
    var l3 = getState(CH_LIGHT3).val ? '' : '';
    var l4 = getState(CH_LIGHT4).val ? '' : '';
    var l5 = getState(CH_LIGHT5).val ? '' : '';
    var l6 = getState(CH_LIGHT6).val ? '' : '';
    var l7 = getState(CH_LIGHT7).val ? '' : '';
    var l8 = getState(CH_LIGHT8).val ? '' : '';
    var l9 = getState(CH_LIGHT9).val ? '' : '';
    //Отправляем меню
    sendTo('telegram.0', {
        text:   message_text,
        reply_markup: {
            keyboard: [
                [LIGHT1+l1, LIGHT2+l2, LIGHT3+l3],
                [LIGHT4+l4, LIGHT5+l5, LIGHT6+l6],
                [LIGHT7+l7, LIGHT8+l8, LIGHT9+l9]
            ],
            resize_keyboard:   true,
            one_time_keyboard: true
        }
    });
}
//Изменение состояния освещения
function changeLight(room, channel) {
    //Проверяем доступность контроллера освещения
    var alive = getState("mqtt.0.info.connection").val;
    if (alive.includes("PLC55_Lighting")) {
        if (getState(channel).val) {
            setState(channel, false, false, function () {
                sendLightMenu(room+' ВЫКЛ');
            });
        } else { 
            setState(channel, true, false, function () {
                sendLightMenu(room+' ВКЛ');
            });
        }
    } else {
        sendLightMenu('Контроллер освещения OFFLINE');
    }
}
//Подписываемся на переменную request драйвера телеграмм, любое изменения без подтверждения
on({id: "telegram.0.communicate.request", ack: false, change: 'any'}, function (obj) {
    var msg = obj.state.val;
    var command = obj.state.val.substring(obj.state.val.indexOf(']')+1);
    var user = obj.state.val.substring(obj.state.val.indexOf('[')+1,obj.state.val.indexOf(']'));
    var chat_id = getState("telegram.0.communicate.requestChatId").val;
    var message_id = getState("telegram.0.communicate.requestMessageId").val;
    var handled = false;
    //Выводим меню по типичным начальным командам
    if (command == '/start' || command == '/menu' || command == 'меню' || command == 'Меню') {
        sendLightMenu("Меню");
        handled = true;
    }
//######################## Lighting menu and commands ################
    if (command == LIGHT1 || command == LIGHT1+'') {
        changeLight(LIGHT1, CH_LIGHT1);
        handled = true;
    }
    if (command == LIGHT2 || command == LIGHT2+'') {
        changeLight(LIGHT2, CH_LIGHT2);
        handled = true;
    }
    if (command == LIGHT3 || command == LIGHT3+'') {
        changeLight(LIGHT3, CH_LIGHT3);
        handled = true;
    }
    if (command == LIGHT4 || command == LIGHT4+'') {
        changeLight(LIGHT4, CH_LIHT4);
        handled = true;
    }
    if (command == LIGHT5 || command == LIGHT5+'') {
        changeLight(LIGHT5, CH_LIGHT5);
        handled = true;
    }
    if (command == LIGHT6 || command == LIGHT6+'') {
        changeLight(LIGHT6, CH_LIGHT6);
        handled = true;
    }
    if (command == LIGHT7 || command == LIGHT7+'') {
        changeLight(LIGHT7, CH_LIGHT7);
        handled = true;
    }
    if (command == LIGHT8 || command == LIGHT8+'') {
        changeLight(LIGHT8, CH_LIGHT8);
        handled = true;
    }
    if (command == LIGHT9 || command == LIGHT9+'') {
        changeLight(LIGHT9, CH_LIGHT9);
        handled = true;
    }
    //Если команда не совпала ни с одним вариантом, то передаем её в драйвер text2command
    if (!handled) {
        sendTo('text2command.0', {
            text: command.replace(///g, '#').replace(/_/g, ' '),
            id: chat_id,
            user: user
        }, function (response) {
            if (response && response.response) {
                sendTo('telegram.0', {user: user, text: response.response});
            }
        });
    }
});
//Если вручную переключили свет, просто обновим меню
on({id: /^mqtt.0.PLC55_Lighting.lighting..*$/, ack: true, change: 'ne'}, function (obj) {
    sendLightMenu("Ручное управление");
});
//При рестарте драйвера или скрипта сразу отправляем меню
sendLightMenu("Меню");

В итоге должно получиться примерно так:

Беспроводные устройства Xiaomi в умном доме ioBroker - 31

Заключение

Статья получилась длинной, но надеюсь полезной, и может она облегчит некоторым пользователям жизнь или сподвигнет кого-нибудь на создание своего умного дома.
На данный момент моя система умного дома на базе ioBroker «крутится» уже 4 года и я вполне ей доволен. К ней кроме ZigBee ещё подключено несколько самодельных контроллеров по MQTT и HTTP для управления освещением, вентиляцией и прочими системами, сеть температурных датчиков по шине 1-wire, устройство мониторинга параметров электросети по шине RS485 и протоколу modbus RTU и много чего еще.

В моей копилке решений для умного дома накопилось много идей, хотя, наверное их надо воспринимать скорее, как копилка проблем для умного дома (те кто в теме поймут, о чём я). Оставляйте свои пожелания в комментариях, чтобы помочь мне определиться с темой следующей статьи.

Автор: Андрей Андреев

Источник

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


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