Want to start Innovating with Arduino, Raspberry Pi and Internet of things (IoT) ? Click here to learn about our July 2017 training

Build your own Smart TV Using Raspberry Pi

Posted by Momen 06/07/2017 0 Comment(s)

interface-of-TV

You have a Raspberry Pi? And you want to do a special project and you have no idea what to do? What about building your own smart TV using your Raspberry Pi, Node.js, and Socket.io? If you are a curiosity of how doing it then let’s start learning and hope you enjoying.

 

              Overview.

After this tutorial you will understand:

  • How to install software to the Raspberry Pi.
  • How to install and use Node.js, Express.js and Socket.io
  • How to use remote mobile app.

 

You will need some software and hardware components:

Hardware:

  • Raspberry Pi.
  • Ethernet cable.
  • SD/MicroSD card (8 GB+).

Software

  • Raspbian that include:
    • Node.js
    • Socket.io – to control the connection between our Remote and TV.
    • Express – to handle some basic HTTP requests
    • Omxcontrol – a simple module to control the OMXPlayer which is the best video player on the RPI
    • Chromium Browser
    • OMXPlayer
    • Youtube-dl – a script that let you download youtube videos
    • Quo.js – to handle swipe gestures on the mobile web app
    • HTML5, CSS3 transitions, Javascript, and Moustache as a template engine
    • Youtube API

 

If you don’t have Node.js, open Raspberry terminal and type the following command:

wget http://node-arm.herokuapp.com/node_latest_armhf.deb

sudo dpkg -i node_latest_armhf.deb

To make sure it ran correctly, run node -v. It should return the current version.

 

If you don’t have Chromium browser, open a Raspberry terminal and type the following command:

sudo apt-get install chromium-browser

To Install and update Youtube-dl script

sudo apt-get install youtube-dl

sudo youtube-dl –U

If you’re connecting to your Pi via SSH, you’d have to update your DISPLAY environment variables by typing:

 

export DISPLAY=:0.0

 

                 Implemetation.

 

Create a new file and name it Package.json and write the following code:

{

    "name": "RasPi.TV",

    "version": "0.0.1",

    "private": false,

    "scripts": {

        "start": "node app.js"

    },

    "dependencies": {

    "express": "3.1.1",

    "socket.io":"0.9.14",

    "omxcontrol":"*"

    }

}

Open terminal and type the following command to install the dependencies:

npm install

 

 

Now let's start by creating your basic HTTP server with Express.js

Create app.js file and write:

 

var express = require('express')

  , app = express() 

  , server = require('http').createServer(app)

  , path = require('path')

app.set('port', process.env.TEST_PORT || 8080);

app.use(express.favicon());

app.use(express.logger('dev'));

app.use(express.bodyParser());

app.use(express.methodOverride());

app.use(express.static(path.join(__dirname, 'public')));

app.get('/', function (req, res) {

     res.sendfile(__dirname + '/public/index.html');

    });

app.get('/remote', function (req, res) {

      res.sendfile(__dirname + '/public/remote.html');

     });

server.listen(app.get('port'), function(){

  console.log('Express server listening on port ' + app.get('port'));

});

To test the file type the following command but first create static files: index.html and remote.html into the public dir. Write “Hello, World” messages into these pages:

node app.js

 

Socket.io

Socket.io provide real-time connectivity on every browser, without changing in API.

Some of the technologies will make suffer to your server or network at all such as the Adobe® Flash® Socket, to prevent that it should be disabled. And technologies that make suffer like:

  1. WebSocket
  2. Adobe® Flash® Socket
  3. AJAX long polling
  4. AJAX multipart streaming
  5. Forever Iframe
  6. JSONP Polling

 

First, you have to install it on your Raspberry Pi by type this command:

 

npm install socket.io

 

Server side:

To integrate Socket.io, make app.js and write on it:

 

var express = require('express')

  , app = express() 

  , server = require('http').createServer(app)

  , path = require('path')

  , io = require('socket.io').listen(server)

  , spawn = require('child_process').spawn

 

Your Socket.io Server is ready, but it doesn’t do anything yet. You implement how you process messages and events sent from the client to the server by:

 

io.sockets.on('connection', function (socket) {

    socket.emit('message', { message: 'welcome to the chat' });

    socket.on('send', function (data) {

        io.sockets.emit('message', data);

    });

});

Now, whenever a new client connects to the server, it will send “message”  and waits for an event name “send” to process the data and send it back to all connected clients.

