This is the multi-page printable view of this section. Click here to print.
Signage
- 1: Anthias (Screenly)
- 1.1: Anthias Deployment
- 1.2: API
1 - Anthias (Screenly)
Overview
Anthias (AKA Screenly) is a simple, open-source digital signage system that runs well on a raspberry pi or Intel PC. When plugged into a monitor, it displays images, video or web sites in slideshow fashion. It’s managed directly though a web interface on the device and there are fleet and support options.
Preparation
On a Raspberry Pi
Use the Raspberry Pi Imager to create a 64 bit Raspberry Pi OS Lite image. Select the gear icon at the bottom right to enable SSH, create a user, configure networking, and set the locale. Use SSH continue configuration.
setterm --cursor on
sudo raspi-config nonint do_change_locale en_US-UTF-8
sudo raspi-config nonint do_configure_keyboard us
sudo raspi-config nonint do_wifi_country US
sudo timedatectl set-timezone America/New_York
sudo raspi-config nonint do_hostname SOMENAME
sudo apt update;sudo apt upgrade -y
sudo reboot
On a PC
Install Debian
Boot from the Debian installer ISO and make the following choices.
- In disk layout, use the whole disk but change the main partition from EXT4 to BTRFS (for resiliency)
- In software selection, deselect desktop options and choose only SSH and common utilities
After installing, add sudo and allow the user you created during install to use it without prompt. (as per Athnias docs)
# Become root
apt install sudo
adduser SOMEBODY sudo
echo "SOMEBODY ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/SOMEBODY
chmod 0440 /etc/sudoers.d/SOMEBODY
Configure WiFi
Use the newer iwd service for better handling of outages. It expects resolved for DNS.
sudo apt install iwd systemd-resolved
sudo systemctl enable --now iwd systemd-resolved
Set iwd to handle DHCP for WiFi. This is more reliable for outage recovery.
sed -i 's/^#\s*EnableNet.*/EnableNetworkConfiguration=true/' /etc/iwd/main.conf
Tell iwd which WiFi network to join. It will connect as soon as you save the config.
# Generate a preshared key from the SSID and Passphrase
python3 -c 'import hashlib; print(hashlib.pbkdf2_hmac("sha1", b"Your_Passphrase", b"Your_SSID", 4096, 32).hex())'
sudo vi /var/lib/iwd/Your_SSID.psk
# Add this section if it's a hidden SSID
[Settings]
Hidden=true
[Security]
PreSharedKey=paste_your_python_output_hash_here
Harden the System
Let’s make the PC more resilient to power loss and hangs. Using BTRFS helps a lot, but we can also configure the BIOS, update the kernel settings and use a watchdog timer.
Turn Back On
Enter the BIOS and under power settings, configure to power-on on power recovery.
Reboot On Panic
Configure the system to reboot instead of hang on a kernel panic.
sudo vi /etc/sysctl.d/99-panic-reboot.conf
kernel.panic = 10
kernel.panic_on_oops = 1
Handle Failed Boots
Change GRUB to handle failed boots better.
echo "GRUB_RECORDFAIL_TIMEOUT=2" | sudo tee -a /etc/default/grub
sudo update-grub
Add the Watchdog Service
Your chipset may provide a watchdog timer that once engaged, will trigger a power-cycle if the operating system stops updating it.
ls -la /dev/watchdog*
If you have any devices listed, you can install and configure the Watchdog service.
sudo apt install watchdog
sudo systemctl stop watchdog.service
# Load the module early in the boot
echo "iTCO_wdt" | sudo tee /etc/modules-load.d/watchdog.conf
sudo vi /etc/watchdog.conf
Add these to the bottom
# Tell the daemon to talk to your Dell's hardware chip
watchdog-device = /dev/watchdog
# Send a heartbeat to the hardware chip every 10 seconds
interval = 10
# Force a hardware reset if the system remains frozen for 60 seconds
watchdog-timeout = 60
# Test that you can allocate memory
allocatable-memory = 1
sudo systemctl start watchdog.service
Enable automatic updates and enable reboots
You normally want to apply security automatically, and control updates to the rest. If you don’t have a good structure you can of course apply all, as this config exemplifies.
sudo apt -y install unattended-upgrades
sudo tee /etc/apt/apt.conf.d/52unattended-upgrades-local > /dev/null <<'EOF'
Unattended-Upgrade::Origins-Pattern {
"origin=Debian";
};
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "02:00";
Unattended-Upgrade::Allow-APT-Mark-Fallback "true";
EOF
sudo systemctl restart unattended-upgrades.service
Installation
sudo apt install curl
# When prompted, install the latest but don't allow Anthias to manage the network
bash <(curl -sL https://www.screenly.io/install-ose.sh)
You can add a regular update by dropping a cronjob for the Anthias update script.
sudo tee /etc/cron.d/anthias-update > /dev/null <<'EOF'
# Anthias weekly update
0 3 * * 0 root /home/SOMEBODY/screenly/bin/run_upgrade.sh
EOF
Operation
Adding Content
Navigate to the Web UI at the IP address of the device. You may wish to enter the settings and add authentication and change the device name.
You may add common graphic types, mp4, web and youtube links. It will let you know if it fails to download the youtube video. Some heavy web pages fail to render correctly, but most do.
Images must be sized to for the screen. In most cases this is 1080. Larger images are scaled down, but smaller images are not scaled up. For example, PowerPoint is often used to create slides, but it exports at 720. On a 1080 screen creates black boarders. You can change the resolution on the Pi with rasp-config or add a registry key to Windows to change PowerPoint’s output size.
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\PowerPoint\Options]
"ExportBitmapResolution"=dword:00000096
Schedule the Screen
You may want to turn off the display during non-operation hours. The vcgencmd command can turn off video output and some displays will choose to enter power-savings mode. Some displays misbehave or ignore the command, so testing is warranted.
Note: This is only for the Raspberry Pi. Most PCs lack the CEC interface needed without a dedicated add-on.
sudo tee /etc/cron.d/screenpower << EOF
# m h dom mon dow usercommand
# Turn monitor on
30 7 * * 1-5 root /usr/bin/vcgencmd display_power 1
# Turn monitor off
30 19 * * 1-5 root /usr/bin/vcgencmd display_power 0
# Weekly Reboot just in case
0 7 * * 1 root /sbin/shutdown -r +10 "Monday reboot in 10 minutes"
EOF
Troubleshooting
YouTube Fail
You may find you must download the video manually and then upload to Anthias. Use the utility yt-dlp to list and then download the mp4 version of a video
yt-dlp --list-formats https://www.youtube.com/watch?v=YE7VzlLtp-4
yt-dlp --format 22 https://www.youtube.com/watch?v=YE7VzlLtp-4
WiFi Disconnect
WiFi can go up and down, and some variants of the OS do not automatically reconnect. You way want to add the following script to keep connected. This is mostly for the Pi as iwd is fault tolerant.
sudo touch /usr/local/bin/checkwifi
sudo chmod +x /usr/local/bin/checkwifi
sudo vim.tiny /usr/local/bin/checkwifi
#!/bin/bash
# Exit if WiFi isn't configured
grep -q ssid /etc/wpa_supplicant/wpa_supplicant.conf || exit
# In the case of multiple gateways (when connected to wired and wireless)
# the `grep -m 1` will exit on the first match, presumably the lowest metric
GATEWAY=$(ip route list | grep -m 1 default | awk '{print $3}')
ping -c4 $GATEWAY > /dev/null
if [ $? != 0 ]
then
logger checkwifi fail `date`
service wpa_supplicant restart
service dhcpcd restart
else
logger checkwifi success `date`
fi
sudo tee /etc/cron.d/checkwifi << EOF
# Check WiFi connection
*/5 * * * * /usr/bin/sudo -H /usr/local/bin/checkwifi >> /dev/null 2>&1"
EOF
Hidden WiFi
If you didn’t set up WiFi during imaging, you can use raspi-config after boot, but you must add a line if it’s a hidden network, and reboot.
sudo sed -i '/psk/a\ scan_ssid=1' /etc/wpa_supplicant/wpa_supplicant.conf
Splash Screen
You may want to turn this off or adjust it.
# You can turn off the splash screen in the GUI or in the .conf
sed -i 's/show_splash =.*/show_splash = off/' /home/pi/.screenly/screenly.conf
# Or you can correct it in the docker file
vi ./screenly/docker-compose.yml
White Screen or Hung
Anthias works best when the graphics are the correct size. It will attempt to display images that are too large, but this flashes a white screen and eventually hangs the box (at least in the current version). Not all users get the hang of sizing things correctly, so if you have issues, try this script.
#!/bin/bash
# If this device isn't running signage, exit
[ -d /home/pi/screenly_assets ] || { echo "No screenly image asset directory, exiting"; exit 1; }
# Check that mediainfo and imagemagick convert are available
command -v mediainfo || { echo "mediainfo command not available, exiting"; exit 1; }
command -v convert || { echo "imagemagick convert not available, exiting"; exit 1; }
cd /home/pi/screenly_assets
for FILE in *.png *.jpe *.gif
do
# if the file doesn't exist, skip this iteration
[ -f $FILE ] || continue
# Use mediainfo to get the dimensions at it's much faster than imagemagick
read -r NAME WIDTH HEIGHT <<<$(echo -n "$FILE ";mediainfo --Inform="Image;%Width% %Height%" $FILE)
# if it's too big, use imagemagick's convert. (the mogify command doesn't resize reliably)
if [ "$WIDTH" -gt "1920" ] || [ "$HEIGHT" -gt "1080" ]
then
echo $FILE $WIDTH x $HEIGHT
convert $FILE -resize 1920x1080 -gravity center $FILE
fi
done
No Video After Power Outage
If the display is off when you boot the pi, it may decide there is no monitor. When someone does turn on the display, there is no output. Enable hdmi_force_hotplug in the `/boot/config.txt`` to avoid this problem, and specify the group and mode to 1080 and 30hz.
sed -i 's/.*hdmi_force_hotplug.*/hdmi_force_hotplug=1/' /boot/config.txt
sed -i 's/.*hdmi_group=.*/hdmi_group=2/' /boot/config.txt
sed -i 's/.*hdmi_mode=.*/hdmi_mode=81/' /boot/config.txt
1.1 - Anthias Deployment
If you do regular deployments you can create an image. A reasonable approach is to:
- Shrink the last partition
- Zero fill the remaining free space
- Find the end of the last partition
- DD that to a file
- Use raspi-config to resize after deploying
Or you can use PiShrink to script all that.
Installation
wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh
chmod +x pishrink.sh
sudo mv pishrink.sh /usr/local/bin
Operation
# Capture and shrink the image
sudo dd if=/dev/mmcblk0 of=anthias-raw.img bs=1M
sudo pishrink.sh anthias-raw.img anthias.img
# Copy to a new card
sudo dd if=anthias.img of=/dev/mmcblk0 bs=1M
If you need to modify the image after creating it you can mount it via loop-back.
sudo losetup --find --partscan anthias.img
sudo mount /dev/loop0p2 /mnt/
# After you've made changes
sudo umount /mnt
sudo losetup --detach-all
Manual Steps
If you have access to a graphical desktop environment, use GParted. It will resize the filesystem and partitions for you quite easily.
# Mount the image via loopback and open it with GParted
sudo losetup --find --partscan anthias-raw.img
# Grab the right side of the last partition with your mouse and
# drag it as far to the left as you can, apply and exit
sudo gparted /dev/loop0
Now you need to find the last sector and truncate the file after that location. Since the truncate utility operates on bytes, you convert sectors to bytes with multiplication.
# Find the End of the last partition. In the below example, it's Sector *9812664*
$ sudo fdisk -lu /dev/loop0
Units: sectors of 1 * 512 = 512 bytes
Device Boot Start End Sectors Size Id Type
/dev/loop0p1 8192 532479 524288 256M c W95 FAT32 (LBA)
/dev/loop0p2 532480 9812664 9280185 4.4G 83 Linux
sudo losetup --detach-all
sudo truncate --size=$[(9812664+1)*512] anthias-raw.img
Very Manual Steps
If you don’t have a GUI, you can do it with a combination of commands.
# Mount the image via loopback
sudo losetup --find --partscan anthias-raw.img
# Check and resize the file system
sudo e2fsck -f /dev/loop0p2
sudo resize2fs -M /dev/loop0p2
... The filesystem on /dev/loop0p2 is now 1149741 (4k) blocks long
# Now you can find the end of the resized filesystem by:
# Finding the number of sectors.
# Bytes = Num of blocks * block size
# Number of sectors = Bytes / sector size
echo $[(1149741*4096)/512]
# Finding the start sector (532480 in the example below)
sudo fdisk -lu /dev/loop0
Device Boot Start End Sectors Size Id Type
/dev/loop0p1 8192 532479 524288 256M c W95 FAT32 (LBA)
/dev/loop0p2 532480 31116287 30583808 14.6G 83 Linux
# Adding the number of sectors to the start sector. Add 1 because you want to end AFTER the end sector
echo $[532480 + 9197928 + 1]
# And resize the part to that end sector (ignore the warnings)
sudo parted resizepart 2 9730409
Great! Now you can follow the remainder of the GParted steps to find the new last sector and truncate the file.
Extra Credit
It’s handy to compress the image. xz is pretty good for this
xz anthias-raw.img
xzcat anthias-raw.img | sudo dd of=/dev/mmcblk0
In these procedures, we make a copy of the SD card before we do anything. Another strategy is to resize the SD card directly, and then use dd and read in X number of sectors rather than read it all in and then truncate it. A bit faster, if a but less recoverable from in the event of a mistake.
1.2 - API
The API docs on the web refer to screenly. Anthias uses an older API. However, you can access the API docs for the version your working with at
http://sign.your.domain/api/docs/
You’ll have to correct the swagger form with correct URL, but after that you can see what you’re working with.