Simple way to control Raspberry GPIO and Omxplayer with Javascript and php

image

I was looking for an easy way to control the RaspberryPi via a web based user interface. As I’m not familar whith Python I wanted to implement this via php an Javascript/jQuery.

I also wanted to write a php script that schould be able to be reused for other projects.

After some testing and smashing my head to some walls a lot of time I developed this, in my eys, simple solution.

So what’s needed on the RaspberryPi is:

The Scripts

PHP: phprunner.php

The php is build to run as a webservice that consumes a simple JSON via GET.

   1: <?php

   2: $sProject  =  $_GET['project'];

   3: $sCommand  =  $_GET['command'];

   4: $sValue    =  $_GET['value'];

   5:  

   6: switch ($sProject){

   7:     case "PiStarShip":

   8:         switch ($sCommand){

   9:             case "play":

  10:                 exec("omxplayer $sValue",$response);

  11:                 $result  =  array(status=>"playing",value=>$response);

  12:                 break;

  13:             case "stop":

  14:                 exec("killall omxplayer & killall omxplayer.bin &",$response);

  15:                 $result  =  array(status=>"stopped",value=>$response);

  16:                 break;

  17:             case "GPIOOut":

  18:                 $arrValue    = split(",",$sValue);

  19:                 exec("gpio -g mode $arrValue[0] out");

  20:                 exec("gpio -g write $arrValue[0] $arrValue[1]",$response);

  21:                 exec("gpio -g read $arrValue[0]",$response);

  22:                 $result  =  array(status=>"GPIO",value=>$response);

  23:                 break;

  24:             default:

  25:         }    

  26:         break;

  27:     default:

  28:         $result  =  array(status=>"No Project defined!");

  29:         break;

  30: }

  31: echo json_encode($result);

  32: ?>

I put a first switch in line 6 to seperate different projects – for later development.

Tho first running project is the “PiStarShip”. I built a woodden model of a star ship for my son, it shoul play sounds and do some light effects via the Pi and controlled via a web interface on a smartphone or tablet. 

Current implemented php functions:

“play”: Play sound (mp3 file) – line 9-12

JSON:

PlayIntro        : {

    command    : "play",

    value        : "/var/www/StarShip/intro.mp3"

    },

So the command play will call the omxplayer to play the file in value.

 

stop”: Stop all processes of omxlplayer

Yes, I know, this is a hard way to stop the omxplayer, but as of now, I didn’t find a smoother way. Any ideas?

JSON:

Stop        : {

    command:    "stop"   
    },

GPIOOut”: Set’s the value of a given GPIO-Port – line 17-23

JSON:

GPIOOut17    :    {

    command    : "GPIOOut",

    value        :    "17,1"

},

The “GPIOOut”command puts the GPIO Port in the “out”mode – line 19

The value is split into the portnumber and the GPIO value. Line 20 calls gpio to switch the port to the given value. In this case GPIO 17 will be switched on.

After that the port will be read to get the current value (line 21) and will return the result in a JSON again.

Javascript

To call the php function I implemented a global JSON variable and an Ajax call. So this is my JSON:

   1: var g_arrPHPJob;

   2:     g_arrPHPJob = {

   3:             project    : "PiStarShip",

   4:             Stop        : {

   5:                 command:    "stop"    

   6:                 },

   7:             PlayIntro        : {

   8:                 command    : "play",

   9:                 value        : "/var/www/StarShip/intro.mp3"

  10:                 },

  11:             PlaySound01        : {

  12:                 command    : "play",

  13:                 value        : "/var/www/StarShip/sounds/LaserShotII.mp3"

  14:                 },    

  15:             PlaySound02        : {

  16:                 command    : "play",

  17:                 value        : "/var/www/StarShip/sounds/LaserShot01.mp3"

  18:                 },    

  19:             GPIOOut17    :    {

  20:                 command    : "GPIOOut",

  21:                 value        :    "17,1"

  22:             },

  23:         };

The JSON includes the commands and the defalut values to call run the ajax calls.

The ajax call “F_PHPRunnerDoJob” itselfes looks like this:

   1: function F_PHPRunnerDoJob(sProject,objJobData) {

   2:         var arrPHPJob = {

   3:             project : sProject,

   4:             command : objJobData.command,

   5:             value        : objJobData.value,

   6:         };

   7:         

   8:     $.ajax({ 

   9:         url: '/core/phprunner.php', 

  10:         type: 'get',

  11:         datatype: 'json',

  12:         data: arrPHPJob,

  13:         success: function(data) { 

  14:             // // Do something with data that came back.  

  15:             // var objData = jQuery.parseJSON(data);

  16:                          console.log("Success");

  17:         },

  18:         error:function(exception){

  19:           console.log(exception);

  20:         }

  21:     });

  22: }

To impelment this in an HTML file I put a button on the page that has an onclick event:

onclick="F_PHPRunnerDoJob(g_arrPHPJob.project, g_arrPHPJob.PlayIntro)"

That’s it.

