Concurrent functions running in separate process using pygame and multiprocessing - python

Suppose we want to drive an autonomous car by predicting image labels from a previous set of images and labels collected (A Machine Learning application). For this task, the car is connected via bluetooth serial (rfcomm) to the Host Computer (A PC with *NIX) and the images are streamed directly from an Android phone using IP Webcam, meanwhile, the PC is running a program that links this two functions, displaying the captured images in a drawing environment created by pygame, and sending the instructions back to the car using serial.
At the moment, I've tried to implement those processes using the multiprocessing module, the seemed to work, but when I execute the client, the drawing function (if __name__ == '__main__') works after the getKeyPress() function ends.
The question is: It is possible to parallelize or synchronize the drawing fuinction enclosed within the if __name__ == '__main__' with the process declared in getKyPress(), such that the program works in two independent processes?
Here's the implemented code so far:
import urllib
import time
import os
import sys
import serial
import signal
import multiprocessing
import numpy as np
import scipy
import scipy.io as sio
import matplotlib.image as mpimg
from pygame.locals import *
PORT = '/dev/rfcomm0'
SPEED = 115200
ser = serial.Serial(PORT)
status = False
move = None
targets = []
inputs = []
tic = False
def getKeyPress():
import pygame
pygame.init()
global targets
global status
while not status:
pygame.event.pump()
keys = pygame.key.get_pressed()
targets, status = processOutputs(targets, keys)
targets = np.array(targets)
targets = flattenMatrix(targets)
sio.savemat('targets.mat', {'targets':targets})
def rgb2gray(rgb):
r, g, b = np.rollaxis(rgb[...,:3], axis = -1)
return 0.299 * r + 0.587 * g + 0.114 * b
def processImages(inputX, inputs):
inputX = flattenMatrix(inputX)
if len(inputs) == 0:
inputs = inputX
elif inputs.shape[1] >= 1:
inputs = np.hstack((inputs, inputX))
return inputs
def flattenMatrix(mat):
mat = mat.flatten(1)
mat = mat.reshape((len(mat), 1))
return mat
def send_command(val):
connection = serial.Serial( PORT,
SPEED,
timeout=0,
stopbits=serial.STOPBITS_TWO
)
connection.write(val)
connection.close()
def processOutputs(targets, keys):
global move
global status
global tic
status = False
keypress = ['K_p', 'K_UP', 'K_LEFT', 'K_DOWN', 'K_RIGHT']
labels = [1, 2, 3, 4, 5]
commands = ['p', 'w', 'r', 'j', 's']
text = ['S', 'Up', 'Left', 'Down', 'Right']
if keys[K_q]:
status = True
return targets, status
else:
for i, j, k, g in zip(keypress, labels, commands, text):
cmd = compile('cond = keys['+i+']', '<string>', 'exec')
exec cmd
if cond:
move = g
targets.append(j)
send_command(k)
break
send_command('p')
return targets, status
targetProcess = multiprocessing.Process(target=getKeyPress)
targetProcess.daemon = True
targetProcess.start()
if __name__ == '__main__':
import pygame
pygame.init()
w = 288
h = 352
size=(w,h)
screen = pygame.display.set_mode(size)
c = pygame.time.Clock() # create a clock object for timing
pygame.display.set_caption('Driver')
ubuntu = pygame.font.match_font('Ubuntu')
font = pygame.font.Font(ubuntu, 13)
inputs = []
try:
while not status:
urllib.urlretrieve("http://192.168.0.10:8080/shot.jpg", "input.jpg")
try:
inputX = mpimg.imread('input.jpg')
except IOError:
status = True
inputX = rgb2gray(inputX)/255
out = inputX.copy()
out = scipy.misc.imresize(out, (352, 288), interp='bicubic', mode=None)
scipy.misc.imsave('input.png', out)
inputs = processImages(inputX, inputs)
print inputs.shape[1]
img=pygame.image.load('input.png')
screen.blit(img,(0,0))
pygame.display.flip()
c.tick(1)
if move != None:
text = font.render(move, False, (255, 128, 255), (0, 0, 0))
textRect = text.get_rect()
textRect.centerx = 20 #screen.get_rect().centerx
textRect.centery = 20 #screen.get_rect().centery
screen.blit(text, textRect)
pygame.display.update()
if status:
targetProcess.join()
sio.savemat('inputs.mat', {'inputs':inputs})
except KeyboardInterrupt:
targetProcess.join()
sio.savemat('inputs.mat', {'inputs':inputs})
targetProcess.join()
sio.savemat('inputs.mat', {'inputs':inputs})
Thanks in advance.

