Всем привет!

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

Но денег не особо много, чтобы покупать какие-то специализированные решения, поэтому решено было поскрести по завалам хлама в серверной и с разрешения руководства утащить домой IP-камеру Xblitz iSee P2P IP WiFi.

image

Камера Xblitz iSee P2P IP WiFi

В камере была заявлена поддержка ONVIF, что автоматически наталкивало на мысль, что нужно ставить ZoneMinder и управлять устройством через него.

Установил, но, как оказалось, эта камера ни при каких настройках не хотела работать с ним.
В веб-интерфейсе камеры выяснилось, что изготовителем камеры до брендирования для польского рынка является китайский производитель netcam360.

Веб-интерфейс камеры


image

После определения настоящего производителя, через поисковик, выяснилось, что не только я имею проблемы с вышеуказанным форматом. И не только мне не удалось настроить на работу с указанным протоколом. Видимо, включение ONVIF в интерфейсе — это ни что иное как шутка от программистов из Китая.

Включение ONVIF в интерфейсе


image

Было решено, что захватывать буду через RTSP. Благо, этот метод работал.
Но, так как я заинтересовался темой написания сервиса в systemd, определил сделать не простой bash-скрипт для захвата потока, а такой себе сервис.

Как оказалось, написание сервиса очень простая процедура. Вот код незамысловатого сервиса под названием «camera@.service», который размещен в /etc/systemd/system

Сервис «сamera»


[Unit]
Description=Camera Service on %I
After=network.target

[Service]
Type=simple
KillSignal=HUP
User=camera
SyslogIdentifier=camera_%i
ExecStart=/bin/bash -a -c '</dev/tcp/%i/10554 && source /etc/camera.conf && mkdir -p /home/camera/%i && cd /home/cam
era/%i && exec /usr/bin/openRTSP -D 5 -F $DATE -K -4 -P 3600 -l -b 200000 rtsp://%i:10554/udp/av0_0'
Restart=always
RestartSec=10
#Restart=on-failure

[Install]
WantedBy=multi-user.target

Как видно, сервис запускается командой «systemctl start camera@IP-address».
В /etc/camera.conf всего лишь одна строчка, сделано было для того, чтобы соответствовать канонам Linux-сервиса

Содержание конфигурационного файла


DATE=$(date "+%Y_%m_%d_%H_%M_%S")

Для удобства прописал в /etc/hosts на этот IP имя «eye01».
Предполагается, что камер в дальнейшем может быть три.

Осталось только в cron добавить удаление устаревших файлов, так как один час записи — это файл примерно 1,5 ГБ.

find /home/camera/eye01 -mtime +2 -delete

И можно спокойно мониторить.

Но, через несколько дней я выяснил, что камера иногда перестает отвечать и видео прерывается.

Пришлось еще запланировать в cron проверку камеры с помощью скрипта, информирование об этом в slack и рестарт камеры. Опытным путем определил, что зависать она может один раз в 10-12 часов. Поэтому планировщик проверяет пишет ли камера один раз в полчаса. Потеря получаса записи для меня не критична.

Скрипт проверки камеры


#!/bin/bash -e
exec 1> >(logger -s -t "$(basename $0) $1") 2>&1
SIZE1=$(du -sb /home/camera/$1 | cut -f1)
sleep 5
SIZE2=$(du -sb /home/camera/$1 | cut -f1)

if [ $SIZE1 -eq $SIZE2 ]
then
    echo "Size of $1 is not increasing, probably not recording"
    if [ ! -f /tmp/$1 ]
        then
        touch /tmp/$1
        /usr/local/bin/slackcat -n beholder "Size of $1 is not increasing, probably not recording. Rebooting."
        /usr/local/bin/reboot_camera.sh $1
        fi
    exit 1
else
    echo "Size of $1 is increasing, probably recording"
    if [ -f /tmp/$1 ]
        then
        rm -f /tmp/$1
        /usr/local/bin/slackcat -n beholder "Size of $1 is increasing, probably recording"
        fi
    exit 0
fi

Скрипт перезапуска камеры


#!/bin/bash
exec 1> >(logger -s -t "$(basename $0) $1") 2>&1
if [ "$1" == "eye01" ]; then
    curl "http://$1/reboot.cgi?loginuse=admin&loginpas=PASSWORD"
elif [ "$1" == "eye02" ]; then
    curl "http://$1/reboot.cgi?loginuse=admin&loginpas=PASSWORD"
elif [ "$1" == "eye03" ]; then
    curl "http://$1/reboot.cgi?loginuse=admin&loginpas=PASSWORD"
else
    echo "Not recognized camera $1"
    exit 1
