From 030cfb19c35997450a54a8c6cce44ee8131a7118 Mon Sep 17 00:00:00 2001 From: Ashish Date: Thu, 13 Mar 2025 10:52:51 +0530 Subject: [PATCH 1/7] implemented app mode selection --- monitor.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/monitor.py b/monitor.py index 8ae17fa..36c5da6 100644 --- a/monitor.py +++ b/monitor.py @@ -9,7 +9,7 @@ import configparser import pyautogui from winotify import Notification, audio -from PyQt6.QtWidgets import QApplication, QMessageBox +from PyQt6.QtWidgets import QApplication, QMessageBox, QPushButton import sys import random import time @@ -38,7 +38,7 @@ def capture_screen(): opencv_img = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR) return opencv_img -def show_alert(): +def show_pop_up(): app = QApplication.instance() or QApplication(sys.argv) msg = QMessageBox() @@ -54,7 +54,20 @@ def show_alert(): stop_music() if result == QMessageBox.StandardButton.No or result == QMessageBox.StandardButton.Yes: return result - return show_alert() + return show_pop_up() + +def show_app_mode_pop_up(): + app = QApplication.instance() or QApplication(sys.argv) + msg = QMessageBox() + msg.setWindowTitle("Desktop Monitor") + msg.setText("Please select application mode!") + standardModeButton = msg.addButton("Standard", QMessageBox.ButtonRole.ActionRole) + aggressiveModeButton = msg.addButton("Agressive", QMessageBox.ButtonRole.ActionRole) + # msg.setStandardButtons(standardModeButton | aggressiveModeButton) + result = msg.exec() + if (msg.clickedButton() == standardModeButton): + return 'standard' + return 'aggressive' def show_toast_notification(message): @@ -111,6 +124,9 @@ def play_music(self): def monitor(self): """Main monitoring loop""" + print_line("Choose application mode") + appMode = show_app_mode_pop_up() + print_line(f"Selected application mode: {appMode}") print_line(f"Starting desktop monitoring. Looking for image: {self.target_image_path}") print_line(f"Will check every 10 to 20 seconds") @@ -126,9 +142,12 @@ def monitor(self): if not image_found: print_line("Target image not found! Playing alert...") self.play_music() + # if(appMode == 'agressive'): + # click_acquire_button() + # Present a popup asking if the user wants to continue - result = show_alert() + result = show_pop_up() if result == QMessageBox.StandardButton.Yes: # User clicked "Yes" print_line("User chose to continue monitoring.") # Notify user and wait for 30 seconds before starting From 3b89e5ec108b3b4bef73707ef1ff2a64d2c3b96f Mon Sep 17 00:00:00 2001 From: Ashish Date: Thu, 13 Mar 2025 15:51:15 +0530 Subject: [PATCH 2/7] implemented aggressive mode --- config.ini | 1 + monitor.py | 38 +++++++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/config.ini b/config.ini index b20b34b..45c07f7 100644 --- a/config.ini +++ b/config.ini @@ -1,5 +1,6 @@ [Files] image_name = image1.png +acquire_button_image_name = acquireButton.png mp3_name = for_elise_by_beethoven.mp3 [Settings] diff --git a/monitor.py b/monitor.py index 36c5da6..c4fe4b6 100644 --- a/monitor.py +++ b/monitor.py @@ -91,12 +91,16 @@ def __init__(self): # Set up paths self.project_dir = Path(__file__).parent self.target_image_path = self.project_dir / self.config['Files']['image_name'] + self.acquire_button_image_path = self.project_dir / self.config['Files']['acquire_button_image_name'] self.alert_sound_path = self.project_dir / self.config['Files']['mp3_name'] # Load the reference image self.reference_image = cv2.imread(str(self.target_image_path)) if self.reference_image is None: raise FileNotFoundError(f"Reference image not found at {self.target_image_path}") + self.acuire_image = cv2.imread(str(self.acquire_button_image_path)) + if self.acuire_image is None: + raise FileNotFoundError(f"Acuire button image not found at {self.acquire_button_image_path}") # Load the alert sound if not self.alert_sound_path.exists(): @@ -117,6 +121,34 @@ def find_image(self, screen_img): print_line(f"Image matched '{max_val}' percent on screen for threshold {threshold}") return max_val > threshold + def find_location_of_acquire_button(self, screen_img): + try: + result = cv2.matchTemplate(screen_img, self.acuire_image, cv2.TM_CCOEFF_NORMED) + min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) + threshold = float(self.config['Settings']['match_threshold']) + if max_val >= threshold: + location = max_loc + else: + raise ValueError("Acquire button image not found on screen") + return location + except Exception as e: + print_line(f"Error finding location of acquire button: {e}") + return None + + def click_acquire_button(self, screen_img): + """Get Location of acquire button""" + location = self.find_location_of_acquire_button(screen_img) + """Click the acquire button on the screen""" + if location is not None: + x, y = location + x += 50 # Move to the center of the button + y += 20 # Move to the center of the button + pyautogui.moveTo(x, y, duration=0.7, tween=pyautogui.easeInOutQuad) + pyautogui.click(x, y) + print_line(f"Clicked acquire button at location {x}, {y}") + else: + print_line("Acquire button location not found") + def play_music(self): """Play the alert sound""" pygame.mixer.music.load(str(self.alert_sound_path)) @@ -142,9 +174,9 @@ def monitor(self): if not image_found: print_line("Target image not found! Playing alert...") self.play_music() - # if(appMode == 'agressive'): - # click_acquire_button() - + # Click on Acquire button if in aggressive mode + if(appMode == 'aggressive'): + self.click_acquire_button(screen_img) # Present a popup asking if the user wants to continue result = show_pop_up() From 948935ce4550a0d854e4ee0fd85b99a9c1562fb4 Mon Sep 17 00:00:00 2001 From: Ashish Date: Thu, 13 Mar 2025 16:17:52 +0530 Subject: [PATCH 3/7] Revert "Merge branch 'main' of https://github.com/ghadoje/auto-refresh-python into feature/aggressive_mode" This reverts commit 932c34726bbfb9f18e540b890aa0c7789266fae7, reversing changes made to 3b89e5ec108b3b4bef73707ef1ff2a64d2c3b96f. --- monitor.py | 67 ++++++++++++++++-------------------------------------- 1 file changed, 20 insertions(+), 47 deletions(-) diff --git a/monitor.py b/monitor.py index 53d19fd..c4fe4b6 100644 --- a/monitor.py +++ b/monitor.py @@ -86,7 +86,7 @@ def __init__(self): pygame.mixer.init() # Load configuration - self.config = self.load_config() + self.config = load_config() # Set up paths self.project_dir = Path(__file__).parent @@ -109,24 +109,7 @@ def __init__(self): # Initialize Tesseract if os.name == 'nt': # Windows pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' - - def load_config(self): - """Load configuration from config.ini""" - config = configparser.ConfigParser() - config_path = Path(__file__).parent / 'config.ini' - - if not config_path.exists(): - raise FileNotFoundError(f"Configuration file not found at {config_path}") - - config.read(config_path) - return config - - def capture_screen(self): - """Capture the entire screen and convert to CV2 format""" - screenshot = ImageGrab.grab() - opencv_img = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR) - return opencv_img - + def find_image(self, screen_img): """Try to find the reference image in the screenshot""" # Use template matching to find the image @@ -135,6 +118,7 @@ def find_image(self, screen_img): # Get threshold from config threshold = float(self.config['Settings']['match_threshold']) + print_line(f"Image matched '{max_val}' percent on screen for threshold {threshold}") return max_val > threshold def find_location_of_acquire_button(self, screen_img): @@ -169,7 +153,7 @@ def play_music(self): """Play the alert sound""" pygame.mixer.music.load(str(self.alert_sound_path)) pygame.mixer.music.play() - + def monitor(self): """Main monitoring loop""" print_line("Choose application mode") @@ -179,15 +163,12 @@ def monitor(self): print_line(f"Will check every 10 to 20 seconds") # Notify user and wait for 30 seconds before starting - toaster = win10toast.ToastNotifier() - toaster.show_toast("Desktop Monitor", "Will start monitoring in 30 seconds", duration=10) + show_toast_notification("Will start monitoring in 30 seconds") time.sleep(30) - toaster.show_toast("Desktop Monitor", "Started monitoring", duration=10) - alert_shown = False # To track whether the alert has been shown recently while True: try: - screen_img = self.capture_screen() + screen_img = capture_screen() image_found = self.find_image(screen_img) if not image_found: @@ -209,36 +190,28 @@ def monitor(self): break else: - print("Target image found on screen, refreshing") + print_line("Target image found on screen, refreshing") pyautogui.press('f5') # Press F5 to refresh - alert_shown = False # Reset the alert flag since the image was found - - interval = random.randint(10, 20) # Random interval between checks + if self.config.getboolean('Settings', 'notify_on_refresh'): + show_toast_notification("Refreshed the screen.") + + average_wait_seconds = int(self.config['Settings']['check_interval']) + min_value = int(average_wait_seconds * 0.7) + max_value = int(average_wait_seconds * 1.3) + interval = random.randint(min_value, max_value) # Random interval between checks + print_line(f"Waiting for {interval} seconds") time.sleep(interval) except KeyboardInterrupt: - print("\nMonitoring stopped by user") + print_line("\nMonitoring stopped by user") break - except Exception as e: - print(f"An error occurred: {e}") - raise(e) - - def stop(self): - self.root.quit() # Quit Tkinter when monitoring is stopped - - def show_alert(self): - root = Tk() - root.geometry("600x300") - w = Label(root, text ='Python Auto Refresh', font = "50") - w.pack() - root.withdraw() - result = messagebox.askquestion("Desktop Monitor", "Target image not found! Do you want to continue monitoring?") - root.destroy() - return result + except Exception as exception: + print_line(f"An error occurred: {exception}") + raise exception if __name__ == "__main__": try: monitor = DesktopMonitor() monitor.monitor() except Exception as e: - print(f"Failed to start monitoring: {e}") \ No newline at end of file + print_line(f"Failed to start monitoring: {e}") \ No newline at end of file From 5fc7ca24607f18315f0a4bc0d8f9f1b98de3bf65 Mon Sep 17 00:00:00 2001 From: Ashish Date: Fri, 14 Mar 2025 08:48:20 +0530 Subject: [PATCH 4/7] made button name generic --- config.ini | 2 +- monitor.py | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/config.ini b/config.ini index 45c07f7..1f6c421 100644 --- a/config.ini +++ b/config.ini @@ -1,6 +1,6 @@ [Files] image_name = image1.png -acquire_button_image_name = acquireButton.png +button_image_name = button.png mp3_name = for_elise_by_beethoven.mp3 [Settings] diff --git a/monitor.py b/monitor.py index c4fe4b6..e3fdc1f 100644 --- a/monitor.py +++ b/monitor.py @@ -91,16 +91,16 @@ def __init__(self): # Set up paths self.project_dir = Path(__file__).parent self.target_image_path = self.project_dir / self.config['Files']['image_name'] - self.acquire_button_image_path = self.project_dir / self.config['Files']['acquire_button_image_name'] + self.button_image_path = self.project_dir / self.config['Files']['button_image_name'] self.alert_sound_path = self.project_dir / self.config['Files']['mp3_name'] # Load the reference image self.reference_image = cv2.imread(str(self.target_image_path)) if self.reference_image is None: raise FileNotFoundError(f"Reference image not found at {self.target_image_path}") - self.acuire_image = cv2.imread(str(self.acquire_button_image_path)) - if self.acuire_image is None: - raise FileNotFoundError(f"Acuire button image not found at {self.acquire_button_image_path}") + self.button_image_path = cv2.imread(str(self.button_image_path)) + if self.button_image_path is None: + raise FileNotFoundError(f"Button image not found at {self.button_image_path}") # Load the alert sound if not self.alert_sound_path.exists(): @@ -121,7 +121,7 @@ def find_image(self, screen_img): print_line(f"Image matched '{max_val}' percent on screen for threshold {threshold}") return max_val > threshold - def find_location_of_acquire_button(self, screen_img): + def find_location_of_button(self, screen_img): try: result = cv2.matchTemplate(screen_img, self.acuire_image, cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) @@ -129,25 +129,25 @@ def find_location_of_acquire_button(self, screen_img): if max_val >= threshold: location = max_loc else: - raise ValueError("Acquire button image not found on screen") + raise ValueError("Button image not found on screen") return location except Exception as e: - print_line(f"Error finding location of acquire button: {e}") + print_line(f"Error finding location of button: {e}") return None - def click_acquire_button(self, screen_img): - """Get Location of acquire button""" - location = self.find_location_of_acquire_button(screen_img) - """Click the acquire button on the screen""" + def click_button(self, screen_img): + """Get Location of button""" + location = self.find_location_of_button(screen_img) + """Click the button on the screen""" if location is not None: x, y = location x += 50 # Move to the center of the button y += 20 # Move to the center of the button pyautogui.moveTo(x, y, duration=0.7, tween=pyautogui.easeInOutQuad) pyautogui.click(x, y) - print_line(f"Clicked acquire button at location {x}, {y}") + print_line(f"Clicked button at location {x}, {y}") else: - print_line("Acquire button location not found") + print_line("Button location not found") def play_music(self): """Play the alert sound""" @@ -174,9 +174,9 @@ def monitor(self): if not image_found: print_line("Target image not found! Playing alert...") self.play_music() - # Click on Acquire button if in aggressive mode + # Click on button if in aggressive mode if(appMode == 'aggressive'): - self.click_acquire_button(screen_img) + self.click_button(screen_img) # Present a popup asking if the user wants to continue result = show_pop_up() From aad50b18ae6c4b5630ce5801b5d5d70ef48a21aa Mon Sep 17 00:00:00 2001 From: Ashish Date: Mon, 17 Mar 2025 10:20:16 +0530 Subject: [PATCH 5/7] fixed variable name button_image_path --- monitor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index e3fdc1f..2094182 100644 --- a/monitor.py +++ b/monitor.py @@ -123,7 +123,7 @@ def find_image(self, screen_img): def find_location_of_button(self, screen_img): try: - result = cv2.matchTemplate(screen_img, self.acuire_image, cv2.TM_CCOEFF_NORMED) + result = cv2.matchTemplate(screen_img, self.button_image_path, cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) threshold = float(self.config['Settings']['match_threshold']) if max_val >= threshold: From 903cf2e49f4859e5ab4e15ff5006e19659945bb2 Mon Sep 17 00:00:00 2001 From: Ashish Date: Mon, 17 Mar 2025 17:35:45 +0530 Subject: [PATCH 6/7] updated to check immediatly after refresh --- monitor.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/monitor.py b/monitor.py index 2094182..13bcd61 100644 --- a/monitor.py +++ b/monitor.py @@ -153,6 +153,18 @@ def play_music(self): """Play the alert sound""" pygame.mixer.music.load(str(self.alert_sound_path)) pygame.mixer.music.play() + + def random_wait(self): + average_wait_seconds = int(self.config['Settings']['check_interval']) + min_value = int(average_wait_seconds * 0.7) + max_value = int(average_wait_seconds * 1.3) + interval = random.randint(min_value, max_value) # Random interval between checks + print_line(f"Waiting for {interval} seconds") + time.sleep(interval) + + def refresh_screen(self): + pyautogui.press('f5') # Press F5 to refresh + time.sleep(10) def monitor(self): """Main monitoring loop""" @@ -164,10 +176,11 @@ def monitor(self): # Notify user and wait for 30 seconds before starting show_toast_notification("Will start monitoring in 30 seconds") - time.sleep(30) while True: try: + self.random_wait() + self.refresh_screen() # Press F5 to refresh screen_img = capture_screen() image_found = self.find_image(screen_img) @@ -191,17 +204,9 @@ def monitor(self): else: print_line("Target image found on screen, refreshing") - pyautogui.press('f5') # Press F5 to refresh if self.config.getboolean('Settings', 'notify_on_refresh'): show_toast_notification("Refreshed the screen.") - average_wait_seconds = int(self.config['Settings']['check_interval']) - min_value = int(average_wait_seconds * 0.7) - max_value = int(average_wait_seconds * 1.3) - interval = random.randint(min_value, max_value) # Random interval between checks - print_line(f"Waiting for {interval} seconds") - time.sleep(interval) - except KeyboardInterrupt: print_line("\nMonitoring stopped by user") break From b93e6bfb8aadbbf1e96b232a94341622f2dbc113 Mon Sep 17 00:00:00 2001 From: Ashish Date: Mon, 17 Mar 2025 17:36:45 +0530 Subject: [PATCH 7/7] removed wrong print line --- monitor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/monitor.py b/monitor.py index 13bcd61..b532c45 100644 --- a/monitor.py +++ b/monitor.py @@ -172,7 +172,6 @@ def monitor(self): appMode = show_app_mode_pop_up() print_line(f"Selected application mode: {appMode}") print_line(f"Starting desktop monitoring. Looking for image: {self.target_image_path}") - print_line(f"Will check every 10 to 20 seconds") # Notify user and wait for 30 seconds before starting show_toast_notification("Will start monitoring in 30 seconds")