|
|
@@ -1,105 +1,159 @@
|
|
|
-from re import A, I
|
|
|
+import platform
|
|
|
import customtkinter as ctk
|
|
|
-import json
|
|
|
from PIL import Image, ImageTk
|
|
|
import time
|
|
|
-import asyncio
|
|
|
-from dobluetooth import connect, getData
|
|
|
+import threading
|
|
|
+import tkinter as tk
|
|
|
import dobluetooth
|
|
|
|
|
|
-# This could probably go in dobluetooth.py
|
|
|
-try:
|
|
|
- from bleak.backends.winrt.util import allow_sta
|
|
|
- # tell Bleak we are using a graphical user interface that has been properly
|
|
|
- # configured to work with asyncio
|
|
|
- allow_sta()
|
|
|
-except ImportError:
|
|
|
- # other OSes and older versions of Bleak will raise ImportError which we
|
|
|
- # can safely ignore
|
|
|
- pass
|
|
|
-
|
|
|
-"""
|
|
|
-parse esp32 data string and make each axis and accell data its own varible
|
|
|
-then do math on all those varibles to give us ONE NUMBER from all six numbers
|
|
|
-
|
|
|
-"""
|
|
|
-def getCurrentScore():
|
|
|
- #than do math to figure out power level
|
|
|
- return 30
|
|
|
+# If on Windows, allow STA for Bleak
|
|
|
+if platform.system() == "Windows":
|
|
|
+ try:
|
|
|
+ from bleak.backends.winrt.util import allow_sta
|
|
|
+ allow_sta()
|
|
|
+ except ImportError:
|
|
|
+ pass
|
|
|
+
|
|
|
+# UI setup
|
|
|
+ctk.set_appearance_mode("System")
|
|
|
+ctk.set_default_color_theme("blue")
|
|
|
+
|
|
|
+app = ctk.CTk()
|
|
|
+app.geometry("1440x1024")
|
|
|
+
|
|
|
+canvas = ctk.CTkCanvas(app, width=250, height=250, highlightthickness=0)
|
|
|
+canvas.config(background="white")
|
|
|
+canvas.place(x=0, y=0)
|
|
|
+
|
|
|
+# Score variables
|
|
|
+currentScore = tk.DoubleVar()
|
|
|
+currentScore.set(0)
|
|
|
|
|
|
names = []
|
|
|
scores = []
|
|
|
-currentScore = getCurrentScore()
|
|
|
+
|
|
|
highestScore = 100
|
|
|
highScoreName = ""
|
|
|
|
|
|
-if currentScore > highestScore :
|
|
|
- highestScore = currentScore
|
|
|
- f = open("scores.txt", "rw")
|
|
|
- f.write(str(highestScore) + highScoreName)
|
|
|
- scores.append(highestScore)
|
|
|
- names.append(highScoreName)
|
|
|
+punch_on = False
|
|
|
|
|
|
+# Punch control
|
|
|
+def startPunch():
|
|
|
+ global punch_on
|
|
|
+ punch_on = True
|
|
|
+ print("STARTED PUNCH")
|
|
|
|
|
|
-ctk.set_appearance_mode("System") # Modes: system (default), light, dark
|
|
|
-ctk.set_default_color_theme("blue") # Themes: blue (default), dark-blue, green
|
|
|
+def stopPunch():
|
|
|
+ global punch_on, highestScore
|
|
|
+ punch_on = False
|
|
|
+ print("STOPPED PUNCH")
|
|
|
|
|
|
-app = ctk.CTk() # create CTk window like you do with the Tk window
|
|
|
-app.geometry("1440x1024")
|
|
|
-canvas = ctk.CTkCanvas(app, width=250, height=250,highlightthickness=0,)
|
|
|
-canvas.config(background="white")
|
|
|
-canvas.place(x=0,y=0)
|
|
|
-
|
|
|
-def placeLeaderboard():
|
|
|
- canvas.create_rectangle(0, 0, 500, 500, fill="grey20", width=2) #grey14 to match background
|
|
|
+ if currentScore.get() > highestScore:
|
|
|
+ highestScore = currentScore.get()
|
|
|
+ try:
|
|
|
+ with open("scores.txt", "w") as f: # Fixed mode from "rw" to "w"
|
|
|
+ f.write(f"{highestScore} {highScoreName}")
|
|
|
+ except Exception as e:
|
|
|
+ print("Error writing to file:", e)
|
|
|
|
|
|
- intx = 0
|
|
|
- inty = 60
|
|
|
- for i in range(len(names)):
|
|
|
- label1 = ctk.CTkLabel(width=124,height=39,text_color="white",text=names[i], font=("Arial",15),master=app)
|
|
|
- label1.place(x=intx,y=inty)
|
|
|
- label2 = ctk.CTkLabel(width=124,height=39,text_color="white",text=scores[i], font=("Arial",15),master=app)
|
|
|
- label2.place(x=intx+125,y=inty)
|
|
|
- inty+=40
|
|
|
- LEADERBOARD = ctk.CTkLabel(width=249,height=39,text_color="white",text="Leaderboard", font=("Arial",50),master=app)
|
|
|
- LEADERBOARD.place(x=0,y=0)
|
|
|
- StartButton = ctk.CTkButton(width=00,height=150,text="START",fg_color="green",corner_radius=50,font=("Arial",50),text_color="gray99",master=app)
|
|
|
- StartButton.place(x=50,y=300)
|
|
|
- ResetButton = ctk.CTkButton(width=00,height=150,text="RESET",fg_color="orange2",corner_radius=50,font=("Arial",50),text_color="gray99", master=app)
|
|
|
- ResetButton.place(x=50,y=500)
|
|
|
- scoreTitle = ctk.CTkLabel(width=50,height=20,text_color="white",text="Current Score", font=("Arial",50),master=app)
|
|
|
- scoreTitle.place(x=350, y=20)
|
|
|
- scoreLabel = ctk.CTkLabel(width=50,height=20,text_color="white",text=currentScore, font=("Arial",50),master=app)
|
|
|
- scoreLabel.place(x=500, y=100)
|
|
|
- nameEntry = ctk.CTkEntry(width=300,height=50,master=app,font=("Arial",50))
|
|
|
- nameEntry.place(x=370,y=200)
|
|
|
- nameEntryButton = ctk.CTkButton(width=50,height=50,text="ENTER",fg_color="green",font=("Arial",20),text_color="gray99", master=app)
|
|
|
- nameEntryButton.place(x=670,y=205)
|
|
|
+ scores.append(highestScore)
|
|
|
+ names.append(highScoreName)
|
|
|
|
|
|
- image = Image.open("./BellDrawing.png")
|
|
|
- photo = ImageTk.PhotoImage(image)
|
|
|
- #ctkphoto = ctk.CTkImage(image)
|
|
|
+def resetPunch():
|
|
|
+ global currentScore
|
|
|
+ currentScore.set(0)
|
|
|
+ print("reset punch")
|
|
|
|
|
|
- image_label = ctk.CTkLabel(image=photo,text="",width=10, master=app)
|
|
|
- image_label.place(x=800,y=0)
|
|
|
+dinger = ctk.CTkLabel(width=40, height=30, text="", fg_color="gray77", master=app)
|
|
|
+dinger.place(x=1405, y=900)
|
|
|
|
|
|
- dinger = ctk.CTkLabel(width=40,height=30,text="",fg_color="gray77",master=app)
|
|
|
- dinger.place(x=1405,y=900)
|
|
|
+# Leaderboard & UI setup
|
|
|
+def placeLeaderboard():
|
|
|
+ canvas.create_rectangle(0, 0, 500, 500, fill="grey20", width=2)
|
|
|
|
|
|
-placeLeaderboard()
|
|
|
+ intx = 0
|
|
|
+ inty = 60
|
|
|
+ for i in range(len(names)):
|
|
|
+ label1 = ctk.CTkLabel(width=124, height=39, text_color="white", text=names[i], font=("Arial", 15), master=app)
|
|
|
+ label1.place(x=intx, y=inty)
|
|
|
+ label2 = ctk.CTkLabel(width=124, height=39, text_color="white", text=scores[i], font=("Arial", 15), master=app)
|
|
|
+ label2.place(x=intx + 125, y=inty)
|
|
|
+ inty += 40
|
|
|
|
|
|
+ ctk.CTkLabel(width=249, height=39, text_color="white", text="Leaderboard", font=("Arial", 50), master=app).place(x=0, y=0)
|
|
|
+ ctk.CTkButton(width=0, height=150, text="START", fg_color="green", corner_radius=50, font=("Arial", 50),
|
|
|
+ text_color="gray99", master=app, command=startPunch).place(x=50, y=300)
|
|
|
+ ctk.CTkButton(width=0, height=150, text="STOP", fg_color="orange2", corner_radius=50, font=("Arial", 50),
|
|
|
+ text_color="gray99", master=app, command=stopPunch).place(x=50, y=500)
|
|
|
+ ctk.CTkButton(width=0, height=150, text="RESET", fg_color="red1", corner_radius=50, font=("Arial", 50),
|
|
|
+ text_color="gray99", master=app, command=resetPunch).place(x=50, y=700)
|
|
|
|
|
|
+ ctk.CTkLabel(width=50, height=20, text_color="white", text="Current Score", font=("Arial", 50), master=app).place(x=350, y=20)
|
|
|
+ ctk.CTkLabel(width=50, height=20, text_color="white", textvariable=currentScore, font=("Arial", 50), master=app).place(x=500, y=100)
|
|
|
|
|
|
-#label = customtkinter.CTkLabel(app, text=f"Current Highest Record is: {highestRecord} | this was acomplished by: {highestRecordName}", fg_color="brown")
|
|
|
-#progressbar = customtkinter.CTkProgressBar(app, height=300,orientation="vertical",width=40,fg_color="blue",progress_color="green",mode='determinate')
|
|
|
+ nameEntry = ctk.CTkEntry(width=300, height=50, master=app, font=("Arial", 50))
|
|
|
+ nameEntry.place(x=370, y=200)
|
|
|
|
|
|
-#progressbar.set(float(f"0.{highestRecord}"))
|
|
|
+ ctk.CTkButton(width=50, height=50, text="ENTER", fg_color="green", font=("Arial", 20),
|
|
|
+ text_color="gray99", master=app).place(x=670, y=205)
|
|
|
|
|
|
-#label.grid(column=0,row=0)
|
|
|
-#progressbar.grid(column=25,row=8)
|
|
|
+ image = Image.open("./BellDrawing.png")
|
|
|
+ photo = ImageTk.PhotoImage(image)
|
|
|
+ ctk.CTkLabel(image=photo, text="", width=10, master=app).place(x=800, y=0)
|
|
|
+
|
|
|
+# BLE thread setup
|
|
|
+def ble_thread_func():
|
|
|
+ import asyncio
|
|
|
+ loop = asyncio.new_event_loop()
|
|
|
+ asyncio.set_event_loop(loop)
|
|
|
+ loop.run_until_complete(dobluetooth.getData())
|
|
|
+
|
|
|
+def start_ble_thread():
|
|
|
+ thread = threading.Thread(target=ble_thread_func, daemon=True)
|
|
|
+ thread.start()
|
|
|
+
|
|
|
+def update_dinger_position():
|
|
|
+ global dinger
|
|
|
+ score = currentScore.get()
|
|
|
+
|
|
|
+ # Example logic: map score (0–100) to y-position (900 to 300)
|
|
|
+ # You can adjust the ranges to suit your needs
|
|
|
+ max_score = 100
|
|
|
+ min_y = 300
|
|
|
+ max_y = 900
|
|
|
+
|
|
|
+ # Clamp score between 0 and max_score
|
|
|
+ score = min(max(score, 0), max_score)
|
|
|
+
|
|
|
+ # Calculate the new y position
|
|
|
+ new_y = max_y - int((score / max_score) * (max_y - min_y))
|
|
|
+
|
|
|
+ # Move the label
|
|
|
+ dinger.place_configure(y=new_y)
|
|
|
+
|
|
|
+ # Call this again after a short delay
|
|
|
+ app.after(100, update_dinger_position)
|
|
|
+
|
|
|
+
|
|
|
+# Data processing loop in background thread
|
|
|
+def data_loop():
|
|
|
+ while True:
|
|
|
+ bledata = dobluetooth.getDataArr()
|
|
|
+ if punch_on:
|
|
|
+ accel_mag: float = bledata[7]
|
|
|
+ app.after(0, lambda val=accel_mag: currentScore.set(currentScore.get() + val))
|
|
|
+ app.after(0, update_dinger_position)
|
|
|
+ time.sleep(0.1)
|
|
|
+
|
|
|
+def start_data_loop_thread():
|
|
|
+ thread = threading.Thread(target=data_loop, daemon=True)
|
|
|
+ thread.start()
|
|
|
+
|
|
|
+# Run UI setup
|
|
|
+placeLeaderboard()
|
|
|
|
|
|
-def data():
|
|
|
- asyncio.run(dobluetooth.getData())
|
|
|
+# Start threads after UI initializes
|
|
|
+app.after(500, start_ble_thread)
|
|
|
+app.after(1000, start_data_loop_thread)
|
|
|
|
|
|
-app.after(1000,data)
|
|
|
app.mainloop()
|