Исследование и доработка IP-видеосервера на базе Orange Pi PC

в 13:24, , рубрики: bash, gpio, linux, Orange Pi, squashfs, системное администрирование

Исследование и доработка IP-видеосервера на базе Orange Pi PC - 1

Около полугода назад мне достался миниатюрный видеосервер, применение которому я нашёл в арендуемом для мотоцикла гараже, где он всё это время благополучно работал в связке с двумя китайскими NoName IP-камерами, худо-бедно поддерживающими ONVIF, и 3G-модемом, что позволяло мне удалённо посмотреть видео с камер при оповещениях о детекции движения, к счастью совпадавшими пока только с моим приходом в гараж. Не дал этому микросерверу спокойно работать дальше я сам, так как, ещё когда только получил его в руки, из любопытства разобрал и неожиданно для себя обнаружил, что построен он на одноплатнике Orange Pi PC, который незадолго до этого, благодаря низкой цене, широко освещался в интернете, в том числе и на Geektimes, поэтому я примерно представлял его возможности.

Собственно, спустя полгода использования, в дополнение к основным функциям видеосервера мне захотелось задействовать гребёнку GPIO на его борту для подключения датчика дыма, датчика открытия двери и реле для включения сирены. Самым интересным и, на мой взгляд, сложным этапом этого хобби-проекта, я решил поделиться с сообществом, надеясь получить советы по дальнейшему развитию. Внимание: описанные дальше действия, скорее всего, лишили меня гарантии на устройство, я производил их на свой страх и риск и привожу лишь как пищу для ума, но не руководство к действию.

Исследование прошивки

Первым делом, в надежде, что видеосервер использует полноценный дистрибутив, я попробовал подключить монитор и клавиатуру к плате, но никакого сигнала на выходе HDMI не было, похоже, порт просто никак не задействован в прошивке, о чём, впрочем, и говорят разработчики, заявляя, что это устройство класса MicroNVR (Network Video Recorder), не подразумевающее никакого взаимодействия пользователя с сервером, кроме удалённого доступа. Вторая цель — ssh, порт которого на устройстве открыт, но сервер поддерживает только авторизацию по ключу, который мне никак раздобыть не удалось.

К счастью для меня, устройство базируется на той версии одноплатника, которая идёт без eMMC, и загрузка осуществляется с обычной MicroSD-карты, выступающей с торца платы. Собственно, всё что нужно для получения доступа к содержимому прошивки — вставить карту в кардридер. На 8Gb SanDisk'е расположено 3 раздела:

/dev/sdb1 on /media/user/disk type squashfs
/dev/sdb2 on /media/user/UBOOT type vfat
/dev/sdb3 on /media/user/07836191-ddf8-45ab-b02b-1103320c2e5b type ext4

Размеры разделов:

/dev/sdb1	25M   25M     0 100% /media/user/disk
/dev/sdb2	16M  2.2M   14M  14% /media/user/UBOOT
/dev/sdb3	58M  9.4M   45M  18% /media/user/07836191-ddf8-45ab-b02b-1103320c2e5b

Раздел «UBOOT», судя по всему, используется только загрузчиком U-Boot. Раздел с ext4 содержит логи (/log) основных подсистем (kern, lighttpd, line, netcfgd, syslog) и настройки сервервера видеонаблюдения, доступные изменению пользователем (/lib/line). А на разделе «disk» со squashfs (compressed read-only) расположены уже все файлы ОС и программ. Получается, операционная система и логическая часть со всеми «Аналитиками» и «Облаками» умещена разработчиками в 25 Мб, что совпадает с размером обновлений на их сайте, т.е. заменяется вся прошивка целиком, а не только ПО видеонаблюдения.

Основной раздел содержит привычный набор директорий:

bin   dev  factory  media  root  sbin  tmp  var
boot  etc  lib      proc   run   sys   usr

В целом, ничего необычного в дереве каталогов нет, всё на своих местах. Запускаемые runit-сервисы лежат в /etc/service:

dropbear  hwclock-fix  lighttpd  line  netcfgd  socklog-klog  socklog-unix

Увидев в списке lighttpd, я решил проверить, смогу ли использовать его для своих целей. Запускается он с конфигурацией:

server.modules += ( "mod_cgi" )

