Wednesday, July 11, 2012

Raspberry Pi and GPIO Permissions



It works! Okay, back up a little. Getting a PHP web interface to talk to hardware proved to be rather difficult. You need root access to control hardware but the web service runs with minimal permissions. So how does one bridge the gap without compromising the system? The answer, very carefully. I found a few workarounds but they involved either using MySQL or the gpio-admin library that works from commandline or shell scripts. In my case I wanted to stay with using C programs with the wiringPi library being called from PHP. C is much faster to control GPIO and PHP gives me a web front end. Here is how I did it.


First the PHP process needs a way to run the binary as root. In this example, I am using the blink.c program. The way we do this at the command line is "sudo" but this required a password and PHP wouldn't be able to do that without exposing your password. What we do know is apache/lighttpd is running at the user "www-data". Hmm, what can we do there?

  1. Create a blink.c and compile it. If you need help look at this post  Raspberry Pi CommandIR and Beyond
  2. Edit the sudoers file.
    1. sudo visudo
    2. Under "User privilege specification" add this 
      1. www-data ALL=NOPASSWD: /path/to/binary, /path/to/another/binary
      2. Save and exit (had a hard time with this for some reason, I used ESC CTRL-C Y ENTER CRTL-C CTRL-C(Looks like Wheezy works the normal way for nano)
  3. Then in your PHP script you can call it like this
    1. $result=exec('sudo /path/to/binary');
Basically, you are allowing the 'www-data' user to run only your program as root without prompting for password. This keeps it secure but allows you to control the GPIOs. You can also pass pararmeters and return data. Here is a complete example assuming 'blink' is in /var/www/gpio.

<?php  
   if (isset($_POST['blink']))  
   {  
    print ('Blinking LED...');  
    $result=exec('sudo gpio/blink'); //or ('sudo gpio/blink > /dev/null &')
    print ($result);  
   }  
 ?>  
<FORM NAME="blink" Method='POST'>  
  <p>  
    <button name="blink">Blink LED</button>  
  </p>  
</FORM>  

Just copy and paste this code into a PHP file (blink.php) and save it to the root of your web folder. It should should be /var/www/.

Here are the links to the other options if they work for you:

Using MySQL
http://www.instructables.com/id/Web-Control-of-Raspberry-Pi-GPIO/

GPIO-Admin
http://quick2wire.com/2012/05/safe-controlled-access-to-gpio-on-the-raspberry-pi/

In case you are using python which uses GPIO-Admin
http://quick2wire.com/2012/05/quick2wire-python-api-released/


Edit: If you want it to blink the LED in the background and return control to the webpage right away change

$result=exec('sudo gpio/blink');
to
$result=exec('sudo gpio/blink > /dev/null &');

10 comments:

  1. Many thanks from Portugal.

    ReplyDelete
  2. This was very helpful, cheers from Sweden! :D

    ReplyDelete
  3. Thanks from Denmark!

    ReplyDelete
  4. thank you so much, yo're the only one on the entire internet who solved my problem.

    ReplyDelete
  5. Thanks From Indonesia

    ReplyDelete
  6. Thanks from France!! the only solution works on the Internet!

    ReplyDelete
  7. It works very well but not with html.
    ex : print("Hello
    ") doesnt' work

    ReplyDelete
  8. Thank you from Greece! Keep up the good work!

    ReplyDelete
  9. when using vi (visudo edits the sudoers file in vi) use Esc to stop editing then :wq. The : tells vi to respond to a user command, w to write the changes to file and q to quit.

    ReplyDelete