Learn how you can Unlock Limitless Customer Lifetime Value with CleverTap’s All-in-One Customer Engagement Platform.
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.
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.
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.
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:~#
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
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
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"
}
}
}
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;
}
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 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
By default, X server can only be started by root. To change this behavior, edit /etc/X11/Xwrapper.config
and set allowed_users=anybody
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 "$@"
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
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.
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
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.