A dashboard viewer with remote control

January 29, 2018

As a DevOps, I love dashboards for Jenkins, my Azure platform status or some custom figures about running softwares. In an openspace, it is usrfull to have big screens showing those dashboards. Let's build a solution with a raspberry pi and a small custom software to control it.

Hardware

System

Installation

The image is based on Raspbian Lite. Why lite version ? Remember that I have a old and slow Raspberry Pi so running the minimal software stack is necessary. First, run a global update :


            $ sudo apt-get update
            $ sudo apt-get upgrade
        
Now installing 3 pieces of software we need : lxde, chromium and unclutter (hide the cursor)

            $ sudo apt-get install lxde chromium-browser unclutter
        

Automation

Previously, I recommanded installing lxde. Edit the file /home/pi/.config/lxsession/LXDE/autostart : remove the line :


            @xscreensaver -no-splash    
        
at the end of the file, add :

            @xset s off
            @xset -dpms
            @xset s noblank
            @unclutter
            @chromium-browser --noerrdialogs --kiosk --incognito https://status.status.io/
        
On boot, we do not want to have to log in manually. There is a simple way to do this :

            $ sudo raspi-config
        
go to "boot options", "Desktop / CLI", then "Desktop autologin"
Now try to reboot your pi and voila, status page is shown in fullscreen mode.

Custom software

My friend Thbkrkr wrote 2 years ago a fantastic Go program : https://github.com/thbkrkr/go-apish/
This program transforms a set of bash scripts into a REST API. Each script have to return a JSON result. Scripts called via POST method had the body given into the standard input. I use it for many projects on raspberry. It is the simpliest way for building REST API without programming.
All bash scripts in the current directory (or a directory given at startup) are callable under /api. A directory called "_static" can contains HTML/JS files, accessible with host:4242/s/.
Add this line to /home/pi/.config/lxsession/LXDE/autostart


            ./go-apish-arm --apiDir ./
        

POST dashboard URL

I created a regular file (/home/pi/dashboad-remote/page_url) which only contains the remote URL.


                #!/bin/bash -eu
                IN="$(cat /dev/stdin)"
                PAGE_URL=$(jq .page_url  <<< $IN | tr -d \")
                rm /home/pi/remote-dashboard/page_url
                echo $PAGE_URL > /home/pi/remote-dashboard/page_url
                echo ' { "page_url":  "'$PAGE_URL'" }'
        

Load chromium with the url

I replaced in /home/pi/.config/lxsession/LXDE/autostart the line launching chromium with a call to this script :


                #!/bin/bash -eu
                # inspired from https://www.raspberrypi.org/forums/viewtopic.php?t=163316
                # Run browser after boot to desktop
                export DISPLAY=:0.0
                /bin/sleep 3
                PAGE_URL=$(cat /home/pi/remote-dashboard/page_url)
                sudo -u pi chromium-browser --kiosk --incognito $PAGE_URL &
                # End of script
        

Reload Chromium


            #!/bin/bash -eu
            export DISPLAY=:0.0
            killall chromium-browser
            bash /home/pi/remote-dashboard/start_chromium.sh
            echo ' { "status":  "ok" }'
            # End of script
        

Simple webapp

I built this POC, just an HTML form with some JS using JQuery, no more.

                <body> 
                    <div class="row">
                        <div class="col-md-12">
                            <input type="text" id="page_url" /> 
                            <br /> 
                            <input type="button" onclick="changePage()" value="Change" /> 
                        </div> 
                        <div class="col-md-12">
                            <input type="button" onclick="reload()" value="Reload" /> 
                        </div> 
                        <div class="col-md-12"> 
                            <input type="button" onclick="reboot()" value="Reboot" /> 
                        </div> 
                    </div> 
                </body>                
        
This is the entire JS :

        function changePage() {
            page_url=$("#page_url").val();
            var settings = {
                "async": true,
                    "crossDomain": true,
                    "url": "/api/set",
                    "method": "POST",
                    "headers": {
                        "content-type": "application/json",
                        "cache-control": "no-cache",
                    },
                    "processData": false,
                    "data": "{\"page_url\":\"" + page_url + "\"}"
            }

            $.ajax(settings).done(function (response) {
                    console.log(response);
            });
        }
        function getPage() {
            $.get( "/api/status", function (data ){
                        $("#page_url").val(data.page_url);
                });
        }
        function reboot() {
                $.get( "/api/reboot", function (data ){
                });
        }
        function reload() {
                $.get( "/api/reload", function (data ){
                });
        }
        

API definition

Checkout the code at https://github.com/mathieupassenaud/remote_dashboard