$SERVER["socket"] == ":19587" {
    include_shell "/usr/share/adm/lighttpd-gencert"

    server.document-root = "/usr/share/adm/www"

    cgi.execute-x-only = "enable"
    cgi.assign = ( "" => "" )
}

Содержимое /usr/share/adm/www:

datetime       firmware  password  profiles  sysinfo   timezones
factory-reset  locale    profile   settings  timezone

По набору скриптов понятно, что HTTP-сервер предоставляет возможности для утилиты, позволяющей изменить системные настройки устройства и обновить прошивку, получается, всё это можно сделать и без её участия по протоколу HTTP. Например, получить архив со сведениями о системе можно и через браузер:

https://192.168.1.2:19587/sysinfo

Сервер использует генерируемый самоподписанный сертификат и стандартную авторизацию с возможностью поменять пароль (на устройстве хранится только хэш). Готовый HTTPS-сервер с авторизацией и очень простой возможностью добавить свой скрипт сэкономил мне кучу времени и я приступил непосредственно к GPIO.

Доработка прошивки

Простой запрос в гугле «Orange Pi PC GPIO» сразу вывел меня на команды:

echo 0 > /sys/class/gpio_sw/PA1/data
echo 1 > /sys/class/gpio_sw/PA1/data

Найти имена портов тоже не было проблемой:

Исследование и доработка IP-видеосервера на базе Orange Pi PC - 2

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


#!/bin/sh
set -e

. ../lib/devline/http.sh
. ../lib/devline/auth.sh

is_auth || http_err_unauth

[ "$REQUEST_METHOD" = "PUT" ] || http_err_method PUT

value="$(head -c "$CONTENT_LENGTH" | tr -d '.')"

echo $value > /sys/class/gpio_sw/PA3/data

echo "Content-Type: text/plain"
echo
echo OK

Обновление прошивки

Мне оставалось только добавить новый файл на устройство, что нельзя сделать обычным копированием, т.к. целевая файловая система работает только на чтение. Наверное, существуют разные способы внесения изменения в squashfs, но я пошёл самым простым, на мой взгляд. Первым делом я считал образ раздела в файл:

dd if=/dev/sdb2 of=sdb2.img

Затем распаковал squashfs в обычную директорию:

unsquashfs sdb2.img

Скопировал скрипт alarm по нужному пути в squashfs-root и собрал из неё новый squashfs образ:

mksquashfs squashfs-root sdb2-new.img

Который потом залил обратно на флешку:

dd if=sdb2-new.img of=/dev/sdb2

Итог

На данный момент я могу по защищённому каналу замкнуть реле:

curl -X PUT -k --data '1' https://admin:j3ks92ls8f@192.168.1.2:19587/alarm

и разомкнуть его:

curl -X PUT -k --data '0' https://admin:j3ks92ls8f@192.168.1.2:19587/alarm

По большому счёту, лично для меня это было просто оценкой технической возможности реализации задумки. Оценка положительная: у меня есть доступ к портам ввода-вывода и я могу добавить свою логику в прошивку устройства. Бонусом я получил готовый к использованию HTTPS-сервер.

По моему мнению, это была самая интересная часть разработки, дальше по большей части остаётся только рутина, и я не уверен закончу ли всё задуманное в полном объёме. В любом случае, если кто-то решит повторить что-то подобное, вот пара идей по дальнейшему развитию текущего результата:

  1. Написать скрипт службы, которая будет отслеживать состояние входов с датчиками и реагировать на сработку (оповещать, включать сирену). Тут всё понятно, сложностей ни со службой ни с оповещением не предвидится, даже исполняемый файл curl уже есть на устройстве, т.е. для оповещений есть несколько вариантов: SMTP и получение сообщений по IMAP, готовые сервисы отправки SMS, свой сервер;
  2. Добиться работы через интернет без прямого IP-адреса. Дело в том, что через облако работает только основной софт видеосервера, а lighttp-сервер, реализующий системные настройки, доступен только прямо, что, конечно, не плохо само себе. По этому пункту я не так уверен в простоте реализации, мои идеи пока ограничиваются двумя вариантами: ssh-тунель (надо добавить свой публичный ключ на устройство) или свой сервер и long polling со стороны устройства.

Буду благодарен за ваши идеи.

Автор: motorcycle

Источник


  1. Шамиль:

    Можно попробовать поднять ipv6 тунель на какой нибудь брокер, и будет доступ отовсюду!

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js