fi

Собственно все. Надеюсь кому-то еще мое решение поможет быстро и недорого организовать видеонаблюдение.

Буду благодарен любой критике и предложениям по его усовершествованию.

Ссылки и использованные публикации


Репозиторий
Интеграция Slack с помощью slackcat
Как написать сервис systemd

Спасибо за внимание.

Комментарии (34)


  1. saboteur_kiev
    26.10.2017 17:58

    if [ "$1" == "eye01" ]; then
        curl "http://$1/reboot.cgi?loginuse=admin&loginpas=PASSWORD"
    elif [ "$1" == "eye02" ]; then
        curl "http://$1/reboot.cgi?loginuse=admin&loginpas=PASSWORD"


    А почему у вас эти условия, они же ничего не делают, если $1 вы даете рабочее имя для url


    1. lex-tsy Автор
      26.10.2017 18:20

      Как не делают?
      Это же простая проверка на правильность вписания аргумента. Если он будет отличный от eye01, eye02, eye03, то получим сообщение, что такая камера неизвестна.


      1. saboteur_kiev
        26.10.2017 18:33

        аа, тогда просто вот так было бы лучше:

        case $1 in
          eye01|eye02|eye03 )
            curl "http://$1/reboot.cgi?loginuse=admin&loginpas=PASSWORD" ;;
        else
            echo "Not recognized camera $1"
            exit 1 ;;
        esac

        Я просто пытался вглядеться в URL, пытаясь увидеть в чем разница =)


        1. lex-tsy Автор
          26.10.2017 18:38

          Да, действительно, так лучше. Но я все никак не могу привыкнуть так писать код.
          Спасибо за предложение. Изменю в репозитории.


          1. lex-tsy Автор
            26.10.2017 18:39

            Хотя это подойдет, только если пароль будет одинаков.


            1. saboteur_kiev
              26.10.2017 19:07

              Если пароль разный, тогда еще проще

              if [ -f /etc/camera/${1}.properties ]; then
                . /etc/camera/${1}.properties
                curl "${URL}?loginuse=${USER}&loginpas=${PASS}"
              else
                  echo "Not recognized camera $1"
                  exit 1 ;;
              fi
              

              И просто накидываете проперти файлики. При этом у вас уже имя камеры и конкретный URL уже могут быть связаны, но отличаться. Для добавления камеры даже скрипт править не нужно — просто еще один /etc/camera/eyeXX.properties добавить, в котором просто

              URL="http://eyexx.local.net/reboot.cgi"
              USER="admin"
              PASS="PASSWORD"


              1. lex-tsy Автор
                27.10.2017 01:29

                Круто. Как-то мне в голову даже не пришло. Спасибо!


                1. vaniacer
                  27.10.2017 15:42

                  Еще можно использовать именованный массив как вариант.

                  код
                  declare -A CAM=(
                    [eye01user]=user  [eye01pass]=123
                    [eye02user]=admin [eye02pass]=456
                    [eye03user]=loser [eye03pass]=789
                  )
                  
                  URL="http://$1/reboot.cgi?loginuse=_L_&loginpas=_P_"
                  URL=${URL//_L_/${CAM[${1}user]}}
                  URL=${URL//_P_/${CAM[${1}pass]}}
                  
                  [[ ${CAM[${1}user]} ]] && curl "$URL" || echo "Unknown camera $1"
                  


                  1. vaniacer
                    27.10.2017 15:51

                    Рефакторинг)
                    declare -A CAM=(
                      [eye01user]=user  [eye01pass]=123
                      [eye02user]=admin [eye02pass]=456
                      [eye03user]=loser [eye03pass]=789
                    )
                    
                    URL="http://$1/reboot.cgi?loginuse=${CAM[${1}user]}&loginpas=${CAM[${1}pass]}"
                    
                    [[ ${CAM[${1}user]} ]] && curl "$URL" || echo "Unknown camera $1"
                    


                    1. saboteur_kiev
                      27.10.2017 16:14

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


                      1. vaniacer
                        27.10.2017 17:03

                        У каждого варианта свои плюсы и минусы. Массив с логинами\паролями тоже можно вынести в отдельный файл

                        ~/cameras
                        declare -A CAM=(
                          [eye01user]=user
                          [eye01pass]=123
                        
                          [eye02user]=admin
                          [eye02pass]=456
                        
                          [eye03user]=loser
                          [eye03pass]=789
                        )
                        


                    1. VJean
                      27.10.2017 16:55
                      +1

                      Пожалуйста, не надо превращать скобками баш в лисп


                      1. vaniacer
                        27.10.2017 17:06
                        -1

                        Дело вкуса.


                        1. VJean
                          27.10.2017 17:35
                          +1

                          Дурной вкус. Сравните свой же код (код vs Рефакторинг) с подсветкой синтаксиса от хабра. Потеряетесь в скобках или нет? А если подсветку выключить? А теперь вернемся к коду через пару недель, а лучше месяцев…


                          1. vaniacer
                            27.10.2017 17:56

                            Потерялся в трёх скобках)


  1. vak0
    26.10.2017 18:20

    >… стала задача мониторинга, как он делает уроки…
    Напомнило «Подзорную трубу» из «Денискиных рассказов» Драгунского. Фильм такой старый тоже есть. :-)


  1. Sly_tom_cat
    26.10.2017 18:41

    Вотжежблин, и как же мы выросли и выучились, когда предки весь день на работе, а дома даже проводного телефона не было — не то что интернета и камер…


    1. lex-tsy Автор
      26.10.2017 18:52

      Бабушки-дедушки были? Они все-таки немного контролировали. Плюс продленка.
      Но тема не об этом. Хотелось бы без оффтопа.


      1. Sly_tom_cat
        26.10.2017 19:00
        -1

        (Отвечаю на вопрос, а не офтоп-тред продолжаю): Когда я пошел в школу у меня оставалась в живых одна бабушка, жила она на расстоянии примерно 2500 км. На продленку не было спроса — и ее не было в нашей школе.


      1. TriLka
        27.10.2017 17:56

        Русские традиции… жить с бабушками в одной квартире… до их смерти, судя по всему.


    1. Alex625000
      27.10.2017 01:27

      Жду статьи на храбре от данного ребенка, типа "Как обойти видео-мониторинг родителей и вместо уроков заниматься робототехникой"


      1. lex-tsy Автор
        27.10.2017 01:28

        Я только за. Если оторвется от ютуба и телефона.


      1. VJean
        27.10.2017 08:11

        Он явно пытался, камера зависала не спроста.


    1. igorp1024
      27.10.2017 19:53

      Потому, что не было канала в бесконечный развлекательный мир. И от скуки можно было творить, выдумывать, пробовать. За всё что я знаю, спасибо скажу именно ей.


      1. Sly_tom_cat
        27.10.2017 21:02

        Это вы зря телек тогда показывал довольно много интересного и познавательного. В дневное время крутили именно документальное и научно-популярное.


        1. igorp1024
          27.10.2017 21:11

          Но не было возможности залипнуть в познавательное на 4-5 часов в сутки. И было оно по расписанию, а не когда нечем заняться.


  1. kvaps
    27.10.2017 02:59

    Есть ещё такая штука как ZoneMinder, она бесплатна, камерами можно рулить через веб-интерфейс, настаивать зоны, просматривать записи, вот это все.
    Возможно вам будет интересно.


  1. Miharus
    27.10.2017 08:53

    Народ, мне одному кажется что это какой то адище следить за ребёнком в камеру? Это может казаться ребёнку капец как унизительно. И он вырастет не самостоятельным, это в лучшем случае.
    Это вопрос к тем кто в этом разбирается, а не предъява автору.


    1. reinvent
      27.10.2017 16:51

      Хотя автор просил не офтопить, но полагаю, это один из тех случаев, когда эффективное решение не лежит в технической плоскости. Даже взрослые положительно на надзор не реагируют (некоторые готовы смириться). Мне помогли наладить контакт и обучение книги Фабер и Мазлиш, в том числе «Как говорить с детьми, чтобы они учились». Всем родителям советую.


  1. nipnull
    27.10.2017 13:57

    Пару лет назад реализовал в виде bash скрипта > 100 строк оболочку над ffmpeg для записи rtsp. В том числе с групповой и пользовательской политикой, e-mail сообщениями при чп и т.д. Могу расписать, если интересно.


    1. lex-tsy Автор
      27.10.2017 13:59

      Конечно интересно. Буду ждать Вашей публикации.


  1. Anthrax_Beta
    27.10.2017 13:58

    Лучше писать небольшими кусочками минут по 5, как в авторегистраторах. Тогда шанс потерять что-то нужное стремится к минимуму.


  1. vaniacer
    27.10.2017 14:49

    Вы уже установили что камера зависает один раз в 10-12 часов, какой смысл это дополнительно проверять и ждать этого? Вдруг пронесет?) Просто сделайте плановую перезагрузку (крон) раз в 5-10 часов. Или просто в определенное время чтобы она «гарантированно» отработала 10-12 часов.


  1. TriLka
    27.10.2017 15:28

    >мониторинга, как он делает уроки, сколько времени занимается фортепиано
    Соболезную.