Building a Raspberry Pi Message Board – Part 1

posted by

Part 1 of 2 on how to build a self-updating message board system, using WordPress, a TV and a Raspberry Pi.

The Raspberry Pi is a great piece of hardware which can be used to build many things – including a self-updating message board system that displays information across multiple screens in different locations.

This post series will show you how to build one such system, using WordPress, a TV screen and a Pi. This first post focuses on building the self-updating website, using WordPress as the content management system, while the second post will cover the use of the Pi.

Getting Started

There are plenty of tutorials out there detailing how WordPress themes are put together and how you can build your own, so I won’t focus on that side of things. Instead I’ll be showing you how you can get your theme to load posts from WordPress via AJAX automatically.

So let’s get started. Download WordPress and set it up on your webserver. Once done, create a new folder in “Themes” called “messageboard”. In this folder create a couple of files: index.php, style.css, and functions.php. These are the bare minimum files we will need.

index.php is where the HTML for the message board display will be, along with the JavaScript to load the posts via AJAX.

style.css contains the CSS used to style the HTML, as well as the theme name and description.

functions.php will hold some functions that allow WordPress to respond to our AJAX requests and return content for the message board.

create theme files

Building the message board screen

For the purposes of this tutorial we’re only going to make a very basic message board. We’ll have 4 panels displaying different posts depending on their categories.

index.php

Create 4 divs for the panels and link the CSS file in the header. For the css link we will need to get the theme directory because relative links won’t work. bloginfo(‘template_url’) can do this for us.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Message Board</title>

    <link rel="stylesheet" href="<?php bloginfo('template_url'); ?>/style.css">
  </head>

  <body>
    <div class="panel panel-1">
      <div class="posts">loading...</div>
    </div>
    <div class="panel panel-2">
      <div class="posts">loading...</div>
    </div>
    <div class="panel panel-3">
      <div class="posts">loading...</div>
    </div>
    <div class="panel panel-4">
      <div class="posts">loading...</div>
    </div>
  </body>
</html>

index.php

In the style.css add some basic styling for the panels. We’ll use percentages for a fluid design that fits any screen size.

* {
 box-sizing: border-box;
}
html, body {
 width: 100%;
 height: 100%;
 margin: 0;
 padding: 0;
 font-family: 'Helvetica', 'Segoe UI', sans-serif;
}
.panel {
 width: 45%;
 height: 40%;
 float: left;
 margin: 2.5%;
 padding: 2em;
 color: #FFF;
 overflow: hidden;
}
.panel-1 {
 background-color: #37BC9B;
}
.panel-2 {
 background-color: #E9573F;
}
.panel-3 {
 background-color: #3BAFDA;
}
.panel-4 {
 background-color: #F6BB42;
}

 

Loading posts via AJAX

To load the content to display in the frontend we will be making AJAX requests with jQuery to the backend. First we need to set up wordpress to return the posts we want when we request them. Then we need to build the JavaScript that will make the requests periodically and display the content in the panels.

functions.php

We can use the wp_ajax_ hook to run a function when we make AJAX requests to wordpress. This hook follows the format "wp_ajax_$action", where $action is the AJAX request’s 'action' property. We will create a "loadPanel" action and an associated function "loadPanelPosts()".
(You can read more about creating ajax hooks in the codex.)

add_action('wp_ajax_loadPanel', 'loadPanelPosts');         //for logged in users
add_action('wp_ajax_nopriv_loadPanel', 'loadPanelPosts');  //for public users

function loadPanelPosts() {
    //...
}

In the  "loadPanelPosts()" function we will be loading posts and returning them as a JSON string. We can’t just return the posts as we get them however, we need to apply html formatting to the post content to convert spaces and line breaks into their HTML equivalents.
Here is our final function:

function loadPanelPosts() {
    $response = [];

    //get the request parameters
    $category = isset($_GET['category']) ? $_GET['category'] : null;
    $max      = isset($_GET['max']) ? $_GET['max'] : 1;
 
    //store the panel the content is destined for
    $response['panel'] = isset($_GET['panel']) ? $_GET['panel'] : null;

    //load the posts, filtered as per the request
    $args = array(
        'cat' => $category,
        'orderby' => 'post_date',
        'order' => 'DESC',
        'numberposts' => $max,
        'posts_per_page' => $max
    );
    $allPosts = get_posts($args);

    $response['posts'] = [];
    foreach ($allPosts as $thisPost) {
        //Reformat the content to add in <p> tags etc
        $thisPost->post_content = apply_filters('the_content', $thisPost->post_content); 
        $response['posts'][] = $thisPost;
    }
 
    //return the response as json
    header( "Content-Type: application/json" );
    echo json_encode($response);
    exit;
}

