Возникла у меня необходимость выводить дашборд с мониторингом на несколько экранов в офисе. В распоряжении имеется несколько стареньких Raspberry Pi Model B+ и гипервизор с практически неограниченным количеством ресурсов.
По видимому Raspberry Pi Model B+ не обладает достаточной произвольностью чтобы держать постоянно запущенным браузер и отрисовывать большое количество графики в нем, из-за чего бывает, что страница частично глючит и часто вылетает.
Нашлось достаточно простое и элегантное решение, которым я и хочу с вами поделиться.
Как известно все Raspberry имеют достаточно мощный видеопроцессор, который отлично подходит для аппаратного декодирования видео. Так появилась идея запускать браузер с дашбордом где-нибудь ещё, а на малинку передавать готовый поток с отрендеренной картинкой.
Плюс ко всему это должно было упростить управление, так как в данном случае вся настройка будет выполняться на одной виртуалке, которую проще обновлять и бэкапить.
Сказано – сделано.
Серверная часть
Мы воспользуемся готовым Cloud Image для Ubuntu. Не требуя установки, он содержит всё необходимое для быстрого развертывания виртуальной машины, а поддержка Cloud-Init помогает моментально настроить сеть, добавить ssh-ключи и быстро ввести ее в строй.
Разворачиваем новую виртуалку и первым делом установим на ней Xorg, nodm и fluxbox:
apt-get update
apt-get install -y xserver-xorg nodm fluxbox
sed -i 's/^NODM_USER=.*/NODM_USER=ubuntu/' /etc/default/nodm
Так же воспользуемся конфигом для Xorg, любезно предоставленным нам Diego Ongaro, добавив только новое разрешение 1920x1080, так как все наши мониторы будут использовать именно его:
cat > /etc/X11/xorg.conf <<\EOT
Section "Device"
Identifier "device"
Driver "vesa"
EndSection
Section "Screen"
Identifier "screen"
Device "device"
Monitor "monitor"
DefaultDepth 16
SubSection "Display"
Modes "1920x1080" "1280x1024" "1024x768" "800x600"
EndSubSection
EndSection
Section "Monitor"
Identifier "monitor"
HorizSync 20.0 - 50.0
VertRefresh 40.0 - 80.0
Option "DPMS"
EndSection
Section "ServerLayout"
Identifier "layout"
Screen "screen"
EndSection
EOT
systemctl restart nodm
Теперь установим Firefox, запускать мы его будем как system сервис, так что заодно и напишем unit-файл для него:
apt-get install -y firefox xdotool
cat > /etc/systemd/system/firefox.service <<\EOT
[Unit]
Description=Firefox
After=network.target
[Service]
Restart=always
User=ubuntu
Environment="DISPLAY=:0"
Environment="XAUTHORITY=/home/ubuntu/.Xauthority"
ExecStart=/usr/bin/firefox -url 'http://example.org/mydashboard'
ExecStartPost=/usr/bin/xdotool search --sync --onlyvisible --class "Firefox" windowactivate key F11
[Install]
WantedBy=graphical.target
EOT
systemctl enable firefox
systemctl start firefox
Xdotool необходим нам для того чтобы запускать firefox сразу в полноэкранном режиме.
Используя параметр -url
можно указать любую страницу чтобы она открывалась автоматически при запуске браузера.
На этом этапе наш киоск уже готов, но теперь нам нужно экспортировать картинку по сети на другие мониторы и устройства. Для этого мы воспользуемся возможностями Motion JPEG, формата который чаще используется для стриминга видео с большинства web-камер.
Для этого нам понадобится две вещи: FFmpeg с модулем x11grab, для захвата картинки с иксов и streamEye, который будет раздавать ее нашим клиентам:
apt-get install -y make gcc ffmpeg
cd /tmp/
wget https://github.com/ccrisan/streameye/archive/master.tar.gz
tar xvf master.tar.gz
cd streameye-master/
make
make install
cat > /etc/systemd/system/streameye.service <<\EOT
[Unit]
Description=streamEye
After=network.target
[Service]
Restart=always
User=ubuntu
Environment="DISPLAY=:0"
Environment="XAUTHORITY=/home/ubuntu/.Xauthority"
ExecStart=/bin/sh -c 'ffmpeg -f x11grab -s 1920x1080 -r 1 -i :0 -f mjpeg -q:v 5 - 2>/dev/null | streameye'
[Install]
WantedBy=graphical.target
EOT
systemctl enable streameye
systemctl start streameye
Так как наша картинка не требует быстрого обновления, я указал частоту обновления: 1 фрейм в секунду (параметр -r 1
) и качество сжатия: 5 (параметр -q:v 5
)
Теперь пробуем зайти на http://your-vm:8080/, в ответ вы увидите постоянно обновляемый скриншот рабочего стола. Отлично! — то что и было нужно.
Клиентская часть
Здесь все еще проще, как я уже сказал использовать мы будем Raspberry Pi Model B+.
Первым делом установим на нее Arch Linux ARM, для этого следуем инструкции на официальном сайте.
Нам также потребуется выделить больше памяти для нашего видеочипа, для этого отредактируем в /boot/config.txt
gpu_mem=128
Загрузим нашу новую систему и не забыв инициализировать pacman keyring, установим OMXPlayer:
pacman -Sy omxplayer
Что примечательно, OMXPlayer может работать без иксов, по этому все что нам требуется — это написать unit-файл для него и запустить:
cat > /etc/systemd/system/omxplayer.service <<\EOT
[Unit]
Description=OMXPlayer
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/omxplayer -r --live -b http://your-vm:8080/ --aspect-mode full
[Install]
WantedBy=multi-user.target
EOT
systemctl enable omxplayer
systemctl start omxplayer
В качестве параметра -b http://your-vm:8080/
мы передаем URL с нашего сервера.
На этом все, на подключенном экране сразу должна появиться картинка с нашего сервера. В случае возникновения каких либо проблем, стрим будет автоматически перезапущен, а клиенты переподключатся к нему.
В качестве бонуса можно установить полученную картинку в качестве скринсейвера на все компьютеры в офисе. Для этого вам понадобятся MPV и XScreenSaver:
mode: one
selected: 0
programs: \
"Monitoring Screen" mpv --really-quiet --no-audio --fs \
--loop=inf --no-stop-screensaver \
--wid=$XSCREENSAVER_WINDOW \
http://your-vm:8080/ \n\
maze -root \n\
electricsheep --root 1 \n\
Теперь ваши коллеги будут очень довольны :)