понедельник, 28 мая 2018 г.

Lazy MQTT: FAQ

О чем это


В этой статье собираются заметки, советы и решения проблем для программы Lazy MQTT (Play market), о которой я упоминал ранее в статье про умный дом. Это MQTT-клиент с огромными возможностями по оформлению и обработке сообщений для просмотра состояния и управления устройствами по MQTT.

У программы две версии: бесплатная (с рекламой) и платная (без рекламы). Вторая отличается еще поддержкой виджетов, в остальном они одинаковые и настройки можно переносить из одной в другую. Если нравится программа - напишите отзыв в Play Market, если хотите дополнительно отблагодарить автора - купите платную версию :)

Начало


1) Где получить больше информации о программе?
- в программу встроено общее описание с примерами (Меню->Помощь)
- в окне редактирования скрипта есть подсказка по встроенным функциям и переменным
- в программе есть демо-настройки
- в форуме 4PDA можно задать вопрос

2) Как экспериментировать с настройками или настроить программу для работы на другом устройстве?
- поддерживается 10 независимых наборов настроек, между которыми можно переключаться (Меню->Установках->Слот настроек)
- настройки можно экспортировать в текстовый формат и импортировать обратно для бэкапирования и переноса между устройствами (см. Меню->Настройки)

3) Как восстановить демо-настройки?
- Меню->Настройки->Импорт демо. Не забудьте предварительно переключить слот настроек на свободный в Установках, чтобы не потерять свои текущие настройки

4) С чего начать?
- посмотрите встроенное описание (Меню->Помощь)
- посмотрите примеры в Демо-настройках
- сделайте новую страницу (Меню->Страницы...->+) или используйте существующие
- добавляйте плитки. Если включить Меню->Режим дизайна, то плитки можно перемещать и менять их размеры пальцем

5) Как узнать причину ошибки (ошибка соединения, не работает скрипт и др.)?
- см. Меню->Текст последней ошибки

Оформление интерфейса


1) Каковы возможности по оформлению?
- плитки могут быть любого размера и располагаться в любом месте
- у плитки настраиваются цвета, текст заголовка/подвала, основой текст, иконка
- плитка может иметь два состояния с независимым оформлением (включена-выключена)
- плитки могут быть (полу-)прозрачными
- плитки могут перекрываться

2) Не хватает встроенных иконок. Что делать?
- при долгом нажатии на кнопку выбора иконки можно выбрать любую картинку на устройстве

3) Как задать цвет иконки отличный от цвета текста?
- можно сделать 2 Украшения:
а) основное украшение с цветом для текста
б) родитель для первого украшения с иконкой и цветом для нее

4) Что означают цвета точек на плитках?
- эти точки - статус данных и MQTT-соединения. Их можно отключать (Статус данных у Плитки)
- нет точки: изменено условие показа точки (Статус данных у Плитки) или у Плитки не указаны Данные, соединенные с каким-либо сервером 
- черный: устанавливается соединение
- светло-зеленый: соединение установлено, данные после этого не приходили
- зеленый: после соединения данные уже приходили
- красный и темно-красный - ошибка соединения
- желтый: после нажатия на плитку и отправки данных на сервер не получено подтверждение отправки. Например из-за плохого интернет-соединения

5) Как сделать радио-кнопки (несколько переключателей, когда выбор одного выключает все остальные)?
- сделайте несколько плиток, одна рядом с другой
- сделайте Данные к ним, у которых скрипт на отправку управляет сразу всеми этими Данными (например, данные d1, d2, d3. При активации d2 скрипт сбрасывает значения d1 и d3. Визуально значения обычно привязаны к статусу on-off)

6) Как к одной плитке подключить несколько слайдеров вo всплывающем окошке и отправлять их данные сразу по кнопке "Отправить"?
- сделать отдельную страницу со слайдерами (несколько плиток, у каждой слайдер) и плиткой "Отправить"
- при клике на плитку на основной странице открывается страница со слайдерами (в скриптах есть команда page="имя страницы" - переход на страницу)
- при клике на "Отправить" отправляются данные и происходит переход на основную страницу
- похожий пример есть в Демо, на странице с деревенским домом, у двери кнопка домофона

7) Возможно ли сделать шкалу на слайдере?
- cейчас шкалу можно сделать, если добавить на плитку со слайдером картинку с прозрачным фоном, на которой нарисована шкала, и подогнать настройкой ее размер и размер плитки, чтобы ровно ложилась на слайдер

