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