Push button (GPIO) to perform kodi actions

For the kitchen I’m planning to build a radio based on a RPi B. Currently I have installed OSMC on it and via autoexec.py I have a ‘default_radio_station.m3u’ starting on boot.
Furthermore I have one push button connected to GPIO running the script to restart (short press) or shutdown (5 second press) the Pi (script is found on the internet and included on the bottom of this post).
Also I have Spotify connect web running.

To complete the build I want to add another push button which:

  1. On short press:
    stop what’s playing (both from inside Kodi and Spotify (via http://:4000/api/playback/pause)),
    start playing ‘default_radio_station.m3u’
  2. On long press:
    stop playing ‘default_radio_station.m3u’,
    start playing a shuffled playlist (preferred from Spotify (seems difficult) so to start with it would be nice to play a .m3u file).

For ‘1’ I currently have:

import RPi.GPIO as GPIO
import time
import os

#adjust for where your switch is connected
buttonPin = 8

while True:
  #assuming the script to call is long enough we can ignore bouncing
  if (GPIO.input(buttonPin)):
  #this is the script that will be called (as root)
  os.system(xbmc-send --action="PlayMedia(/home/osmc/kitchen_extras/default_radio_station.m3u)")

But the command the start ‘default_radio_station.m3u’ is resulting in 'keyword cannot be an expression. When I run the command below in a SSH session it does work.
xbmc-send --action="PlayMedia(/home/osmc/kitchen_extras/default_radio_station.m3u)"

Could someone give me a hint in the right direction? If I could get the command on the bottom line working I plan to reuse the restart/shutdown script to get both function ‘1’ and ‘2’.

The script for the Restart/shutdown button:

#This script was authored by AndrewH7 and belongs to him (www.instructables.com/member/AndrewH7)
#You have permission to modify and use this script only for your own personal usage
#You do not have permission to redistribute this script as your own work
#Use this script at your own risk

import RPi.GPIO as GPIO
import time
import os

#Replace YOUR_CHOSEN_GPIO_NUMBER_HERE with the GPIO pin number you wish to use
#Make sure you know which rapsberry pi revision you are using first
#The line should look something like this e.g. "gpio_pin_number=7"

#Use BCM pin numbering (i.e. the GPIO number, not pin number)
#WARNING: this will change between Pi versions
#Check yours first and adjust accordingly

GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_UP)
#It's very important the pin is an input to avoid short-circuits
#The pull-up resistor means the pin is high by default

button_previous = 1
button_current = 1
brojac = 0
flag_pressed = 0

while True:
  button_current = GPIO.input(7);

  flag_pressed = button_previous + button_current

  if (not(flag_pressed)):
  brojac += 1
  brojac = 0

  if (button_current and (not button_previous)):
  os.system("sudo shutdown -r now")
  if ((not flag_pressed) and brojac >= 100):
  os.system("sudo shutdown -h now")

  button_previous = button_current

#Revert all GPIO pins to their normal states (i.e. input = safe)

Put the xbmc send command in a bash script
Verify it works and chmod +x it
Then call it with os.system

Thank you very much for the quick response. I created two additional scripts:

For ‘1’: ‘xbmc-send.stop_play_radio.sh’ with the following content:

(curl http://<IP>:4000/api/playback/pause; xbmc-send --action="PlayMedia(/home/osmc/kitchen_extras/default_radio_station.m3u)")

And for ‘2’: ‘xbmc-send.stop.sh’ with the following content:

xbmc-send --action="stop"

Running these scripts via SSH works!

The usage will be as follow:

For music (stored on the NAS):
Normaly radio is played. Via Yatse the desired music album is started (Kodi will stop the radio by itself and starts playing music).
If the button above is shortly pressed a ‘pause’ command will be sent to Spotify-connect (not active, so no change) and the radio station will be started.

For Spotify-connect:
The button has to be pressed for >3 seconds to stop whatever Kodi is playing (default: radio). This is required because otherwise Kodi and Spotify will be heard simultaneously. Now via the Spotify app one can start playing music.
If the button above is shortly pressed a ‘pause’ command will be sent to Spotify-connect and the radio station will be started.

Now I can almost see the finish line :slight_smile:.
I reused the script for the restart/shutdown button, included two parameters which point to the new bash scripts:

script_short_press = "sh ./home/osmc/kitchen_extras/xbmc-send.stop_play_radio.sh"
script_long_press = "sh ./home/osmc/kitchen_extras/xbmc-send.stop.sh"

and changed the ‘os.system(xxx)’ commands to:


After a reboot only one of the two functions works, for one time only. I suspect this is due to the ‘while true’ loop. I need to dig a bit further how to solve this. Once I found the solution I’ll report back :slight_smile: (or if someone has a solution for this… :blush:).

Try using complete paths for the commands I inside your scripts.

It’s been a while since reporting back (the birth of my first child delayed some other projects :slight_smile:).

In reply to @ActionA: I was under the impression that I already use complete paths. Is it not a complete path because of the dot in front of it? I’ve removed the dot, but still no luck.
Pressing the button shortly results in ‘start playing radio’. Pressing longer to have Kodi stop playing music isn’t working. I’ve verified this via SSH; the stop command is shown, but after releasing the button it ends with the ‘start playing radio’ command :confused:.

After some more searching I found the script below and edited it for my usage. The script doesn’t look as neat as the script for the restart/shutdown button but it works :slight_smile:.

#!/usr/bin/env python2.7

from time import sleep
import subprocess
import RPi.GPIO as GPIO

CHANNEL = 11 # GPIO channel 11 is on pin 23 of connector P1
# it will work on any GPIO channel

GPIO.setup(CHANNEL, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# setup the channel as input with a 50K Ohm pull up. A push button will ground the pin,
# creating a falling edge.

def system_action(CHANNEL):
    print('Button press = negative edge detected on channel %s'%CHANNEL)
    button_press_timer = 0
    while True:
            if (GPIO.input(CHANNEL) == False) : # while button is still pressed down
                button_press_timer += 1 # keep counting until button is released
            else: # button is released, figure out for how long
                if (button_press_timer > 2) : # pressed for > 2 seconds
                    print "long press > 2 : ", button_press_timer
                    # do what you need to do before the command below
                    subprocess.call("/home/osmc/kitchen_extras/xbmc-send_stop.sh", shell=True)
                elif (button_press_timer > 0) : # press for > 0 < 2 seconds
                    print "short press > 0 < 2 : ", button_press_timer
                    # do what you need to do before the command below
                    subprocess.call("/home/osmc/kitchen_extras/xbmc-send_stop_play_radio.sh", shell=True)
                button_press_timer = 0

GPIO.add_event_detect(CHANNEL, GPIO.FALLING, callback=system_action, bouncetime=200)
# setup the thread, detect a falling edge on channel 11 and debounce it with 200mSec

# assume this is the main code...
    while True:
        # do whatever
        # while "waiting" for falling edge on port 11
        sleep (2)

except KeyboardInterrupt:
    GPIO.cleanup()       # clean up GPIO on CTRL+C exit
GPIO.cleanup()           # clean up GPIO on normal exit

The referred bash scripts:

  1. xbmc-send_stop.sh:

xbmc-send --action=“stop”

  1. xbmc-send_stop_play_radio.sh:

(curl http://IP_OF_PI:4000/api/playback/pause; xbmc-send --action=“PlayMedia(/home/osmc/kitchen_extras/default_radio_station.m3u)”)