8) Можно ли сделать промежуточный статус украшения, кроме 2-х существующих (on-off)?
- поверх основной плитки сделайте еще одну плитку (т.е. у нее z-координата д.б. больше)
- у новой плитки поставьте Данные, у которых нет скрипта на отправку и нет соединения - в этом случае она не будет хватать нажатия на нее, а пропускать их ниже себя
- у новой плитки поставьте одно украшение прозрачное, чтобы ее не было видно, а второе -  промежуточное, как вы хотите
- в скрипте основной плитки управляйте статусом Данных новой плитки, чтобы переключать ее Украшение
- вуаля, у вас есть три состояния

Работа с данными


1) Как расположить данные из нескольких источников на одной плитке?
- eсть Данные с именами d1 и d2
- создаем для общих данных новый элемент Данных my_data (к серверу подсоединять не требуется)
- у d1 и d2 указываем скрипт на прием, в котором пишем
my_data="data1:"+d1+"\ndata2:"+d2
- создаем плитку и указываем у нее Данные my_data. Все. Это один из вариантов

2) Если из скрипта отправляется сразу несколько сообщений с QoS=0, то почему до сервера доходит только одно из них?
- клиент не успевает послать сообщения и, вероятно, отбрасывает их, так как QoS=0 означает, что не очень-то и важно. Решение - поставить у Данных, которые отправляют такие сообщения, QoS=1

3) В скрипте управляют статусом данных (status="on"...), однако, статус сам сбрасывается. Что не так?
- проверьте флаг Авто "on" в Данных. Если он включен, то статус ставится автоматически. Если вы ставите его вручную, то выключите "Авто"

Скрипты


1) Как округлить число?
- Math.round(x)
- описание встроенных JavaScript функций и вообще языка: см. Rhino

2) Как написать скрипт, чтобы при изменении полученных данных с 0 на 1, было сообщение?
- скрипт:
if(this.my_old_data===undefined) my_old_data=null // нужно, если my_old_data - переменная
if(val==1 && my_old_data==0) notify('Заголовок', 'Текст', 'A')
my_old_data=val
- здесь my_old_data - имя переменной JS (значения переменных сохраняются между вызовами скриптов). Если существуют Данные с именем my_old_data, то значение my_old_data будет сохраняться и при выходе из программы (потому что значения Данных сохраняются)

3) При проверке моей переменной, пока она еще не определена, получаю ошибку ReferenceError: "zz" is not defined

if(val!=zz) zz=val // ошибка ReferenceError: "zz" is not defined
Перед проверкой значения переменной надо проверить, определена ли она:
if(this.zz===undefined) zz=null // если не определена, то определяем zz с пустым значением
if(val!=zz) zz=val // ошибки нет

Соединения


1) На плитке постоянно меняется цвет точки - то красная, то зеленая. Данные то отправляются, то пишет "нет соединения". Что происходит?
- это симптомы неверной настройки, когда несколько MQTT-клиентов, подключающихся к одному серверу имеют одинаковые Client ID (Имя Клиента). Client ID должен быть уникальным в пределах сервера. Client ID настраивается:
a) в Установках->Имя Клиента (предпочтительный способ)
б) в Соединении->Имя Клиента (следует использовать только если по какой-то причине вам нужно создать несколько Соединений к одному серверу, чтобы указать у них разные имена. В противном случае уберите имя из Соединения и используйте первый способ)

Режим работы с MQTT сервером


Lazy MQTT автоматически соединяется с сервером, если соединение потеряно, и специально следить за этим не нужно. Она также замечательно работает в сеансовом режиме (когда ее периодически запускают для просмотра или управления) и при обновлении содержимого виджетов по-расписанию.
При работе в постоянном режиме есть нюансы.
Lazy MQTT не будет поддерживать соединение с сервером, если устройство, на котором она запущена, засыпает (экономия батареи в первую очередь). Сервер в этом случае автоматически разорвет соединение по истечении таймаута (keep alive) умноженного на 2-3. По-умолчанию это порядка минут. Это не имеет значения, потому что программа, когда ей нужно, соединится сама. Имеет значение другое: даже если соединение есть, но устройство спит, сообщения не будут доходить сразу (ведь клиент спит). И тут возникает множество вариантов: сообщения QoS=0 могут вообще не прийти, когда программа спит, QoS>0 придут при просыпании программы, если соединение не было разорвано или даже если было, но у соединения сброшен флаг "Чистая сессия". В чистой сессии гарантированно придут retained-сообщения.

