Raspbian 在睡眠时检测键盘输入

问题描述

我在 Raspbian 中有一个 python 脚本,它无限循环并在主函数执行之间休眠 15 分钟。 Main 是线程化的,但通常需要 3 秒才能运行。我不希望任何代码中断,及时进行下一次调用。在睡眠期间,我想检测按键 'r' 以选择性地启动另一个 func,也可能是线程化的。

我尝试了 pynput 模块,但出现了奇怪的暂停,这似乎与线程处理和使用 VNC 签入有关,这是我需要的。我还在线程中尝试了常规的旧输入,但在没有用户输入的情况下无法结束线程。

键盘模块在 Windows 中运行良好,但没有检测到 Raspbian 的按键。我正在使用 sudo "sudo python3 scriptname.py" 运行脚本我并不在乎是否通过使用线程即时检测密钥。如果需要,我可以在一分钟左右后切断我的睡眠周期以调用函数。我只是不能有很大的停顿。

import time
import keyboard
import threading

def mainFunc():
    print('does stuff')

def keyFunc():
    print('do key detect stuff')

while True:
    t1 = threading.Thread(target=mainFunc)
    t1.start()
    time.sleep(60)
    t1.join()
    keyboard.on_press_key("r",lambda _:keyFunc())
    for _ in range(14):
        time.sleep(60)
    keyboard.unhook_all()

解决方法

我认为有帮助的一种方法是从 datetime 对象创建一个时间跨度持续时间,并将其用于主循环。

这是我创建的示例。希望对您的 pi raspbian 脚本有所帮助。

from datetime import *
import time
import keyboard
import threading

#every 3 second function
x_start = datetime.now()
xSleep=3
def mainFunc():
    newTime = datetime.now()
    if(getTimeDiff(x_start,newTime)>xSleep):
        setXStart(datetime.now())
        return True
#every 15 minute function
y_start = datetime.now()
ySleep=900
def fifteenMinuteFunction():
    newTime = datetime.now()
    if(getTimeDiff(y_start,newTime)>ySleep):
        setYStart(datetime.now())
        return True 
#key press function (from pressing p)
def keyFunc():
    print("do keystuff")
#calculate time difference since last call
def getTimeDiff(start,end):
    span = end - start
    #convert to string
    spanStr = str(span)[0:7]
    hours   = spanStr[0:1]
    minutes = spanStr[2:4]
    seconds = spanStr[5:7]
    #convert to rounded int (seconds)
    seconds = int(seconds) + (int(minutes) * 60) + (int(hours) * 60 * 60)
    return int(seconds)
#set new start time for 3 second function
def setXStart(newTime):
    global x_start 
    x_start = newTime
#set new start tiem for 15 minute function
def setYStart(newTime):
    global y_start 
    y_start = newTime

#bind keyboard keys
keyboard.on_press_key("p",lambda _:keyFunc())                  # p do stuff function

while True:
    if keyboard.is_pressed('x'):                                # exit keybind to x
        exit()
    elif mainFunc():
        print("Doing thingy every "+str(xSleep)+" seconds")     # 3 seconds
    elif fifteenMinuteFunction():
        print("Doing thingy every "+str(ySleep)+" seconds")     # 15 mins
    else:
        time.sleep(.1)                                          

输出:

do keystuff
doing thingy every 3 seconds
do keystuff
doing thingy every 3 seconds
doing thingy every 3 seconds
....
doing thingy every 900 seconds
...
,
def inputDaemon():
    while True:
        x = input('r to reload')
        if x == 'r': doTheFunc()

inpD = threading.Thread(target=inputDaemon)
inpD.daemon = True
inpD.start()

我最终使用的并且运行良好。