Содержание статьи
Поводом для того, чтобы смешать дома умные устройства разных производителей, может быть желание сэкономить, выбирая наиболее выгодные варианты, или наоборот — стремление взять все самое лучшее. Но чаще всего ответ более прозаичный: «так вышло». Сначала ты покупаешь лампочки и датчики движения Philips, а потом обнаруживаешь, что, к примеру, умных розеток эта компания не делает вовсе, а тебе позарез нужна одна из них.
Опять же, если ты выбрал Xiaomi (а предложение этой компании — одно из самых выгодных), то тебя ждет хаб с китайским софтом, подключенный к фирменному сервису. С точки зрения безопасности — далеко не самый лучший вариант.
В этой статье я покажу, как сконструировать универсальный хаб на основе Raspberry Pi Zero W и экстремально дешевого контроллера. А поможет мне в этом программа под названием zigbee-shepherd. Она поддерживает множество устройств ZigBee, в том числе и выключатели Xiaomi на батарейках серии Aqara, и позволяет писать скрипты на JavaScript.
Выбираем и прошиваем железо
Сначала нужно определиться, на каком железе собирать хаб. В принципе, ты можешь взять что угодно (хоть свой основной компьютер, если ты его не выключаешь), но Raspberry Pi Zero W — это сверхкомпактный, дешевый и достаточно производительный вариант.
Xakep #235. Возрождение эксплоит-китов
Zigbee-shepherd совместим с чипами ZigBee производства Texas Instrument CC2530 и CC2531. У TI есть референсный USB-стик CC2531 USB Evaluation Module Kit за 49 долларов, но есть и полная документация и схемы по сборке такого стика, поэтому будет несложно найти в Поднебесной такой же стик, но за 7 долларов.
Для работы стика с zigbee-shepherd потребуется файл прошивки с GitHub, а чтобы ее зашить, понадобится программатор CC Debugger за 49 долларов или его китайская копия за 12.
Прошивают USB-стик с помощью официальной утилиты TI SmartRF Flash Programmer. Чтобы все заработало, нужно подключить CC Debugger в один порт компьютера, стик ZigBee — в другой и шлейфом соединить их между собой.
В настройках программатора выбираем прошиваемое устройство (1), прошивку (2), задаем нужные действия (3) и прошиваем (4).
Проверить, что USB-стик удачно прошился и работает, можно, подключив его к Raspberry Pi Zero W и выполнив команду
$ ls /dev
Устройство будет отображаться в системе как ttyACM0.
Ставим сервер zigbee-shepherd на Raspberry Pi Zero W
Установка zigbee-shepherd и сопутствующих пакетов будет проводиться на последней версии ОС Raspbian для Raspberry Pi Zero W — Stretch.
Zigbee-shepherd написан на JavaScript и работает на Node.js. Для начала ставим Node.js:
$ wget -O - https://raw.githubusercontent.com/sdesalas/node-pi-zero/master/install-node-v.lts.sh | bash`
Для установки расширений из npm нужно установить утилиты для сборки:
$ sudo apt-get install -y build-essential
И сама установка zigbee-shepherd:
$ npm install zigbee-shepherd - -save
Проверить, правильно ли работает zigbee-shepherd, можно, запустив скрипт zigbee-server.js
. Во время работы скрипт выводит информацию о каждом этапе добавления устройства и время выполнения операции.
var ZShepherd = require('zigbee-shepherd');
// Create a ZigBee server
var zserver = new ZShepherd('/dev/ttyACM0');
zserver.on('ready', function () {
console.log('Server is ready. Allow devices to join the network within 60 seconds');
zserver.permitJoin(60);
});
zserver.on('permitJoining', function (joinTimeLeft) {
console.log(joinTimeLeft);
});
// Start the server
zserver.start(function (err) {
if (err) console.log(err);
});
Запускаем zigbee-shepherd в режиме отладки:
$ sudo DEBUG=* node zigbee-server.js
INFO
На этапе разработки скрипта для Node.js всегда используй отладочный режим. Вывод при этом более подробный, легче отловить ошибки, а zigbee-shepherd показывает все данные, которые он отправляет и получает.
Работаем с выключателями Xiaomi из zigbee-shepherd
Первым делом следует добавить устройство ZigBee в сеть. Для этого сначала нужно сбросить его настройки на заводские и тем самым удалить информацию о предыдущей сети, если оно было добавлено прежде. Комбинация сброса и добавления устройства для выключателей Xiaomi Aqara следующая: зажать кнопку на пять секунд, пока светодиоды не начнут мигать, после чего отпустить и ждать, когда закончится процесс добавления. Если включен дебаг, то при добавлении устройства выводится подробный лог. Добавление устройства может занять до одной минуты.
После добавления устройства важно еще правильно с ним работать. Zigbee-shepherd не предоставляет веб-интерфейса для добавления устройств и управления ими, вместо этого мощный JS API позволяет получить полный контроль над любым устройством и написать собственную систему автоматизации.
В вики есть полное описание всех функций. Но чтобы быстрее разобраться с ними, нужно понимать программную структуру устройства.
IEEE address. Каждое устройство ZigBee имеет уникальный 48-битный MAC-адрес, он зашит в девайс, и сбросить его невозможно. По MAC-адресу можно обращаться к устройству и получать информацию о нем.
Endpoint. В устройстве может быть несколько функций, например датчик температуры и влажности или выключатель с двумя кнопками. Для каждой функции устройства создается отдельный Endpoint.
Clusters. Группа команд, которые можно отправлять устройству. Например, команда genOnOff
включает или выключает устройство, а если это лампа с диммером, то команда genLevelCtrl
позволит задать уровень яркости.
Attributes. У устройства можно запросить его текущее состояние, обратившись в интересующий Cluster. Например, командой genOnOff
можно узнать состояние атрибута onOff
— оно может быть 0 или 1.
Выключатель Xiaomi Aqara с одной кнопкой имеет следующую структуру:
{
"profId": 260,
"epId": 1,
"devId": 24321,
"inClusterList": [0, 3, 18, 25, 65535],
"outClusterList": [0, 3, 4, 5, 18, 25, 65535],
"clusters": {
"genBasic": {
"dir": {
"value": 3
},
"attrs": {}
},
"genIdentify": {
"dir": {
"value": 3
},
"attrs": {}
},
"genGroups": {
"dir": {
"value": 2
},
"attrs": {}
},
"genScenes": {
"dir": {
"value": 2
},
"attrs": {}
},
"genMultistateInput": {
"dir": {
"value": 3
},
"attrs": {}
},
"genOta": {
"dir": {
"value": 3
},
"attrs": {}
},
"manuSpecificCluster": {
"dir": {
"value": 3
},
"attrs": {}
}
}
}
Чтобы обрабатывать нажатие кнопки, нужно отловить сообщение от выключателя. Делается это с помощью события ind
. Изменим код следующим образом:
var ZShepherd = require('zigbee-shepherd');
var zserver = new ZShepherd('/dev/ttyACM0');
zserver.on('ind', function (msg) {
console.log("msg");
});
zserver.start(function (err) {
if (err) console.log(err);
});
При нажатии кнопки придет сообщение:
{
endpoints: [
{
isLocal: [Function],
device: [Object],
profId: 260,
epId: 1,
devId: 24321,
inClusterList: [Array],
outClusterList: [Array],
clusters: [Object],
onAfDataConfirm: null,
onAfReflectError: null,
onAfIncomingMsg: null,
onAfIncomingMsgExt: null,
onZclFoundation: null,
onZclFunctional: null,
foundation: [Function],
functional: [Function],
bind: [Function],
unbind: [Function],
read: [Function],
write: [Function],
report: [Function]
}
],
data: {
cid: 'genOnOff',
data: {
onOff: 0
}
}
}
Здесь
msg.endpoints[0].device.ieeeAddr
— MAC-адрес устройства;msg.endpoints[0].epId
— канал (endpoint) устройства;msg.data
— ID кластера и атрибут, в данном случае выключатель прислал командуgenOnOff:0
.
Если проверять эти данные, то, нажимая на кнопку выключателя, можно будет управлять другими устройствами ZigBee по определенному алгоритму. Например, при каждом нажатии включать-выключать или только выключать группу устройств.
Zigbee-shepherd полностью поддерживает работу с диммируемыми лампами Ikea Trådfri и Philips Hue, поэтому для примера можно настроить простой алгоритм включения лампы с помощью выключателя Xiaomi Aqara. Добавляем в код обработчик нажатия кнопки и включение лампы Ikea Trådfri на максимальную яркость:
var ZShepherd = require('zigbee-shepherd');
var zserver = new ZShepherd('/dev/ttyACM0');
zserver.on('ind', function (msg) {
console.log(msg);
switch (msg.type) {
case 'attReport':
var epId = msg.endpoints[0].epId;
var ieeeAddr = msg.endpoints[0].device.ieeeAddr;
var data = msg.data;
if (ieeeAddr === "0x00158d00015efcef" && epId === 1 && data.cid === "genOnOff") {
// Get lamp endpoint
var lamp = zserver.find(0x000b57fffe3298aa,1);
// Turn on lamp
lamp.functional("genLevelCtrl", "moveToLevelWithOnOff", {level: 255, transtime: 0}, function (err, rsp) {});
}
break;
default:
console.log(msg);
break;
}
});
zserver.start(function (err) {
if (err) console.log(err);
});
Увязываем наше решение с другими
Zigbee-shepherd использует инфраструктуру Node.js, поэтому можно реализовать управление любыми объектами, для которых есть соответствующие библиотеки. Например, протокол MQTT дает возможность интеграции со многими системами домашней автоматизации, такими как OpenHub и Home Assistant. Для последней существует готовый проект на GitHub.
Многие хабы и самостоятельные устройства Wi-Fi вроде розеток поддерживают управление через запросы HTTP. Команды можно узнать из документации, либо подглядеть в веб-интерфейсе хаба умного дома, либо проанализировать трафик от мобильного приложения.
Z-Wave-контроллер RaZberry имеет хорошо документированный HTTP API, поэтому не составит труда написать запрос на выключение света. Для отправки HTTP-запросов требуется установить библиотеку request:
$ npm install request --save
Добавляем в код поддержку HTTP-запросов и сам запрос на выключение света:
var ZShepherd = require('zigbee-shepherd');
var zserver = new ZShepherd('/dev/ttyACM0');
var request = require('request');
zserver.on('ind', function (msg) {
switch (msg.type) {
case 'attReport':
var epId = msg.endpoints[0].epId;
var ieeeAddr = msg.endpoints[0].device.ieeeAddr;
var data = msg.data;
if (ieeeAddr === "0x00158d00015efcef" && epId === 1 && data.cid === "genOnOff") {
request('http://admin:admin@192.168.1.108:8083/ZAutomation/api/v1/devices/ZWayVDev_zway_7-0-37/command/off', function (error, response, body) {
if (error) { console.log("--- Error send request:", error); }
});
}
break;
default:
console.log(msg);
break;
}
});
zserver.start(function (err) {
if (err) console.log(err);
});
Минимальная домашняя автоматизации готова! В 26 строках кода запускается сервер ZigBee, отслеживается нажатие кнопки и исполняется команда управления светодиодной лампой или команда HTTP. Если подключить фреймворк веб-приложений для Node.js (например, express), то можно реализовать полноценный HTTP API для работы с устройствами ZigBee.
Zigbee-shepherd позволяет добавить к уже существующей домашней автоматизации на KNX, Z-Wave или Wi-Fi недорогие устройства ZigBee, которых с каждым годом выпускается все больше.