Отсюда выводы:
- Lazy MQTT на засыпающем устройстве нельзя использовать как устройство экстренного оповещения
- все сообщения о состоянии (именно состоянии), которые различные датчики и устройства посылают на MQTT-сервер, по-хорошему должны быть retained (потому что это их суть: если это состояние, то оно сохраняется до изменения, а не до момента прихода сообщения). Однако, многие устройства в этом плане поступают как попало. Решением может быть программа на сервере, которая автоматически перепубликует такие сообщения с флагом retained

Тогда возникает вопрос, на что влияет "время работы сервиса" в Установках Lazy MQTT, если работа программы при спящем телефоне все равно не возможна?
Указанное время работы позволяет не выгружать программу и ее настройки из памяти, поэтому повторный запуск происходит моментально. Кроме этого, если устройство не спит или часто просыпается, то сообщения приходить будут. И последнее: для устройства, которое постоянно не спит (например, панель управления на стене, которая никогда не выключается), режим с постоянной работой позволяет получать все сообщения сразу.

Lazy MQTT (платная версия) на спящем устройстве можно настроить для периодической проверки сообщений. Для этого нужно:
- создать виджет, в данных плиток виджетов должны быть указаны те Данные, которые для вас важны
- настроить время обновления виджетов в Установках
- при желании, поставить флаг "Будить устройство" там же (если его не ставить, то обновления будут происходить, если телефон разбудила какая-то другая программа)

О "Чистой сессии"
Если у соединения сброшен флаг "Чистая сессия", то сообщения будут приходить, даже если устройство спало или соединения не было. Приходить они будут, когда соединение появится и программа проснется. Это позволяет не пропускать сообщения, с одной стороны. С другой, такие задержанные сообщения могут прийти в программу не в том порядке, в котором они изначально появились. А это значит, что состояние устройства, например, может быть отображено неверно. Тут надо экспериментировать с вашим сервером.


Другое


1) Приложение само закрывается через какое-то время или не обновляет виджет
- приложение само не закрывается. Его может закрыть другое приложение или система. Этим грешат всякие экономщики батареи - нужно им сказать, чтобы они не трогали Lazy MQTT. Как их выключить - зависит от системы. Например, опция может называться Умное питание. На MUIU может быть так: заходим в настройки телефона, затем вкладка все приложения, находим Lazy MQTT, заходим в настройки приложения и ставим флаг "Разрешить Автозапуск". Не ясно как флаг с таким названием влияет на закрытие приложения, но помогает. Здесь статья на эту тему. Здесь список экономщиков от разных производителей телефонов и как их найти.

пятница, 15 декабря 2017 г.

Управление освещением в квартире и другая электрика: техническое устройство

В этой статье я хочу описать техническое устройство реально работающей на конец 2017 года системы в моей квартире. Это не конец, планов много, это текущее состояние.


Светодиоды

Весь свет сделан на мощных светодиодных лентах теплого белого света с типоразмером светодиодов 5050, мощностью не менее 12 Вт/м, напряжением 12 и 24 В. В спальне (в гостиной планируется так же) кроме белой установлена мощная RGB лента на 24 В.
В ванной и туалете ленты в профилях, светят под 45 градусов к полу.

Фотоаппарат снизил общую яркость, чтобы было видно профиль

Реальная освещенность

В остальных местах ленты спрятаны на полочках и свет не прямой, а отражение от белого потолка. Свет не такой яркий, как от мощных люстр, но по моему опыту - сначала непривычно, а потом хватает, нет желания ставить ленты еще (техническая возможность есть). Более того, я часто включаю свет не на полную яркость.

Фотоаппарат снизил общую яркость


Блоки питания

Несколько безвентиляторных блоков питания мощностью 200-250 Вт на 24 В. Соответственно, ленты на 12 В включены последовательно по два одинаковых куска.


Диммеры

Несколько четырехканальных DALI-диммеров с током до 5 А на канал (при 24 В дает 120 Вт на канал)


Настенные выключатели

Все без фиксации, часть - переделанные из обычных с фиксацией, часть - заводские "для жалюзи". Все выключатели подключены к шине DALI через четырехканальные адаптеры "контакт->DALI".

Подробнее про DALI, ленты, питание, диммеры, выключатели см. Освещение на протоколе DALI и его компоненты


Сервер


Назначение сервера

