208 lines
6.8 KiB
Python

import queue
import threading
import time
import tkinter as tk
from kitt import KITT
import serial.tools.list_ports
from pynput import keyboard
from dist_func import process
from student_code import dist_func
if __name__ == "__main__":
serial_selector = tk.Tk()
serial_selector.title("Select serial port")
ports = list(serial.tools.list_ports.comports())
length = len(ports) * 25
serial_selector.geometry(f"600x{length+50}")
selected_port = tk.StringVar()
for port in ports:
tk.Radiobutton(serial_selector,text = f"{port.device}",variable=selected_port,value= port.device).pack()
def select_port():
global selected_port
selected_port = selected_port.get()
serial_selector.destroy()
button = tk.Button(serial_selector, text="Select serial port", command=select_port)
button.pack()
serial_selector.mainloop()
car = KITT(f"{selected_port}")
root = tk.Tk()
root.title("Patatje Oorloog")
root.geometry("800x600")
# Speed
speed_label = tk.Label(root, text=f"Speed {car.get_speed()}")
speed_label.grid(row = 0, column = 0)
speed_var = tk.StringVar()
speed_entry = tk.Entry(root, textvariable=speed_var)
speed_entry.grid(row = 0, column = 1)
def speed_btn():
global car
car.set_speed(speed_var.get())
speed_label.config(text = f"Speed {car.get_speed()}")
speed_set_btn = tk.Button(root, text="Set Speed", command=speed_btn)
speed_set_btn.grid(row = 0, column = 2)
# Steering
angle_label = tk.Label(root, text=f"Angle {car.get_angle()}")
angle_label.grid(row = 1, column = 0)
angle_var = tk.StringVar()
angle_entry = tk.Entry(root, textvariable=angle_var)
angle_entry.grid(row=1, column=1)
def angle_btn():
global car
car.set_angle(angle_var.get())
angle_label.config(text=f"Speed {car.get_angle()}")
angle_set_btn = tk.Button(root, text="Set Angle", command=angle_btn)
angle_set_btn.grid(row=1, column=2)
# Beacon
beacon_label = tk.Label(root, text=f"Beacon {car.get_beacon_state()}")
beacon_label.grid(row = 2, column = 0)
def toggle_beacon_btn():
global car
car.toggle_beacon()
beacon_label.config(text = f"Beacon {car.get_beacon_state()}")
beacon_toggle = tk.Button(root, text="Toggle Beacon", command=toggle_beacon_btn)
beacon_toggle.grid(row = 2, column = 1)
# Recording time
rec_time_var = tk.StringVar()
rec_time_label = tk.Label(root, text=f"Rec Time {rec_time_var}")
rec_time_label.grid(row = 3, column = 0)
rec_time_entry = tk.Entry(root, textvariable=rec_time_var)
rec_time_entry.grid(row=3, column=1)
# Distance sensor
sensor_label = tk.Label(root, text=f"Speed {dist_func.process(rec_time_var)}")
sensor_label.grid(row=0, column=0)
sensor_var = tk.StringVar()
sensor_entry = tk.Entry(root, textvariable=sensor_var)
sensor_entry.grid(row=0, column=1)
def sensor_btn():
dist_func.process(rec_time_var)
sensor_label.config(text=f"Speed {dist_func.process(rec_time_var)}")
sensor_set_btn = tk.Button(root, text="Request Sensor Reading", command=sensor_btn)
sensor_set_btn.grid(row=0, column=2)
# Close UI and disconnect serial connection
def close_btn_func():
car.stop_beacon()
car.stop()
try:
car.close()
except OSError:
pass
root.destroy()
close_btn = tk.Button(root, text="Close", command=close_btn_func)
close_btn.grid(row = 10,column = 0)
# Thread-safe queue for passing keys from listener to Tkinter
key_queue = queue.Queue()
last_key = None
def start_listener():
"""Start pynput listener in a background thread."""
def on_press(key):
# Put a string representation of the key into the queue
global last_key
try:
key_queue.put(f"{key.char}")
if True: #not key == last_key :
if key.char == "w":
car.set_speed(165)
speed_label.config(text = f"Speed {car.get_speed()}")
if key.char == "s":
car.set_speed(140)
speed_label.config(text=f"Speed {car.get_speed()}")
if key.char == "a":
car.set_angle(200)
angle_label.config(text=f"Angle {car.get_angle()}")
if key.char == "d":
car.set_angle(100)
angle_label.config(text=f"Angle {car.get_angle()}")
#last_key = key
except AttributeError:
key_queue.put(str(key))
if str(key) == "Key.space":
car.toggle_beacon()
beacon_label.config(text=f"Beacon {car.get_beacon_state()}")
def on_release(key):
# Stop listener if ESC is pressed
if key == keyboard.Key.esc:
return False
try :
if key.char == "w":
car.set_speed(150)
speed_label.config(text=f"Speed {car.get_speed()}")
if key.char == "s":
car.set_speed(150)
speed_label.config(text=f"Speed {car.get_speed()}")
if key.char == "a":
car.set_angle(150)
angle_label.config(text=f"Angle {car.get_angle()}")
if key.char == "d":
car.set_angle(150)
angle_label.config(text=f"Angle {car.get_angle()}")
except AttributeError:
pass
return None
def run_listener():
with keyboard.Listener(on_press=on_press,
on_release=on_release) as listener:
listener.join()
# Run listener in its own thread so it does not block Tkinter
t = threading.Thread(target=run_listener, daemon=True)
t.start()
def poll_queue():
"""Check the queue for new keys and update the label."""
try:
while True:
k = key_queue.get_nowait()
current = label_var.get()
label_var.set(f"Last key: {k}")
except queue.Empty:
pass
# Schedule next poll
root.after(10, poll_queue)
label_var = tk.StringVar(value="Press any key (global). ESC stops listener.")
label = tk.Label(root, textvariable=label_var, width=50)
label.grid(row = 9,column = 0)
start_button = tk.Button(root, text="Start listener", command=start_listener)
start_button.grid(row = 9, column = 1)
# Start polling the queue
root.after(10, poll_queue)
root.protocol("WM_DELETE_WINDOW", close_btn_func)
root.mainloop()