Модераторы: powerfox, ZeeLax
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Автоматическое скачивание фотографий с камеры, с помощью udev 
V
    Опции темы
nickless
Дата 29.8.2007, 02:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


Профиль
Группа: Участник Клуба
Сообщений: 2976
Регистрация: 29.8.2005
Где: Germany

Репутация: 41
Всего: 181



Речь пойдёт о дигитальных камерах с USB-интерфейсом, которые распознаются в линуксе как внешний носитель (USB storage device), на примере "Pentax Optio M30".

Скачивание фотографий с этой камеры происходит обычно примерно так:
  •  подключаем камеру
  •  жмём "Скачать фотографии в digiKam" в появившемся диалоге
  •  добавляем новый альбом в дигикам
  •  маркируем нужные (если помним какие) фотки
  •  жмём скачать, ждём
  •  отключаем камеру
  •  сортируем фотки по дате
  •  итд
Итог - много ручной работы.

Цель: автоматизировать процесс до невозможности, т.е.:
  •  подключаем камеру
  •  ждём пока скриптик сделает всё за нас
  •  отключаем камеру
Для начала немного о самом udev.

udev

Udev это динамический настраиваемый мэнеджер устройств, его задача - следить за физическими устройствами в системе и отображать их в папке /dev. Это позволяет показывать в /dev только те устройства, которые действительно подключены к компьютеру, а так же даёт много других преймуществ, о которых вам с удовольствием расскажет гугль и этот сайт.

Вот некоторые вещи, которые позволяет делать udev:
  •  переименовывать устройства, в том числе с помощью вывода других програм
  •  добавлять дополнительные имена устройств и/или создавать символические ссылки на них
  •  менять права и влаельцев устройства
  •  запускать скрипт при присоединении/удалении устройства
  •  переименовывать сетевые интерфейсы
Из этого всего нас интересует в основном 4 пункт.

udev-правила

Udev является стандартом начиная с ядра 2.6.13 и используется во всех современных дистрибутивах.
Всё, что делает udev, настраивается с помощью так называемых правил (udev rules), которые находятся в /etc/udev/rules.d/. Все правила из этой папки читаются в алфавитном порядке, их принято именовать
Код

XX-название-через-тире.rules

где ХХ это двузначное число. Основные правила находятся в файле 50-udev.rules.

Во всех дистрибутивах (на счет LFS не уверен smile ) есть набор правил, облегчающих жизнь пользователей. Многие программы зависят от правильных названий устройств, по этому не стоит менять существующие правила.

План следующий:
написать правило для udev, которое распознаёт нужную камеру, называет соответствующее устройство /dev/camera и запускает скрипт, который монтирует её, копирует фотографии попутно создавая папки основываясь на информации в exiv и после этого демонтирует камеру. Всё это в сопровождении прогресс-диалога из kdialog.

Идентификация камеры и написание правила

В каждом файле правил есть много отдельных правил и условных переходов по типу goto.
Синтакс довольно прост, каждое правило состоит из ключей, разделённых запятыми. Часть ключей (match keys) отвечают за идентификацию устройства, часть (assignment keys) за действия, предпринимаемые в таком случае.
Примеры проверочные ключей: KERNEL=="sd?", SUBSYSTEM=="block", ATTRS{idVendor}=="0a17" 
Примеры ключей присваивания: NAME="pentax", GROUP="plugdev", OPTIONS+="last_rule"
Действия выполняются только если все проверки верны.
Набор ключей, относящихся к одному и тому же правилу должен быть на одной строке.
Т.е.
Код
# Это коментарий
# Правильно
KERNEL=="sd?", SUBSYSTEM=="block", ATTRS{idVendor}=="0a17", NAME="pentax", GROUP="plugdev"
KERNEL=="sdа1", NAME="pentax", SUBSYSTEM=="scsi"

# Не правильно
KERNEL=="sd?",
    SUBSYSTEM=="block",
    ATTRS{idVendor}=="0a17",
        NAME="pentax",
        GROUP="plugdev"

Советую посмотреть на другие правила из /etc/udev/rules.d/, там достаточно примеров.
Почитать про синтакс можно еще сдесь (кстати очень полезная статья) и в udev(8)

Набрать ключей для идентификации камеры можно с помощью программы udevinfo, например
Код
udevinfo -a -p $(udevinfo -q path -n /dev/sda1)
расскажет всё об устройстве, названном /dev/sda1, сразу в формате правил к udev.
Имейте ввиду, что вместе можно использовать только те ключи, которые относятся к одному устройству (они разделены пустой строкой).

В моём случае нужные мне аттрибуты (ID производителя и продукта, которые так же можно посмотреть в lsusb) не доступны в конечном разделе /dev/sdb1, по этому я пишу их в переменную окружения, и это прекрасно работает:
Код
SUBSYSTEM!="block", GOTO="pentax-camera_rules_end"