Для управления освещением с помощью выключателей достаточно сконфигурировать DALI-диммеры (может понадобиться спец. устройство). Для расширенного функционала нужен сервер, который умеет слушать шину DALI, отправлять по ней команды и общаться с внешним миром. Устройство системы таково, что в случае сбоя сервера выключатели и свет будут продолжать работать.
Сервер должен обладать следующим функционалом:
  • конфигурирование устройств DALI вручную
  • управление освещением DALI вручную и автоматизированно (например, по движению в кадре камеры)
  • удаленное управление освещением с помощью программ типа "умный дом"
  • удаленное управление освещением со смартфона
  • просмотр состояния устройств и датчиков как локально, так и удаленно
  • расширение функционала добавлением камер, датчиков, управляемых устройств


Устройство сервера

Готового сервера с указанным функционалом я не нашел. Существуют различные шлюзы DALI-USB, DALI-Ethernet, но они обладают целым рядом недостатков: они не умеют слушать шину, т.е. не могут реагировать на нажатия, например, выключателя. Программы для управления могут не позволять организовать дистанционное управление светом (т.е. могут работать только мышкой). При этом, все они имеют неадекватно высокую цену (я покупал самый дешевый вариант DALI-USB, который делает финский умелец, для опытов и чтобы с чего-то начать, и стоил он как три Raspberri Pi 3).

Поэтому было решено написать программу самостоятельно, и спаять самодельный адаптер DALI<->GPIO (некоторые подробности его работы см. в Raspberry Pi 3, работа с GPIO в Linux и DALI). Подробнее см. Программа DALI Controller.

Оборудование сервера состоит из Raspberry Pi 3 и самодельного DALI<->GPIO-адаптера. Питание 5 В сервер получает от эффективного DC-DC преобразователя, который подключен к блоку питания светодиодных лент на 24 В.
Шина DALI требует блока питания, он также самодельный (см. Простой блок питания шины DALI), питается от 24 В.
Raspberry подключен к домашней сети по Wi-Fi (возможно подключение по Ethernet), и имеет доступ в Internet.
К Raspberry по GPIO подключены 2 датчика типа DHT-22 (температура и влажность, улица и дом).


Программное обеспечение

На Raspberry под управлением Raspbian (это такой Linux для Raspberry) работают:
  • самописный сервер DALI Controller
  • MQTT-брокер (прием и отправка MQTT-сообщений)
  • программа MajorDoMo ("Умный Дом") с WEB-интерфейсом, доступным с других компьютеров
Кроме этого, программа, которая раз в 10 минут снимает кадр с камеры (отслеживание сосулек ;) и публикует его в MQTT.


Как это работает

Вот схема, на которой показаны программные и аппаратные средства системы:


Пользователь может управлять системой через браузер (WEB UI), программу MQTT-клиент (например, на смартфоне) и настенные выключатели (Wall switch).
Выключатели подключены к шине DALI (DALI line) и напрямую адресуют диммеры, поэтому свет будет работать даже при сбое сервера.

Изменение состояния светильников отслеживает программа DALI Controller, прослушивая шину DALI и команды через MQTT, и публикует их состояние в MQTT.
В MQTT же публикуется температура и влажность с датчиков, кадры с камер, состояние противообледенительного нагревательного кабеля крыши балкона.
Эти состояния затем видны в браузере и любых MQTT-клиентах (в т.ч. на смартфоне).

Управление светом и другими устройствами осуществляется путем посылки MQTT-сообщения (из браузера через "Умный Дом" или любой MQTT-клиент, в т.ч. со смартфона).

Программа DALI Controller

Для расширения функционала управления освещением квартиры было решено сделать DALI<->GPIO-адаптер и написать собственный сервер.

Почему не использовать уже готовые решения, что должен уметь сервер, подробнее про адаптер и протокол MQTT описано в статье Управление освещением в квартире и другая электрика: техническое устройство (раздел "Устройство сервера").

Здесь описывается устройство и функционал программы (сервера) DALI Controller.

Окружение программы

Сервер должен работать на низкопроизводительном компьютере Raspberry, прослушивать шину DALI и посылать в нее команды через GPIO. В качестве операционной системы выступает Raspbian (один из вариантов Linux для Raspberry). Для удаленного управления сервером поддерживается сетевое подключение.

Выбор инструментов и технологий

Для работы с GPIO в Raspbian существует несколько различных third-party библиотек. В качестве надежной (работа с GPIO по DMA, что резко снижает зависимость от загрузки процессора и прерываний) и продуманной, будет использоваться C-библиотека pigpio (подробнее про нее см. Raspberry Pi 3, pigpio, шина DALI и программа для работы с ней). Причем, в режиме работы - демон (вместо линковки).
Сервер должен поддерживать управление из консоли, командной строки и через MQTT, а также публиковать статус устройств по MQTT.

