Pull to refresh

Простой интерфейс к умному дому с nooLite

Smart House DIY
Sandbox
Сколько-то месяцев тому назад я поставил у себя дома «умный дом» на базе компонентов белорусской «Ноотехники», о которых на Хабре и Гиктаймсе писали много-много раз. Строго говоря, я не рассматривал его именно как умный дом — а в первую очередь как удобный: начинался он с желания получить управление лампами из разных мест квартиры без капремонта проводки, а заодно сделать посекционное включение для тех ламп, к которым сейчас проведена одна пара проводов.

Если полистать публикации по данной теме, они в основном сводятся к трём вещам: «как я установил первый выключатель», «как я пишу супернавороченный интерфейс с плагинами и собственным скриптовым языком» и «как я настраиваю полную автоматизацию, чтобы вообще больше выключателей не видеть».

Увы, ни одна из них ничего практически ценного мне не давала: помимо того, что последние две категории обычно находятся в вечном состоянии work-in-progress, я не верю в осмысленную автоматизацию света в городской квартире (больше тут автоматизировать особо нечего), а также не хочу собственный скриптовый язык. Я хочу систему, которая, будучи однажды установленной, позволяла бы и мне, и другим людям удобно управляться со светом в квартире, по возможности не поднимая задницу с кресла и не требуя никаких специальных знаний. И не только включать и выключать, но и, например, поменять функцию конкретной кнопки.



В общем, я её сделал.

Но обо всём по порядку.

Причины выбора именно nooLite довольно типичны: сравнительно недорогой, простой, с гарантией и вообще поддержкой — если потребуется — проблем возникнуть не должно. Довольно невзрачный дизайн выключателей меня совершенно не пугает — мне важнее, чтобы они были удобные, чем красивые, а тут у nooLite обнаружилась пара преимуществ, о которых ниже. Однозначным плюсом относительно ещё более дешёвой китайчатины было наличие настенных выключателей самих по себе — я не очень представляю, как в квартире вместо настенных выключателей пользоваться опять затерявшимся куда-то брелком.

Главный же недостаток — причём присутствующий не только у nooLite — оказался в том, что для любого изменения функционирования системы надо лезть под потолок. Например, захотелось поменять функцию кнопки на выключателе — снимай люстру, выковыривай из-под натяжного потолка силовой блок, запускай его в режим привязки, меняй функцию.

Второй недостаток — быстро кончились кнопки на выключателях, хотя у nooLite их по три штуки на каждом. Вот, например, комната. В ней настольная лампа, бра, люстра с двумя секциям. Это — уже четыре кнопки. Упс.

К счастью, у nooLite есть такие прекрасные, хотя и весьма дорогие штуки, как USB-приёмник и USB-передатчик. При взгляде на эту парочку простая, но в то же время мудрая мысль не заставила себя ждать: ведь можно же завернуть всё общение выключателей с силовыми блоками через сервер, который и будет определять, что именно делать при получении сигнала от кнопки такой-то. Хотим изменить функцию этой кнопки — лезем на сервер и программно меняем. Хотим сделать для кнопки какую-то сложную логику — лезем на сервер и пишем её. Хотим блекджека и женщин лёгкого поведения — ну вы поняли.

Тут надо заметить, что у nooLite есть своё устроство под названием «Ethernet-шлюз», но умеет оно чуть больше чем ничего — показывать температуру с датчиков (спасибо, у меня есть три метеостанции) и включать-выключать силовые блоки через веб.

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

Получилось примерно так:
  • Работа на x86 под линуксом и на роутерах с OpenWRT
  • Работа со стандартными приёмником и передатчиком nooLite
  • Привязка-отвязка силовых блоков и выключателей через веб-интерфейс
  • Возможность повесить на один выключатель сколько угодно ламп
  • Стандартные функции — включение, отключение и переключение ламп
  • Дополнительные функции: последовательное включение нескольких ламп при последовательных нажатиях одной кнопки (удобно для многосекционных люстр), включение по цепочке (предыдущая лампа гаснет), управление группой ламп (если все выключены — включить все, если включена хоть одна — выключить все), отключение всех ламп в доме разом
  • Отдельные функции на короткое и длинное нажатие кнопки выключателя
  • Настройка всех ламп, выключателей и взаимодействия между ними из веб-интерфейса
  • Отображение в веб-интерфейсе текущего состояния ламп (см. картинку в начале заметки)
  • Приложение под Android


