Как стать автором
Обновить

Домашняя автоматизация с openHAB: освещение и удаленное управление обогревателями. Часть 1

Время на прочтение 9 мин
Количество просмотров 135K


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

Оглавление


Часть 1
Вступление
Общее описание
Управление нагрузкой
Управление светом
  Выключатели
    Как выключатели взаимодействуют с OpenHAB
    Arduino Nano + Ehernet Shield
    Raspberry Pi
my.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, скрипты для выключателей и т.д. доступны в репозитории homeAutomationExample

Общее описание



Компоненты системы:

  • Сервер (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 в репозитории minimalArduinoWebApi.
Вот пример запроса состояния пина 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(.*<status>(.+)</status>.*)]
      "
    }

(Группы в OpenHAB удобно использовать, например, чтобы выключить весь свет или взять среднее с температурных датчиков.)
(Переносы строк добавлены для удобства чтения, в таком виде работать не будет.)

Строка >[ON:… определяет запрос, который выполнит OpenHAB при получении Light_1 команды ON.
То есть если в консоль отправить:
    > 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 <SPI.h>
    #include <Ethernet.h>

на
    #include <UIPEthernet.h>


Так же надо сделать в используемых библиотеках, если они подключают Ethernet.h
Из 2kB доступной памяти arduino_uip использует 400-600B, это стоит учитывать.



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

my.openHAB


В завершение первой части расскажу про сервис от создателей OpenHAB, он позволят подключится к OpenHABу находясь за перделами локальной сети. Для меня это удобно так как у мастерской нет отдельного внешнего ip. Подключаться можно как через браузер, так и из мобильных приложений(Android, iOS). Пока проект в закрытой бете, заявку на инвайт можно подать тут.
Теги:
Хабы:
+29
Комментарии 75
Комментарии Комментарии 75

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн
PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн