Vu+ Duo 4K SE BT initial bringup
Table of Contents
My existing Enigma2 receiver, a Dreamdbox DM900 UHD, has been replaced by a Vu+ Duo4K SE.
This is my braindump of the initial bringup.
Why Decommission the DM900 UHD
A month or three ago, my DM900 UHD’s display stopped displaying pictures, from powerup on it would light its backlight but only display a white image :-(
This behaviour is not uncommon (German page).
Sadly, replacing both the display and the controlled board, did not help. So a new Linux based settop box was in the cards.
While I did try MythTV in the past, I am a long time Enigma2 (E2) user and before that was using VDR. Having used a certain interface for decades, I prefer hardware that can run E2 and is silent.
Which Distro to Pick
I started by looking at distros under the OE-Alliance.
There OpenBh caught my eye because
- their easily locatable repos seem active
- they have a Pyhon 3 branch (which is even the default branch). I much prefer a current Python version over EOL Python2.
root@vuduo4kse:~# python --version
Python 3.9.7
root@vuduo4kse:~# python2 --version
-bash: python2: command not found
Which Hardware to Pick
Once I had picked a distro, it was time to choose a hardware vendor.
My requirements a probably not common, but they are as follows
- have a display so I need not switch on the TV for some actions
- be able to ssh into the box
- run a Linux distro
- able to wake from deep sleep for a recording
- able to handle at least 2 DVB-C streams, so that I can record one channel while watching another
- able to accept a local SATA storage device for recordings
- the ability to add software of my choosing to the running OS
Bonus points for
- supporting Wake on LAN so I can power up the box without walking to it
- concurrently recording/showing more than 2 DVB-C streams
- the ability to also receive DVB-T2, again 2 channels at the same time as a minimum
- Gigabit Ethernet rather than 100 Mbit/s
- using a packaging system, I do not miss the days of
./configure && make && make install
at all - offering a repository with pre-made packages
Why a Vu+ Duo 4K SE
With the above requirements, I settled (more or less on a whim) at a VU+ Duo 4K SE BT FBC Twin PVR 1xC/T2 bk 1xDVB-C/1xDVB-T2 FBC Twin Tuner PVR BT. While I currently have no DVB-T2 antenna in use, I want to be able to use one in addition to my current DVB-C feed.
That model also has plenty of RAM and flash space for now with 3 GiB RAM and 4GiB eMMC flash coupled with 4 ARMv7 cores at 1500MHz.
I live in Europe and thus have 2 weeks to send back any on-line orders, so while my choice was more expensive than quite a few of the alternatives, the hardware vendor needs to make enough profit to stay around for the years to come and if it all turned out to be horrible, I could just return to the German reseller I chose.
It was a bit odd that, at the end of February 2022, the English Vu+ site did not yet list the Duo 4K SE BT in their products list, it only lists the older non SE model. But well, the vendor is from South Korea so maybe they are just a bit slow with the foreign language site updates. It is listed on Wikipedia as available since 2020. It is listed on the Vu+ image download server. It is listed at Satco Europe. Since Satco Europe does not sell to private end users, I bought mine from ALTERNATE GmbH, a shop I have been using happily for a while now.
The one thing I did not look at was Linux mainline support for the tuners, that was dumb of me :-(
Verify that the Box is functional
This was done with the preinstalled Vu+ image. Nothing to report; the expected E2 initial bringup wizard came up on first boot, I went through the steps and watched a few minutes of live TV to ensure the box works before reflashing it.
Install OpenBh 5.0
Now since I wanted a recent, maintained, sources easily available distro, I Installed OpenBh 5.0.
I grabbed the archive for my model and installed with the refreshingly straightforward software update functionality; unpack an archive to a USB stick, keeping the folder structure inside the archive! The Vu+ picks it up on cold boot and you confirm via a button press on the box. This is guided by the box’ display. If you do not confirm, then the box boots normally. Nice, I wish all hardware was this flash friendly. No mucking about with fastboot, boot button pressese or LARTing the hardware into understanbding that when I bought a pice of hardware, then I expect to have control over which OS is installed on it.
This gets the brand Vu+ a huge plus in my book.
Configuration Steps Taken
- set a root password while logged in via ssh
- installed my ssh public key as
/home/root/.ssh/authorized_keys
, unusual place for root’s homedir, but no matter - While initially I enabled DVB-C Service scan workaround, as per https://github.com/BlackHole/enigma2/issues/99, this is fixed in OpenBh 5.0 since 5.0.013
- for shits ’n giggles, I enabled CrossEPG, as per https://vuplus-forum.org/wbb4/index.php?thread/26215-crossepg-f%C3%BCr-kabel-sinnvoll/&s=55678377a382d92faa7f2cb7d0d0f52b345de286
- set up some quick ’n dirty Ansible job to allow for automatic deletion of recordings, ses below for details
Not that I really need CrossEPG, the EPG coming over DVB-C has been good in this location with my previous E2 boxes, but I did want to try it.
For those that do not understand German, the post roughly translates to;
Execute Update Rytec Providers once to get a full XMLTV providers list, then select your region under XMLTV providers
In my case, I chose the region Deutschland/Osterreich/Switzerland - Gemeinsam (xz).
Use Ansible to Setup the Enigma 2 box to Autodelete Recordings
Why on Earth Would I use Ansible for This
My primary use case of Enignma 2 is that it allows me switch it on at a time of my choosing and find the latest news available for watching. While this is easily achieved with Open Bh 5.0’s AutoTimers function, I also want to be able to have older recordings deleted after a while.
As such, like on all my previous live TV recording setups, I cobbled something together. This time, instead of having to dig out yet another E2 forum post of mine each time I flash a different distribution on my currently used STB and then do some copypasta, I used a template, some inventory entries and a playbook simply because i can™ :-).
Template to Create the Autoclean Script
The template simply iterates over 3 lists (populated in inventory);
- shows I want to delete if they are older than 2 days
- shows I want to delete if they are older than 7 days
- shows I want to delete if they are older than 28 days
to create some entries along the lines of
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*Das Erste HD - Tagesschau*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +7 -name "*Das Erste HD - FIFA WM*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +28 -name "*Das Erste HD - ttt - titel thesen temperamente*" -print -delete
followed up with a run of the extremely useful cleanup.py
from jbretsch’s pvrutils. That allows for my /media/hdd/movie/autoclean
to never fill up, even if I record shows not explicitly deleted after N days.
templates/Enigma 2/E2-auto-clean-script.bash.j2
reads
#!/bin/bash
#
# {{ ansible_managed }}
#
# make subdirs in /media/hdd/movie/
# /media/hdd/movie/autoclean
# /media/hdd/movie/keep (remember to set this as your default Enignma2 recording path)
#
# This script will is meant to remove recordings after a set amont of days by using the
# find command with the delete flag. So it should contain lines like the following:
# /usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*Das Erste HD - Tagesschau*" -delete
#
# The idea is that e.g. news recorded every day are really only interesting for a couple days,
# so one might as well delete them after two days.
#
# See the thread https://dreambox.de/board/index.php?thread/17617-automatisches-l%C3%B6schen-von-%C3%A4lteren-serien/
#
date
echo disk space before cleaning
df -h /media/hdd/movie/autoclean
# {{ ansible_managed }}
# begin of automatically constructed lines
# iff (if and only if) e2_autoclean_after_…days (02, 07 and 28) are defined in Ansible inventory
# then the following three blocks will be populated
# please be aware that you can easily shoot yourself in the foot with 'find … -delete',
# so review the generated script before running it!
echo "deleting the following shows, whose recordings are older than 2 days:"
# iff the list e2_autoclean_after_02days is populated in Ansible inventory, then we will get lines here
{% for e2_autoclean_pattern_02d in e2_autoclean_after_02days %}
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "{{ e2_autoclean_pattern_02d }}" -print -delete
{% endfor %}
echo
echo "deleting the following shows, whose recordings are older than 7 days:"
# iff the list e2_autoclean_after_07days is populated in Ansible inventory, then we will get lines here
{% for e2_autoclean_pattern_07d in e2_autoclean_after_07days %}
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +7 -name "{{ e2_autoclean_pattern_07d }}" -print -delete
{% endfor %}
echo
echo "deleting the following shows, whose recordings are older than 28 days:"
# iff the list e2_autoclean_after_28days is populated in Ansible inventory, then we will get lines here
{% for e2_autoclean_pattern_28d in e2_autoclean_after_28days %}
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +28 -name "{{ e2_autoclean_pattern_28d }}" -print -delete
{% endfor %}
echo
# end of automatically constructed lines
echo "running cleanup.py from https://github.com/jbretsch/pvrutils"
# keep 100GB free
/home/root/bin/cleanup.py -s 102400 /media/hdd/movie/autoclean
echo disk space after cleaning
df -h /media/hdd/movie/autoclean
echo
echo "all done"
date
Inventory Entries
In my hosts
file (yes, I know, this would be cleaner as a host_var);
vuduo4kse ansible_host=vuduo4kse.internal.pcfe.net ansible_user=root
And in host_vars/vuduo4kse/E2-auto-clean-script.yml
I define the 3 lists for 2, 7 and 28 days retention.
# The filenames of recordings will be in the form
# /media/hdd/movie/autoclean/20220315 1958 - Das Erste HD - Tagesschau.eit
# /media/hdd/movie/autoclean/20220315 1958 - Das Erste HD - Tagesschau.ts.sc
# /media/hdd/movie/autoclean/20220315 1958 - Das Erste HD - Tagesschau.ts.cuts
# /media/hdd/movie/autoclean/20220315 1958 - Das Erste HD - Tagesschau.ts.ap
# /media/hdd/movie/autoclean/20220315 1958 - Das Erste HD - Tagesschau.ts
# /media/hdd/movie/autoclean/20220315 1958 - Das Erste HD - Tagesschau.ts.meta
#
# So for the autoclean after N days lists below, you need to carefully test first with e.g.
# /usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -name "*heute*"
# when deciding on the patterns you list here.
# Obviously, the more generic your entry (e.g. '*heute*'), the greater the risk that you delete more than you bargained for,
# so it is preferable to use something more specific (e.g. '*Das Erste HD - Tagesschau*')
# The three below lists will be used to construct a script containing lines like the following
# /usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*rbb Berlin HD - Abendschau*"
# but with the -delete option added.
e2_autoclean_after_02days:
- '*rbb Berlin HD - Abendschau*'
- '*Das Erste HD - Tagesschau*'
- '*Das Erste HD - Tagesthemen*'
- '*Das Erste HD - Nachtmagazin*'
- '*Das Erste HD - Weltspiegel*'
- '*Das Erste HD - Wetter vor acht*'
- '*Das Erste HD - Sportschau*'
e2_autoclean_after_07days:
- '*Formel 1*'
- '*Formula 1*'
- '*Das Erste HD - FIFA WM*'
- '*ZDF HD - ZDF WM live*'
- '*Eishockey*'
e2_autoclean_after_28days:
- '*Das Erste HD - ttt - titel thesen temperamente*'
- '* - extra 3.*'
- '* - heute-show.*'
The Playbook
Is really just a couple tasks to create directories used by E2-auto-clean-script.bash
,
construct the script, put it in place and do a (dirty, with a hardcoded path) copy task
to have cleanup.py
from jbretsch/pvrutils available on the Vu+.
---
- name: Ensure Enigma 2 on my Vu+ Duo 4K SE is set up they way I want
hosts:
- vuduo4kse
# I connect as root, so no need for become
become: false
tasks:
# n.b. root's homedir is in the unusual location '/home/root/', not the usual '/root/'.
- name: Ensure /home/root/bin/ exists
ansible.builtin.file:
path: /home/root/bin
state: directory
mode: u=rwx,g=rx,o=rx
group: root
owner: root
- name: Ensure the generated E2-auto-clean-script.bash exists and is current
ansible.builtin.template:
src: templates/Enigma 2/E2-auto-clean-script.bash.j2
dest: /home/root/bin/E2-auto-clean-script.bash
mode: u=rwx,g=rx,o=rx
owner: root
group: root
- name: Ensure cleanup.py from https://github.com/jbretsch/pvrutils.git is copied over
ansible.builtin.copy:
src: /home/pcfe/work/git/github.com/pvrutils/cleanup.py
dest: /home/root/bin/
mode: u=rwx,g=rx,o=rx
group: root
owner: root
# it is quite intentional that the 2 paths are hardcoded instead of variables (both here and in the template),
# this Ansible construct to create a script, run by root, containing many lines of "find … -delete",
# all that is already enough of a bespoke foot bazooka as it is.
- name: Ensure /media/hdd/movie/autoclean/ exists
ansible.builtin.file:
path: /media/hdd/movie/autoclean
state: directory
mode: u=rwx,g=rx,o=rx
group: root
owner: root
- name: Ensure /media/hdd/movie/keep/ exists
ansible.builtin.file:
path: /media/hdd/movie/keep
state: directory
mode: u=rwx,g=rx,o=rx
group: root
owner: root
# Dont do that (add a cronjob with the cron ansible module), CronManager.py is fragile
# either write to a file not parsed by CronManager.py or enter by hand in Enigma 2
# https://github.com/opendroid-Team/enigma2-plugin-extensions-extrapanel/blob/master/usr/lib/enigma2/python/Plugins/Extensions/Infopanel/CronManager.py
# - name: Ensure E2-auto-clean-script.bash is called by cron and visible in E2's Infopanel extension Cron Manager
# cron:
# minute: "15"
# hour: "19"
# user: root
# job: "/home/root/bin/E2-auto-clean-script.bash"
# cron_file: /etc/cron/crontabs/root
# then https://dreambox.de/board/index.php?thread/17617-automatisches-l%C3%B6schen-von-%C3%A4lteren-serien/&postID=179202#post179202
# but old SysV init style or on OpenBh's cron timers config section
I do not know yet if I’ll add more tasks to the playbook, for that I would have to first hunt down the files changed by my settings in the E2 TV interface and I’m not sure I will bother.
Example of Generated Script
Here is an example of a generated /home/root/bin/E2-auto-clean-script.bash
;
#!/bin/bash
#
# This file is managed by Ansible. Manual changes will be overwritten at the next Ansible run.
#
# make subdirs in /media/hdd/movie/
# /media/hdd/movie/autoclean
# /media/hdd/movie/keep (remember to set this as your default Enignma2 recording path)
#
# This script will is meant to remove recordings after a set amont of days by using the
# find command with the delete flag. So it should contain lines like the following:
# /usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*Das Erste HD - Tagesschau*" -delete
#
# The idea is that e.g. news recorded every day are really only interesting for a couple days,
# so one might as well delete them after two, seven or 28 days.
#
# See the threads
# https://dreambox.de/board/index.php?thread/17617-automatisches-l%C3%B6schen-von-%C3%A4lteren-serien/
# https://board.openbh.net/threads/automatic-deletion-of-recordings-possible-in-openbh-5-0.784/
date
echo disk space before cleaning
df -h /media/hdd/movie/autoclean
# This file is managed by Ansible. Manual changes will be overwritten at the next Ansible run.
# begin of automatically constructed lines
# iff (if and only if) e2_autoclean_after_…days (02, 07 and 28) are defined in Ansible inventory
# then the following three blocks will be populated
# please be aware that you can easily shoot yourself in the foot with 'find … -delete',
# so review the generated script before running it!
echo "deleting the following shows, whose recordings are older than 2 days:"
# iff the list e2_autoclean_after_02days is populated in Ansible inventory, then we will get lines here
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*rbb Berlin HD - Abendschau*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*Das Erste HD - Tagesschau*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*Das Erste HD - Tagesthemen*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*Das Erste HD - Nachtmagazin*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*Das Erste HD - Weltspiegel*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*Das Erste HD - Wetter vor acht*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +2 -name "*Das Erste HD - Sportschau*" -print -delete
echo
echo "deleting the following shows, whose recordings are older than 7 days:"
# iff the list e2_autoclean_after_07days is populated in Ansible inventory, then we will get lines here
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +7 -name "*Formel 1*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +7 -name "*Formula 1*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +7 -name "*Das Erste HD - FIFA WM*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +7 -name "*ZDF HD - ZDF WM live*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +7 -name "*Eishockey*" -print -delete
echo
echo "deleting the following shows, whose recordings are older than 28 days:"
# iff the list e2_autoclean_after_28days is populated in Ansible inventory, then we will get lines here
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +28 -name "*Das Erste HD - ttt - titel thesen temperamente*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +28 -name "* - extra 3.*" -print -delete
/usr/bin/find /media/hdd/movie/autoclean -maxdepth 1 -mtime +28 -name "* - heute-show.*" -print -delete
echo
# end of automatically constructed lines
echo "running cleanup.py from https://github.com/jbretsch/pvrutils"
# keep 100GB free
/home/root/bin/cleanup.py -s 102400 /media/hdd/movie/autoclean
echo disk space after cleaning
df -h /media/hdd/movie/autoclean
echo
echo "all done"
date