ACTION=="add", GOTO="pentax-camera_rules_apply"
ACTION=="remove", GOTO="pentax-camera_rules_apply"
GOTO="pentax-camera_rules_end"

LABEL="pentax-camera_rules_apply"
ATTRS{idVendor}=="0a17", ATTRS{idProduct}=="0033", ENV{PENTAX_DIGICAM}="yes"

KERNEL=="sd?", ENV{PENTAX_DIGICAM}=="yes", NAME="camera", MODE="660", GROUP="plugdev"
KERNEL=="sd?1", ENV{PENTAX_DIGICAM}=="yes", NAME="camera1", MODE="660", GROUP="plugdev", RUN+="/root/scripts/udev-pentax-digicam.sh", OPTIONS+="last_rule"

LABEL="pentax-camera_rules_end"


Правила можно проверить программой udevtest, лучше всего подключить камеру, и не отключая её писать правила, проверяя их udevtest-ом.
Перевести название устройства в путь, нужный udevtest можно тем же udevinfo:
Код
udevinfo -q path -n /dev/sda1


Скрипт

Моя камера называет фотографии "imgp1234.jpg", а видеоролики "imgp1234.mov", причем удалённые файлы не используются по второму разу. Я хочу сортировать файлы по дням, которые записаны в картинках. Эту информацию можно прочитать программой exiv2
Код
$ LC_ALL="C" exiv2 imgp0522.jpg
File name       : imgp0522.jpg
File size       : 2721408 Bytes
Camera make     : PENTAX Corporation
Camera model    : PENTAX Optio M30
Image timestamp : 2007:08:25 12:05:57
Image number    :
Exposure time   : 1/100 s
Aperture        : F6.2
Exposure bias   : 0
Flash           : (88)
Flash bias      :
Focal length    : 11.3 mm (35 mm equivalent: 68.0 mm)
Subject distance:
ISO speed       : 64
Exposure mode   :
Metering mode   : Multi-segment
Macro mode      :
Image quality   :
Exif Resolution : 3072 x 2304
White balance   :
Thumbnail       : JPEG, 6184 Bytes
Copyright       :
Exif comment    :


Моя камера использует файловую систему FAT32 и один раздел, udev-правила создают ноды /dev/camera и /dev/camera1.
Скрипт создаёт нужные папки, и копирует туда фотографии и видеоролики, если таких файлов в папках еще нет. Видеоролики не содержат данных exiv, по этому они копируются в папку, на основании информации из предидущей картинки.
Прогресс-диалог создаётся программой kdialog и показывается первому пользователю из списка в NOTIFY_USERS. Все пользователи из этого списка должны иметь bin/ папку KDE с kdialog в PATH.

Код
#!/bin/bash

# udev-pentax-digicam.sh
#
# all paths should not have any spaces
# camera should not use file names of deleted images
# user notification uses "kdialog", set NOTIFY_USERS="" if you don't want it
# all users listed in NOTIFY_USERS should have KDE bin/ directory in PATH to be able to see the notification
# all users listed in NOTIFY_USERS should use bash as shell, otherwise there'll be a syntax error
#
# this program is provided AS IS, use at your own risk
#

DEVICE="/dev/camera1"
MNTPOINT="/mnt/camera"
NOTIFY_USERS="foo bar"
DEST_DIR="/home/foo/pictures/digicam"
DEST_OWN="foo:users"
DEST_MODE="660"
DEST_DIRMODE="770"
DELETE_AFTER_SYNC=false
LOGFILE="/var/log/udev-pentax.log"


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

date '+%Y-%m-%d %T' >> $LOGFILE

# find user
USERNAME=""
for u in $NOTIFY_USERS; do
    if users | grep -q $u; then
        USERNAME=$u
        break;
    fi
done

