Элементы умного дома на OpenWRT роутере
В наличии имеется китайский GL.inet роутер, USB хаб, камера и GSM модем.
Задача: на удаленном объекте с плохой связью настроить видеонаблюдение и элементы управления и мониторинга.
Для прочих свистелок имеем дома или где-то (есть бесплатные хостинги) настроенный WWW(для просмотра снэпшотов),FTP(удаленно складывать снэпшоты),openvpn(не обязательно, рулить удаленно).
Как настроить на роутере SSH и зайти, в текущей статье рассматриваться не будет, так как путей сделать это много. В данном роутере первоначальную настройку я делал в Luci, зайдя по адресу http://192.168.8.15/cgi-bin/luci/
Добрый совет: при настройке SSH, расшарьте его наружу, если требуется удаленное управление, и смените его порт на некий другой, чтобы не соблазнять интересующихся. (С 22 на 2222 например)
Подключаемся к LAN порту роутера по SSH:
(я использую ubuntu, если у вы любитель windows - ваш путь - putty +)
ssh -p2222 -lroot 192.168.8.1
root@192.168.8.1's password:
root@openwrt:~#
root@openwrt:~# uname -a
Linux openwrt 3.18.23 #6 Mon Jan 4 11:55:23 HKT 2016 mips GNU/Linux
MOTION
Motion выбран по причине его гибкости настроек, хотя под такую задачу можно было выбрать что-то по проще, типа mjpeg-streamer. Motion будет сохранять снэпшоты по движению и раз в 5 минут, так как канал плохой и процессор не силен.
Обновляем список пакетов:
opkg update
Устанавливаем поддержку USB модема:
opkg install kmod-usb-serial kmod-usb-serial-wwan kmod-usb-serial-cp210x kmod-usb-serial-option
При удачной установке должны появиться /dev/ttyUSB0 и тд.
Устанавливаем поддержку USB камеры (всяких, для верности) (список - https://wiki.openwrt.org/doc/howto/usb.video):
opkg install kmod-video-core kmod-video-gspca-core kmod-video-uvc kmod-video-gspca-zc3xx kmod-video-gspca-sonixj kmod-video-gspca-sonixb
При удачном определении камеры должно появиться устройство /dev/video
Устанавливаем motion (нужно удалить или остановить предустановленные видео-сервисы, если есть):
opkg install motion wput
Конфигурируем /etc/motion.conf:
(желательно, чтобы логи, pid'ы, jpg'и он складывал в /tmp, чтобы продлить жизнь флэш-памяти)
Примерный конфиг моего /etc/motion.conf. Не забудьте исправить логины и пароли.
создаем скрипт отсылки снэпшотов:
find /tmp/motion/ -name 'video_????????????????????.jpg' > /tmp/dvrdir.lst
cd /tmp/motion/
ls -t | grep -v \/ | head -n 1 | while read var; do echo "$var"; cp $var /tmp/lastsnap.jpg; done
wput -R -i /tmp/dvrdir.lst ftp://ftpuser:ftppassword@server_addr/ddvr/jpgs/
создаем расписание в /etc/crontabs/root для отсылки снэпшотов
*/5 * * * * /etc/motion/wput_dvr.sh
Таким образом получилась схема отправки снэпшотов на удаленный сервер. Можно остановиться на этом, а можно дописать визуализация и формирование видео.
GPIO
В GL.Inet6416 их всего 5 (GPIO18-GPIO22). Не так много, как в raspberry, зато дешевле. С помощью них можно управлять внешними устройствами, контролировать замыкание контактов и снимать данные с некоторых сенсоров. Есть другие модели бюджетных роутеров, у которых разведены GPIO, отдельно, на кнопки и светодиодную индикацию.
Схема разводки выходов GPIO и др на GL.Inet
GPIO (General Purpose Input Output) - низкоуровневый интерфейс ввода-вывода прямого управления.
Базовая схема подключения к GPIO. VCC - 3.3.V.
Схема включения реле.
В моей реализации мониторинг и управление осуществляется связкой Bash-скрипта (демон бэкэнд) и PHP-скрипта (фронтэнд). Два порта будут заведены на сухой контакт (герконы), два - на реле, один - на 1-wire.
Основной принцип работы с GPIO:
Установка ввода - in, или вывода - out порта:
echo in > /sys/class/gpio/18/direction
Чтение состояния порта:
cat /sys/class/gpio/18/value
Запись состояния:
echo 1 > /sys/class/gpio/18/value
Вывод информации о GPIO:
cat /sys/kernel/debug/gpio
В некоторых моделях есть управление питанием USB: (keenetic kn-1211,
echo 0 > /sys/class/gpio/usbpower/value
Устанавлваем lighttpd, php,bash и тд:
opkg install lighttpd lighttpd-mod-auth lighttpd-mod-cgi lighttpd-mod-expire lighttpd-mod-fastcgi php5 php5-cgi php5-mod-curl
Конфигурируя всё это нужно постараться оставить рабочим Luci, если оно вообще было и нужно.
Примерный конфиг /etc/lighttpd/lighttpd.conf:
# version=3.0
server.modules = (
"mod_cgi",
"mod_auth",
)
server.network-backend = "write"
server.error-handler-404="/welcome.html"
server.document-root = "/www/"
server.pid-file = "/tmp/run/lighttpd.pid"
server.errorlog = "/tmp/log/lighttpd/error.log"
index-file.names = ( "welcome.html","login.html","index.php","index.php" )
$HTTP["url"] =~ "\.html" {
expire.url = ( "" => "access plus 1 seconds" )
}
##
# which extensions should not be handle via static-file transfer
#
# .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi
#static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
######### Options that are good to be but not neccesary to be changed #######
## bind to port (default: 80)
server.port = 80
server.upload-dirs = ( "/tmp" )
fastcgi.server = (
"/cgi-bin/download_file" => (
"download_file.handler" => (
"socket" => "download_file.socket",
"check-local" => "disable",
"bin-path" => "/www/cgi-bin/download_file",
"max-procs" => 1,
"allow-x-send-file" => "enable"
)
)
)
#### CGI module
$HTTP["url"] =~ "^/cgi-bin/" {
cgi.assign = ( "" => "" )
}
include "/etc/lighttpd/mime.conf"
include_shell "cat /etc/lighttpd/conf.d/*.conf"
# Access control
#auth.backend = "htpasswd"
#auth.backend.htpasswd.userfile="/etc/lighttpd/lighttpd-htpasswd.user"
#auth.require = ( "/files" =>
# (
# "method" => "basic",
# "realm" => "files",
# "require" => "user"
# )
/etc/lighttpd/conf.d/10-cgi.conf
server.modules += ( "mod_cgi" )
cgi.assign = ( ".pl" => "/usr/bin/perl",
".cgi" => "/usr/bin/perl",
".rb" => "/usr/bin/ruby",
".erb" => "/usr/bin/eruby",
".py" => "/usr/bin/python",
".php" => "/usr/bin/php-cgi" )
Также в php.ini нужно указать корневую директорию, временную - в /tmp и желательно подкрутить timezone.
В конечном итоге должно получиться следующее:
Скрипты и картинки для управления и мониторинга GPIO
Основная логика состоит в создании флагов в /tmp. Фронтэнд создает флаг состояния реле, а бэкэнд реализует его. И наоборот, бэкэнд выставляет флаг срабатывания датчика, а фронтэнд выводит его. Вся конфигурация GPIO происходит в скрипте бэкэнда, и интуитивно понятна. В коде бэкэнда заремирована возможность отправки СМС через gnokii или отправки e-mail через msmtp, предварительно установив их и сконфигурировав.
1-wire
1-wire - двунаправленная шина связи для устройств с низкоскоростной передачей данных. То есть в идеале, имеется жила питания/данных и жила земли. В одной сети могут находится некоторое, в зависимости от удаленности и потребления, количество ведомых (slave) устройств и одно ведущее (master) устройство. В моем случае мастером будет выступать GPIO с драйвером 1w из ядра. Покупка USB мастеров достаточно накладна, но сильно уменьшает количество проблем со slave устройствами, сложнее термодатчиков, но это не наш путь. Устанавливаем поддержку 1-wire на GPIO:
opkg install kmod-w1 kmod-w1-gpio-custom kmod-w1-master-gpio kmod-w1-slave-therm
В данном случае буду использовать GPIO18, поэтому:
echo "w1-gpio-custom bus0=0,18,0" > /etc/modules.d/59-w1-gpio-custom
reboot && exit
ls /sys/bus/w1/drivers/w1_slave_driver/
28-000000483037 29-000000174f7c bind uevent unbind
, где 28-000000483037 - DS18B20 (цифровой датчик температуры), 29-000000174f7c
- DS2408 (8-портовая микросхема ввода/вывода)
Припаиваем длинный гибкий кабель к ногам, запаиваем в термоусадку (головка датчика должна торчать) и выкидываем на теневую сторону избушки.
Схема включения DS18B20
Считываем значение датчика:
cat /sys/bus/w1/drivers/w1_slave_driver/*/w1_slave
a0 00 4b 46 7f ff 10 10 53 : crc=53 YES
a0 00 4b 46 7f ff 10 10 53 t=10000
Температура это значение t=10000, то есть 10.00 гр.С. Делим температуру на 1000:awk -F= '/t=/ {printf "%.02f\n", $2/1000}' /sys/bus/w1/drivers/w1_slave_driver/*/w1_slave
(Для нескольких датчиков обращаемся конкретно по их ID.)
Есть возможность просматривать историю температуры в виде графика изменения.
Требуется установка curl и bash:
opkg install curl bash
Создаем св /etc/ bash cкрипт themp.update следующего содержания
#!/bin/bash
themp=$(awk -F= '/t=/ {printf "%.00f\n", $2/1000}' /sys/bus/w1/drivers/w1_slave_driver/*/w1_slave)
#testing only
#themp=$(( ( RANDOM % 35 ) - 15 ))
echo $themp
curl -k "http://1.1.1.1/themp-graph.php?p=12345&themp1=$themp"
,где 1.1.1.1 - IP или адрес домашнего сервера. Прописываем его запуск раз в 2 часа в /etc/crontabs/root:
3 0,2,4,6,8,10,12,14,16,18,20,22 * * * /etc/themp.update
На домашнем сервере требуется настроенный PHP с GD. Создаем PHP скрипт учета и построения графика
DS2408
На текущем этапе мне, к сожалению, не удалось завести DS2408. Буду ждать обновлений. Но по идее должно работать так:ls /sys/devices/w1_bus_master1/29-000000174f7c/
Считывание:
dd if=./rw bs=1 count=1 | hexdump
Запись:
echo -e '\x00' |dd of=rw bs=1 count=1
echo -e '\xff' |dd of=rw bs=1 count=1
DS2408 рассматривалась как експандер портов ввода/вывода, однако для этой цели могут подойти аналоги MCP23017, но уже с использованием шины I2C.
В перспективе думается связать роутер по I2C с AVR и управлять, например светом, как с роутера по беспроводной связи или удаленно, так и с кнопок, установленных вмести выключателей. Таким образом должна будет осуществлена некая защита управления от выхода из строя роутера со всей обвязкой, и лавный контроль управления ложится на AVR. Но об этом позднее...
Возможные проблемы при настройке OpenWRT
* Из webLUCI при настроенной системе нельзя сменить внутренний IP интерфейса и DHCP:
Сделать это можно в консоли:
uci set network.lan.ipaddr='192.168.2.1'
uci commit
/etc/init.d/network restart
Далее исправить правила фаервола и статических адресов
Ilya L. / 2016