Blog Engineering

Using Raspberry Pi to build a commercial grade wall information dashboard

Francis Pereira Francis Pereira, a founding member at CleverTap, leads the security and infrastructure engineering teams, focusing on infrastructure automation, security, scalability, and finops.
Using Raspberry Pi to build a commercial grade wall information dashboard

We recently built wall-information display screens for our offices to show interesting metrics of our production environment along with some business numbers we care about. While looking up how people do this kind of stuff with a Raspberry Pi (Rpi), I came across most folks using a display manager, like LightDM, and user auto log-in at boot to trigger the user’s session.
It’s not a safe thing to do.
You don’t want a user logged-in on a terminal at remote locations that you don’t have physical control over. Most of the articles also encourage the use of Chromium from untrusted sources because it’s no longer packaged by Debian for ARM.
This post documents using Iceweasel, a fork of Mozilla Firefox, as a browser and X server without having to use a display manager or a user auto log-in, to build a robust wall display dashboard.
Yes, Iceweasel works in full screen mode without having to use an add-on.

Prerequisites

  • Latest Raspbian lite running on your Pi.
  • Working network connectivity – WiFi or wired
  • Hostname and timezone setup
  • A display that supports HDMI input and 1920×1080 (HD) resolution

Configuring your display to show up in portrait mode

In most circumstances you need the display to be oriented in portrait mode instead of landscape – like the ones at the Airport that display flight information.
To change the orientation, set display_rotate=1 in /boot/config.txt and restart. Almost magically, the Pi begins to drive the connected display in portrait mode. If your display is up-side-down, set display_rotate=3 and reboot again.

HDMI always with predefined resolution.

If your display doesn’t come up before the Pi starts booting, it doesn’t know your display resolution. This is most often the case when both the Pi and the display are connected to the same power source. The instance you power up, the Pi begins to boot but most TV screens go into standby mode and wait for the user to power up by using the remote. We want to ensure that regardless of the start-up order, our Pi always assumes the correct resolution. It just needs to work when deployed in the wild
Using the below mentioned steps, figure out your display’s preferred resolution


# Dump display's EDID info
root@display2:~# tvservice -d /tmp/edid_info
# Parse the info to get preferred and other supported modes
root@display2:~# edidparser /tmp/edid_info | grep 'preferred mode'
HDMI:EDID preferred mode remained as CEA (16) 1920x1080p @ 60 Hz with pixel clock 148 MHz

This connected display is reporting CEA (16) 1920x1080p @ 60 Hz where 16 is its preferred mode.
Based on this information, edit /boot/config.txt and set/uncomment the following parameters:


# Always force HDMI display over DVI
hdmi_group=2
# HDMI mode as reported by the display
hdmi_mode=16

Disconnect the display and reboot the Pi. Once it has booted, connect the HDMI display wire and voila! – the display comes to life with the correct resolution.

Create a user that runs X server and Iceweasel

We want a non admin user to run our X server and Iceweasel for us. Running the browser as root or pi is not a bright idea.
For the article, I am going to call the user screen


