epoll() for /dev/input device? - python

I am working with events coming from /dev/input/event0, buttons. I'm currently polling in an infinite loop but would prefer to wait for an event.
import struct
# https://docs.python.org/3/library/struct.html#format-characters
FORMAT = 'llHHI'
EVENT_SIZE = struct.calcsize(FORMAT)
EV_KEY = 0x01
KEY_UP = 0
KEY_DOWN = 1
KEY_AUTO = 2
with open('/dev/input/event0', 'rb') as infile:
state = 0
while True:
event = infile.read(EVENT_SIZE)
(tv_sec, tv_usec, typ, code, value) = struct.unpack(FORMAT, event)
if 0 == state:
if EV_KEY == typ and KEY_DOWN == value:
print('You pressed a button')
state = 1
elif 1 == state:
if EV_KEY == typ and KEY_UP == value:
print('You released a button')
state = 0
Can I use epoll() with python to accomplish this in much less code?

Related

Python PyQt5 setting the label of 32 textlabel by for loop

I am getting some voltage value from the box and based on that I need to update the text of all 32 text labels one by one.
if switch == 'J1':
if StatusPT[0] == True and StatusLED[0] == True:
self.color[0] = Qt.green
self.StatusJ1.setText('Pass')
if StatusPT[0] == False:
self.color[0] = Qt.red
self.StatusJ1.setText(StatusPT[1])
elif StatusLED[0] == False:
self.color[0] = Qt.red
self.StatusJ1.setText(StatusLED[1])
if switch == 'J2':
if StatusPT[0] == True and StatusLED[0] == True:
self.color[1] = Qt.green
self.StatusJ2.setText('Pass')
elif StatusPT[0] == False:
self.color[1] = Qt.red
self.StatusJ2.setText(StatusPT[1])
elif StatusLED[0] == False:
self.color[1] = Qt.red
self.StatusJ2.setText(StatusLED[1])
so I have 32 self.Status(J1-J32).setText
is there any way I do for loop to update them?

Detecting when a key is pressed and break when another key is pressed[Python]

So I'm making a game without PyGame, and I want to add a section where you try to press the correct keyboard letters given the "number" of the letter, which would mean A - 1, B - 2, C - 3, etc. I want to make it so you can't mash every key, so I added a counter. However - the counter doesn't work. Help!
def keyboardpart(l,x,num):
for i in range(num):
keypress = False
c = 0
dn = random.randint(0,25)
var = l[dn]
print(dn+1)
flag1 = False
start = time.time()
while time.time()-start < x:
if keypress and not keyboard.is_pressed(var):
if c > 3:
break
c+=1
elif keyboard.is_pressed(var) and not keypress:
keypress = True
print(keypress,c)
if not keypress:
print("Sorry, you missed that key.")
flag1 = True
break
if flag1:
keyboardpart(l,x,num)
Check if any keys are pressed then check if the target key is pressed. Also wait until all keys are released before retry.
Try this code:
import random, keyboard, time
l = [chr(65+i) for i in range(26)] # A-Z
def keyboardpart(l,x,num):
for i in range(num):
keyboard.is_pressed(65) # process OS events
while len(keyboard._physically_pressed_keys): pass # wait until keys released
keypress = False
c = 0
dn = random.randint(0,25)
var = l[dn]
print(dn+1, l[dn])
flag1 = False
start = time.time()
while time.time()-start < x:
if len(keyboard._physically_pressed_keys): # any key down
if keyboard.is_pressed(var): # check target key
keypress = True
break
else: # wrong key
c+=1
if c >= 3: break # allow 3 tries
while len(keyboard._physically_pressed_keys): pass # wait until keys released
print(keypress, c)
print(keypress,c)
if not keypress:
print("Sorry, you missed that key.")
flag1 = True
break
if flag1:
keyboardpart(l,x,num)
keyboardpart(l,100,4)

Getting the rate of change of a variable