Сначала ядро программы было написано C, но в какой-то момент я понял, что развитие программы тормозится неудобной организацией межпоточного взаимодействия. Вместо концентрации на функционале программы приходится прилагать много сил, чтобы реализовать это на C. Я решил посмотреть другие варианты и, наконец, попробовать Golang. Это был мой первый подход к языку, и после небольшого исследования возможностей я понял:
  • Go имеет встроенные решения для эффективной многопоточности 
  • на Go можно писать под Raspbian
  • из Go можно вызывать C-код и линковать C-библиотеки
  • Go компилируется в эффективный код
  • для Go существует множество сторонних библиотек

Устройство программы

Сервер состоит из нескольких модулей, которые работают параллельно:
  • прослушивание шины DALI для перехвата команд, отправляемых другими устройствами (выключателями) и ответов на команды. Используется для логирования, отслеживания изменения статусов устройств, запуска настраиваемых на событие JavaScript-скриптов
  • JavaScript-интерпретатор для настраиваемых скриптов
  • MQTT-клиент для получения команд управления и публикации статусов
  • псевдографическая цветная консоль, показывающая лог, список и статусы устройств, прогресс выполнения долгих команд. Имеет поле для ручного ввода команды
  • встроенная помощь по всем командам DALI и другим командам сервера
  • отправка команд в шину DALI (полученных как параметры запуска приложения, через MQTT, ручным вводом в консоли или из JavaScript)
  • дополнительно: модуль опроса устройств DHT-22 (датчик температуры и влажности) с публикацией в MQTT

На снимке экрана видно:
  • лог команд (в скобках указан источник команды: шина DALI, MQTT или JavaScript)
  • иногда возникающие ошибки опроса уличного датчика DHT-22 (слишком длинные провода до него)
  • список устройств с DALI-адресом и статусом. Видно, что часть устройств на шине не имеют имени (они пока не используются)

Это снимок самодельного мобильного приложения, работающего по MQTT. Оно общается с сервером DALI Controller для показа статуса устройств и управления ими.

Работа программы

При запуске программа опрашивает устройства, чтобы выяснить их начальный статус. Затем статус отслеживается путем анализа команд, которые посылаются этому устройству (в том числе путем нажатия настенных выключателей). Любое изменение статуса публикуется по MQTT и все заинтересованные MQTT-клиенты (в т.ч. мобильные приложения) сразу же отражают это изменение у себя.
При управлении (светом) из мобильного приложения (или другого MQTT-клиента), сервер получает команду по MQTT и отправляет ее в шину DALI, отражая, если нужно, изменение статуса.
Консоль программы позволяет, при необходимости, вводить команды вручную. Обычно это требуется при подключении новых устройств для их конфигурирования.


В работе всей этой кухни есть интересная особенность. В арсенале DALI нет команды "переключить светильник". Есть различные варианты "включить" и "выключить", а "переключить" - нет. Это значит, что настенный выключатель должен помнить последнюю команду, которую он посылал, чтобы при следующем нажатии посылать обратную. Да, возможен вариант, когда выключатель отслеживает или опрашивает реальное состояние устройства перед решением, что же ему посылать. Но дешевые выключатели этого точно не делают (про дорогие я не осведомлен).
Представьте картину:
  • включаем свет выключателем (он отправляет команду "вкл" и запоминает факт, что свет включился)
  • выключаем из мобильного приложения
  • хотим снова включить его выключателем, но ничего не происходит. Поскольку выключатель помнит, что свет включен, он пошлет команду "выкл". И чтобы свет все-таки включить, нужно нажать выключатель еще раз (он снова пошлет обратную команду - теперь уже "вкл")
Для устранения этой неприятной ситуации в сервере используется возможность написать JavaScript на событие.
Что делает скрипт:
  • при получении команды по шине DALI запускается скрипт
  • если команда послана настенным выключателем (а в данный момент все команды, пришедшие по DALI, от выключателей) и она включает или выключает свет, то команда сверяется с текущим статусом светильника (его правильный статус помнит сервер)
  • если команда от выключателя пытается "повторить" уже существующее состояние света, но скрипт тут же самостоятельно посылает этому устройству обратную команду
Работа этого скрипта устраняет проблему с нажатие выключателя, при котором ничего не происходит. Эта ситуация реально видна на снимке экрана выше:
10:52:43 on спальня (dali)
10:52:43 off спальня (scr)
первая строка - по шине DALI получена команда "включить свет в спальне". Однако скрипт видит, что свет уже включен, а значит нажатием выключателя требовалось его выключить, и он сам посылает новую команду "выключить свет в спальне". Это вторая команда с источником "(scr)" (что означает JavaScript).

