I am just starting to learn python and using it with my raspberry pi and GPIO. I am trying to program this so it runs this line "echo p >> /home/pi/.config/pianobar/ctl" which would pause the song that is playing. I got it to print it but it doesnt actually pause the song.
#!/usr/bin/python
import os
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN)
while True:
mybutton = GPIO.input(11)
if mybutton == False:
print "pause"
os.system("echo 'echo 'p' >> /home/pi/.config/pianobar/ctl'")
time.sleep(.2)
and the output is: echo p >> /home/pi/.config/pianobar/ctl
pause
but nothing actually happens.
This line:
os.system("echo 'echo 'p' >> /home/pi/.config/pianobar/ctl'")
has two echos, and the >> operator is quoted, so all it's doing is printing something to standard output. Try:
os.system("echo 'p' >> /home/pi/.config/pianobar/ctl")
Related
I want to run a program using the subprocess module. While running the program, there are cases where it waits for a button press to continue. It is not waiting for this input to the stdin input. The input sent to stdin is ignored by the program. Only when I press a button on the console will the program continue running.
I tried it like this:
proc = Popen("festival.exe level.sok", stdin=PIPE, text=True)
proc.stdin.write('.')
proc.stdin.flush()
It this case nothing happened.
and like this:
proc = Popen...
proc.communicate('.')
In this case, the python code will not continue running until I press a button on the console. If I set a timeout then the python code continues to run but festival.exe does not continue to run.
What should I do to make festival.exe continue running?
P.S.: festival.exe is a solver for sokoban. This case occurs when the given level cannot be solved. E.g.:
########
#.. $ $#
# # #
########
assuming you have the festival program like this:
from random import getrandbits
solved = getrandbits(1)
if solved:
print("executed correctly")
else:
print('a error ocurred')
input('press a button to continue')
exit(1)
you can solve with:
from subprocess import Popen, PIPE
p = Popen(['python3','festival.py'],stdin=PIPE)
p.communicate(input=b'any\n')
I have a little problem with understand what is going on with my code.
I have a lot of lines in my code so i decided to simulate my problem with shorter version.
Im using raspberry pi 4, flirone on rapsbian.
import sys
import os
import time
import subprocess
global shellscript
#global pid
def subprocess_settings():
shellscript = subprocess.Popen(["/home/pi/Desktop/init_flir.sh"], close_fds=True)
#shellscript = subprocess.Popen(["/home/pi/Desktop/init_flir.sh", "&> /dev/null"], stdin=None, stdout=None, close_fds=True)
#pid = shellscript.pid
try:
x = 1
while True:
if x == 0:
sys.exit()
elif x == 1:
print("Yas, x=1")
time.sleep(2)
subprocess_settings()
time.sleep(5)
print("Driver test is in background mode")
time.sleep(2)
print("Close process")
subprocess.Popen.kill(shellscript)
x=0
except KeyboardInterrupt:
subprocess.Popen.kill(shellscript)
and my .sh file:
#!/bin/bash
cd /home/pi/github/flirone-v4l2
sudo modprobe v4l2loopback exclusive_caps=0,0 video_nr=1,2,3
sudo ./flirone ~/github/flirone-v4l2/palettes/Iron2.raw
I want to run my .sh file. It has to work in background. I need to terminate this with 2 ways, first one from keyboard and second inside my elif.
At the end i need to hide terminal output from .sh file.
What im doing wrong??
Is this is a problem with global variables?
How to fix this to work properly?
Thanks for any help.
This solution works properly, as i wanted. In flirone driver i runned ./flirone and opened 1 process from subprocess.Popen and 2 additional processes in flirone code. I checked this running command sudo ./flirone ~/github/flirone-v4l2/palettes/Iron2.raw and ps aux | grep flirone . I used pidof flirone command to check main ID. When im killing this process everything works as should be and other processes ends too.
import sys
import os
import signal
import time
import subprocess
def subprocess_kill():
pidof = subprocess.check_output("pidof flirone", shell=True)
time.sleep(1)
subprocess.check_output("sudo kill -9 %s " % (pidof), shell=True)
try:
x = 1
while True:
if x == 0:
sys.exit()
elif x == 1:
print("x=1")
time.sleep(2)
os.chdir("/home/pi/github/flirone-v4l2")
shellscript = subprocess.Popen("sudo modprobe v4l2loopback exclusive_caps=0,0 video_nr=1,2,3", shell=True)
shellscript2 = subprocess.Popen("sudo ./flirone ~/github/flirone-v4l2/palettes/Iron2.raw", shell=True)
time.sleep(5)
print("Driver test is in background mode")
time.sleep(2)
print("Close process")
subprocess_kill()
x=0
except KeyboardInterrupt:
print("hey")
When i deleted killing method from except KeyboardInterrupt processes ends too.
If you want to hide output of subprocess u can use:
FNULL = open(os.devnull, "w")
shellscript2 = subprocess.Popen("sudo ./flirone ~/github/flirone-v4l2/palettes/Iron2.raw", shell=True, stdout=FNULL)
More: How to hide output of subprocess in Python 2.7
Subprocess python 2.7 lib
I explain my need : i wish to run ffmpeg with a python script (that's ok) but i need to know of the script is launched with a blink led connected on the GPIO of my RPI, But i dont know why i can launch my script and start le blink (or just a led on)
Can u help me ? show me the light, please ;)
import RPi.GPIO as GPIO
import time
import os
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(22,GPIO.IN)
# fonction qui fait clignoter la led
def blink(led):
GPIO.output(led,True)
time.sleep(0.5)
GPIO.output(led,False)
time.sleep(1)
# input of the switch will change the state of the LED
while 1:
if ( GPIO.input(22) == True ):
print "start broadcast"
os.system("sudo /home/pi/videopi/webcam.sh")
blink(4) << not ok like this !
time.sleep(1)
Assuming your os script runs successfully (I would recommend subprocess instead), what you're describing is called concurrency -- https://realpython.com/python-concurrency/
I would structure your code like this:
import RPi.GPIO as GPIO
import time
import os
from threading import Thread
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(22,GPIO.IN)
# fonction qui fait clignoter la led
def blink(led):
while True:
GPIO.output(led,True)
time.sleep(0.5)
GPIO.output(led,False)
time.sleep(1)
# input of the switch will change the state of the LED
while True:
if ( GPIO.input(22) == True ):
blinking = Thread(target=blink, args=(4,)) # create thread
blinking.start() # start blinking
print("start broadcast")
os.system("sudo /home/pi/videopi/webcam.sh")
blinking.join() # stops blinking once webcam.sh completed
print("broadcast complete")
I'm trying to make a python script that starts mdk3 when a switch is flipped on (LOW) and kills it when it's switched off (HIGH). However, the mdk3 command always starts when the script is started, regardless of the switch's position. Starting the script with the switch in the ON position and then switching it OFF while it's running kills the command, as expected. However, it does not begin running again when switching it back ON. Interestingly, the text set to print functions exactly as would be expected. My code is as follows:
import RPi.GPIO as GPIO
import time
import subprocess
import os
import signal
FSU = 'sudo mdk3 mon0 d'
pro = 'subprocess.Popen(FSU, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid)'
# tell the GPIO module that we want to use the chip's numbering scheme
GPIO.setmode(GPIO.BCM)
# Set up GPIO16 as an input with internal pull-up resistor to hold it HIGH until it is pulled down to GND by the connected switch
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP)
running = False
while True:
if GPIO.input(16) == GPIO.LOW:
if running == False:
print('Button was pushed!')
pro
running = True
time.sleep(0.1)
elif running == True:
print('The process is running.')
time.sleep(0.1)
elif GPIO.input(16) == GPIO.HIGH and running == True:
os.killpg(os.getpgid(pro.pid), signal.SIGTERM)
print('Process killed.')
running = False
time.sleep(0.1)
elif running == False:
print('The process is not running.')
time.sleep(0.1)
else:
print('Critical error.')
time.sleep(0.1)
The reason I'm using my own loop to poll the GPIO pins instead of the event detection built-in in the RPi.GPIO library is because it has caused me nothing but problems and doing it myself seemed simpler. Any help would be appreciated.
Edit: I'm not sure why I didn't think of putting that call into quotes. Now it doesn't run on script start, but it only runs once. As in: I start the script with the switch OFF, and it doesn't run (as expected). I switch it ON and it runs. I switch it back OFF and it successfully kills the script. However, switching it back ON doesn't restart the script. Sorry if this is a bad explanation.
subprocess.Popen() starts the process as soon as it is called and also returns the process.
So, you can simply start the process again in the loop when it needs to be running by calling the same function again.
Slightly modifying your code:
import RPi.GPIO as GPIO
import time
import subprocess
import os
import signal
proc = subprocess.Popen(FSU, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
FSU = 'sudo mdk3 mon0 d'
# tell the GPIO module that we want to use the chip's numbering scheme
GPIO.setmode(GPIO.BCM)
# Set up GPIO16 as an input with internal pull-up resistor to hold it HIGH until it is pulled down to GND by the connected switch
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP)
running = False
while True:
if GPIO.input(16) == GPIO.LOW:
if running == False:
print('Button was pushed!')
# declare the proc variabe again and also start the process
proc = subprocess.Popen(FSU, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
running = True
time.sleep(0.1)
elif running == True:
print('The process is running.')
time.sleep(0.1)
elif GPIO.input(16) == GPIO.HIGH and running == True:
os.killpg(os.getpgid(pro.pid), signal.SIGTERM)
print('Process killed.')
running = False
time.sleep(0.1)
elif running == False:
print('The process is not running.')
time.sleep(0.1)
else:
print('Critical error.')
time.sleep(0.1)
More on subprocess
I own a 3d printer which is connectet to a raspberry. To controll (like shut on and off via relais) the printer remotely, I made a small python script.
One possibility to controll it is to use the Telegram Bot (telepot) which seems to work properly.
The other method to shut the printer on and off is a hardware switch. For secutity reasons, I want the printer to shut off only if the switch is pressed for 3 seconds.
The problem is, the script crashes sometimes (most at after a long uptime).
I assume that it's my while loop at the end, but I don't really understand why it only crashes after a variable amount of time and how to improve that.
That's the code so far:
#!/usr/bin/python
import time
import subprocess
import os
import datetime
import telepot
import urllib
import RPi.GPIO as GPIO
chat_id_auth = XXXXXXXXXXX
# Warnungen ausschalten
GPIO.setwarnings(False)
# Pin Nummern verwenden
GPIO.setmode(GPIO.BOARD)
# Pin 11 als Input
GPIO.setup(29, GPIO.IN)
GPIO.setup(11, GPIO.OUT)
GPIO.output(11, 0) #on
def handle(msg):
chat_id = msg['chat']['id']
command = msg['text']
print 'Got command: %s' % command
if chat_id == chat_id_auth:
if command == '/status':
bot.sendMessage(chat_id, 'online')
elif command == '/picture':
bashCommand = 'wget --output-document snapshot.jpg http://127.0.0.1:8080/?action=snapshot'
subprocess.check_output(bashCommand, shell=True)
print ('downloaded photo')
bot.sendPhoto(chat_id, open('snapshot.jpg','rb'), caption='Printer Status')
print ('sent photo')
bashCommand = 'rm snapshot.jpg'
subprocess.check_output(bashCommand, shell=True)
print ('removed photo')
elif command == '/ip':
bashCommand = 'ifconfig eth0 | grep \'inet addr:\' | cut -d: -f2 | awk \'{ print $1}\''
output = subprocess.check_output(bashCommand, shell=True)
bot.sendMessage(chat_id, output)
print(output)
elif command == '/on':
#bashCommand = 'echo \'0\' > /sys/class/gpio/gpio17/value'
#output = subprocess.check_output(bashCommand, shell=True)
GPIO.output(11, 0) #on
bot.sendMessage(chat_id, 'Drucker wird eingeschaltet..')
#print(output)
elif command == '/off':
#bashCommand = 'echo \'1\' > /sys/class/gpio/gpio17/value'
#output = subprocess.check_output(bashCommand, shell=True)
GPIO.output(11, 1) #off
bot.sendMessage(chat_id, 'Drucker wird ausgeschaltet..')
#print(output)
else:
bot.sendMessage(chat_id, 'You are not authorized.')
bot = telepot.Bot('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
bot.message_loop(handle)
print 'I am listening ...'
global n
n=0
while True:
if GPIO.input(29):
if GPIO.input(11) == 0:
if n >= 300: #Taster 3s halten zum Ausschalten
GPIO.output(11, 1) #off
n=0
time.sleep(2)
elif GPIO.input(11) == 1:
GPIO.output(11, 0) #on
n=0
time.sleep(2)
time.sleep(0.01)
n+=1
else:
n=0
print n
GPIO.cleanup()
I cannot see a clear reason for a crash but the while loop at the end seems to be very busy waiting when nothing is done (no button pressed). From what I understand it then prints 0 and loops without any delay, so it will print zeros as fast as it can and keeping the Raspi busy as much as possible. Maybe that load is the indirect reason for any crash you experience (but that is just wild guessing).
Anyway, I propose to improve on that massively busy waiting. Even if it does not address the crashes, it would improve your code. To achieve this, simply add a time.sleep(0.1) in the else: branch to loop at most ten times per second (and not as fast as the CPU can).
In any case you should debug the situation. Find out why there is a crash.
Log your output into some file. (./script.py >& script.log)
try/except your exceptions and print debugging stuff in case you catch some.
Whoever starts it should monitor its exit code and log it.
Unix signals received result in an exit code of 128 + the signal number.
Type kill -l on the command line to see a list of all signals and their numbers.