Change rendering method for GUI
Add installation scripts for Windows and Linux, and update README for usage instructions
This commit is contained in:
		
							parent
							
								
									1a01676d9f
								
							
						
					
					
						commit
						f6aa6cd626
					
				
							
								
								
									
										
											BIN
										
									
								
								DISCORD.lnk
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								DISCORD.lnk
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										40
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								README.md
									
									
									
									
									
								
							| @ -11,14 +11,6 @@ This project allows you to control Discord mute and deafen status using an ESP32 | ||||
| - An ESP32 device | ||||
| - A USB cable to connect the ESP32 to your computer | ||||
| 
 | ||||
| ### Python Packages | ||||
| 
 | ||||
| Install the required Python packages using pip: | ||||
| 
 | ||||
| ```sh | ||||
| pip install pyserial keyboard pygetwindow pyautogui mss numpy pystray pillow | ||||
| ``` | ||||
| 
 | ||||
| ### Clone the Repository | ||||
| 
 | ||||
| Clone this repository to your local machine: | ||||
| @ -28,14 +20,38 @@ git clone https://github.com/yourusername/ESP32-discord.git | ||||
| cd ESP32-discord | ||||
| ``` | ||||
| 
 | ||||
| ### Windows Installation | ||||
| 
 | ||||
| Run the following batch file to set up the virtual environment and install the required Python packages: | ||||
| 
 | ||||
| ```sh | ||||
| install_windows.bat | ||||
| ``` | ||||
| 
 | ||||
| ### Linux Installation | ||||
| 
 | ||||
| Run the following shell script to set up the virtual environment and install the required Python packages: | ||||
| 
 | ||||
| ```sh | ||||
| ./install_linux.sh | ||||
| ``` | ||||
| 
 | ||||
| ## Usage | ||||
| 
 | ||||
| ### Running the Script | ||||
| 
 | ||||
| You can run the script with the following command: | ||||
| 
 | ||||
| #### Windows | ||||
| 
 | ||||
| ```sh | ||||
| python main.py | ||||
| start.bat | ||||
| ``` | ||||
| 
 | ||||
| #### Linux | ||||
| 
 | ||||
| ```sh | ||||
| ./start.sh | ||||
| ``` | ||||
| 
 | ||||
| ### Specifying the COM Port | ||||
| @ -43,13 +59,17 @@ python main.py | ||||
| You can specify the COM port directly when running the script: | ||||
| 
 | ||||
| ```sh | ||||
| python main.py -com=COM3 | ||||
| pythonw main.pyw -com=COM3 | ||||
| ``` | ||||
| 
 | ||||
| ### Hiding the Console Window | ||||
| 
 | ||||
| If the COM port is specified, the script will hide the console window and run in the system tray. You can quit the application from the tray icon. | ||||
| 
 | ||||
| ### GUI | ||||
| 
 | ||||
| The script now includes a GUI that looks like Windows 11 dark mode. It will automatically hide the console window and show the GUI. | ||||
| 
 | ||||
| ## Notes | ||||
| 
 | ||||
| - Ensure that your ESP32 device is connected to your computer via USB. | ||||
|  | ||||
							
								
								
									
										15
									
								
								install_linux.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								install_linux.sh
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| #!/bin/bash | ||||
| 
 | ||||
| # Create a virtual environment | ||||
| python3 -m venv .venv | ||||
| 
 | ||||
| # Activate the virtual environment | ||||
| source .venv/bin/activate | ||||
| 
 | ||||
| # Install the required Python packages | ||||
| pip install pyserial keyboard pygetwindow pyautogui mss numpy pystray pillow | ||||
| 
 | ||||
| # Deactivate the virtual environment | ||||
| deactivate | ||||
| 
 | ||||
| echo "Installation complete. You can now run the application using start.sh." | ||||
							
								
								
									
										15
									
								
								install_windows.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								install_windows.bat
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| @echo off | ||||
| REM Create a virtual environment | ||||
| python -m venv .venv | ||||
| 
 | ||||
| REM Activate the virtual environment | ||||
| call .venv\Scripts\activate | ||||
| 
 | ||||
| REM Install the required Python packages | ||||
| pip install pyserial keyboard pygetwindow pyautogui mss numpy pystray pillow | ||||
| 
 | ||||
| REM Deactivate the virtual environment | ||||
| deactivate | ||||
| 
 | ||||
| echo Installation complete. You can now run the application using start.bat. | ||||
| pause | ||||
| @ -10,6 +10,25 @@ from PIL import Image, ImageDraw | ||||
| import threading | ||||
| import ctypes | ||||
| import os | ||||
| import tkinter as tk | ||||
| from tkinter import messagebox | ||||
| from tkinter import ttk | ||||
| 
 | ||||
| # Define the region where the mute and deafen icons are located | ||||
| x = -1772 | ||||
| y = 1064 | ||||
| x2 = -1746 | ||||
| y2 = 1063 | ||||
| 
 | ||||
| # Define the size of the region to check | ||||
| width = 4 | ||||
| height = 4 | ||||
| grid = 4 | ||||
| 
 | ||||
| # Define the expected color of the mute and deafen icons | ||||
| expected_r = 242 | ||||
| expected_g = 63 | ||||
| expected_b = 67 | ||||
| 
 | ||||
| # Set the title for the PowerShell window | ||||
| ctypes.windll.kernel32.SetConsoleTitleW("ESP32 Discord Controller") | ||||
| @ -26,26 +45,32 @@ def get_serial_port(): | ||||
|     if len(sys.argv) > 1 and sys.argv[1].startswith("-com="): | ||||
|         return sys.argv[1].split("=")[1] | ||||
|      | ||||
|     ports = list(list_ports.comports()) | ||||
|     ports = [port for port in list(list_ports.comports()) if port.device != "COM1"] | ||||
|     if not ports: | ||||
|         print("No serial ports found. Please connect a device.") | ||||
|         messagebox.showerror("Error", "No serial ports found. Please connect a device.") | ||||
|         return None | ||||
|     print("Available Ports:") | ||||
|     for i, port in enumerate(ports): | ||||
|         print(f"{i}: {port.device}") | ||||
|     choice = int(input("Select a port by number: ")) | ||||
|     return ports[choice].device | ||||
|      | ||||
| x = -1772 | ||||
| y = 1064 | ||||
| x2 = -1746 | ||||
| y2 = 1063 | ||||
| width = 4 | ||||
| height = 4 | ||||
| expected_r = 242 | ||||
| expected_g = 63 | ||||
| expected_b = 67 | ||||
| grid = 4 | ||||
|     if len(ports) == 1: | ||||
|         return ports[0].device | ||||
|      | ||||
|     port_choices = [port.device for port in ports] | ||||
|      | ||||
|     def on_select(): | ||||
|         selected_port.set(port_listbox.get(port_listbox.curselection())) | ||||
|         port_window.destroy() | ||||
|      | ||||
|     port_window = tk.Tk() | ||||
|     port_window.title("Select Serial Port") | ||||
|     port_window.configure(bg="#1e1e1e") | ||||
|     tk.Label(port_window, text="Available Ports:", bg="#1e1e1e", fg="#ffffff").pack() | ||||
|     port_listbox = tk.Listbox(port_window, bg="#2d2d2d", fg="#ffffff", selectbackground="#0078d7") | ||||
|     for port in port_choices: | ||||
|         port_listbox.insert(tk.END, port) | ||||
|     port_listbox.pack() | ||||
|     selected_port = tk.StringVar() | ||||
|     tk.Button(port_window, text="Select", command=on_select, bg="#0078d7", fg="#ffffff").pack() | ||||
|     port_window.mainloop() | ||||
|     return selected_port.get() | ||||
| 
 | ||||
| def get_discord_status(): | ||||
|     with mss.mss() as sct: | ||||
| @ -61,10 +86,6 @@ def get_discord_status(): | ||||
|         mute_image = np.array(mute_screenshot) | ||||
|         deafen_image = np.array(deafen_screenshot) | ||||
|          | ||||
|         # # Save the screenshots to files | ||||
|         # mss.tools.to_png(mute_screenshot.rgb, mute_screenshot.size, output="mute_screenshot.png") | ||||
|         # mss.tools.to_png(deafen_screenshot.rgb, deafen_screenshot.size, output="deafen_screenshot.png") | ||||
|          | ||||
|         # Check the pixel color in a 2x2 region | ||||
|         mute_status = any( | ||||
|             (mute_image[i, j, 2] == expected_r and | ||||
| @ -95,32 +116,35 @@ def create_image(): | ||||
|     return image | ||||
| 
 | ||||
| def toggle_console(): | ||||
|     whnd = ctypes.windll.kernel32.GetConsoleWindow() | ||||
|     if whnd != 0: | ||||
|         if ctypes.windll.user32.IsWindowVisible(whnd): | ||||
|             ctypes.windll.user32.ShowWindow(whnd, 0) | ||||
|         else: | ||||
|             ctypes.windll.user32.ShowWindow(whnd, 1) | ||||
|     if console_window.state() == "normal": | ||||
|         console_window.withdraw() | ||||
|     else: | ||||
|         console_window.deiconify() | ||||
| 
 | ||||
| def log_message(message): | ||||
|     log_text.insert(tk.END, message + "\n") | ||||
|     log_text.see(tk.END) | ||||
| 
 | ||||
| def on_quit(icon, item): | ||||
|     icon.stop() | ||||
|     if 'ser' in globals() and ser.is_open: | ||||
|         ser.close() | ||||
|         print("Serial connection closed.") | ||||
|         log_message("Serial connection closed.") | ||||
|     console_window.withdraw() | ||||
|     console_window.quit() | ||||
|     sys.exit(0) | ||||
| 
 | ||||
| def hide_console(): | ||||
|     whnd = ctypes.windll.kernel32.GetConsoleWindow() | ||||
|     if whnd != 0: | ||||
|         ctypes.windll.user32.ShowWindow(whnd, 0) | ||||
|         ctypes.windll.kernel32.CloseHandle(whnd) | ||||
|     log_message("Hiding console window...") | ||||
|     time.sleep(2) | ||||
|     console_window.withdraw() | ||||
| 
 | ||||
| def hide_in_tray(): | ||||
|     hide_console() | ||||
|     icon = pystray.Icon("ESP32-discord") | ||||
|     icon.icon = create_image() | ||||
|     icon.menu = pystray.Menu(pystray.MenuItem('Quit', on_quit), pystray.MenuItem('Toggle Console', toggle_console)) | ||||
|     threading.Thread(target=icon.run).start() | ||||
|     hide_console() | ||||
| 
 | ||||
| def main(): | ||||
|     global ser | ||||
| @ -131,20 +155,20 @@ def main(): | ||||
|     try: | ||||
|         ser = serial.Serial(port, 115200, timeout=1) | ||||
|         time.sleep(2)  # Wait for the connection to initialize | ||||
|         print("Listening for commands...") | ||||
|         log_message("Listening for commands...") | ||||
|          | ||||
|         last_mute_status, last_deafen_status = get_discord_status() | ||||
|         print(f"Mute: {last_mute_status}, Deafen: {last_deafen_status}") | ||||
|         log_message(f"Mute: {last_mute_status}, Deafen: {last_deafen_status}") | ||||
|         ser.write(f"Mute: {last_mute_status}, Deafen: {last_deafen_status}\n".encode('utf-8')) | ||||
|          | ||||
|         if len(sys.argv) > 1 and sys.argv[1].startswith("-com="): | ||||
|             hide_in_tray() | ||||
|         hide_in_tray() | ||||
| 
 | ||||
|          | ||||
|         while True: | ||||
|             try: | ||||
|                 if ser.in_waiting > 0: | ||||
|                     line = ser.readline().decode('utf-8').strip() | ||||
|                     print(f"Received: {line}") | ||||
|                     log_message(f"Received: {line}") | ||||
|                      | ||||
|                     if line == "mute": | ||||
|                         keyboard.send('ctrl+shift+f16') | ||||
| @ -154,28 +178,39 @@ def main(): | ||||
|                         mute_status, deafen_status = get_discord_status() | ||||
|                         ser.write(f"Mute: {mute_status}, Deafen: {deafen_status}\n".encode('utf-8')) | ||||
|                     else: | ||||
|                         print(f"Unknown command: {line}") | ||||
|                         log_message(f"Unknown command: {line}") | ||||
|                      | ||||
|                 current_mute_status, current_deafen_status = get_discord_status() | ||||
|                 if current_mute_status != last_mute_status or current_deafen_status != last_deafen_status: | ||||
|                     ser.write(f"Mute: {current_mute_status}, Deafen: {current_deafen_status}\n".encode('utf-8')) | ||||
|                     print(f"Mute: {current_mute_status}, Deafen: {current_deafen_status}") | ||||
|                     log_message(f"Mute: {current_mute_status}, Deafen: {current_deafen_status}") | ||||
|                     last_mute_status, last_deafen_status = current_mute_status, current_deafen_status | ||||
|                  | ||||
|                 time.sleep(0.1) | ||||
|             except KeyboardInterrupt: | ||||
|                 print("Exiting program.") | ||||
|                 log_message("Exiting program.") | ||||
|                 break | ||||
|             except Exception as e: | ||||
|                 print(f"Error during execution: {e}") | ||||
|                 log_message(f"Error during execution: {e}") | ||||
|                 break | ||||
|      | ||||
|     except serial.SerialException as e: | ||||
|         print(f"Could not open serial port: {e}") | ||||
|         messagebox.showerror("Error", f"Could not open serial port: {e}") | ||||
|     finally: | ||||
|         if 'ser' in globals() and ser.is_open: | ||||
|             ser.close() | ||||
|             print("Serial connection closed.") | ||||
|             log_message("Serial connection closed.") | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     main() | ||||
|     console_window = tk.Tk() | ||||
|     console_window.title("ESP32 Discord Controller") | ||||
|     console_window.configure(bg="#1e1e1e") | ||||
|     style = ttk.Style() | ||||
|     style.theme_use('clam') | ||||
|     style.configure("TLabel", background="#1e1e1e", foreground="#ffffff") | ||||
|     style.configure("TButton", background="#0078d7", foreground="#ffffff") | ||||
|     style.configure("TText", background="#2d2d2d", foreground="#ffffff") | ||||
|     log_text = tk.Text(console_window, wrap=tk.WORD, bg="#2d2d2d", fg="#ffffff") | ||||
|     log_text.pack(expand=True, fill=tk.BOTH) | ||||
|     threading.Thread(target=main).start() | ||||
|     console_window.mainloop() | ||||
							
								
								
									
										9
									
								
								start.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								start.bat
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| @echo off | ||||
| REM Activate the virtual environment | ||||
| call .venv\Scripts\activate | ||||
| 
 | ||||
| REM Run the Python script | ||||
| start pythonw main.pyw | ||||
| 
 | ||||
| REM Deactivate the virtual environment | ||||
| deactivate | ||||
| @ -2,7 +2,7 @@ | ||||
| & .venv\Scripts\activate | ||||
| 
 | ||||
| # Run the Python script | ||||
| python main.py -com=COM3 | ||||
| pythonw main.pyw | ||||
| 
 | ||||
| # Deactivate the virtual environment | ||||
| deactivate | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user