В итоге, например, настройка конкретной люстры выглядит у меня так: первое нажатие кнопки — включаются 2 лампы из 5; второе нажатие — включаются оставшиеся 3 лампы; третье нажатие — все лампы гаснут. Длинное нажатие при всех выключенных лампах — включаются сразу все 5; длинное нажатие при 2 или 5 включённых — все лампы гаснут. То есть, полное управление двухсекционной люстрой с помощью только одной кнопки пульта.

Disclaimer:
  • Я не собирался делать эту систему поддерживаемой, расширяемой и так далее — мне оно абсолютно незачем. Это замкнутая в себе система, которая решает конкретную задачу
  • Я не программист. Ни на C, ни на Javascript, ни на Java, ни на PHP (далее будут встречаться все четыре)
  • В системе не сделаны те вещи, которые мне не были нужны (есть лишь зачатки работы с диммерами, нет ничего про расписания, нет ничего про ноолайтовские датчики). Скорее всего, я их не сделаю никогда, так что если вам они нужны — быстрее будет сделать самим
  • Весь код — под лицензией WTFPL


Теоретически, на момент покупки мной nooLite'овского комплекта уже существовали неофициальные драйверы под него, которые я и надеялся использовать: драйвер приёмника при получении команды пинает PHP-скрипт, а тот пинает драйвер передатчика, сообразуясь со своей внутренней логикой.

Эти надежды прожили недолго — до первого личного знакомства с драйверами: они оказались не столько драйверами, сколько технологической демонстрацией, что в принципе nooLite под линуксом работать может. Внутри было много всего, от прямых опечаток и ошибок (например, попытка отвязать один канал приёмника грохала всю его конфигурацию) до вещей типа забитого прямо в код вызова wget, который и должен был пинать PHP-скрипт. Пользоваться ими было можно, но любить себя за это — вряд ли.

В итоге комплект софта под линукс был переписан (GitHub) и обзавёлся следующим:

  • Приёмник nooliterx: выполняемая команда задаётся в конфигурационном файле или командной строке, есть режим демона, есть UNIX-сокет, через который оный демон слушает команды привязки-отвязки пультов
  • Передатчик noolitepc: причёсаны команды, исправлены ошибки
  • Передатчик noolitepcd: если noolitepc — консольная утилита, то это — демон, принимающий команды через UNIX-сокет. Это не только быстрее работает, но и позволяет построить элементарную очередь команд с автоматической задержкой между ними, так как передатчик nooLite при запихивании в него команд быстрее чем раз в 400 мс захлёбывается
  • Конфигуратор передатчика nooliterxcfg: консольная утилита для привязки-отвязки пультов. Фактически более не нужна — это можно делать через веб-интерфейс и nooliterx с его сокетом


Из nooliterx и noolitepcd собирается скелетик, в который остаётся только добавить логику, связывающую выход первого со входом второго. Эта логика сделана на PHP (GitHub) — по двум причинам: во-первых, простота модернизации на живом пациенте, во-вторых, лёгкость прикручивания веб-интерфейса. Последний я хоть и не рассматриваю как основное средство управления светом в доме (дотянуться до выключателя обычно проще, чем до смартфона), но его удобно иметь.

Наконец, смартфонное приложение. Мне показалось некрасивым просто хранить ссылку на IP роутера, где живёт всё это добро (тем более, что IP может быть вещью непостоянной), поэтому я запустил на роутере avahi-daemon, орущий «светом рулят здесь!» на всю сеть, а на смартфон склепал приложение из WebView и Network Service Discovery (GitHub), которое по этим воплям определяет нужный IP и показывает его. Для смартфонов сделан отдельный компактный веб-интерфейс, разумеется, без красивых картинок.



Так, какой из языков мы ещё не посчитали? А, да, Javascript. На Javascript сделана конфигурация ламп и выключателей в веб-морде.