I would personally suggest writing this without using the multiprocessing module: it uses fork() which has unspecified effects with most complex libraries, like in this case pygame.
You should try to write this as two completely separate programs. It forces you to think about what data needs to go from one to the other, which is both a bad and a good thing (as it may clarify things). You can use some inter-process communication facility, like the stdin/stdout pipe; e.g. in one program (the "main" one) you start the other as a sub-process like this:
popen = subprocess.Popen([sys.executable, '-u', 'my_subproc.py'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
(The -u is for unbuffered.)
Then read/write the data to popen.stdin/popen.stdout in the parent process, and to sys.stdin/sys.stdout in the subprocess. The simplest example would be if the two processes only need a synchronization signal, e.g. the parent process waits in a loop for the subprocess to say "next please". To do this the subprocess does print 'next please', and the parent process does popen.stdin.readline(). (The print goes to sys.stdin in the subprocess.)
Unrelated small note:
keypress = ['K_p', ...]
...
cmd = compile('cond = keys['+i+']', '<string>', 'exec')
exec cmd
if cond:
This looks like very heavy code to just do:
keypress = [K_p, ...] # not strings, directly the values
...
if keys[i]:

My suggestion is to use separate threads.
#At the beginning
import threading
#Instead of def getKeyPress()
class getKeyPress(threading.Thread):
def run(self):
import pygame
pygame.init()
global targets
global status
while not status:
pygame.event.pump()
keys = pygame.key.get_pressed()
targets, status = processOutputs(targets, keys)
targets = np.array(targets)
targets = flattenMatrix(targets)
sio.savemat('targets.mat', {'targets':targets})
#Instead of
#targetProcess = multiprocessing.Process(target=getKeyPress)
#targetProcess.daemon = True
#targetProcess.start()
gkp = getKeyPress()
gkp.start()
An alternative would be creating two different scripts and using sockets to handle the inter-process communication.

Related

why does the keyboard.is_pressed() function refuse to work when pressed?

i have less than 3 months of python programming under my belt but basically, i have a program that pulls values from the CoinGecko API indefinitely and creates processes so the functions that pull the data can run independently from one another, but id like for it to break its loop after i press the specified hotkey which is set to 'q'. whenever i press the hotkey, nothing happens and the loop just keeps running. i've tried using the keyboard.read_key() function, but that just stops my program from running until i press the q button, which causes the program to run the loop once and then close. i have no idea why the is_pressed() function refuses to work and id like some help from more advanced people
Piece of Code in question:
from multiprocessing.dummy import freeze_support
from pycoingecko import CoinGeckoAPI
import time
from multiprocessing import Process
from multiprocessing import Pool
import multiprocessing
import keyboard as kb
import psutil
cg = CoinGeckoAPI()
class CGCoin:
def __init__(self, coinname, coinid):
self.coinname = coinname
self.coinid = coinid
def pulldata(self):
while True:
wishtoquit = False
if kb.is_pressed('Q'):
print('ending after this loop')
wishtoquit = True
timestarted = time.asctime()
self.prices = []
self.daychanges = []
self.volumes = []
self.marketcaps = []
self.weekchanges = []
self.highs = []
self.lows = []
self.times = []
print(f'starting {self.coinname} reading at {timestarted}')
loops = 0
maxloops = 2
while loops < maxloops:
time.sleep(15)
coin = cg.get_coin_by_id(f'{self.coinid}')
time.sleep(5)
coinvalues = coin.get('market_data')
coinprices = coinvalues.get('current_price')
coinvolumes = coinvalues.get('total_volume')
mrktcaps = coinvalues.get('market_cap')
dayhigh = coinvalues.get('high_24h')
daylow = coinvalues.get('low_24h')
daychangepercentage = coinvalues.get('price_change_percentage_24h')
weekchangepercentage = coinvalues.get('price_change_percentage_7d')
coinprice = coinprices.get('usd')
coinvolume = coinvolumes.get('usd')
coincap = mrktcaps.get('usd')
coindayhigh = dayhigh.get('usd')
coindaylow = daylow.get('usd')
timepulled = time.asctime()
self.prices.append(coinprice)
self.daychanges.append(daychangepercentage)
self.volumes.append(coinvolume)
self.marketcaps.append(coincap)
self.weekchanges.append(weekchangepercentage)
self.highs.append(coindayhigh)
self.lows.append(coindaylow)
self.times.append(timepulled)
loops = loops + 1
print(loops)
timeended = time.asctime()
})
print(f'stopping {self.coinname} reading at {timeended}')
if wishtoquit:
print('ending loops')
break
time.sleep(5)
bitcoin = CGCoin('Bitcoin', 'bitcoin')
ethereum = CGCoin('Ethereum', 'ethereum')
if __name__ == '__main__':
freeze_support()
btcpul = Process(target=bitcoin.pulldata, name=bitcoin.coinname)
btcpul.start()
if anyone has any ideas or fully-functional workarounds id really like to hear them. id be extremely grateful for any help recieved
It looks like PyPi keyboard needs root permissions on linux.
You could just do kb.on_press_key("p", lambda _: sys.exit(0)) and just do a sys.exit(0) to end the script.
If you're running this in the terminal you should just be able to press ctrl+c to interrupt its execution.
ref: How to detect key presses?

