ESP32-discord/main.py

165 lines
5.5 KiB
Python

import serial
import time
import keyboard
import serial.tools.list_ports as list_ports
import mss
import numpy as np
import sys
import pystray
from PIL import Image, ImageDraw
import threading
import ctypes
# Set the title for the PowerShell window
ctypes.windll.kernel32.SetConsoleTitleW("ESP32 Discord Controller")
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())
if not ports:
print("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
def get_discord_status():
with mss.mss() as sct:
# Define the region where the mute and deafen icons are located
mute_region = {"top": y, "left": x, "width": width, "height": height}
deafen_region = {"top": y2, "left": x2, "width": width, "height": height}
# Capture the screen region
mute_screenshot = sct.grab(mute_region)
deafen_screenshot = sct.grab(deafen_region)
# Convert the screenshots to numpy arrays
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
mute_image[i, j, 1] == expected_g and
mute_image[i, j, 0] == expected_b)
for i in range(grid) for j in range(grid)
)
deafen_status = any(
(deafen_image[i, j, 2] == expected_r and
deafen_image[i, j, 1] == expected_g and
deafen_image[i, j, 0] == expected_b)
for i in range(grid) for j in range(grid)
)
return mute_status, deafen_status
def create_image():
# Generate an image for the system tray icon
width = 64
height = 64
image = Image.new('RGB', (width, height), (255, 255, 255))
dc = ImageDraw.Draw(image)
dc.rectangle(
[(width // 2, 0), (width, height // 2)],
fill="black")
dc.rectangle(
[(0, height // 2), (width // 2, height)],
fill="black")
return image
def on_quit(icon, item):
icon.stop()
if 'ser' in globals() and ser.is_open:
ser.close()
print("Serial connection closed.")
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)
def hide_in_tray():
hide_console()
icon = pystray.Icon("ESP32-discord")
icon.icon = create_image()
icon.menu = pystray.Menu(pystray.MenuItem('Quit', on_quit))
threading.Thread(target=icon.run).start()
def main():
global ser
port = get_serial_port()
if not port:
return
try:
ser = serial.Serial(port, 115200, timeout=1)
time.sleep(2) # Wait for the connection to initialize
print("Listening for commands...")
last_mute_status, last_deafen_status = get_discord_status()
print(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()
while True:
try:
if ser.in_waiting > 0:
line = ser.readline().decode('utf-8').strip()
print(f"Received: {line}")
if line == "mute":
keyboard.send('ctrl+shift+f16')
elif line == "deafen":
keyboard.send('ctrl+shift+f15')
elif line == "status":
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}")
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}")
last_mute_status, last_deafen_status = current_mute_status, current_deafen_status
time.sleep(0.1)
except KeyboardInterrupt:
print("Exiting program.")
break
except Exception as e:
print(f"Error during execution: {e}")
break
except serial.SerialException as e:
print(f"Could not open serial port: {e}")
finally:
if 'ser' in globals() and ser.is_open:
ser.close()
print("Serial connection closed.")
if __name__ == "__main__":
main()