В нём можно сделать всё: добавить выключатель (по номеру канала приёмника, к которому он привязан), повесить на него лампы, определить, что он с ними может делать. Хранится всё в файле switch.xml, который при желании можно править руками (и в первой версии примерно так и было сделано, но как-то меня внешний вид этого не удовлетворил).



В соседней вкладке можно прописать имеющиеся лампочки (по номерам каналов передатчика) и растащить их по схеме своей квартиры, поставив в нужных местах (чтобы убрать лампочку со схемы квартиры — вытащите её за пределы картинки). Помимо лампочек, есть тип устройства «Другое» — отличается только иконкой. Лампы хранятся в lamps.xml.



Привязка силовых блоков и выключателей к приёмнику и передатчику делается тут же. Разумеется, для неё нужен физический доступ к блокам — но эта привязка делается один раз перед установкой нового блока и больше никогда не трогается: на то, какие выключатели блоком смогут управлять, она не влияет.

Так как всё управление лампами проходит через сервер, то теоретически — за исключением случая, когда из-за помех команда до лампы не дошла — он знает текущее состояние всех управляемых ламп в квартире. Оно хранится в SQLite-базе lamps.db, при первом запуске интерфейс предложит вам её создать, заполнив нулями.

В случае сбоев связи — nooLite от них, увы, не застрахован, так как у него нет обратной связи и подтверждения приёма команды — достаточно будет прощелкать цикл кнопкой выключателя, пока база и реальная лампа не «синхронизируются» (в простейшем случае команды «переключение»: 1) лампа включена, команда на выключение до неё не дошла, лампа остаётся работать, в базе значится как выключенная; 2) второе нажатие — лампа получила команду на включение, продолжила светить, при это в базе она тоже значится как включённая).

Установка


Для сборки под OpenWRT (ссылка на готовый пакет для AR71xx и OpenWRT 12.09 будет ниже) нужен toolchain OpenWRT, развёрнутый где-нибудь на большом ПК. В нём после стандартной подготовки надо взять отсюда Makefile и положить в папку package/noolite/ внутри тулчейна, после чего сделать make package/noolite/compile. Если сегодня — ваш день, а GitHub не забанен Роскомнадзором, то всё соберётся и окажется в папке bin/<arch>/packages/ в виде готового к установке пакета.

Из сторонних не слишком стандартных пакетов нужен libusb1 для работы и libusb1-dev для сборки.

Устанавливаем его на роутер (opkg install <пакет>), потом копируем файл noolite в /etc/init.d/ этого роутера и делаем /etc/init.d/noolite enable — теперь утилиты будут стартовать при загрузке роутера. В /etc/ создаём файл noolite.conf и пишем в него:

command = wget -q -T 5 "http://localhost/lampcontrol.php?channel=%ch&command=%cm" -O /dev/null &
timeout = 250


Первое — команда, которую будет вызывать демон приёмника при получении чего-нибудь; в данном случае дальше он из принятого передаёт номер канала и номер команды (он разный для разных типов кнопок на пультах и короткого или длинного нажатия), но в принципе может передавать что угодно из стандартной информации nooLite в произвольном порядке. Коды есть в документации в /doc проекта. Второе — таймаут, в течение которого программа чего-то ждёт после запроса к приёмнику; принципиальной роли в жизни общества не играет.

Если не создать конфиг или указать в командной строке параметр -i, то утилита nooliterx будет выдавать полученные ей данные в консоль в отформатированном для чтения человеком виде — это удобно при отладке.

Если вы ставите систему себе под x86, то сборка — ./configure && make && make install.

Для веб-морды нужен веб-сервер с поддержкой PHP, например, под OpenWRT (со всем необходимым набором) это opkg install lighttpd lighttpd-mod-cgi php5 php5-cgi php5-mod-simplexml php5-mod-xml php5-mod-sqlite3 coreutils-timeout. Если память роутера позволяет оставить родные пакеты на месте — удобно перенастроить его изначальный веб-сервер на какой-нибудь порт типа 8080, а управление светом повесить на стандартный :80, чтобы и сохранить LuCI, и не мешать котлеты с мухами.

