Run a command whenever Volumio Plays on Raspberry Pi

Prob. something like this. Code is untested, so you might need to tweak it.

import os
import subprocess
import json

from time import sleep
import RPi.GPIO as GPIO

# Which GPIO
leda =24
ledb =23

# Set active state to avoid loop
playing = 0
GPIO.setmode(GPIO.BCM)
GPIO.setup(leda,GPIO.OUT)
GPIO.setup(ledb,GPIO.OUT)

def getStatus():
	process = subprocess.Popen("volumio status".split(), stdout=subprocess.PIPE)
	output = process.communicate()[0]
	pythonObj = json.loads(output)
	global status = pythonObj['status']

while True:
	getStatus()

	if ((status == "play") and (playing == 0)) :
		# Execute code for play
		GPIO.output(leda,GPIO.HIGH)
		sleep(1)
		GPIO.output(leda,GPIO.LOW)
		playing = 1
	if ((status == "stop")  and (playing == 1)) :
		# Execute code for stop
		GPIO.output(ledb,GPIO.HIGH)
		sleep(0.5)
		GPIO.output(ledb,GPIO.LOW)
		playing = 0
	elif (status == "pause"):
		sleep(5)
		getStatus()
		if (status == "pause"):
			GPIO.output(ledb,GPIO.HIGH)
			sleep(0.5)
			GPIO.output(ledb,GPIO.LOW)
	sleep(0.3) # To avoid CPU overload
from socketIO_client import SocketIO
import RPi.GPIO as GPIO

# Which GPIO
leda=24
ledb=23


# Open up a ws client
socketIO = SocketIO('localhost', 3000)
socketIO.on('pushState', parseStatus)
socketIO.emit('getState', '', parseStatus)


def parseStatus(state):
	global curstate = state['status']
	if (curstate == "play"):
		onPlay()
<snip> you get the idea ;-) 

Pseudo code - but give something along these lines also a shot.
You will need socketIO-clientpip install socketIO-client

That a cleaner solution, but in a good literal Dutch 2 English translation.

(Dat kon ik niet even snel uit mijn mouw schudden)
That can I not even fast out my sleeve shake.

1 Like

Misschien, I can’t just pull a rabbit out of the hat. Or, nothing springs to mind.

Hahahah :smiley: I am sure you can if you have more time :wink:

This should be much more efficient :slight_smile:

from socketIO_client import SocketIO
import RPi.GPIO as GPIO

# Which GPIO
leda=24
ledb=23
laststate = ""

def onPlay():
    print("Actions for Play")

def onStop():
    print("Actions for Stop")


def parseStatus(state):
    global laststate
    curstate = state['status'] if 'status' in state else "undefined"
    if (laststate != curstate):
        if (curstate == "play"):
            print(f"Playing.. {state['title']}")
            onPlay()
        if (curstate == "stop"):
            print(f"Stopped")
            onStop()
        laststate=curstate
    

# Open up a ws client
socketIO = SocketIO('localhost', 3000)
socketIO.on('pushState', parseStatus)
socketIO.emit('getState', '', parseStatus)
    
def main():
    socketIO.wait()
    time.sleep(0.5)

try:
    main()
except KeyboardInterrupt:
    print("Exiting...")
    pass

Yes, this will do the job. smart to add laststate to avoid additional blinking.

Thanks for the reply Wheaten!

I am getting an syntax error when trying to run the script:

  File "script4.py", line 22
    global status = pythonObj['status']
                  ^

SyntaxError: invalid syntax

global status
status = pythonObj[‘status’]

Hi Ash,

Thanks for the help,

I keep getting this message when running the script:

An incompatible websocket library is conflicting with the one we need.
You can remove the incompatible library and install the correct one
by running the following commands:

yes | pip uninstall websocket websocket-client
pip install -U websocket-client

I followed those commands, uninstall and then install. I keep getting the same message poppping up.

When i run: yes | pip uninstall websocket websocket-client

I get:


Traceback (most recent call last):
  File "/usr/bin/pip", line 9, in <module>
    load_entry_point('pip==1.5.6', 'console_scripts', 'pip')()
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 356, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 2476, in load_entry_point
    return ep.load()
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 2190, in load
    ['__name__'])
  File "/usr/lib/python2.7/dist-packages/pip/__init__.py", line 75, in <module>
    from pip.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter
  File "/usr/lib/python2.7/dist-packages/pip/baseparser.py", line 14, in <module>
    class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
AttributeError: 'module' object has no attribute 'IndentedHelpFormatter

and afterwards when I run:

  File "/usr/bin/pip", line 9, in <module>
    load_entry_point('pip==1.5.6', 'console_scripts', 'pip')()
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 356, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 2476, in load_entry_point
    return ep.load()
  File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 2190, in load
    ['__name__'])
  File "/usr/lib/python2.7/dist-packages/pip/__init__.py", line 75, in <module>
    from pip.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter
  File "/usr/lib/python2.7/dist-packages/pip/baseparser.py", line 14, in <module>
    class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
AttributeError: 'module' object has no attribute 'IndentedHelpFormatter'

i tried manually installing the required packages socketio-client and websocket and I get the same errors.

replace pip with pip3

ended up getting this when using pip3 to install

Installing collected packages: websocket-client
*** Error compiling '/tmp/pip-build-kvg_gjb8/websocket-client/websocket/tests/echo-server.py'...
  File "/tmp/pip-build-kvg_gjb8/websocket-client/websocket/tests/echo-server.py", line 12
    async def echo(websocket, path):
            ^
SyntaxError: invalid syntax

Successfully installed websocket-client
Cleaning up...

also the updated code you have provided with the new elif pause section is giving me abit of trouble as every 5 seconds the led blinks lol.

EDIT: I just added the missing the ‘playing == 0’ bit in the pause section of coding. Now it doesnt blink every 5 seconds. haha! woo!

EDIT2: It seems to just wait 5 seconds to trigger the led and not listen to the status change.

the code updated:

import os
import subprocess
import json

from time import sleep
import RPi.GPIO as GPIO

# Which GPIO
leda =24
ledb =23

# Set active state to avoid loop
playing = 0
GPIO.setmode(GPIO.BCM)
GPIO.setup(leda,GPIO.OUT)
GPIO.setup(ledb,GPIO.OUT)

def getStatus():
        process = subprocess.Popen("volumio status".split(), stdout=subprocess.PIPE)
        output = process.communicate()[0]
        pythonObj = json.loads(output)
        global status
        status = pythonObj['status']

while True:
        getStatus()

        if ((status == "play") and (playing == 0)) :
                # Execute code for play
                GPIO.output(leda,GPIO.HIGH)
                sleep(1)
                GPIO.output(leda,GPIO.LOW)
                playing = 1
        if ((status == "stop")  and (playing == 1)) :
                # Execute code for stop
                sleep(8)
                getStatus()
                if (status == "stop") and (playing == 1) :
                        GPIO.output(ledb,GPIO.HIGH)
                        sleep(0.5)
                        GPIO.output(ledb,GPIO.LOW)
                        playing = 0
        elif (status == "pause") and (playing == 1) :
                sleep(8)
                getStatus()
                if (status == "pause") and (playing == 1) :
                        GPIO.output(ledb,GPIO.HIGH)
                        sleep(0.5)
                        GPIO.output(ledb,GPIO.LOW)
                        playing = 0

        sleep(0.3) # To avoid CPU overload


You’re welcome :partying_face:

1 Like

I’ve updated my GPIO control plugin for v3 with delay and duration features. Hopefully, this will be available on the plugin store at some point.

1 Like