Выглядит как "костыль". Но на самом деле, это "костыль" не к серверу, а к недостатку протокола DALI: с одной стороны, он имеет множество команд управления светом, а с другой, сделать простейший выключатель без памяти состояния (или необходимости аппаратной и программной имплементации приемной части интерфейса) не позволяет.

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

четверг, 14 декабря 2017 г.

Управление освещением в квартире и другая электрика: что сделано

Здесь я хочу описать реально работающую на конец 2017 года систему, которую я сделал в своей квартире. Это не конец, планов много, это текущее состояние.


Квартира

3 комнаты, гостиная-кухня, длинный коридор, прихожая, ванная, туалет, балкон. План виден на снимке экрана мобильного приложения ниже.


Освещение

В одной из комнат, коридоре и на балконе освещения пока нет. В остальных местах - мощные светодиодные ленты, подключенные к диммерам, питание 24 В от нескольких безвентиляторных блоков питания.

Фотоаппарат снижает общую яркость из-за засветки потолка

Все диммеры подключены к шине DALI, на все белые ("теплый белый") ленты есть настенные выключатели (на прихожую - две штуки, из разных мест. На коридор, кухню тоже планируется по два). В спальне, кроме белого освещения, есть RGB (управления RGB с выключателей не планируется, сделаю "цвет рассвета" утром). Все светильники можно не только включать, но и управлять их яркостью с выключателей. Это, кстати, позволяет ограничиться одним источником света и одной кнопкой управления там, где ранее устанавливались люстры с несколькими лампами и несколькими выключателями, или люстра и торшеры.

Свет в мастерской и малиновый свет в спальне


Другая электрика

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


На стене дома со стороны улицы установлен датчик температуры и влажности (типа DHT-22). Такой же датчик находится в квартире.


Управление

Управлять электронным хозяйством хочется не только с выключателей, но и удаленно (со смартфона, планшета, компьютера). Зачем управлять светом удаленно - опишу ниже. Кроме того, хочется видеть статус некоторых устройств (температуру на улице, по крайней мере) и, возможно, изображения с камер, если такие имеются.
Для централизации управления организован сервер на Raspberry Pi 3, все состояния устройств публикуются на внутренний MQTT-сервер, через него же устройствами можно управлять.

Что такое и зачем MQTT? Это небольшое хранилище сообщений, специально разработанное для общения и управления умными устройствами. По сути очень похоже на мессенджер. Для Android существует множество программ, которые позволяют настроить управление и отображение статуса через протокол MQTT. Для компьютеров существует несколько систем управления умным домом, большинство из них также понимают этот протокол.

Какая информация доступна на сервере?
  • состояние всех источников света
  • температура и влажность на улице и в квартире (обновление каждые 10 минут, настраивается)
  • состояние нагревательного кабеля на крыше балкона. Если он включен, то доступна текущая потребляемая мощность и напряжение сети 220 В
  • фотография с камеры, показывающая состояние края крыши балкона (для отслеживания появления сосулек, позволяет также оценить погоду, обновление каждые 10 минут, настраивается)
Чем можно управлять через сервер?
  • посылать в DALI любые команды управления освещением. Наиболее актуально: вкл./выкл., включить неярко, выбрать цвет и яркость для RGB-лент
  • вкл./выкл. обогрева крыши балкона
Чем можно управлять с настенных выключателей (даже при неработающем сервере)?
  • включить, выключить свет (однократное нажатие); увеличить, уменьшить яркость (удерживание)
  • вкл./выкл. обогрева крыши балкона
Благодаря наличию сервера, подключенного к DALI, ничто не мешает настроить сценарии для отдельных выключателей (например, в прихожей сделать кнопку "выключить освещение везде")


Опыт использования системы с удаленным управлением

Каждый слышал слова "умный дом", но, по-моему, никто точно не знает, ни что это такое, ни зачем это надо, ни как этим заинтересовать других. Поэтому удел таких систем сейчас - энтузиасты, которые в меру своих потребностей и интереса собирают самостоятельно нечто, и потом оценивают, что получилось.
Если бы меня полгода назад спросили, зачем управлять светом со смартфона, я бы не смог ответить. Зачем современному человеку, который всю жизнь включает свет выключателями, управление со смартфона? Это просто неудобно - его надо носить все время с собой? Вместо одной клавиши на стене нужно разблокировать телефон, запустить программу?
Лучше обстоит дело с управлением с голоса: если дом будет понимать, что от него просят и делать это... Но такие системы только начинают появляться, и на сегодняшний день, работающей по всей квартире (микрофоны в каждом помещении?) при приемлемой цене, с русским языком - я не знаю такой.
Сейчас более реалистичный вариант - управление светом по присутствию человека - анализом движения с камер или датчиков движения. Такая система не работает или работает плохо, если человек не движется, и она может быть только дополнением к другим.