index.php

We will use jQuery’s $.ajax() function to do AJAX requests to  /wp-admin/admin-ajax.php, the file that responds to AJAX requests and fires the hooks we set up in functions.php. First let’s download jQuery to the theme folder and include it in index.php just before the closing </body> tag.

Then let’s create a  getPosts() function that takes a  panel and a  category as its arguments, makes a GET request and then outputs the post content. We will be calling this function at a set interval for each of the 4 panels, passing in the panel element along with which post category the panel will display.

...
 <script src="<?php bloginfo('template_url'); ?>/jquery-2.1.3.min.js"></script>
 <script>
 function loadPosts(panel, category) {
     $.ajax({
         url:"/_wordpress/wp-admin/admin-ajax.php",
         data:"action=loadPanel&max=10&category="+category,
         type:"GET",
         cache:false,
         dataType: "json",
         context:this,
         success: function(JSON) {
             var totalPosts = JSON.posts.length;
             var wrapperWidth = (100*totalPosts) + "%";
             var postWidth = (100/totalPosts) + "%";
             var html = '';
             $.each(JSON.posts, function(index, post) {
                 html += '<div class="post" style="width: '+ postWidth +'">'
                      + '<h1 class="title">'+ post.post_title +'</h1>'
                      + '<div class="content">'+ post.post_content +'</div></div>';
             });
             //set the total posts and currently displayed post
             $(panel).attr('data-total', totalPosts).attr('data-current', 0);
             //set the width and add the posts to the DOM
             $('.posts', panel).css('width', wrapperWidth).html(html);
         },
         error:function(JSON) {
             console.error("Could not load posts");
         } 
     });

     //call this function again after a set time (5mins) to refresh posts
     setTimeout(function() {
         loadPosts(panel, category);
     }, 300000);
 }

...

We also need to create an animation that changes which post is being displayed after a set time. We can do this by giving a negative margin to the div containing the posts, increasing by the panel width for each post.

 function postSlider(panel) {
     var totalPosts = $(panel).attr('data-total');
     var currentPost = $(panel).attr('data-current');
     //cycle through the posts
     currentPost++;
     if (currentPost == totalPosts) {
         currentPost = 0;
     }
     var leftMargin = (-currentPost*100) + "%";
     $('.posts', panel).css('margin-left', leftMargin);
     //update the current post
     $(panel).attr('data-current', currentPost);
 }

Now let’s get everything going by running the above functions…

 ...
     //load the posts for each panel
     loadPosts($('.panel-1'), 12);
     loadPosts($('.panel-2'), 13);
     loadPosts($('.panel-3'), 14);
     loadPosts($('.panel-4'), 15);

     //begin the animations (cycle posts every 20s)
     setInterval(function(){
         postSlider($('.panel-1'));
         postSlider($('.panel-2'));
         postSlider($('.panel-3'));
         postSlider($('.panel-4'));
     }, 20000);
     </script>
 </body>
</html>

style.css

Finally let’s add the CSS to style the posts a bit and add in nice transitions for the slider animation.

...

.panel .posts {
  transition: all 1s ease-in-out;
}
.panel .post {
  float: left;
  width: 100%;
  padding: 2em;
}

Ready to create content

There’s just one thing left to do before seeing it all in action. We need to create 4 categories in wordpress which will decide which panel posts will be displayed in.

Create the categories  "panel-1", "panel-2", "panel-3", and "panel-4". Then when you’re in the Categories section of the wordpress dashboard, click on each category and take note of the tag_ID value in the url. This is the category id we need to use in our JavaScript when calling the  loadPosts() function.

finding category ids in wordpress

 

That’s it, you’re all done.
Now just create some posts, apply these categories, and open the website in your browser!

Final Result

See the final result live here.

message board theme final result

 

Download the project files

Here’s all the project files in a single zip: messageboard theme files

Update: 09 September 2015

A mistake was pointed out whereby the javascript ajax url was incorrect. The files and post have now been updated to fix this.

Get In Contact

Let us help you realise your project

Fill in the fields to the right and send a message outlining the scope of your project. We will get back to you as soon as possible.

Phone:+44 (0) 79 385 01770
Please check your input
Please check your input
Please check your input