Changes

8,149 bytes added ,  12:09, 18 February 2020
added webpage code
Line 36: Line 36:  
   sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' /home/pi/.config/chromium/Default/Preferences
 
   sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' /home/pi/.config/chromium/Default/Preferences
 
    
 
    
   /usr/bin/chromium-browser --noerrdialogs --disable-infobars --kiosk https://www.bio.fsu.edu/grad/kiosk/unit1.html
+
   /usr/bin/chromium-browser --noerrdialogs --disable-infobars --kiosk https://www.bio.fsu.edu/grad/kiosk/kiosk.html?kiosk=Unit%20I
   −
Create a system daemon service file <code>kiosk.service</code>, and copy it to <code>/lib/systemd/system/kiosk.service</code> (don't forget to use <code>sudo</code> to do the copying).
+
This script:
 +
 +
* disables the screen saver (the xset commands)
 +
 
 +
* hides the mouse (unclutter)
 +
 
 +
* deletes any chromium crash notice settings (the sed commands)
 +
 
 +
* Points the pi to the kiosk.html webpage, with the physical location of the kiosk as a query parameter, eg <code>https://www.bio.fsu.edu/grad/kiosk/kiosk.html?kiosk=King%20Atrium</code>
 +
 
 +
 
 +
 
 +
5. Create a system daemon service file <code>kiosk.service</code>, and copy it to <code>/lib/systemd/system/kiosk.service</code> (don't forget to use <code>sudo</code> to do the copying).
      Line 70: Line 82:       −
5. Reboot the Pi.  Note: use <code>sudo reboot</code> to restart the pi from the command line.
+
6. Reboot the Pi.  Note: use <code>sudo reboot</code> to restart the pi from the command line.
      Line 123: Line 135:  
* Columns C-?: "<kiosk name>" -- The query key for each of your kiosks, eg. "Lobby", "Dept Office", etc. The cells in these columns indicate the number of seconds used to display each slide on that particular kiosk. Enter zero seconds to hide the slide from that particular kiosk.
 
* Columns C-?: "<kiosk name>" -- The query key for each of your kiosks, eg. "Lobby", "Dept Office", etc. The cells in these columns indicate the number of seconds used to display each slide on that particular kiosk. Enter zero seconds to hide the slide from that particular kiosk.
    +
Get the "Publish to Web" key for this Google Sheet via "File" -> "Publish to the Web" -> "Publish" button. This key (which is NOT the same as the shared link for editing) will be used by the website php script to get access to the sheet contents.
    +
==Kiosk Webpage==
 +
 +
1. On the public website, install the following <code>kiosk_slides.php</code> file
 +
 +
<?php
 +
header("Content-type: text/csv");
 +
 +
readfile('<nowiki>https://docs.google.com/spreadsheets/d/e/</nowiki><google_sheet_key>/pub?gid=0&single=true&output=csv');
 +
 +
where <code><google_sheet_key></code> is the "Publish to Web" key for the google sheet listing the slides and display times (keep this a secret if there are shared links to the presentations in this sheet).
   −
==Kiosk Webpage==
        −
Point the pi to the kiosk.html webpage, with its location as a query parameter, eg <code>https://www.bio.fsu.edu/grad/kiosk/kiosk.html?kiosk=King%20Atrium</code>
+
2. In the same directory as <code>kiosk_slides.php</code>, create the <code>kiosk.html</code> page. Each Pi kiosk will look at this page, which cycles through the presentations as specified in the google sheet. Note that there is nothing private (ie no secrets) in the webpage itself. Even accessing the <code>kiosk_slides.php</code> file will only display the google sheet contents with the public presenation keys (but not any shared editable links).
 +
 +
<nowiki>
 +
<!DOCTYPE html>
 +
<html lang="en">
 +
      <head>
 +
 +
          <meta http-equiv="refresh" content="3600" /><!-- force refresh every 60 minutes, in case of changes to this page on the server-->
 +
          <meta charset="utf-8">
 +
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
 +
          <meta name="description" content="">
 +
          <meta name="author" content="">
 +
          <title>Pi Kiosk</title>
 +
   
 +
          <script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
 +
 +
          <!-- integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8="  -->
 +
 +
      </head>
 +
 +
      <body>
 +
 +
          <style>
 +
 +
                html,body {
 +
                    padding: 0;
 +
                    margin: 0;
 +
                }
 +
                iframe {
 +
                    display: block;
 +
                    width: 1980px;
 +
                    height: 1114px;
 +
                    position:relative;
 +
                    left:-28px;
 +
                    top:-4px;
 +
                }
 +
 +
                .slide {
 +
                    width:1920px;
 +
                    height:1080px;
 +
                    overflow:hidden;
 +
                    border:solid 1px gray;
 +
                }
 +
 +
          </style>
 +
 +
          <div id="slide0" class="slide">
 +
                <div style="text-align:center;margin-top:300px;"><h1>Announcements</h1></div>
 +
          </div>
 +
          <div id="slide1" class="slide"></div>
 +
          <div id="slide2" class="slide"></div>
 +
 +
          <div id="slide3" class="slide"></div>
 +
          <div id="slide4" class="slide"></div>
 +
          <div id="slide5" class="slide"></div>
 +
 +
          <div id="slide6" class="slide"></div>
 +
          <div id="slide7" class="slide"></div>
 +
          <div id="slide8" class="slide"></div>
 +
 +
          <div id="slide9" class="slide"></div>
 +
          <div id="slide10" class="slide"></div>
 +
          <div id="slide11" class="slide"></div>
 +
 +
 +
          <div id="slide12" class="slide"></div>
 +
          <div id="slide13" class="slide"></div>
 +
          <div id="slide14" class="slide"></div>
 +
 +
          <script>
 +
 +
                /*
 +
                    look up list of google presentations from a google sheet (retrieved by kiosk_slides.php)
 +
                    filter the list by our kioskName, taken from ?kiosk=<kioskName> parameter
 +
                    construct iframe based on "publish to web" url of the google presentation
 +
                    assign each slide iframe to one of the predefined slide divs (#slide0-#slide<max_slides>)
 +
                    based on display time in the google sheet, show then hide each slide div in sequence
 +
     
 +
                */
 +
 +
 +
                function getParameterByName(name, url) {
 +
                    if (!url) {
 +
                        url = window.location.href;
 +
                    }
 +
                    name = name.replace(/[\[\]]/g, "\\$&");
 +
                    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
 +
                        results = regex.exec(url);
 +
                    if (!results) return null;
 +
                    if (!results[2]) return '';
 +
                    return decodeURIComponent(results[2].replace(/\+/g, " "));
 +
                }
 +
 +
                function ParseGradPhileFormQuery(query) {
 +
 +
                    // note that fsuid, eval_year, eval_term, default_eval_year, default_eval_term, qr_abbr and auth are globals
 +
 +
                    var kiosk_param = getParameterByName("kiosk", query);
 +
 +
                    if (kiosk_param) {
 +
                        kioskName = kiosk_param;
 +
                    }
 +
 +
 +
                }
 +
 +
 +
                var kioskName = "_none";
 +
                const max_slides = 15;
 +
                var slides = [];
 +
 +
                // get kioskName from query
 +
                ParseGradPhileFormQuery(window.location.search);
 +
 +
                jQuery.get("kiosk_slides.php", function(slides_csv) {
 +
 +
                    var rows = slides_csv.split("\n");
 +
 +
                    var my_column_index = rows[0].split(",").indexOf(kioskName)
 +
 +
                    if (-1 == my_column_index) {
 +
                        // unknown kiosk
 +
                        return;
 +
                    }
 +
                    // remove header row
 +
                    rows = rows.slice(1);
 +
 +
                    rows.forEach(function(r) {
 +
                        var cells = r.split(",");
 +
                        var display_time = parseInt(cells[my_column_index], 10);
 +
 +
                        if (0 != display_time) {
 +
                            slides.push({
 +
                                // url to display first slide of a google presentation
 +
                                'url': "https://docs.google.com/presentation/d/e/" + cells[1] + "/embed?start=true&loop=false&delayms=60000",
 +
                                'display_time': display_time * 1000
 +
 +
                            })
 +
                        }
 +
 +
                    }); // next rows
 +
 +
                    if (slides.length == 0) {
 +
                        // no slides allocated to this kiosk
 +
                        return;
 +
                    }
 +
 +
                    // we only have max_slides number of divs allocated for slides,
 +
                    // so discard the excess slides
 +
                    while (max_slides < slides.length) {
 +
                        slides.pop();
 +
                    }
 +
 +
                    var current_slide = 0;
 +
 +
                    // initialize  content of slides
 +
                    // TODO: put in status check before switching to this url
 +
                    for (var i = 0; i < slides.length; i++) {
 +
                        // iframe to display slide from google presentation
 +
                        // width="2016" height="1134"
 +
                        $("#slide" + i).html('<iframe src="' + slides[i].url + '" frameborder="0"  allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>');
 +
                    }
 +
 +
                    // cycle through the slides, delaying for the associated display_time before going to next slide
 +
                    function updateSlide() {
 +
                        current_slide = (current_slide + 1) % slides.length;
 +
 +
                        console.log("curent_slide: " + current_slide + " display_time: " + slides[current_slide].display_time);
 +
 +
                        $(".slide").hide();
 +
                        $("#slide" + current_slide).show();
 +
                        setTimeout(updateSlide, slides[current_slide].display_time);
 +
                    }
 +
 +
                    // start the display cycle
 +
                    updateSlide();
 +
 +
 +
                }); // get php callback
 +
 +
          </script>
 +
 +
      </body>
 +
</html>
 +
</nowiki>