import grovepi import time import threading from sensors.lock import grove_lock from shared.logging import log button = 2 button_switch_state = 0 grovepi.pinMode(button, "INPUT") button_callback = None def read_button_state(): # Increase timeout slightly so the button thread can wait for long I2C sensor reads to finish if not grove_lock.acquire(timeout=0.2): return None try: return grovepi.digitalRead(button) except Exception as e: log(f"BTN Error: {e}") return None finally: grove_lock.release() def monitor_button(): global button_switch_state last_button_state = button_switch_state while True: current_state = read_button_state() if current_state is not None: # Rising edge detection (0 -> 1 transition) if current_state == 1 and last_button_state == 0: if button_callback: button_callback() last_button_state = current_state time.sleep(0.02) # Fast 20ms poll when lock is clear else: # Lock was busy; retry quickly without updating last_button_state time.sleep(0.01) def start_button_monitoring_thread(): threading.Thread(target=monitor_button, daemon=True).start() def set_callback(callback): global button_callback button_callback = callback