Complete HTML page:

   1: <!DOCTYPE html>

   2: <html lang="de">

   3:   <head>

   4:         <meta http-equiv="content-type" content="text/html; charset=UTF-8">

   5:         <meta http-equiv="expires" content="0" />

   6:         <meta http-equiv="cache-control" content="no-cache" />

   7:         <meta http-equiv="pragma" content="no-cache" />

   8:                 

   9:     <title>RasPi-Wars (c) by PiHunter</title>

  10:         <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  11:         <link rel="apple-touch-icon" sizes="144x144" href="iOsIcon114.png" />

  12:  

  13:         <link href="/core/pi.css" rel="stylesheet" /> 

  14:     <link href="/jquery.mobile-1.4.5.css" rel="stylesheet" />

  15:         <script type='text/javascript' src='/jquery-1.11.3.js'></script>
   1:     

   2:         <script type='text/javascript' src='/jquery.mobile-1.4.5.js'>

   1: </script>        

   2:       <script type='text/javascript' src='/core/phprunner.js'>

   1: </script>

   2:         <script type='text/javascript' src='effects.js'>

</script>

  16:   </head>

  17:   <body>

  18:     <div id="ContentContainer">

  19:                 <div id="ContentHeader">RasPi-Wars (c) by PiHunter

  20:                 </div>

  21:                 <div id="Content">

  22:         <fieldset>

  23:                     <div data-role="fieldcontain" onclick="F_PHPRunnerDoJob(g_arrPHPJob.project, g_arrPHPJob.PlayIntro)">

  24:                     <a class="ui-btn ui-btn-inline ui-icon-audio ui-btn-icon-right" href="#">Start Intro</a>

  25:           </div>

  26:           <div data-role="fieldcontain" onclick="F_PHPRunnerDoJob(g_arrPHPJob.project, g_arrPHPJob.PlaySound01)">

  27:                     <a class="ui-btn ui-btn-inline ui-icon-audio ui-btn-icon-right" href="#">Laser Shot II</a>

  28:           </div>

  29:           <div data-role="fieldcontain" onclick="F_PHPRunnerDoJob(g_arrPHPJob.project, g_arrPHPJob.PlaySound02);F_LaserFlash(50)">

  30:                     <a class="ui-btn ui-btn-inline ui-icon-audio ui-btn-icon-right" href="#">Laser mit LED</a>

  31:           </div>

  32:         </fieldset>

  33:         <fieldset>

  34:           <div data-role="fieldcontain" onclick="F_PHPRunnerDoJob(g_arrPHPJob.project, g_arrPHPJob.Stop)">

  35:                     <a class="ui-btn ui-btn-inline ui-icon-delete ui-btn-icon-right" href="#">Stop</a>

  36:          </div>

  37:         </fieldset>

  38:           <br>

  39:           </div>

  40:           (c) by <a href="http://eta-arts.de" target="_blank">eta-arts.de</a>

  41:     </div>

  42:   </body>

  43: </html>

Complete Javascript functions:

   1: var g_FlashTimer;

   2: var g_arrPHPJob;

   3:     g_arrPHPJob = {

   4:             project    : "PiStarShip",

   5:             Stop        : {

   6:                 command:    "stop"    

   7:                 },

   8:             PlayIntro        : {

   9:                 command    : "play",

  10:                 value        : "/var/www/StarShip/intro.mp3"

  11:                 },

  12:             PlaySound01        : {

  13:                 command    : "play",

  14:                 value        : "/var/www/StarShip/sounds/LaserShotII.mp3"

  15:                 },    

  16:             PlaySound02        : {

  17:                 command    : "play",

  18:                 value        : "/var/www/StarShip/sounds/LaserShot01.mp3"

  19:                 },    

  20:             GPIOOut17    :    {

  21:                 command    : "GPIOOut",

  22:                 value        :    "17,1"

  23:             },

  24:         };

  25:         

  26:  

  27: function F_LaserLEDOn(iTimer){

  28:     var objJobData = {

  29:         command    : "GPIOOut",

  30:         value        :    "17,1"

  31:     };

  32:     F_PHPRunnerDoJob(g_arrPHPJob.project,objJobData);

  33:     if(iTimer>0){

  34:         var result = setTimeout(F_LaserLEDOff, iTimer);

  35:     }

  36: }

  37:  

  38: function F_LaserLEDOff(){

  39:     var objJobData = {

  40:         command    : "GPIOOut",

  41:         value        :    "17,0"

  42:     };

  43:     F_PHPRunnerDoJob(g_arrPHPJob.project,objJobData);

  44:     //clearInterval(g_FlashTimer);

  45: }

  46:  

  47: function F_LaserFlash(iTimer){

  48:     intrvl=0;

  49:     for(nTimes=0;nTimes<iTimer;nTimes++){

  50:         intrvl += 100;

  51:         setTimeout(F_LaserLEDOn(),intrvl);

  52:         intrvl += 100;

  53:         setTimeout(F_LaserLEDOff(),intrvl);

  54:   }

  55:     F_LaserLEDOff();

  56: }