python-evdev icon indicating copy to clipboard operation
python-evdev copied to clipboard

Using evdev in the background/in crontab

Open mhoejgaard opened this issue 7 years ago • 2 comments

This issue may or may not be related to evdev itself, if not please excuse my ignorance. I guess it could also be related to permissions.

I am attempting to use evdev to read button input on a NVIDIA Jetson TX2. When I run the script directly the terminal I get the desired output. When running in the background or in crontab the device.read_loop() causes the script to hang indefinetely or at least not print anything or even crash.

The script is given below:

import evdev
from evdev import ecodes
import sh
import time

DOWN = 1

print("Waiting 10 seconds for correct start up")
time.sleep(10)
print("Wait complete")

device = evdev.InputDevice("/dev/input/event3")
print(device)

# become the sole recipient of all incoming input events
device.grab()
for event in device.read_loop():
    print(evdev.categorize(event))
    if event.code == ecodes.KEY_POWER:
        print "KEY_POWER", str(event.value)
        if event.value == DOWN:
            print "Sleeping before shutdown"
            time.sleep(5)
            #sh.shutdown("now")
    elif event.code == ecodes.KEY_VOLUMEUP:
        print "KEY_VOLUMEUP", str(event.value)
#device.ungrab()

The nvidia user has been added to the input group for permission to read events without root.

I run from crontab with: @reboot python /home/nvidia/testButton.py &> /home/nvidia/testButton.log

I run in the backgrorund with: python /home/nvidia/testButton.py &> /home/nvidia/testButton.log

I run normally as: python /home/nvidia/testButton.py

mhoejgaard avatar Nov 22 '18 16:11 mhoejgaard

I'm coming across the same problem. Did you ever solve it?

rwlloyd avatar May 16 '20 13:05 rwlloyd

Sorry about the latency. We had to solve it very fast and implemented a workaround solely to solve our use case of detecting a push and release using the read_one method. I have extracted our "solution" and attached it below.

We determine the InputDevice programmatically since we had some difficulties when specifying it statically.

import evdev
import time
import os

## Find the device ##

path = "/proc/bus/input/devices"

# Open the file and get
# the file descriptor associated
# with it using os.open() method
fd = os.open(path, os.O_RDONLY)


 # Number of bytes to be read
n = 5000

# Read at most n bytes
# from file descriptor fd
# using os.read() method
readBytes = os.read(fd, n)
gpin = readBytes.find('gpio')
gpEV = readBytes.find('EV=',gpin)
gpevent = readBytes[gpEV+3]

# close the file descriptor
os.close(fd)

## Check the button ##

device = evdev.InputDevice(device+gpevent)
key = evdev.ecodes.KEY_VOLUMEUP

def check_button(value):
    event = device.read_one()
    retval = False
    if event:
        if event.code == key and event.value == value:
            retval = True
    return retval

def button_down():
    return check_button(value=evdev.KeyEvent.key_down)

def button_up():
    return check_button(value=evdev.KeyEvent.key_up)

delay = 0.01
while True:
    if button_down():
        print("Button down")
        break
    time.sleep(delay)
while True:
    if button_up():
        print("Button up")
        break
    time.sleep(delay)

mhoejgaard avatar May 25 '20 07:05 mhoejgaard