Pygame read MIDI input

I referenced the Pygame MIDI documentation and this code to try to get MIDI input to work.
The MIDI Interface (Avid Eleven Rack) receives MIDI data from my MIDI controller just fine in my audio software (Pro Tools). Using Pygame, however, I can not seem to read any information at all.
Source Code
import pygame
from pygame.locals import *
from pygame import midi
class MidiInput():
def __init__(self):
# variables
self.elevenRackInID = 2
# init methods
pygame.init()
pygame.midi.init()
self.midiInput = pygame.midi.Input(self.elevenRackInID, 100)
def run(self):
# print(pygame.midi.Input(3, 100))
# for i in range(10):
# print(pygame.midi.get_device_info(i), i)
self.read = self.midiInput.read(100)
# self.convert = pygame.midi.midis2events(self.read, self.elevenRackInID)
print(self.read)
test = MidiInput()
while True:
test.run()
The only thing printed to the console are empty square brackets:
[]
Additional Info
I just checked again: the input ID is the right one and it is in fact an input.
"self.midiInput.poll()" returns False. So according to the Pygame documentation there is no data coming in.
You can see the data, poll and device info below:
data: [] || poll: False || device info: (b'MMSystem', b'Eleven Rack', 1, 0, 1)
A list of all my MIDI devices according to Pygame (with indexes):
(b'MMSystem', b'Microsoft MIDI Mapper', 0, 1, 0) 0
(b'MMSystem', b'External', 1, 0, 0) 1
(b'MMSystem', b'Eleven Rack', 1, 0, 1) 2
(b'MMSystem', b'Maschine Mikro MK2 In', 1, 0, 0) 3
(b'MMSystem', b'Microsoft GS Wavetable Synth', 0, 1, 0) 4
(b'MMSystem', b'External', 0, 1, 0) 5
(b'MMSystem', b'Eleven Rack', 0, 1, 0) 6
(b'MMSystem', b'Maschine Mikro MK2 Out', 0, 1, 0) 7
Any help or suggestions are greatly appreciated!
I got an answer in another forum. It turns out that there is an example file which shows how to get the code to work.
So if someone else stumbles over this problem here is the useful part of example code:
import sys
import os
import pygame as pg
import pygame.midi
def print_device_info():
pygame.midi.init()
_print_device_info()
pygame.midi.quit()
def _print_device_info():
for i in range(pygame.midi.get_count()):
r = pygame.midi.get_device_info(i)
(interf, name, input, output, opened) = r
in_out = ""
if input:
in_out = "(input)"
if output:
in_out = "(output)"
print(
"%2i: interface :%s:, name :%s:, opened :%s: %s"
% (i, interf, name, opened, in_out)
)
def input_main(device_id=None):
pg.init()
pg.fastevent.init()
event_get = pg.fastevent.get
event_post = pg.fastevent.post
pygame.midi.init()
_print_device_info()
if device_id is None:
input_id = pygame.midi.get_default_input_id()
else:
input_id = device_id
print("using input_id :%s:" % input_id)
i = pygame.midi.Input(input_id)
pg.display.set_mode((1, 1))
going = True
while going:
events = event_get()
for e in events:
if e.type in [pg.QUIT]:
going = False
if e.type in [pg.KEYDOWN]:
going = False
if e.type in [pygame.midi.MIDIIN]:
print(e)
if i.poll():
midi_events = i.read(10)
# convert them into pygame events.
midi_evs = pygame.midi.midis2events(midi_events, i.device_id)
for m_e in midi_evs:
event_post(m_e)
del i
pygame.midi.quit()
You can find the file yourself in this directory:
C:\Users\myUser\AppData\Roaming\Python\Python37\site-packages\pygame\examples\midi.py
Replace 'myUser' with your Win username. Also, 'Python37' can vary on the version of Python you have installed.
I don't believe the code posted below by Leonhard W is usable: neither the pygame.midi poll() method nor the pygame.midi read() method are blocking. The result is that CPU consumption goes through the roof (~50%).
Of course in practice the code to read the MIDI events would be run in a separate thread, though this won't help with CPU consumption.
In response to another very useful comment elsewhere, I've taken a look at the Mido library (https://mido.readthedocs.io/en/latest/index.html#). This provides blocking read methods and with just a few lines of code I can look for messages from a MIDI controller keyboard and pass them onto a MIDI synth.
import mido
names = mido.get_input_names()
print(names)
out_port = mido.open_output()
with mido.open_input(names[0]) as inport:
for msg in inport:
out_port.send(msg)
The only downside is that I'm getting a significant delay (perhaps 1/4s) between hitting the key and hearing the note. Oh well, onwards and upwards.

