Домашняя автоматизация с openHAB: освещение и удаленное управление обогревателями. Часть 1
Моя прошлая статья была о выборе лапм освещения для жилой мастерской. В этот раз расскажу про реализацию домашней автоматизации в том же помещении. Мастерская отапливается двумя электрическими обогревателями. Хотелось удаленно их включать, чтобы не приезжать в холодное помещение. И еще хотелось поддерживать заданную температуру, до этого при изменении температуры на улице приходилось каждый раз крутить «термостаты» обогревателей. Ну и управление освещением, датчик открытия двери и т.д.
Часть 1ВступлениеОбщее описаниеУправление нагрузкойУправление светом Выключатели Как выключатели взаимодействуют с OpenHAB Arduino Nano + Ehernet Shield Raspberry Pimy.openHABЧасть 2Управление обогревателями Термодатчики Хранение данных Графики Удаленное управлениеВпечатления от OpenHAB Persistence ИнтерфейсыМониторинг
Хардвер я использовал вполне стандартный, местами не оптимальный, про него особенно интересны замечания и рекомендации.Выбор софта частично сделан с целью попробовать незнакомые инструменты, к примеру, таким образом для хранения данных вабрана InfluxDBПосле беглого поиска open-source решений для домашней автоматизации был выбран OpenHAB, довольно зрелый инструмент с модульной архитектурой, кроме того, он активно развивается. Про него уже есть статья на хабре, рекомендую ее посмотреть тем кто захочет использовать OpenHAB.Еще можно взглянуть на демо-интерфейс.Я опишу хардверную часть моего решения и попутно приведу выдержки из конфигурации OpenHAB.
Чтобы было легче понять мою конфигурацию очень коротко опишу понятия которые используются при настройке OpenHAB:
Items — что-то вроде глобально доступного объекта, обычно представляет внешнее устройство или источник данных. Могут быть разных типов, например Switch для выключателя, Dimmer для диммера. Есть также String и Number, это Items которые содержат строку и число. Sitemaps — описывают интерфейс. Фактически это перечисление Items с добавлением настроек отображения. Rules — скрипты, которые выполняются по расписанию или по событию. События наступают при изменении состояния Items, например, когда выключатель Light_1 получил значение ON. Persistence — файлы, в которых описываются правила сохранения состояния Items в разные БД. Bindings — подключаемые модули, наверное можно назвать плагинами. Используются чтобы добавить в OpenHAB возможность взаимодействовать с разным хардом и софтом. Например binding для KNX или для MySQL и т.д. Вот какие Bindings я использую:
Название Применение xmpp Получаю сообщения от OpenHAB mail Получение оповещений на почту networkhealth Мониторинг доступности хостов в сети myopenhab Удаленный доступ к OpenHAB onewire Получение от owserever данных термодатчиков http Взаимодействие с HTTP API freetts Синтез речи jpa Сохранение данных в PostgreSQL db4o Сохранение данных в db4o influxdb Сохранение данных в influxdb Про xmpp подробнее: этот биндинг дает возможность получать сообщения в гугл-чате (или другом Jabber-аккаунте) и использовать час как консоль для отправки команд OpenHAB. Команды начинающиеся с '>' будут выполнены и результат вернется в ответном сообщении. Мне это пригодилось для отладки при написании Rules. Далее в тексте примеры команд OpenHAB начинаются с символа '>'.Конфигурация OpenHAB, скрипты для выключателей и т.д. доступны в репозитории cherdak_home_automation
Общее описание Компоненты системы: Сервер (OpenHAB, InfluxDB, …) Модуль управления реле Arduino MEGA + Ehernet Shield Выключатель пять кнопок Arduino Nano + Ehernet Shield Выключатель пять кнопок Raspberry Pi На картинке веб-интерфейс OpenHABСразу было понятно, что кроме веб-интерфейса надо сделать несколько физических выключателей, т.к. пользоваться веб-интерфейсом не всегда удобно.Сначала я думал сделать беcпроводные выключатели, но доступные по цене и надежные варианты не нашел, возможно сейчас уже есть из чего выбрать, но тогда я решил использовать Ethernet.По возможности делал так, чтобы компоненты системы общались между собой по протоколу HTTP.Он выбран из-за простоты, прозрачности и привычности. Как альтернативу рассматривал MQTT, но понадобился бы софт для сервера, так как OpenHAB может быть только клиентом.
Нагрузка управляется с помощью реле, сейчас их семь штук. От каждого реле идет отдельная жила кабеля, то есть для трех управляемых розеток используется 4-х жильный кабель (три для фазы и одна жила для ноля).
Использование реле:
3 розетки, к двум из них подключены обогреватели (220v) 2 линии дневного освещения (220v) 1 вечерний свет, лампа накаливания (12v) 1 диодная лента (12v) Все потребители постоянного тока подключены к одному компьютерному блоку питания.
Про безопасноть и контроль доспупа: в OpenHAB можно добавить пользователей и запретить анонимный доступ, но я этого не делал. Сейчас любой хост моей локальной сети имеет доступ к веб-интерфейсу OpenHAB и к другим устройствам доступным по HTTP.
Хотелось сделать HTTP API для включения нагрузки. Используется для этого комбинация Arduino MEGA + Ehernet Shield + реле. Мегу купил давно, стоила она тогда целых $50, не пригодилась и лежала без дела.На основе рекомендаций по управлению нагрузкой c Arduino, пины к которым подключены реле инициализируются вот так: digitalWrite (pin, HIGH); pinMode (pin, OUTPUT); Так можно избежать кратковременного включения реле при включении Arduino.У всех реле, кроме одного, используется нормально-разомкнутый контакт (NO, Normally Open), чтобы по умолчанию вся нагрузка была выключена, например после временного отключения электричества. Исключение сделано для диодной ленты — она подключена к нормально-замкнутому контакту, для аварийного освещения.
В целом Arduino + Ehernet Shield работают без проблем, перебои были только когда я включил их мониторинг из OpenHAB. Есть предположение что OpenHAB открывал keepalive соединение и из-за этого другие соединения не устанавливалсь.А еще есть неприятный момент в работе Ethernet Shield:
ПРОБЛЕМА: Ehernet Shield не работает после включения питания Arduino, а только после ресета. Как я понял, это проблема первой версии шилда на чипе w5100. Вот возможный вариант решения.
Исходники API для Arduino в репозитории minimal_arduino_web_api.Вот пример запроса состояния пина 40, к которому подключено реле управляющее одной из ламп:
Запрос состояния:
GET http://192.168.2.15/pins/40 Текст ответа будет ON или OFF.Выключение:
PUT http://192.168.2.15/pins/40/OFF Включение:
PUT http://192.168.2.15/pins/40/ON Итак, есть HTTP API включения света и розеток, теперь надо как-то использовать его из OpenHAB. Каждый пин, к которому подключено реле, добавлен в конфигурацию OpenHAB как выключатель через http binding.
Например, вот описание пина 40 из файла main.items: Тут определяется Switch с именем Light_1, входящий в группы Lights и DayLights:
Switch Light_1 «First Day Light» (Lights, DayLights)
{
http=»
>[ON: PUT: http://192.168.2.15/pins/40/ON]
>[OFF: PUT: http://192.168.2.15/pins/40/OFF]
<[http://192.168.2.15/pins/40:60000:REGEX(.*
> Light_1.sendCommand (ON) то OpenHAB отправит запрос PUT 192.168.2.15/pins/40/ON.Кроме консоли управлять Light_1 можно через REST API самого OpenHAB.<[http://192.168.2.15/pins/40:60000:REGEX(.*(.+).*)] означает, что раз в две минуты выполняется запрос и к тексту ответа применяется регулярное выражение, результат которого определяет состояние Light_1. Короче говоря, это поллинг состояния.
Чтобы переключатель Light_1 появился в веб-интерфейсе OpenHAB, его нужно добавить в Sitemap, например так:
Switch item=Light_1
Выключатели Я сделал два выключателя, у каждого четыре кнопки и один стандартный выключатель. (Чтобы в предыдущем предложении не возникло рекурсии, выключатель написан курсивом и означает весь модуль с кнопками, в отличии от выключателя — обычного выключателя.)Сначала были сделаны только кнопки, но оказалось, что нащупывать их в темноте неудобно и я добавил обычный выключатель. Три кнопки и обычный выключатель управляют светом, а одна кнопка используется для информирования о температуре внутри и снаружи (с помошью генератора речи).Как выключатели взаимодействуют с OpenHAB При нажатии на кнопки или выключатель отправляется HTTP запрос в OpenHAB.Вот так можно включить Light_1 через REST API OpenHAB из Python: import requests requests.post («http://OPENHAB_URL/rest/items/Light_1», data=«ON») Но чтобы использовать этот способ выключатели должны знать состояние Light_1 в OpenHAB. Чтобы, если свет выключен, отправлять команду ON и наоборот. Для этого пришлось бы использовать поллинг.Оказалось OpenHAB поддерживает еще такие запросы:
GET /CMD? Light_1=TOGGLE т.е. GET используется для изменения состояния Item;( Этот вариант позволяет не хранить состояние, поэтому я использую его.И еще, для гибкости, управление происходит не напрямую через Light_1, Light_2 и т.д., а через Virtual_Switch_1, Virtual_Switch_2 и т.д. К примеру, при нажатии первой кнопки на любом из выключателей запрос отправляется на Virtual_Switch_1, а что при этом происходит определяется в virtual_switches.rules. Таким образом, если нужно будет поменять действия кнопок, то не придется перепрошивать Arduino и менять код скрипта на Raspeberry, а только поменять правила в OpenHAB.
Пока не выбрал окончательно какие действия назначить кнопками и выключателю. Сейчас три кнопки и выключатель управляют светом, а одна используется для оповещения о температуре внутри и снаружи (через генератор речи).Часто при выключении света удобно чтобы он выключился не в момент нажатия кнопки, а чуть позже. Поэтому для выключателя я написал правило, чтобы он работал так:
если весь свет выключен, то включается свет по умолчанию (это Items из группы SmartSwitchDefaultLights) если какой-то свет включен, то выключается весь дневной свет, включается свет по умолчанию и ставится таймер на 5 минут на выключение света Вот код этого правила:
rule «Virtual_Switch_5» when Item Virtual_Switch_5 changed then /* если таймер установлен и еще не выполнен, то отменяем таймер и включаем свет по умолчанию */ if (virtual_switch_off_timer!= null && ! virtual_switch_off_timer.hasTerminated) { virtual_switch_off_timer.cancel () virtual_switch_off_timer = null playSound ('Beep_Negative.mp3') SmartSwitchDefaultLights.members .filter (item| item.state == OFF) .forEach (item| item.sendCommand (ON)) } else { // если весь свет выключен, то включаем свет по умолчанию if (Lights.members.filter (item| item.state == ON).isNullOrEmpty) { SmartSwitchDefaultLights.members.forEach (item| item.sendCommand (ON)) } else { /* выключаем дневной свет и ставим таймер и если весь *вечерний* свет выключен, то включаем свет по умолчанию */ if (NightLights.members .filter (item| item.state == ON).isNullOrEmpty) SmartSwitchDefaultLights.members .filter (item| item.state == OFF) .forEach (item| item.sendCommand (ON)) DayLights.members .filter (item| item.state == ON) .forEach (item| item.sendCommand (OFF)) playSound ('Bleep.mp3') virtual_switch_off_timer = createTimer (now.plusMinutes (5)) [| Lights.members .filter (item| item.state == ON) .forEach (item| item.sendCommand (OFF)) ] } } end Дальше я кратко опишу хардвер выключателей.
Arduino Nano + Ehernet Shield Этот выключатель состоит из Arduino Nano и Ehernet Shield. Код скетча в файле light_switch.ino. Для HTTP запросов к OpenHAB используется библиотека github.com/csquared/arduino-restclient.Питается Arduino через pin 5v от блока питания по проводу ~10 метров длинной.Сначала я подключал 12v на vin т.к. думал что из-за падения напряжения использовать 5v не получится, но при 12v конечно же сильно грелся регулятор Arduino.Питание идет по четырем жилам UTP-кабеля, две жилы +5v и две жилы Gnd.
В этом выключателе я использую Ehernet Shield на основе чипа ENC28J60, это бюджетный и менее распространенный вариант, по сравнению с шилдами на основе w5100.При его использовании нужно вместо стандартной библиотеки Ethernet подключить arduino_uipПосле этого, чтобы скрипты для стандартных модулей заработали, нужно заменить:
#include
Raspberry Pi Немного странно обновлять Linux на выключателе, это я к тому что использовать Raspberry только для включения света это, конечно, не оптимально. Сейчас, кроме кнопок, к Raspberry подключен только датчик двери (геркон).Питание У Raspberry Pi есть />контрольные точки для измерения напряжения во время работы. Напряжение между точками должно быть в диапазоне 4.75 — 5.25V. После подключения к линии 5V от БП напряжение было ниже минимума (слишком длинный провод) и пришлось использовать регулятор.Используется простой линейный регулятор 7805, который я закрепил на радиаторе. До и после регулятора установлены конденсаторы как на схеме.Чтобы снизить мощность, которая рассеивается на радиаторе регулятора, между ним и БП последовательно подключены три диода her801. Если считать что на каждом диоде падение напряжения составляет 1V, то на входе регулятора получаем примерно 9V. Напряжение на входе должно быть не менее чем на 2,5V выше чем выходное, то есть для 7805 7,5v на входе это минимум.Чтобы не было ложных срабатываний кнопки
Код для Raspberry Pi написан на Python, смотреть можно в файле light_switch.py3
В завершение первой части расскажу про сервис от создателей OpenHAB, он позволят подключится к OpenHABу находясь за перделами локальной сети. Для меня это удобно так как у мастерской нет отдельного внешнего ip. Подключаться можно как через браузер, так и из мобильных приложений (Android, iOS). Пока проект в закрытой бете, заявку на инвайт можно подать тут.Вторая часть будет опубликована через неделю.