There are two types of clients:

  • The RPI display (the TV)
  • The mobile Web-app (the remote)

 

var ss;

//Socket.io Server

io.sockets.on('connection', function (socket) {

 

 socket.on("screen", function(data){

   socket.type = "screen";

   //Save the screen socket

   ss = socket;

   console.log("Screen ready...");

 });

 

 socket.on("remote", function(data){

   socket.type = "remote";

   console.log("Remote ready...");

   if(ss != undefined){

      console.log("Synced...");

   }

 });

)};

 

Client side:

Add the following to remote.html file:

 

    <script src="/socket.io/socket.io.js"> </script>

    <script>

          var socket = io.connect('http://raspberrypi.local:8080');

      socket.on('connect', function(data){

        socket.emit('screen');

      });

    </script>

Add the following to index.html file:

 

    <script src="/socket.io/socket.io.js"> </script>

    <script>

          var socket = io.connect('http://raspberrypi.local:8080');

      socket.on('connect', function(data){

        socket.emit('screen');

      });

    </script>

 

Adding OMX-player controller for Node.js

 

OMX Control module will allow you to control OMX-player over HTTP.

Require this module into your main project file.

 

var omx = require('omxcontrol');

app.use(omx());

OMX Control module will create the following routes to control the video playback:

 

http://localhost:8080/omx/start/:filename

http://localhost:8080/omx/pause

http://localhost:8080/omx/quit

'

your final app.js file:

 

/**

 * Module dependencies.

 */

var express = require('express')

  , app = express() 

  , server = require('http').createServer(app)

  , path = require('path')

  , io = require('socket.io').listen(server)

  , spawn = require('child_process').spawn

  , omx = require('omxcontrol');

 

// all environments

app.set('port', process.env.TEST_PORT || 8080);

app.use(express.favicon());

app.use(express.logger('dev'));

app.use(express.bodyParser());

app.use(express.methodOverride());

app.use(express.static(path.join(__dirname, 'public')));

app.use(omx());

 

//Routes

app.get('/', function (req, res) {

  res.sendfile(__dirname + '/public/index.html');

});

 

app.get('/remote', function (req, res) {

  res.sendfile(__dirname + '/public/remote.html');

});

 

//Socket.io Congfig

io.set('log level', 1);

 

server.listen(app.get('port'), function(){

  console.log('Express server listening on port ' + app.get('port'));

});

 

//Run and pipe shell script output

function run_shell(cmd, args, cb, end) {

    var spawn = require('child_process').spawn,

        child = spawn(cmd, args),

        me = this;

    child.stdout.on('data', function (buffer) { cb(me, buffer) });

    child.stdout.on('end', end);

}

//Save the Screen Socket in this variable

var ss;

//Socket.io Server

io.sockets.on('connection', function (socket) {

 

 socket.on("screen", function(data){

   socket.type = "screen";

   ss = socket;

   console.log("Screen ready...");

 });

 socket.on("remote", function(data){

   socket.type = "remote";

   console.log("Remote ready...");

 });

 

 socket.on("controll", function(data){

    console.log(data);

   if(socket.type === "remote"){

 

     if(data.action === "tap"){

         if(ss != undefined){

            ss.emit("controlling", {action:"enter"});

            }

     }

     else if(data.action === "swipeLeft"){

      if(ss != undefined){

          ss.emit("controlling", {action:"goLeft"});

          }

     }

     else if(data.action === "swipeRight"){

       if(ss != undefined){

           ss.emit("controlling", {action:"goRight"});

           }

     }

   }

 });

 

 socket.on("video", function(data){

 

    if( data.action === "play"){

    var id = data.video_id,

         url = "http://www.youtube.com/watch?v="+id;

 

    var runShell = new run_shell('youtube-dl',['-o','%(id)s.%(ext)s','-f','/18/22',url],

        function (me, buffer) {

            me.stdout += buffer.toString();

            socket.emit("loading",{output: me.stdout});

            console.log(me.stdout)

         },

        function () {

            //child = spawn('omxplayer',[id+'.mp4']);

            omx.start(id+'.mp4');

        });

    }   

 

 });

});

 

Dashboard and Remote mobile-app

Create Quo.js file that include:

 

$$(".r-container").swipeLeft(function(){

socket.emit('control',{action:"swipeLeft"});

});

Note: here’s an example of how send the message “Control” back to the server with the data action:”swipeLeft”, the server will handle that message by sending it to the screen, the screen client will handle this message by moving the selected square to the next app (Watch, Listen, Play)

Leave a Comment