Get result from multiprocessing process

I want to know if is there a way to make multiprocessing working in this code. What should I change or if there exist other function in multiprocessing that will allow me to do that operation.
You can call the locateOnScreen('calc7key.png') function to get the screen coordinates. The return value is a 4-integer tuple: (left, top, width, height).
I got error:
checkNumber1 = resourceBlankLightTemp[1]
TypeError: 'Process' object does not support indexing
import pyautogui, time, os, logging, sys, random, copy
import multiprocessing as mp
BLANK_DARK = os.path.join('images', 'blankDark.png')
BLANK_LIGHT = os.path.join('images', 'blankLight.png')
def blankFirstDarkResourcesIconPosition():
blankDarkIcon = pyautogui.locateOnScreen(BLANK_DARK)
return blankDarkIcon
def blankFirstLightResourcesIconPosition():
blankLightIcon = pyautogui.locateOnScreen(BLANK_LIGHT)
return blankLightIcon
def getRegionOfResourceImage():
global resourceIconRegion
resourceBlankLightTemp = mp.Process(target = blankFirstLightResourcesIconPosition)
resourceBlankDarkTemp = mp.Process(target = blankFirstDarkResourcesIconPosition)
resourceBlankLightTemp.start()
resourceBlankDarkTemp.start()
if(resourceBlankLightTemp == None):
checkNumber1 = 2000
else:
checkNumber1 = resourceBlankLightTemp[1]
if(resourceBlankDarkTemp == None):
checkNumber2 = 2000
else:
checkNumber2 = resourceBlankDarkTemp[1]
In general, if you just want to use multiprocessing to run existing CPU-intensive functions in parallel, it is easiest to do through a Pool, as shown in the example at the beginning of the documentation:
# ...
def getRegionOfResourceImage():
global resourceIconRegion
with mp.Pool(2) as p:
resourceBlankLightTemp, resourceBlankDarkTemp = p.map(
lambda x: x(), [blankFirstLightResourcesIconPosition,
blankFirstDarkResourcesIconPosition])
if(resourceBlankLightTemp == None):
# ...