I'm fairly new to Python.
My goal is to press a button and a counter (counta) goes up by 1 every time I press 'a'.
Now I want - for example print out - how many times I've pressed the 'a' button within 10 seconds (for example).
The code is working fine like this. Now i only want to add this feature to print the chagne rate. Any ideas?
Until now my code looks like this:
from pynput.keyboard import Listener
import sched, time
s = sched.scheduler(time.time, time.sleep)
counta = 0
Timer = 0
On = True
def on_press(key):
if key.char == 'a':
#print("")
global counta
counta += 1
#print("Aktuell" + str(counta))
elif key.char == 'p':
print(int(counta/3))
else:
print("wrong button")
print("a = counta")
listener = Listener(on_press=on_press)
listener.start()
while On:
print(int(counta//3))
print(counta)
time.sleep(1)
listener.join()
Is that what you are looking for? And what do you mean by change rate?
from pynput.keyboard import Listener
import time
counta = 0
end = time.time() + 10
def on_press(key):
global counta
if key.char == 'a':
counta += 1
elif key.char == 'p':
print(int(counta/3))
else:
print("Falsche Taste!")
print("a = counta")
listener = Listener(on_press=on_press)
listener.start()
while True:
if end - time.time() >= 0:
pass
# print(end - time.time())
else:
print(counta)
counta = 0
end = time.time() + 10
listener.join()

TypeError: 'InputDevice' object is not iterable

Im going to paste my entire function here before the question.
def trackBoth():
#if event determination variable is 1 it has both K and M if it is 2 it is only K or M if 3 then none
x_max = 800 #defines largest position mouse can go (19th LED)
x_min = -800 #defines smallest position mouse can go (9th LED)
y_max = 800
y_min = -800
try:
keyboardEvent = evdev.InputDevice('/dev/input/event0') #setting keyboard to USB port
mouseEvent = evdev.InputDevice('/dev/input/event1') #setting mouse to USB port
event_det = 1
except:
try:
keyboardEvent = evdev.InputDevice('/dev/input/event0')
event_det = 2
except:
try:
keyboardEvent = evdev.InputDevice('/dev/input/event1')
event_det = 2
except:
event_det = 3
NoKeyboardMouse()
async def print_events(device):
global x, y #must be inside of loop or else nonlocal error is thrown
x = 0 #defines the start of x
y = 0 #defines the start of y
async for event in device.async_read_loop():
if event.type == ecodes.EV_REL: #if the event is a mouse moving
if event.code == ecodes.REL_X: #chechking for x direction
print("REL_X", event.value)
x += event.value #advance the cursor position
#every 80 increments advance 1 led
if event.code == ecodes.REL_Y: #checking for y direction
print("REL_Y", event.value)
y += event.value * -1 #advance the cursor position
print(x, y)
if event.type == ecodes.EV_KEY: #if the event is a button click
c = categorize(event)
if c.keystate == c.key_down: #only reading key for down press not up
print(c.keycode)
if "BTN_LEFT" in c.keycode: #if it is a left mouse click go to check where the cursor is
checkPosition()
if c.keycode == "BTN_RIGHT": #if it is a right click override the current display
rightClick()
if c.keycode == "KEY_1":
ser.write(str.encode('1'))
if c.keycode == "KEY_2":
ser.write(str.encode('2'))
if c.keycode == "KEY_3":
ser.write(str.encode('3'))
if c.keycode == "KEY_4":
ser.write(str.encode('4'))
if c.keycode == "KEY_5":
ser.write(str.encode('5'))
if c.keycode == "KEY_6":
ser.write(str.encode('6'))
if c.keycode == "KEY_7":
ser.write(str.encode('7'))
if c.keycode == "KEY_8":
ser.write(str.encode('8'))
if c.keycode == "KEY_9":
ser.write(str.encode('9'))
if c.keycode == "KEY_0":
ser.write(str.encode('0'))
if c.keycode == "KEY_S":
ser.write(str.encode('s'))
if c.keycode == "KEY_G":
ser.write(str.encode('g'))
if (event_det == 1):
for device in keyboardEvent, mouseEvent:
asyncio.ensure_future(print_events(device))
if (event_det == 2):
for device in keyboardEvent:
asyncio.ensure_future(print_events(device))
loop = asyncio.get_event_loop()
loop.run_forever()
basically my issue is in this section
if (event_det == 1):
for device in keyboardEvent, mouseEvent:
asyncio.ensure_future(print_events(device))
if (event_det == 2):
for device in keyboardEvent:
asyncio.ensure_future(print_events(device))
when i try to run this code assuming event_det is equal to 2 i get this error
Traceback (most recent call last):
File "etho.py", line 569, in <module>
trackBoth()
File "etho.py", line 559, in trackBoth
for device in keyboardEvent:
TypeError: 'InputDevice' object is not iterable
assuming i had both a keyboard and mouse plugged in it would run fine (event_det = 1). Why is it giving me the error when it only attempts to run one event (keyboardEvent) how should i change my code here.

How to change "ON/OFF" string data into 0/1?

I am monitoring and controlling a smart light bulb from my dashboard(User Interface Dashboard) and every time I open or close the light bulb it sends back a data that shows the light bulb is on or off, what I want to do is to change this "ON/OFF" data string in to binary of 1/0, is there anyway I can get 1 or 0 instead of 'ON/OFF'.
this is some of the API code I have used to control the light bulb
def identifyDevice(self):
identifyDeviceResult = False
print(" {0}Agent for {1} is identifying itself by doing colorloop. Please observe your lights"
.format(self.variables.get('agent_id', None), self.variables.get('model', None)))
try:
devicewasoff = 0
if self.get_variable('status') == "OFF":
devicewasoff = 1
self.setDeviceStatus({"status": "ON"})
elif self.only_white_bulb:
self.setDeviceStatus({"status": "OFF"})
if self.only_white_bulb is False:
self.setDeviceStatus({"effect": "colorloop"})
if self.only_white_bulb:
time_iden = 3
else:
time_iden = 10 # time to do identification
t0 = time.time()
self.seconds = time_iden
while time.time() - t0 <= time_iden:
self.seconds = self.seconds - 1
print("wait: {} sec".format(self.seconds))
time.sleep(1)
self.setDeviceStatus({"effect": "none"})
if devicewasoff == 1:
self.setDeviceStatus({"status": "OFF"})
else:
self.setDeviceStatus({"status": "ON"})
identifyDeviceResult = True
except:
print("ERROR: classAPI_PhilipsHue connection failure! # identifyDevice")
return identifyDeviceResult
If you can guarantee that the returned value is always one of 'ON' or 'OFF', you can use the fact that True and 1 are interchangeable
result = state == 'ON'
If you need some error handling, something like this might work.
if state in {'ON', 'OFF'}:
result = state == 'ON'
else:
# handle error state
If you need an int to serialise, call int with the result
>>> state_on = 'ON'
>>> state_off = 'OFF'
>>> int(state_on == 'ON')
1
>>> int(state_off == 'ON')
0

Categories

Resources