Возвращаемся к управлению с телефона.

Самодельное приложение для Android.
Свет включен в двух местах

В спальне глухие ролл-шторы, чтобы зимой не мешало уличное освещение, летом - белые ночи. То есть в спальне темно всегда. Спать я ложусь, когда на улице уже темно, да и позднее всех домашних. Как завершение дня выглядит в обычной квартире?
  • пошел включить свет в комнате (условно - кабинете), в которой сидел с компьютером или телевизором
  • пошел выключил компьютер (после света, потому что иначе выключатель искать в темноте)
  • пошел включить свет в коридоре (или сразу в ванной, но тогда по коридору шел в полутьме, свет от кабинета только)
  • умылся, выключил свет в ванной, пошел включить в спальне, пошел (в полутьме) выключить в коридоре и кабинете
  • разделся, выключил свет в спальне, в темноте ощупью нашел кровать (или сходил включил прикроватный светильник, потом вернулся выключить общий свет)
Как этот же процесс выглядит у меня?
  • с телефона или компьютера включил свет (можно неярко) в кабинете, коридоре, прихожей или ванной и в спальне - в общем сразу осветил весь путь
  • выключил компьютер/телевизор (в кабинете светло)
  • пошел в ванну, потом в спальню (еще светло)
  • разделся, лег в кровать (не ощупью, все еще светло)
  • выключил свет везде с телефона
Неоспоримое достоинство удаленного управления, о котором я узнал только начав пользоваться: не надо ходить туда-обратно из-за света, не надо ходить на ощупь и биться ногой о кровать! При выходе из квартиры не надо вспоминать, везде ли выключил свет - это можно посмотреть и исправить с телефона будучи уже на улице.
Если ночью приспичило попить воды, то с телефона же, прямо с постели, включаю неяркий (чтобы глаза не резало спросонья) свет по пути на кухню.

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

четверг, 13 июля 2017 г.

Использование C-библиотек из Golang 1.8 с callback-функцией и cross-компиляция

Выяснил для себя, что писать системные программы на Golang гораздо приятнее, чем на С. Расплата - минимальный размер программы в 1 Мбайт, в отличие от десятков Кбайт на чистом C. Жалко, конечно, но C требует слишком много лишнего в современном программировании.
Поэтому перевожу сервер поддержки протокола DALI и управления освещением (под Raspberry) с C на Go.
Сложности: как я писал ранее, в сервере используется библиотека pigpio. Поэтому нужен вызов C из Golang. Но мало того, нужен callback на Go-функцию из C. Настоящий хардкор - все это хочется в cross-компиляции.

Пример на Go с вызовом C и Go-callback

В исходнике ниже три примера:
1) вызов функции setCallback C-библиотеки extclib из Go
2) передача в С указателя на Go-функцию goCallback
3) создание C-функции myCFunc прямо в Go-исходном файле с последующим вызовом ее из Go

package main
/*
// (1) подключение внешней C-библиотеки к линковке
// (1) объектный файл extclib, скомпилированный под целевую платформу,
// (1) а также extclib.h, должны быть доступны локально (см. ниже
// (1) "Настройка cross-компиляции")
#cgo LDFLAGS: -lextclib
// (1) подключение заголовочного файла внешней C-библиотеки
// (1) в нем описана функция setCallback (см. ниже)
#include <extclib.h>
#include <stdint.h>
// (2) описание callback-функции на Go в C, чтобы можно было передать в C указатель на нее
extern void goCallback(unsigned data);

#ifndef MYCINCL
#define MYCINCL 1
// (3) static inline - необходимо для предотвращения ошибки компиляции
// (3) о повторном объявлении функции myCFunc
static inline void myCFunc(uint32_t data){
// здесь C-код
}
#endif
*/
import "C"


// (1) вызов C-функции setCallback с передачей указателя на функцию Go
func installCallback(){
C.setCallback((*[0]byte)(C.goCallback))
}

// (2) ниже комментарий "//export goCallback" указывает Go, что функция будет видна из С
// (2) внимание! Пробелов между // и export быть не должно, иначе Go не сделает экспорт
//export goCallback
func goCallback(data C.uint){
}