I=0
if [[ $USERNAME != "" ]]; then
    IPROGRESS=$(sudo -u $USERNAME -i -- -c 'XAUTHORITY="/home/'${USERNAME}'/.Xauthority" kdialog --display ":0" --progressba
r "Image '${I}' of '${N}'"' 2>>$LOGFILE)
    sudo -u $USERNAME -i -- -c 'XAUTHORITY="/home/'${USERNAME}'/.Xauthority" DISPLAY=":0" dcop "'$IPROGRESS'" setAutoClose t
rue' >> $LOGFILE 2>&1
fi

if [[ "$ACTION" == "add" ]]; then
    # mount camera
    echo "Camera connected" >> $LOGFILE
    ls -l $DEVICE >> $LOGFILE 2>&1
    mount $DEVICE $MNTPOINT -t vfat -o noatime >> $LOGFILE 2>&1
    echo "Mounted at /mnt/camera" >> $LOGFILE

    # syncronize pictures
    echo "Starting sync" >> $LOGFILE
    SRC_FILES=$(find $MNTPOINT \( -iname "*.jpg" -o -iname "*.mov" \) -printf "%p " 2>>$LOGFILE)
    N=$(echo $SRC_FILES | wc -w)
    echo "Found $N files" >> $LOGFILE
    for f in $SRC_FILES; do
        FILE=$(echo $f | sed -r 's/^.+\///')
        if echo $FILE | egrep -qv '\.mov$'; then    # videos are moved to the directory of the last image moved before
            DIR=$(LC_ALL="C" exiv2 $f | grep timestamp | sed -r 's/(^.+timestamp : )([0-9]+):([0-9]+):([0-9]+)( .+$)/\2-\3-\
4/')
        fi
        # create directory
        if [[ ! -e "$DEST_DIR/$DIR" ]]; then
            mkdir -m $DEST_DIRMODE -p "$DEST_DIR/$DIR" >> $LOGFILE 2>&1
            chown $DEST_OWN "$DEST_DIR/$DIR" >> $LOGFILE 2>&1
        fi
        # copy file
        if [[ ! -e "$DEST_DIR/$DIR/$FILE" ]]; then
            cp -v $f "$DEST_DIR/$DIR/$FILE" >> $LOGFILE 2>&1
            chmod $DEST_MODE "$DEST_DIR/$DIR/$FILE" >> $LOGFILE 2>&1
            # remove old file if needed
            if $DELETE_AFTER_SYNC; then
                rm -v $f >> $LOGFILE 2>&1
            fi
        fi

        # progressbar
        ((I++))
        if [[ $USERNAME != "" ]]; then
            sudo -u $USERNAME -i -- -c 'XAUTHORITY="/home/'${USERNAME}'/.Xauthority" DISPLAY=":0" dcop "'$IPROGRESS'" setPro
gress '${I}'' >> $LOGFILE 2>&1
            sudo -u $USERNAME -i -- -c 'XAUTHORITY="/home/'${USERNAME}'/.Xauthority" DISPLAY=":0" dcop "'$IPROGRESS'" setLab
el "Image '${I}' of '${N}'"' >> $LOGFILE 2>&1
        fi
    done
    echo "Successfully synced, unmounting camera..." >> $LOGFILE

    # unmount camera
    sync
    umount $DEVICE >> $LOGFILE 2>&1
    echo "Camera unmounted" >> $LOGFILE
    if [[ $USERNAME != "" ]]; then
        sudo -u $USERNAME -i -- -c 'XAUTHORITY="/home/'${USERNAME}'/.Xauthority" DISPLAY=":0" dcop "'$IPROGRESS'" close' >>
$LOGFILE 2>&1
    fi
    chown -R $DEST_OWN "$DEST_DIR" >> $LOGFILE 2>&1

elif [[ "$ACTION" == "remove" ]]; then
    echo "Disconnecting camera..." >> $LOGFILE
    ls -l $DEVICE >> $LOGFILE 2>&1
    echo "Camera disconnected" >> $LOGFILE
else
    echo $ACTION >> $LOGFILE
fi
echo >> $LOGFILE


Мой скрипт может работать не правильно с другими камерами, советую сначала протестировать его.

Удачи.


З.Ы.
Все действия производились на Gentoo,
ядро 2.6.22-gentoo-r5
udev version 114
Exiv2 0.13
KDE: 3.5.7
KDialog: 1.0

Это сообщение отредактировал(а) nickless - 29.8.2007, 02:51

Присоединённый файл ( Кол-во скачиваний: 6 )
Присоединённый файл  udev_camera.tar.bz2 2,22 Kb


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Linux/UNIX: Oбщие вопросы"
nickless
Imple
nerezus

В тему здесь вопросы общие - не привязанные к определенному ПО или дистрибутиву BSD/Linux/UNIX.
Например вопросы о выборе ОС для определенных задач (но если Вы просто хотите узнать "Какой дистрибутив лучше", то для этого есть Клуб юнуксоидов).
Общие вопросы по shell-программированию тоже лучше задавать здесь.


  • Вопросы мобильной разработки тут
  • Вы должны соблюдать правила форума.
  • Помните: какой вопрос, такой и ответ. Прежде чем задать вопрос прочитайте вот эту статью на форуме CIT.
  • Оскорблять запрещается.
  • Религиозные войны в Религиозных войнах.
  • Общение "просто так" в Клубе юнуксоидов. В отличие от многих других разделов, здесь разрешается сдержанно оффтопить и юморить в тему.

За интересные статьи, находки, решения, программы и просто реальную помощь будут ставиться + в репу).


В данный момент этот раздел модерируют nerezus, nickless, powerfox, pythonwin, Imple и ZeeLax. Если вы хотите помочь нам, пишите в ПМ и мы обсудим.


Спасибо. И use UNIX or die; С уважением, nerezus, nickless, powerfox, pythonwin, Imple, ZeeLax.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | *NIX системы: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0807 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.