问题描述:

I am developing a motion detector with a default audio playback once motion is detected with Raspberry Pi.

However when consecutive motion are detected, the next audio will start playing and begin to overlap when the previous one have not even ended.

Any loop I can implement to do this in python?

Currently, I am using a timer loop with the total length of the audio before playing another. However I believe there are better solutions. Any idea?

#!/usr/bin/python

import sched, time

s = sched.scheduler(time.time, time.sleep)

def do_something(sc):

print "Doing stuff..."

# do your stuff

sc.enter(10, 1, do_something, (sc,))

s.enter(10, 1, do_something, (s,))

s.run()

网友答案:

This is just an idea, but easier to write as an answer instead of in the comments. A workaround could be to set a state, where each time the function is running it is 1 higher. If it is over 1, wait until the end of the function, then run the function again, otherwise just run the function normally.

If it doesn't work I'll delete the answer, but I think it might do (though possibly with a couple of tweaks).

import sched, time
s = sched.scheduler(time.time, time.sleep)
state = 0

def do_something(sc):
    global state

    #increase the state, and cancel if it's over 1 (already running)
    state += 1
    if state > 1:
        return

    original_state = state
    print "Doing stuff..."
    # do your stuff
    sc.enter(10, 1, do_something, (sc,))

    #Run again if the state has changed during the function
    if original_state != state:
        s.run()
        state -= 1
    state -= 1

Edit: Made my own function that seems to work. It executes in the background and queues them up using the state idea. The time.sleep(0.01) part is just because the end seemed to overlap with the start of the next one. With args and kwargs, it'll pass them even if it's empty, so you've gotta allow for them in your function.

Main part:

import time
from threading import Thread

class ThreadHelper(Thread):
    def __init__(self, function, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        Thread.__init__(self)
        self.function = function

    def run(self):
        self.function(*self.args, **self.kwargs)

def run_once(func, *args, **kwargs):
    global state

    state[0] += 1
    original_state = state[0]

    if state[0] > 1:
        return

    func(*args, **kwargs)
    time.sleep(0.01)

    while state[0] != original_state:
        state[0] -= 1
        func(*args, **kwargs)
        time.sleep(0.01)

    state[0] -= 1

How you use it:

def dosomething(*args, **kwargs):
    print 'start'
    time.sleep(0.5)
    print 'end'

state = [0]
ThreadHelper(run_once, dosomething, _state=state).start()
ThreadHelper(run_once, dosomething, _state=state).start()
ThreadHelper(run_once, dosomething, _state=state).start()
相关阅读:
Top