Raspberry pi GPIO hardware buttons
#1
Hi!

(I'm very new to xbmc, python and programming in general, so I may say very stupid things. Please help me learn!)

The plan for my raspberry pi is a media center that can run, and be controlled, headless. Like a stereo set. I have an lcd working, now I want controls, and I want to use buttons hooked up to the gpio pins. The buttons work, but I can't get them to work with an xbmc python script.

The problem seems to be the permissions; the python plugin xbmc uses doesn't have root acces, which is required to use the RPi.GPIO python module.
Here's the code I've been using to check for button presses:
Code:
import RPi.GPIO as GPIO
import time
GPIO.setmode(BCM)
GPIO.setup(22, GPIO.IN)
while True:
    if ( GPIO.input(22) == False )
             print("Button pressed")
    time.sleep(0.1); #so I don't have to keep it pressed for too long.
which works if I run it through SSH. The 'print...' bit is a placeholder.
Say I want this button to mean 'navigate right', I figured my code should be:
Code:
import xbmc

xbmc.ExecuteBuiltin("right")
So my question is, how do I get this to work? That is, (I think,) how do I get xbmc the correct permission to do this? Or if someone has a different idea on how to do this, I'm all ears.
Reply
#2
May be too simple, but what about "sudo xbmc"?

Anything started by xbmc should inherit permissions from the user running xbmc
Reply
#3
That might work, but raspbmc boots into xbmc, so I don't start it with a console command. Still, changing the permissions of xbmc could be a solution. Is there another way to give a startup process su permissions?
Reply
#4
I'm a little rusty, but hopefully I can point you in the right direction. Somewhere in your startup process, xbmc is being ran from a startup script, probably somewhere in the init scripts. My first stop would be rc.local.once you find where it's being called from, I think you could just change that to run as root.

Reply
#5
(2013-02-01, 18:36)Bstrdsmkr Wrote: My first stop would be rc.local.

Can you tell me where that is? Also, I'm not entirely confident that the executebuiltin part is correct. Any thoughts on that? The xbmc wiki isn't very clear on that point.
Reply
#6
so I now have one script, default.py:
Code:
import os
os.system("sudo python /home/pi/.xbmc/addons/script.service.hardware.buttons/buttons.py")

and buttons.py:
Code:
import time
import RPi.GPIO as GPIO
import xbmc

GPIO.setmode(BCM)
GPIO.setup(22, GPIO.IN)
while True:
    if ( GPIO.input(22) == False )
             xbmc.executebuiltin("Right")
    time.sleep(0.1);

It doesn't give the 'fail to execute script' message on startup that it did before, but it doesn't do anything either. Wrong 'if' bit maybe?
Reply
#7
your 'if' statement should be like this if im not mistaken

Code:
while True:
    if ( GPIO.input(22) == False ):
             xbmc.executebuiltin("Right")
    time.sleep(0.1)

also you have
Code:
os.system("sudo python /home/pi/.xbmc/addons/script.service.hardware.buttons/buttons.py")
im dont think you would be able to do 'xbmc.executebuiltin("Right")' from that file.

I would find out what group the user, that xbmc runs as, is missing and add it.
it could need the 'dialout' group, which I believe gives hardware access
Reply
#8
Yeah you won't be able to use any of the xbmc modules outside of xbmc (os.system() is starting another python interpreter which won't have access to the builtin xbmc stuff). Another thing to watch out for is since it's a new process, if xbmc crashes or exits, that process you spun off will keep running.

I think Kr0nZ is on the right track though. If you can get the normal user xbmc runs under the correct permissions, it'll make your life easier in general.

If you stick with using the external process, you'll have to call back in to xbmc using the JSONRPC. I think Memphiz posted a snippet somewhere with an example of using the JSONRPC with python
Reply
#9
That makes sense. I'll try to figure out the user group thing. I'll post the results.

EDIT: Okay so I guess xbmc runs under the user 'pi', since the .xbmc folder is installed there, and because that's the only one listed in 'cat /etc/passwd' that made any sense. It was already in the group 'dialout'. Added it to a bunch of other groups just in case, but it didn't help; xbmc still sez "script failed" on startup.

I think I'll just leave this little project for now, and hope someone more knowledgable will figure it out at some point. The feedback from the forums has been really great, but between my noobness, the oddities specific to raspbmc, and the mess of incomplete, outdated and poorly referenced info on the relevant xbmc wiki pages, I don't have any hope of figuring this out myself. Suggestions are still very welcome, but I've clearly bitten off more than I can chew here.
Reply
#10
I was able to control xbmc through button presses with the following, this is my first attempt so I'm sure there are better ways but it works. Hope it helps.



Code:
import os, httplib, time, json
import wiringpi2 as wp


play = 3
stop = 4
rew = 5
fwd = 6
url = "/jsonrpc?request={%22jsonrpc%22:%222.0%22,%22method%22:%22"
url2 = ",%22id%22:1}"
player = "Player.GetActivePlayers%22"
playcode = "player.playpause%22,%22params%22:{%22playerid%22:"
stopcode = "player.stop%22,%22params%22:{%22playerid%22:"
gotocode = "player.GoTo%22,%22params%22:{%22playerid%22:"
rewcode = ",%22to%22:%22previous%22}"
fwdcode = ",%22to%22:%22next%22}"
conn = httplib.HTTPConnection("127.0.0.1:8080")
wp.wiringPiSetup()

