Add system tray functionality and improve Discord status detection logic
This commit is contained in:
parent
2fdfa7d3df
commit
062c6252a2
1
.gitignore
vendored
1
.gitignore
vendored
@ -0,0 +1 @@
|
|||||||
|
./*.png
|
||||||
BIN
DISCORD.lnk
BIN
DISCORD.lnk
Binary file not shown.
60
README.md
Normal file
60
README.md
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# ESP32 Discord Controller
|
||||||
|
|
||||||
|
This project allows you to control Discord mute and deafen status using an ESP32 device. The script captures the screen to detect the status and communicates with the ESP32 via a serial connection.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Python 3.x
|
||||||
|
- pip (Python package installer)
|
||||||
|
- 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:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/yourusername/ESP32-discord.git
|
||||||
|
cd ESP32-discord
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Running the Script
|
||||||
|
|
||||||
|
You can run the script with the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
python main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Specifying the COM Port
|
||||||
|
|
||||||
|
You can specify the COM port directly when running the script:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
python main.py -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.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Ensure that your ESP32 device is connected to your computer via USB.
|
||||||
|
- The script captures a small region of the screen to detect the mute and deafen status. Adjust the coordinates and dimensions in the script if necessary.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License.
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 69 B After Width: | Height: | Size: 99 B |
83
main.py
83
main.py
@ -2,13 +2,21 @@ import serial
|
|||||||
import time
|
import time
|
||||||
import keyboard
|
import keyboard
|
||||||
import serial.tools.list_ports as list_ports
|
import serial.tools.list_ports as list_ports
|
||||||
import pygetwindow as gw
|
|
||||||
import pyautogui
|
|
||||||
import mss
|
import mss
|
||||||
import numpy as np
|
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():
|
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 = list(list_ports.comports())
|
||||||
if not ports:
|
if not ports:
|
||||||
print("No serial ports found. Please connect a device.")
|
print("No serial ports found. Please connect a device.")
|
||||||
@ -20,14 +28,15 @@ def get_serial_port():
|
|||||||
return ports[choice].device
|
return ports[choice].device
|
||||||
|
|
||||||
x = -1772
|
x = -1772
|
||||||
y = 1059
|
y = 1064
|
||||||
x2 = -1745
|
x2 = -1746
|
||||||
y2 = 1064
|
y2 = 1063
|
||||||
width = 1
|
width = 4
|
||||||
height = 1
|
height = 4
|
||||||
expected_r = 242
|
expected_r = 242
|
||||||
expected_g = 63
|
expected_g = 63
|
||||||
expected_b = 67
|
expected_b = 67
|
||||||
|
grid = 4
|
||||||
|
|
||||||
def get_discord_status():
|
def get_discord_status():
|
||||||
with mss.mss() as sct:
|
with mss.mss() as sct:
|
||||||
@ -47,16 +56,57 @@ def get_discord_status():
|
|||||||
mss.tools.to_png(mute_screenshot.rgb, mute_screenshot.size, output="mute_screenshot.png")
|
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")
|
mss.tools.to_png(deafen_screenshot.rgb, deafen_screenshot.size, output="deafen_screenshot.png")
|
||||||
|
|
||||||
# Check the pixel color at (0, 0)
|
# Check the pixel color in a 2x2 region
|
||||||
mute_status = (mute_image[0, 0, 2] == expected_r and
|
mute_status = any(
|
||||||
mute_image[0, 0, 1] == expected_g and
|
(mute_image[i, j, 2] == expected_r and
|
||||||
mute_image[0, 0, 0] == expected_b)
|
mute_image[i, j, 1] == expected_g and
|
||||||
deafen_status = (deafen_image[0, 0, 2] == expected_r and
|
mute_image[i, j, 0] == expected_b)
|
||||||
deafen_image[0, 0, 1] == expected_g and
|
for i in range(grid) for j in range(grid)
|
||||||
deafen_image[0, 0, 0] == expected_b)
|
)
|
||||||
|
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
|
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():
|
def main():
|
||||||
|
global ser
|
||||||
port = get_serial_port()
|
port = get_serial_port()
|
||||||
if not port:
|
if not port:
|
||||||
return
|
return
|
||||||
@ -70,6 +120,9 @@ def main():
|
|||||||
print(f"Mute: {last_mute_status}, Deafen: {last_deafen_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'))
|
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:
|
while True:
|
||||||
try:
|
try:
|
||||||
if ser.in_waiting > 0:
|
if ser.in_waiting > 0:
|
||||||
@ -103,7 +156,7 @@ def main():
|
|||||||
except serial.SerialException as e:
|
except serial.SerialException as e:
|
||||||
print(f"Could not open serial port: {e}")
|
print(f"Could not open serial port: {e}")
|
||||||
finally:
|
finally:
|
||||||
if 'ser' in locals() and ser.is_open:
|
if 'ser' in globals() and ser.is_open:
|
||||||
ser.close()
|
ser.close()
|
||||||
print("Serial connection closed.")
|
print("Serial connection closed.")
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 69 B After Width: | Height: | Size: 110 B |
Loading…
x
Reference in New Issue
Block a user