@unique24: Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Daraus folgt das `send_command()` das Socket-Objekt als Argument braucht und `listen()` das Socket-Objekt und das `InputDevice`-Objekt.
Namen werden in Python klein_mit_unterstrich geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).
Für Wahrheitswerte hat Python einen eigenen Datentyp (`bool`) mit den Werten `True` und `False`. Da sollte man nicht die Zahlen 0 und 1 für missbrauchen. Und man vergleicht dann auch nicht mit `True` und `False` sondern nimmt den Wert direkt oder dessen Gegenteil mit ``not``.
Um die Bedingung von ``if`` gehören keine unnötigen Klammern.
Die ersten beiden ``if``\s in `listen()` lassen sich zusammenfassen.
Der Teiltest ob `event.code` dem letzten Code entspricht ist in allen drei Bedingungen enthalten, das kann man also in ein eigenes, übergeordnetes ``if`` heraus ziehen.
Ob ein Wert zwischen zwei anderen liegt lässt sich mit verketterten Vergleichen ausdrücken was der mathematischen Schreibweise entspricht und leichter lesbar ist.
Der letzte Test scheint mir falsch zu sein weil Dein Code etwas macht wenn `delay` <0,55 ist und er macht etwas wenn `delay` >0,56 ist, aber er macht nichts wenn `delay` *zwischen* 0,55 und 0,56 liegt. Soll das so sein, und wenn ja warum? Wenn man diese Lücke nicht haben will, dann braucht man am Ende auch kein ``elif`` denn dann würde man mit ``else`` einfach den Rest abdecken.
`t1` ist kein guter Name. `t` ist nichtssagend. Man nummeriert keine Namen. Die 1 macht auch gar keinen Sinn, denn es gibt ja gar keine 2.
Bei Threads will man eigentlich fast immer einen „daemon“-Thread erstellen.
Es ist unhöflich und verwirrend einfach so dynamisch Attribute auf fremden Objekten zu setzen. Also `do_run` auf `Thread`-Objekten. Wenn man ein Flag thread-sicher über Threadgrenzen hinweg kommunizieren möchte, verwendet man ein `Event`-Objekt. Wenn man so ein Objekt `send_command()` übergibt, wird ein bisschen deutlicher wie verquer das ist diese Funktion mal synchron und mal asynchron aufzurufen, weil man in beiden Fällen ein Objekt zur Kommunikation über Threadgrenzen hinweg übergibt, das aber in einem Fall gar nicht gemacht werden muss.
Man ruft Methoden nicht auf der Klasse auf und übergibt ein Exemplar sondern ruft die Methode auf dem Exemplar auf. Also nicht ``str.encode(something)`` sondern ``something.encode()``.
Mit einem `Event` sähe `send_command()` so aus:
Code: Alles auswählen
def send_command(cancel_event, udp_socket, key, duration, delay):
print(key, duration)
while not cancel_event.is_set():
time.sleep(delay)
udp_socket.sendto(f"{key}@{duration}".encode(), (UDP_IP, UDP_PORT))
print("command sent")
cancel_event.set()
print("thread canceled")
Die ``while``-Schleife in `send_command()` ist keine Schleife weil die genau einmal durchlaufen wird, also gar nichts wiederholt wird und auch das sie gar nicht durchlaufen wird kann eigentlich nicht passieren. Die kann also weg, womit dann aber auch das `Event` gar nicht mehr verwendet wird. Und die Ausgabe grundsätzlich am Ende macht keinen Sinn weil die ja auch gemacht wird wenn der Thread nicht abgebrochen wurde, selbst wenn das passieren könnte.
Was dann übrig bliebe wäre das hier:
Code: Alles auswählen
#!/usr/bin/env python3
import socket
import threading
import time
import evdev
UDP_IP = "192.168.0.255"
UDP_PORT = 20001
REMOTE_DEVICE_FILENAME = "/dev/input/event0"
def send_command(udp_socket, key, duration, delay):
print(key, duration)
time.sleep(delay)
udp_socket.sendto(f"{key}@{duration}".encode(), (UDP_IP, UDP_PORT))
print("command sent")
print("thread ended")
def listen(udp_socket, device):
last_timestamp = 0
last_key_code = None
is_long_push = False
for event in device.read_loop():
if (
event.type == evdev.ecodes.EV_KEY
and event.code == 2
and event.value == 1
):
if event.code == last_key_code:
delay = event.timestamp() - last_timestamp
if 0.05 <= delay < 0.55:
print("warte auf langen Tastendruck")
is_long_push = False
elif delay < 0.05 and not is_long_push:
print("langer Tastendruck")
print("cancel Thread")
thread.join()
is_long_push = True
send_command(
udp_socket, "KEY_1", "long", 0
)
else:
print("kurzer Tastendruck")
thread = threading.Thread(
target=send_command,
args=(udp_socket, "KEY_1", "short", 0.7),
daemon=True,
)
thread.start()
is_long_push = False
last_key_code = event.code
last_timestamp = event.timestamp()
def main():
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
device = evdev.InputDevice(REMOTE_DEVICE_FILENAME)
print(device)
listen(udp_socket, device)
if __name__ == "__main__":
main()