# run the button loop
var = 1
while var == 1:
    input_value1 = wp.digitalRead(play)
    input_value2 = wp.digitalRead(stop)
    input_value3 = wp.digitalRead(rew)
    input_value4 = wp.digitalRead(fwd)
    if input_value1 == 1:
        conn.request("GET", url + player + url2)
        r = conn.getresponse()
        j = json.loads(r.read())
        playeron = j["result"]
        if     json.dumps(playeron) == "[]":
            conn.request("GET", url + "input.select%22" + url2)
            conn.close()
        else:
            playerid = json.dumps(j["result"][0]["playerid"])
            conn.request("GET", url + playcode + playerid + "}" + url2)
            conn.close()
        conn.close()
        time.sleep(.2)
    elif input_value2 == 1:
        conn.request("GET", url + player + url2)
        r = conn.getresponse()
        j = json.loads(r.read())
        playeron = j["result"]
        if     json.dumps(playeron) == "[]":
            conn.request("GET", url + "input.back%22" + url2)
        else:
            playerid = json.dumps(j["result"][0]["playerid"])
            conn.request("GET", url + stopcode + playerid + "}" + url2)
        conn.close()
        time.sleep(.2)
    elif input_value3 == 1:
        conn.request("GET", url + player + url2)
        r = conn.getresponse()
        j = json.loads(r.read())
        playeron = j["result"]
        if     json.dumps(playeron) == "[]":
            conn.request("GET", url + "input.up%22" + url2)
        else:
            playerid = json.dumps(j["result"][0]["playerid"])
            conn.request("GET", url + gotocode + playerid + rewcode + url2)
        conn.close()
        time.sleep(.2)
    elif input_value4 == 1:
        conn.request("GET", url + player + url2)
        r = conn.getresponse()
        j = json.loads(r.read())
        playeron = j["result"]
        if     json.dumps(playeron) == "[]":
            conn.request("GET", url + "input.down%22" + url2)
        else:
            playerid = json.dumps(j["result"][0]["playerid"])
            conn.request("GET", url + gotocode + playerid + fwdcode + url2)
        conn.close()
        time.sleep(.2)
Reply
#11
So anybody more luck with this?

I've been working on a standalone project : XBMC Tablet.
I've got an old 17" TFT screen which i hooked up to my Pi, bought a VGA Controller from Ebay and that seems to work.
Now i'm working on a set-up (Breadboard) to make the GPIO talk to a button which much talk to XBMC.
Problem is that i can't seem to let the button talk to XBMC.

We already concluded that it's impossible to use an XBMC module outside of XBMC in a python script otherwise it would be easy.
Now i've learned that i can run a script from the userdata dir in a file called autoexec.py . This file runs your python script within the XBMC enviroment which should work with the XBMC.Builtin command.

So file looks like:
import xbmc
xbmc.executebuiltin('XBMC.Runscript(~/home/.xbmc/scripts/test.py)')

Can somebody try out wheter this works with their GPIO setup and what the commands would be in their 'test.py' file to go left/right/up/down , back and select? Smile
Thanks!
Reply
#12
Anybody got any progress in this project?
Reply
#13
I don't have any buttons on my pi but the way I'd envisaged doing this was:

1) Create a script that can run as a background service that listens for GPIO button presses. This could either send commands via JSON or run as an event client (see examples here: https://github.com/xbmc/xbmc/tree/master...entClients)

2) Creating an XBMC service that starts the python service (created above) when XBMC starts and stops it when XBMC shuts down.

Assuming the GPIO script needs to be run as sudo, I'd make sure I'd included the script name in sudoers so that it doesn't require a password.

That may be stupidly overdoing it, but just how I'd do it if it were me.
BBC Live Football Scores: Football scores notifications service.
script.squeezeinfo: shows what's playing on your Logitech Media Server
Reply
#14
(2013-08-02, 13:00)el_Paraguayo Wrote: I don't have any buttons on my pi but the way I'd envisaged doing this was:

1) Create a script that can run as a background service that listens for GPIO button presses. This could either send commands via JSON or run as an event client (see examples here: https://github.com/xbmc/xbmc/tree/master...entClients)

2) Creating an XBMC service that starts the python service (created above) when XBMC starts and stops it when XBMC shuts down.

Assuming the GPIO script needs to be run as sudo, I'd make sure I'd included the script name in sudoers so that it doesn't require a password.

That may be stupidly overdoing it, but just how I'd do it if it were me.

I've been reading about similar solutions but i'm not your experienced coder so i've got a lot of reading / learning to do if i want to pull this one off.
I thought there should be an easier way to get this done but i guess there isn't.

Now i'm considering hacking up some old USB gamepad to add directional pad + buttons. It's going to be a lot easier probaby.
Reply
#15
(2013-08-05, 11:37)troyk Wrote: I've been reading about similar solutions but i'm not your experienced coder so i've got a lot of reading / learning to do if i want to pull this one off.
I thought there should be an easier way to get this done but i guess there isn't.

Now i'm considering hacking up some old USB gamepad to add directional pad + buttons. It's going to be a lot easier probaby.
Easier - probably. But will it be as fun?

Learning to code as a result of having a desired outcome but not knowing how to get there is all part of the fun of Raspberry Pis and XBMC.

Don't be disheartened if something seems difficult. Both the Raspberry Pi and XBMC forums are incredibly supportive and will help with any queries.

As for your original question, one issue I can see is that you'd need a lot of buttons wired to the Raspberry Pi to get this to work (and even then you'd need to edit a keymap quite heavily) - unless you want the button to have one specific function.

Why wouldn't you just get a USB IR remote? A lot of these seem to work with XBMC.

If you've got any other questions, just ask!
BBC Live Football Scores: Football scores notifications service.
script.squeezeinfo: shows what's playing on your Logitech Media Server
Reply

Logout Mark Read Team Forum Stats Members Help
Raspberry pi GPIO hardware buttons0