Python Updating Mayavi Using a Timer While Running Other Threads

Is it possible to create a Mayavi visualization that is updated on a timed bases rather than through Trait events?
I have a visualization that I need to update continually, but the data I am updating is coming from an external source (I.E. not an event from a user input from the graphical interface).
In the mean time, I need to be running a separate thread - so the Mayavi visualization can't control the main loop.
Can this be done? And if so How??
Any help would be very greatly appreciated.
Some dummy code for how I'm trying to tackle this is below:
import numpy
from mayavi.sources.array_source import ArraySource
from pyface.api import GUI
from mayavi.modules.api import Surface
from mayavi.api import Engine
import threading
import time
# Class runs a given function on a given thread at a given scan time
class TimedThread(threading.Thread):
def __init__(self, thread, scan_time, funct, *funct_args):
threading.Thread.__init__(self)
# Thread for the function to operate in
self.thread = thread
# Defines the scan time the function is to be run at
self.scan_time = scan_time
# Function to be run
self.run_function = funct
# Function arguments
self.funct_args = funct_args
def run(self):
while True:
# Locks the relevant thread
self.thread.acquire()
# Begins timer for elapsed time calculation
start_time = time.time()
# Runs the function that was passed to the thread
self.run_function(*self.funct_args)
# Wakes up relevant threads to listen for the thread release
self.thread.notify_all()
# Releases thread
self.thread.release()
# Calculates the elapsed process time & sleeps for the remainder of the scan time
end_time = time.time()
elapsed_time = end_time - start_time
sleep_time = self.scan_time - elapsed_time
if sleep_time > 0:
time.sleep(sleep_time)
else:
print 'Process time exceeds scan time'
# Function to update the visualisation
def update_visualisation(source):
print("Updating Visualization...")
# Pretend the data is being updated externally
x = numpy.array([0, numpy.random.rand()])
y = z = x
data = [x, y, z]
source.scalar_data = data
GUI.invoke_later(source.update)
# Function to run the visualisation
def run_main():
print 'Running Main Controller'
if __name__ == '__main__':
c = threading.Condition()
# Create a new Engine for Mayavi and start it
engine = Engine()
engine.start()
# Create a new Scene
engine.new_scene()
# Create the data
x = numpy.linspace(0, 10, 2)
y = z = x
data = [x, y, z]
# Create a new Source, map the data to the source and add it to the Engine
src = ArraySource()
src.scalar_data = data
engine.add_source(src)
# Create a Module
surf = Surface()
# Add the Module to the Engine
engine.add_module(surf)
# Create timed thread classes
visualisation_thread = TimedThread(c, 2.0, update_visualisation, src)
main_thread = TimedThread(c, 1.0, run_main)
# Start & join the threads
main_thread.start()
visualisation_thread.start()
main_thread.join()
visualisation_thread.join()
Found solution in the following link:
Animating a mayavi points3d plot
Solved by using the #mlab.animator to call the update function and using the yield command to release the animation to allow for user manipulation.
Solution below:
import numpy as np
import threading
import time
from mayavi import mlab
from mayavi.api import Engine
# Class runs a given function on a given thread at a given scan time
class SafeTimedThread(threading.Thread):
def __init__(self, thread_condition, scan_time, funct, *funct_args):
threading.Thread.__init__(self)
# Thread condition for the function to operate with
self.tc = thread_condition
# Defines the scan time the function is to be run at
self.scan_time = scan_time
# Function to be run
self.run_function = funct
# Function arguments
self.funct_args = funct_args
def run(self):
while True:
# Locks the relevant thread
self.tc.acquire()
# Begins timer for elapsed time calculation
start_time = time.time()
# Runs the function that was passed to the thread
self.run_function(*self.funct_args)
# Wakes up relevant threads to listen for the thread release
self.tc.notify_all()
# Releases thread
self.tc.release()
# Calculates the elapsed process time & sleep for the remainder of the scan time
end_time = time.time()
elapsed_time = end_time - start_time
sleep_time = self.scan_time - elapsed_time
if sleep_time > 0:
time.sleep(sleep_time)
else:
print 'Process time exceeds scan time'
# Function to run the main controller
def run_main():
print 'Running Main Controller'
def init_vis():
# Creates a new Engine, starts it and creates a new scene
engine = Engine()
engine.start()
engine.new_scene()
# Initialise Plot
data = np.random.random((3, 2))
x = data[0]
y = data[1]
z = data[2]
drawing = mlab.plot3d(x, y, z, np.ones_like(x))
return drawing
#mlab.animate(delay=500, ui=False)
def update_visualisation(drawing):
while True:
print ('Updating Visualisation')
# Pretend to receive data from external source
data = np.random.random((3, 2))
x = data[0]
y = data[1]
z = data[2]
drawing.mlab_source.set(x=x, y=y, z=z)
yield
if __name__ == '__main__':
# Create Condition for Safe Threading
c = threading.Condition()
# Create display window
dwg = init_vis()
# Create safe timed thread for main thread and start
main_thread = SafeTimedThread(c, 1.0, run_main).start()
# Update using mlab animator
vis_thread = update_visualisation(dwg)
mlab.show()

