Although we're still using this in production at SAPO, we're moving to an Android-based solution due to the lack of accelerated web page rendering on the Raspberry Pi.
As such, we don't plan on developing this further except for bugfixes and "tactical" enhancements, since it's still very easy to use and deploy for relatively static displays.
In an attempt to go for an even smaller footprint, we've switched from Raspbian to Moebius 1.1.1.
Moebius is significantly smaller (it's aimed at embedded deployments) and assumes no desktop environment is installed (it doesn't even ship with X11), so it makes a lot more sense for digital signage.
-
Clone the repo (no surprises here)
-
Copy
etc/config.json.dist
toetc/config.json
, making any required changes -
Run it:
python app.py
-
Go to http://localhost:8000 - or, if you've enabled debugging, http://localhost:8000/debug to see a list of all active local URLs
This code was developed internally at SAPO for running the Codebits 2012 signage atop Raspberry Pi devices, and quickly evolved from a guerrilla solution into a full-blown client-server app.
This is version 2.0 - version 1.0 was used internally at SAPO since October 2012, and 2.0 was deployed mid-2013 before we switched to a simpler video-only solution based on MEO Kanal also using Raspberry Pi hardware.
Here's a brief summary of the original requirements and their impact on solution design:
-
clients were not supposed to store any content locally, except a handful of templates to render baseline content. The idea here is that you'll be running this against a set of web services or a full web server that will render pages to the devices.
-
clients therefore run "playlists", i.e. JSON files listing URLs to render locally. Playlists can contain URLs to HTML content of various descriptions or to video files, and support time intervals and simple "random" groups.
-
the server can push new content to the client in near-realtime (depending on content type), including whole new playlists.
-
communication between client and server was downgraded from websockets to an HTTP(S) polling mechanism to better cope with firewalls, NAT, timeouts, etc.
-
accordingly, the client runs its own HTTP server to allow for disconnected operation (if the central server goes down, we'll always be able to display something, and cache some information in the meantime)
-
we had no idea what displays would be available, so we settled on 1280x720 as default and 1024x768 as a fallback. 1920x1080 is possible, but you'll be stretching the hardware to the limits when rendering HTML locally so it's not advisable (plus most people can't tell the difference when you're projecting or viewing from afar).
-
resolution is explicitely set on views to make it easier to size and position both HTML and SVG elements (the Codebits layouts were extensively based on inline SVG, with some dimensions computed inside views).
-
since we had to deal with both X and
omxplayer
, resolution is assumed to be set in/boot/config.txt
as well as usingfbset
(and even then we make sureuzbl
is launched with thegeometry
option to clip the rendering surface)
The following steps assume you're deploying on the Raspberry Pi as the root
user and starting from a clean Moebius install.
-
Bring your image up to date and install required packages (some of these are only required for development and testing, but they add little to the overall footprint):
sudo apt-get update sudo apt-get dist-upgrade sudo apt-get install ack-grep bash-completion chkconfig denyhosts \ fbi git-core htop ntpdate omxplayer python-pygments tmux \ ttf-mscorefonts-installer unclutter uzbl vim watchdog x11-xserver-utils \ xinit xserver-xorg-video-fbturbo
-
Edit
/boot/config.txt
(moebius.config
will take you there if you chooseInternals
) to set the framebuffer to 1280x720 by uncommenting these two lines:# uncomment to force a console size. By default it will be display's size minus # overscan. framebuffer_width=1280 framebuffer_height=720
This will undo any automatic detection done during the boot process and significantly boost browser performance (full HD is nice, but it is also very slow without proper GPU support).
-
Still in
/boot/config.txt
, set the GPU memory to 64MB to allow GPU video decoding to work:# Set variable gpu_mem gpu_mem=64
-
Change
/boot/cmdline.txt
to disable the boot logo, move the boot VT totty9
, disable the cursor and automatically blank the console:dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty9 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait logo.nologo loglevel=3 quiet vt.global_cursor_default=0 vt.handoff=7 consoleblank=1
-
Clone the repo to
/root
(no surprises here):cd /root git clone https://github.com/sapo/digital-signage-client.git cd digital-signage-client
-
Copy
etc/config.json.dist
toetc/config.json
, making any required changes -
Run
install/deploy.sh
to setup the configuration files and startup scripts -
RECOMMENDED: Check the startup scripts and add corresponding video and image files for your splash screen (if any).
-
RECOMMENDED: use Hexxeh's rpi-update to upgrade to the latest firmware and kernel
-
RECOMMENDED: run
sudo dpkg-reconfigure tzdata
and choose your timezone -
RECOMMENDED: enable the Raspberry Pi's hardware watchdog so that it will automatically reset the board upon freezing:
sudo modprobe bcm2708_wdog sudo sh -c "echo 'bcm2708_wdog' >> /etc/modules" sudo apt-get install watchdog chkconfig sudo sh -c "echo 'watchdog-device = /dev/watchdog' >> /etc/watchdog.conf" sudo chkconfig watchdog on sudo /etc/init.d/watchdog restart
-
Add the following lines to
/etc/default/rcS
to disable swap and enabletmpfs
RAMTMP=yes NOSWAP=yes
-
Add the following lines to
/etc/fstab
:tmpfs /tmp tmpfs nodev,nosuid,size=16M,mode=1777 0 0 tmpfs /var/log tmpfs nodev,nosuid,size=16M,mode=1777 0 0
-
reboot
The startup scripts assume you have four media assets in /root
:
boot.mov
is a 20s long, 12fps boot animationdown.mov
is a 20s long, 12fps shutdown animationready.mov
is an arbitrary "welcome" videoblank.png
is a 1280x720 PNG that acts as an "intermission" image
The 12fps framerate was chosen beause it yields <10MB files at 1280x720 resolution, and you can change the startup scripts to use static images instead.
Moebius differs from Raspbian in not providing a pi
user. Given that a signage client does not provide any services (even though it is physically exposed and thus essentially compromisable from the moment you deploy it), running everything as root
doesn't pose any significant extra risks and significantly simplifies matters.
However, the following are basic security precautions you should follow:
-
RECOMMENDED: change the
root
user password (it'sraspi
in the default Moebius setup, in case you're wondering). -
RECOMMENDED: Disable
sshd
password authentication for the root login indropbear
. -
RECOMMENDED: Set up SSH access and add your public key to
/home/root/.ssh/authorized_keys
for remote maintenance. -
OPTIONAL: change
sshd
to run on another port (even withdenyhosts
, it makes sense for some deployments) or block port 22 access from everywhere but the address(es) you'll be managing these from.
Due to popular demand, I have to state that there are none publicly available yet. Still, if there were, they'd be sized for a 4GB SD card (purely out of cost considerations) and could be created by doing something like:
# a 4GB image has 3904897024 bytes, and we can write it via rdisk devices faster on OS X
sudo dd of=/dev/rdisk2 if=~/Desktop/signage.raw.img bs=4m count=931
Note that the app has built-in support for diagnostics logging (which is kept in RAM and can be sent back to the server if so desired). This is set up as the ram
logger in config.json.dist
.
This can be very helpful in debugging the system remotely, but will not capture tracebacks as is (pull requests towards contributing that functionality are welcome).
The original blog post, wherein you'll find some screenshots of the server.
A few photos of this in action: 1, 2, 3, 4, 5, 6.
SAPO has a strong Open-Source culture and believes in placing credit where credit is due.
- This entire codebase is MIT licensed, and therefore free to use as you please for commercial or non-commercial purposes.
- Sample GIF images are CC Licensed from Wikimedia Commons.
- The Roboto Font is bundled as a convenience (and because it's eminently suited to digital signage) under the Apache License.
- The SAPO logo is a registered trademark of Portugal Telecom. It is included as a default part of this software's branding screen and cannot be reused for any other purpose.
As common courtesy, we ask you to preserve (and contribute to) source code comments, attributions and this README
if you decide to fork, deploy or otherwise redistribute this software.