Read a single event (keypress) from asyncio - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Read a single event (keypress) from asyncio (/thread-33776.html) |
Read a single event (keypress) from asyncio - cygnus_X1 - May-26-2021 I'm using asyncio library to read input from a Infra Red remote control. This is python 3.7 branch on an Orange Pi Zero, using the built in IR receiver as the event loop. The problem is asyncio is so fast that a single keypress will often read multiple times. Is there any way to read a single event, or perhaps wait 50 milliseconds ? Below is the python Code import asyncio from evdev import InputDevice irr = InputDevice('/dev/input/event0') # Receive keypress from IRR and store as 'code' async def rec_code(): await asyncio.sleep(0.1) async for event in irr.async_read_loop(): if event.type == 4: global code await asyncio.sleep(0.2) # small delay to prevent two keypresses code = event.value await asyncio.sleep(0.2) # small delay to prevent two keypresses print("IRC Code ",code) async def delay5(): while True: await asyncio.sleep(5) print("5 sec delay") # Create asyncio loop run two independent timer loops and IR receiver function loop= asyncio.get_event_loop() loop.create_task(delay5()) loop.create_task(rec_code()) loop.run_forever()Below is the output: IRC Code 5 IRC Code 5 IRC Code 2 IRC Code 4 So sometimes a single keypress i.e. 2 or 4 is displayed, but mostly it will report multiple reads as button 5 has been reported twice. Wanted Output: IRC Code 5 IRC Code 2 IRC Code 4 I would like some way to catch just one keypress. I've tried to slow down event loop reading with multiple await asyncio.sleep(0.1) lines, but Im still reading same key twice. Thanks in advance for any help RE: Read a single event (keypress) from asyncio - deanhystad - May-26-2021 This is a difficult question to answer without knowing more about the messages sent by the remote. Does it send a button release message? If so, you can ignore button presses (repeats) between the initial press and the release. If it doesn't send a release you could do something like record the time for each button press event and ignore the press if it occurred to soon after the prior event. RE: Read a single event (keypress) from asyncio - cygnus_X1 - May-26-2021 (May-26-2021, 03:38 PM)deanhystad Wrote: This is a difficult question to answer without knowing more about the messages sent by the remote. Does it send a button release message? If so, you can ignore button presses (repeats) between the initial press and the release. If it doesn't send a release you could do something like record the time for each button press event and ignore the press if it occurred to soon after the prior event. Thanks for your help. The remote control uses RC5 protocol, and I modified the code to print all events as below: import asyncio from evdev import InputDevice irr = InputDevice('/dev/input/event0') list = [] # Receive keypress from IRR and store as 'code' async def rec_code(): await asyncio.sleep(0.2) async for event in irr.async_read_loop(): await asyncio.sleep(0.2) # small delay to prevent two keypresses print (event) if event.type == 4: code = event.value await asyncio.sleep(0.05) # small delay to prevent two keypresses print("IRC Code ",code) async def delay5(): while True: await asyncio.sleep(5) print("5 sec delay") # Create asyncio loop run two independent timer loops and IR receiver function loop= asyncio.get_event_loop() loop.create_task(delay5()) loop.create_task(rec_code()) loop.run_forever()The output is shown below, a key pressed generated a type 04 event and a release generates a type 00 event as below event at 1622048234.443833, code 04, type 04, val 02 IRC Code 2 event at 1622048234.443833, code 00, type 00, val 00 event at 1622048234.554707, code 04, type 04, val 02 IRC Code 2 event at 1622048234.554707, code 00, type 00, val 00 event at 1622048236.268338, code 04, type 04, val 04 IRC Code 4 event at 1622048236.268338, code 00, type 00, val 00 event at 1622048236.379183, code 04, type 04, val 04 IRC Code 4 event at 1622048236.379183, code 00, type 00, val 00 The output is from keys '2' and '4' pressed on the remote. The asyncio is processing so fast and I've slowed down the Orange Pi to run at 400Mhz. I think the problem is even with the delays in asyncio loop it is asynchronously collecting events. RE: Read a single event (keypress) from asyncio - deanhystad - May-26-2021 Remove all the waits while continuing to print the events. If the code shows the event toggling between 04 and 00 it means that there are multiple events sent and you are not looking at the same event over and over. Unless my understanding of evdev.InputDevice is wrong, putting a delay in your event processor (rec_code()) will not change the number of button press events. The events will remain in the event queue until read. The only thing the wait does is make your code take a longer time to process all the events. It sounds like you came to the same conclusion. With your code set up to print all events, press and hold a button. Do you get a stream of 4, 0, events or just one? If you get many events my guess is the remote does the same thing as key-repeat on a keyboard; it is generating press/release events as long as hold the button down. Is the delay the same between each 04 event? To make this easier to spot I would print the elapsed time since last event. Something like this: async def rec_code(): end_time = time() async for event in irr.async_read_loop(): start_time, end_time =endtime, time() print (end_time - start_time, event)Once you know the delay between these repeat events you can use elapsed time to filter them out. async def rec_code(): end_time = time() async for event in irr.async_read_loop(): start_time, end_time =endtime, time() if end_time - start_time > repeat_time: # Process button press |