Raspberry Pi - Python & Flask web control with Adafruit DotStar LEDS

apologies if this isn't the right place to ask, but I did some searching and couldn't find much to point me in the right direction. I wasn't quite sure what to search for. I am a novice with python and programming in general, but usually can do enough googling and stealing other code snippets to get my projects running. However I'm at a bit of a roadblock here.
I need to control an Adafruit DotStar lightstrip with a flask web browser app. I've been able to get the flask app working, I've done a simple proof of concept with turning an LED on and off etc., and I can start my lightstrip script but the code I'm trying to run for the lightstrip needs to loop continuously and still be able to change "modes". I have several different images that display on the light strip and I would like to be able to select which one(s) is/are playing, but for now mainly I would just like to be able to start and stop a "shuffle all" mode. If I run the module in a while loop it just loops forever and I can't change the argument to a different "mode". I built a simple script based on Adafruit's DotStar library (specifically the image persistence of vision script, I'm just using PNG images as the map for the different lightstrip "shows").
It all currently works except it only runs each mode once obviously. I had it all in a while loop and it just looped the first selected mode forever and I was unable to turn it off or switch modes. I also thought maybe I should use multiprocessing, and I looked into getting that working, but I couldn't figure out how to stop a process once it started.
Here is the light strip script:
(the 'off' mode is just a black image. I'm sure theres a cleaner way to do this but I'm not sure on how to do that either)
import Image
from dotstar import Adafruit_DotStar
import random
def lightstrip(mode):
loopLength = 120 #loop length in pixels
fade = "/home/pi/lightshow/images/fade.png"
sparkle = "/home/pi/lightshow/images/sparkle.png"
steeplechase = "/home/pi/lightshow/images/steeplechase.png"
bump = "/home/pi/lightshow/images/bump.png"
spaz = "/home/pi/lightshow/images/spaz.png"
sine = "/home/pi/lightshow/images/sine.png"
bounce = "/home/pi/lightshow/images/bounce.png"
off = "/home/pi/lightshow/images/null.png"
numpixels = 30
datapin = 23
clockpin = 24
strip = Adafruit_DotStar(numpixels, 100000)
rOffset = 3
gOffset = 2
bOffset = 1
strip.begin()
if mode == 1:
options = [fade, sparkle, steeplechase, bump, spaz, sine, bounce]
print "Shuffling All..."
if mode == 2:
options = [bump, spaz, sine, bounce]
print "Shuffling Dance..."
if mode == 3:
options = [fade, sparkle, steeplechase]
print "Shuffling Chill..."
if mode == 0:
choice = off
print "Lightstrip off..."
if mode != 0:
choice = random.choice(options)
print "Loading..."
img = Image.open(choice).convert("RGB")
pixels = img.load()
width = img.size[0]
height = img.size[1]
print "%dx%d pixels" % img.size
# Calculate gamma correction table, makes mid-range colors look 'right':
gamma = bytearray(256)
for i in range(256):
gamma[i] = int(pow(float(i) / 255.0, 2.7) * 255.0 + 0.5)
# Allocate list of bytearrays, one for each column of image.
# Each pixel REQUIRES 4 bytes (0xFF, B, G, R).
print "Allocating..."
column = [0 for x in range(width)]
for x in range(width):
column[x] = bytearray(height * 4)
# Convert entire RGB image into column-wise BGR bytearray list.
# The image-paint.py example proceeds in R/G/B order because it's counting
# on the library to do any necessary conversion. Because we're preparing
# data directly for the strip, it's necessary to work in its native order.
print "Converting..."
for x in range(width): # For each column of image...
for y in range(height): # For each pixel in column...
value = pixels[x, y] # Read pixel in image
y4 = y * 4 # Position in raw buffer
column[x][y4] = 0xFF # Pixel start marker
column[x][y4 + rOffset] = gamma[value[0]] # Gamma-corrected R
column[x][y4 + gOffset] = gamma[value[1]] # Gamma-corrected G
column[x][y4 + bOffset] = gamma[value[2]] # Gamma-corrected B
print "Displaying..."
count = loopLength
while (count > 0):
for x in range(width): # For each column of image...
strip.show(column[x]) # Write raw data to strip
count = count - 1
And the main.py script for running the web app:
from flask import *
from lightshow import *
from multiprocessing import Process
import RPi.GPIO as GPIO
import Image
from dotstar import Adafruit_DotStar
import random
import time
app = Flask(__name__)
#app.route("/")
def hello():
return render_template('index.html')
#app.route("/lightstrip/1", methods=['POST'])
def shuffleall():
lightstrip(1)
return ('', 204)
#app.route("/lightstrip/2", methods=['POST'])
def shuffledance():
lightstrip(2)
return ('', 204)
#app.route("/lightstrip/3", methods=['POST'])
def shufflechill():
lightstrip(3)
return ('', 204)
#app.route("/lightstrip/0", methods=['POST'])
def off():
lightstrip(0)
return ('', 204)
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True)
Again I'm at a bit of a loss here, this may be simple fix or I may be approaching it totally wrong but any and all help would be appreciated. I am a complete beginner to approaching a problem like this. Thank you
Here's an example showing how to start and stop processes using multiprocessing and psutil. In this example the task_runner kills any running processes before starting a new one.
from flask import Flask
import multiprocessing
import psutil
app = Flask(__name__)
def blink(var):
while True:
# do stuff
print(var)
def task_runner(var):
processes = psutil.Process().children()
for p in processes:
p.kill()
process = multiprocessing.Process(target=blink, args=(var,))
process.start()
#app.route("/red")
def red():
task_runner('red')
return 'red started'
#app.route("/blue")
def blue():
task_runner('blue')
return 'blue started'
if __name__ == "__main__":
app.run()
For your question, the task_runner would look something like:
def task_runner(mode):
processes = psutil.Process().children()
for p in processes:
p.kill()
process = multiprocessing.Process(target=lightstrip, args=(mode,))
process.start()

Categories

Resources