Дистанционное управление Motion с помощью Go

Цель — сделать удобное управление для сервачка с системой motion detection. В качестве сервера пригодился классический нетбук Asus Eee PC 701 4-х гигабайтным SSD на борту. На него была установлена Ubuntu 14.04.

Задачи:

  1. Собственно, motion detection (для этого был использован Motion).
  2. Управление настройками Motion через ИК-пульт.
  3. Вывод всех сообщений от Motion и сигналов от пульта на консоль (/dev/tty1).
  4. Минимальное время работы экрана (быстрый переход в энергосберегающйй режим, просыпание по сигналу от пульта).

1. Motion ставится элементарно — apt-get install motion. Важные настройки:

# Максимальный fps
framerate 5

# Снимать на максимальном fps только во время движения
webcam_motion on

# Выкрутил в максимум, чтобы избежать срабатывания на включение света
lightswitch 100

# Кол-во кадров с движением, необходимых для генерации события
minimum_motion_frames 3

# Записать кадры до движения
pre_capture 5

# Записать кадры после движения
post_capture 5

# Маска для определения области детекции, легко делается в Gimp'е из снимка с камеры.
# Области, закрашенные черным, игнорируются.
mask_file /path/to/mask.pgm

# Время определения окончания движения (если за 15 секунд после начала движения
# не было никаких поползновений, то считаем, что событие-движение закончилось)
gap 15

# Отключить создание снимков
output_normal off

# Обозначать движение прямоугольником 
locate on

# Запуск скрипта по началу движения (это симлимк, который указывает на реальный скрипт).
# Изменение симлинка осущестляется по команде с пульта (см. п. 2 про конфиг) 
on_event_start "/etc/motion/handlers/on_event_start"

Для подгонки чувствительности, порога шумов и т.д., нужно использовать setup mode, который активируется при запуске motion -s.

При этом в mjpeg-трансляции область детекции будет обозначена черным, шумы — серым, а распознанное движение — синим.

2. Для управления нетбуком был использован ИК-пульт с USB-приемником. Подобные пульты есть и на aliexpress, и ebay. USB-приемник эмулирует HID-устройство, по сути — обычную клавиатуру.

Для работы с символьными устройствами ввода в Linux есть подсистема evdev. Потестить распознавание сигналов с пульта можно с помощью утилиты evtest.

На гитхабе нашелся пакет для работы с evdev на Go. Проект больше не поддерживается, так что я отфоркался от более свежего форка и сделал rebase на ядро Ubuntu 14.04 (3.13.0-39-generic на данный момент):

cd evdev
make ecodes.go

Поверх golang-evdev я написал evhandler. Эта программа запускается от root’а и слушает события от input device, указанного в конфиге (как правило, /etc/evhandler.toml). Мой конфиг:

[params]
    device = "/dev/input/eventXXX"

[actions]
    KEY_STOPCD = "service motion stop"
    KEY_PLAYPAUSE = "service motion start"
    KEY_PAGEUP = "/etc/motion/handlers/handler-select up"
    KEY_PAGEDOWN = "/etc/motion/handlers/handler-select down"

В разделе actions на кнопки пульта вешаются команды: остановка и запуск motion, и выбор скрипта, который будет запущен при детекции движения. Скрипт handler-select “передвигает” симлинк on_event_start вверх/вниз, устанавливая, таким образом, реальный скрипт, который будет запускаться. Коллекцию этих скриптов я выложил в отдельный проект.

Для чтения и парсинга конфигов я использовал пакет Viper. Это очень классная либа от автора Hugo, которая умеет:

3. Имя устройства неплохо бы зафиксировать, т.к. оно назначается udev’ом и может меняться при перетыках из порта в порт, а также при перезагрузках. Но для начала надо узнать текущее имя устройства.

# lsusb
...
Bus 003 Device 002: ID 073a:2230 Chaplet Systems, Inc. infrared dongle for remote

# evtest 2>&1 | grep "073a:2230"
/dev/input/event10:	HID 073a:2230

Итак, имя устройства в системе — /dev/input/event10. Получим необходимую информацию для построения udev-правила:

# udevadm info -a -p $(udevadm info -q path -n /dev/input/event10)
...
  looking at device '/devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.0/input/input12/event10':
    KERNEL=="event10"
    SUBSYSTEM=="input"
    DRIVER==""

  looking at parent device '/devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.0/input/input12':
    KERNELS=="input12"
    SUBSYSTEMS=="input"
    DRIVERS==""
    ATTRS{name}=="HID 073a:2230"
...

Теперь можно навесить на устройство фиксированный симлинк:

# cat > /etc/udev/rules.d/10-local.rules
KERNEL=="event*", SUBSYSTEM=="input", ATTRS{name}=="HID 073a:2230", SYMLINK+="input/event100"

Для проверки нужно воспользоваться командой udevadm trigger или перезагрузиться. Даже если исходное имя устройства изменится (например, на /dev/input/event11), наш симлинк /dev/input/event100 будет указывать на него.

4. evhandler должен использовать в качестве стандартного вывода /dev/tty1. Сделать это очень просто.

Сначала отключим ввод с /dev/tty1rm /etc/init/tty1.conf.

И создадим новый upstart job в /etc/init/evhandler.conf:

# evhandler - Simple key press listener and handler written in Go

start on runlevel [2345]
stop on runlevel [!2345]

respawn

exec /path/to/go-evhandler > /dev/tty1 2>&1

Теперь evhandler будет запускаться при загрузке, а также перезапускаться, если его процесс будет прибит. Для ручного запуска — start evhandler.

  1. Управлять включением энергосберегающего режима (а именно, гашением экрана) можно з-мя способами:

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

setterm через ssh у меня как-то не заработал.

И только управляющая ESC-последовательность для терминала подошла отлично — echo -e '\033[9;X] (где X - минуты).

Для автоматического запуска этой команды создадим job /etc/init/tty1.conf:

# tty1 - getty
#
# This service is used to maintain a getty on tty1 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345] and (
            not-container or
            container CONTAINER=lxc or
            container CONTAINER=lxc-libvirt)

stop on runlevel [!2345]

# Blank screen after 1 minute timeout
# See http://www.armadeus.com/wiki/index.php?title=FrameBuffer
exec echo -ne "\033[9;1]" > /dev/tty1

Ссылки:

Tags:
comments powered by Disqus