// (3) вызов C-функции из Go
func callCFunc(data uint32){
C.myCFunc(C.uint32_t(data))
}

Настройка cross-компиляции

Для cross-компиляции необходимо локальное наличие компилятора под целевую платформу, заголовочных C-файлов, которые будут использоваться и объектных файлов для линковки (скомпилированных под целевую платформу).
Например, можно установить GNU Toolchain for Raspberry (http://gnutoolchains.com/raspberry/tutorial), который умеет забирать заголовочные и объектные файлы, установленные на Raspberry, себе для локальной cross-компиляции.

Дальше можно сделать bat-файл для компиляции или выставить переменные окружения.
Выставить путь к cross-компилятору, который находится внутри toolchain:
@set CC=arm-linux-gnueabihf-gcc

Установить архитектуру. Если этого не сделать, то получим ошибку вроде "unrecognized command line option '-m64'":
@set GOARCH=arm
@set GOARM=6
и операционную систему, иначе ошибка "unsupported GOOS/GOARCH pair windows/arm":
@set GOOS=linux

Выставить CGO_ENABLED, потому что по-умолчанию она выключена для cross-компиляции (и go build в этом случае молча игнорирует файлы, где есть import "C" - даже ошибки в них не проверяет):
@set CGO_ENABLED=1

Запустить сборку:
@call go build

В результате сборки получим список ошибок (как в Go, так и в C-коде) или готовый исполняемый файл, который можно запускать на Raspberry.

суббота, 20 мая 2017 г.

Выключатель света без фиксации из стандартного своими руками

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

Я уже писал ранее, что в качестве двухклавишного выключателя без фиксации можно найти в продаже такой "для жалюзи". Однако, он стоит заметно дороже обычного. А с одноклавишными - беда.

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

Разбираем выключатель. С обеих сторон есть по 2 отверстия, справа - где нужно добавить возвратные пружины - они не используются.


Пружинки наденем на направляющую, которую согнем из толстой проволоки:


Она должна свободно входить в отверстия, по длине и толщине проволоки - не раскачиваться сильно по вертикальной оси, а по ширине - надежно упираться в снятую ранее черную качалку:

Надеваем две пружины от первых попавшихся авторучек. Одной не хватает жесткости, чтобы вернуть выключатель:

Вставляем направляющую с пружинами в отверстия и ставим качалку на место:


Если направляющая все же сильно болтается, следует закрепить ее на качалке тонкой проволочкой, под которую как раз подойдут имеющиеся на качалке выемки (в данном случае  не потребовалось):


Ставим на место крышку, и это все - теперь после отпускания выключателя, он сам надежно возвращается в исходное.

Двухклавишный выключатель делается заметно сложнее - в нем нет отверстий под направляющую проволоку.

четверг, 18 мая 2017 г.

Простой блок питания шины DALI

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

Особенность блока питания, связанная как раз со способом формирования сигнала, он должен выдавать ток, ограниченный 250 мА (с быстрой реакцией). Напряжение без нагрузки может составлять от 11.5 до 22.5 вольт. В продаже такие блоки, безусловно, есть. Для испытаний можно взять обычный блок питания и ограничить его ток достаточно мощным резистором.

Однако, чтобы без дела не сидеть (и экономия!), уже имея в освещении квартиры, как я писал ранее, блоки питания 24 вольта, можно собрать устройство самому. Для этого нужно 2 линейных стабилизатора, подходящей мощности и напряжения, и 3 резистора.


В интернете есть несколько сайтов со схемами включения и расчетом резисторов и мощности стабилизаторов на ИМС, например, LM317. Первая микросхема включена как стабилизатор напряжения и снижает напряжение с 24 до приблизительно 18 вольт (чтобы, с учетом падения на второй микросхеме, получить на выходе около 16 вольт), вторая включена как стабилизатор тока примерно на 250 мА. Получаем блок питания шины DALI с входным напряжением 20-40 вольт, выходным напряжением 16 вольт без нагрузки и ограничением тока 250 мА.

Что будет с шиной DALI если к ней не подключать питание? Она, во-первых, не будет передавать сигналы, во-вторых, устройства с питанием от шины работать не будут.
Что будет, если включить питание без ограничения тока? Сигналы передаваться не будут, могут сгореть выходные элементы передатчиков (поскольку они рассчитаны на ток до 250 мА, а при передаче замыкают шину DALI, т.е. создают короткое замыкание блоку питания).