root@display2:~# adduser screen
Adding user `screen' ...
Adding new group `screen' (1002) ...
Adding new user `screen' (1002) with group `screen' ...
Creating home directory `/home/screen' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for screen
Enter the new value, or press ENTER for the default
Full Name []: Screen
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n] y
root@display2:~#

Install Iceweasel

To display our information in a web browser, we are going to use Iceweasel. It’s Mozilla Firefox rebranded for licensing purposes. Installation is straight forward. We are going to use packages available in the default repository.
No mucking around with packages from untrusted sources


root@display2:~# apt-get update; apt-get -y install iceweasel

Understanding Iceweasel profiles

Iceweasel stores user configuration details like bookmarks, add-ons, etc in a ~/.mozilla/firefox/ The directory is created if it doesn’t exist at browser launch. The contents of this directory are seed from /etc/iceweasel/profile/ This is interesting because we could put custom configuration into /etc/iceweasel/profile/ and it will always be included in newly created profile. In our use-case, we are going to use it set the browser to full-screen, remove horizontal and vertical scroll bars and set some interesting default behavior

Configuring Iceweasel to open in full-screen mode by default

To ensure that Iceweasel does not need human intervention to open in full-screen mode by default at startup, create a file named xulstore.json in /etc/iceweasel/profile/ with the below content. This file will automatically get copied over to a newly created profile


{
    "chrome://browser/content/browser.xul": {
        "navigator-toolbox": {
            "iconsize": "small"
        },
        "main-window": {
            "width": "1080",
            "height": "1900",
            "screenX": "0",
            "screenY": "0",
            "sizemode": "fullscreen"
        }
    }
}

Hide horizontal and vertical scroll bars

With Iceweasel configured to open full screen by default, let’s make the horizontal and vertical scroll bars disappear. This ensures that the browser fill up 100% of screen real-estate. Create a file named userChrome.css in /etc/iceweasel/profile/chrome and populate it with below mentioned content


@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
/* Hide the horizontal scroll bar */
#content browser {
margin-right: -18px !important;
overflow-y: scroll;
overflow-x: hidden;
}
/* Hide the vertical scroll bar */
#content browser {
margin-bottom: -18px !important;
overflow-y: scroll;
overflow-x: hidden;
}
/* if you look carefully, there is a little border on the left and top. Make it disappear */
#content browser {
margin-left: -2px !important;
}
#content browser {
margin-top: -5px !important;
}

Setting Iceweasel’s default user specific configuration

Let’s get Iceweasel to allow JavaScript execution for an infinite amount of time. Since we are going to open a trusted URL, this should be ok. It’s better than having a dialog box in the middle of the screen that says – ‘A script on this page is causing Mozilla to run slowly’. That’s a pesky dialog box and needs a mouse connected to the Pi to dismiss it. To preconfigure this create a file named user.js in /etc/iceweasel/profile/ and populate it with the line below


user_pref("dom.max_script_run_time", 0);

While we are working with user.js, if you are using basic HTTP authentication to open a URL in Iceweasel, append this line, else a dialog box saying – ‘You are about to log in to the site “example.com” with the username “francis”, but the website does not require authentication. This may be an attempt to trick you.’ will show up


user_pref("network.http.phishy-userpass-length", 100);

At this point we have all the necessary configuration required to run Iceweasel full-screen. When we start it later, all this configuration will be a part of our profile that’s automatically generated

X server and xinit

X server handles all access to the graphics cards, display screens and input devices. We need an instance of this to run Iceweasel.
This section installs and configures the X server. Run the below mentioned commands to install X server


root@display2:~# apt-get update; apt-get -y install Xorg xinit

Allowing X server to be started by all users

By default, X server can only be started by root. To change this behavior, edit /etc/X11/Xwrapper.config and set allowed_users=anybody

Configuring X server start-up parameters and disable screen blanking

X server uses ~/.xserverrc at startup. Create /home/screen/.xserverrc and add the below content. It disables power management at startup in addition to starting an X server. This ensures that our display never goes to sleep and is always available


#!/bin/sh
# Start an X server with power management disabled so that the screen never goes blank
exec /usr/bin/X -s 0 -dpms -nolisten tcp "$@"

Configure post X server start behaviour

X server users ~/.xsession at start-up to launch applications. In our case, we need Iceweasel to start. Create /home/screen/.xsession and add the below content


#!/bin/sh
# This tells X server to start /usr/bin/iceweasel at startup
exec /usr/bin/iceweasel https://google.com

Putting it all together using systemd

Now that we have Iceweasel and X server configured, all we need is some way of starting and managing it. A systemd service fits the bill. Create /etc/systemd/system/information-display.service with content mentioned below


[Unit]
Description=Xserver and Iceweasel
After=network-online.target
Before=multi-user.target
DefaultDependencies=no
[Service]
User=screen
# Yes, I want to delete the profile so that a new one gets created every time the service starts.
ExecStartPre=/bin/rm -rf /home/screen/.mozilla
ExecStart=/usr/bin/startx
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target

Enable this service by running


root@display2:/tmp# systemctl enable information-display

Finally, start it


root@display2:/tmp# systemctl start information-display

X server and Iceweasel should now be running on your display with google.com opened in full screen mode. Replace the URL in /home/screen/.xsession with your own and restart the service.

Debugging

If things didn’t go as planed and a browser is not staring you in the face, take a look at the following
* /home/screen/.xsession-errors
* root@display2:/tmp# journalctl -u information-display

Managing power consumption

You want to turn off the displays when no one is around. We use tvservice -o to power off the HDMI signal in the night. This make the display think that there is no signal and automatically switched to standby mode after a few minutes. Most TV screens (not the cheap ass Micromax) can be configured to do this
To wake up the display, start the HDMI signal again (tvservice -p) and use HDMI CEC commands to get the TV out of standby mode. If you have monitor connected, it should come to life on sensing a HDMI signal.

Further reading

Last updated on March 29, 2024