Далее остаётся развернуть архив с веб-интерфейсом в положенном месте, при желании — открыть файл admin/index.php и поменять там логин и пароль с admin/admin на что-нибудь другое (или вообще выключить авторизацию). Авторизация сделана на очень примитивном уровне и только на админку — чтобы ваши родные и близкие, нажав кнопочку, случайно не грохнули свет в квартире.

Да, если всё-таки вы что-то грохнете — при каждом сохранении XML-файлов старая версия копируется в файл с расширением .bak. Так что откатить на один шаг назад изменения можно, но уже только из консоли — переименовав файл обратно.

При первом заходе на веб-морду система предложит создать вам пустую БД — не отказывайте ей. XML-файлы в ней уже есть, они лежат для примера того, как выглядит готовая конфигурация — посмотрев, сотрите из неё все лампочки и выключатели и задайте свои собственные. Аналогично поступите с картинкой плана квартиры.

Последний штрих — приложение на Android. Чтобы оно само находило, где тут свет включают, поставьте на OpenWRT пакет avahi-daemon, зайдите в /etc/avahi/services и создайте там файл http.service такого содержимого (приложение будет находить IP роутера по имени сервиса):

<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
 <name replace-wildcards="yes">Homelight server</name>
  <service>
   <type>_http._tcp</type>
   <port>80</port>
   <txt-record>path=/</txt-record>
  </service>
</service-group>


Если далее Avahi упирается при запуске и ругается на отсутствие DBus, то в /etc/avahi/avahi-daemon.conf можно добавить строчку enable-dbus=no в раздел [server].

Лирическое отступление про nooLite


После месяцев использования nooLite'а не могу, конечно, не поделиться наболевшим. Во-первых, конечно, отсутствие обратной связи: да, бывает, что команда ушла от выключателя и никуда не пришла. Нечасто, но бывает. Во-вторых, помимо отсутствия защиты передаваемого, у ноолайта вообще не очень хорошо с проверкой целостности данных: бывает, что ушла одна команда, а пришла другая — и включилась не та лампа. Совсем редко, но случается. Наконец, выключатель для уверенности посылает в эфир несколько копий команды — и иногда приёмник умудряется и принять их как две последовательные команды (для борьбы с этим в nooliterx введено ограничение: игнорируется команда, если она поступила менее чем через 300 мс после предыдущей).

К сожалению, системы, удовлетворяющей меня по цене и эстетике и при этом лишённой этих недостатков, я пока не видел. Да, классика на Z-Wave — это хорошо, но стоимость оборудования Z-Wave'ом всей квартиры даже при долларе по 35 рублей вгоняла в дрожь.

Из плюсов: обнаружилось, что невзрачность выключателей nooLite искупается их функциональностью. Можно делать, например, вот так:



Пульт здесь вставлен в стандартную рамку розеток серии W59 Schneider Electric (собственно гнезда под пультом нет, там сразу стена идёт), а в сам пульт вместо родной серой подложки вставлена заламинированная собственной распечатки, на которой указано, что именно какая кнопка выключает.

Советы:
  • Надёжность срабатывания силовых блоков сильно зависит от антенн. Антенна в идеале должна быть распрямлена и направлена перпендикулярно направлению на передатчик. Родные антенны — из мягкого провода, проще всего обеспечить им достаточную жёсткость, надев коктейльную соломинку.
  • Не располагайте антенны ближе 5-10 см от цоколей КЛЛ и светодиодных ламп — их импульсные БП дают заметные наводки. Характерный симптом — блок включается с первого, а выключается с пятого-десятого раза.
  • Антенны на USB-приёмнике и передатчике я поменял на жёсткие штыри из медной проволоки длиной по 165 мм.
  • Уровень сигнала у USB-передатчика выше, чем у настенных пультов, поэтому там, где от настенного пульта срабатывало через два раза на третий, с USB-передатчиком может заработать стабильно.
  • Роутер — единая точка отказа света в вашем доме (ну, помимо щитка на лестнице и трансформатора в соседнем квартале). Купите два-три запасных пульта и привяжите к ним основные силовые блоки напрямую, чтобы можно было включить необходимый минимум света без роутера.


Ссылки


Tags:
Hubs:
Total votes 18: ↑18 and ↓0 +18
Views 16K
Comments Comments 13