from dataclasses import dataclass from enum import Enum, auto from datetime import time, datetime from typing import Optional, Any from time import sleep from pynput import keyboard from pynput.keyboard import Key, Controller # Simple Alarm Clock has 5 functionalities: # 1. Set Alarm Time - Set the time for the alarm to sound, does NOT make the alarm active # 2. Start Alarm - Make the alarm active, which will run the timer until it reaches the specified time # 3. Sound Alarm - Play the sound for the alarm # 4. Snooze Alarm - Stop the alarm sound and wait for some time to play the alarm again # 5. Stop Alarm - If the alarm is active or is playing, stop the alarm (deactivate state) ALARM_TIME = time(19, 13, 0) SNOOZE_SEC = 5 SNOOZE_KEY = keyboard.Key.up ALARM_OFF_KEY = keyboard.Key.esc class AlarmState(Enum): SET = auto(), RUNNING = auto(), PLAYING = auto(), SNOOZED = auto(), DEACTIVATED = auto(), @dataclass class BaseAlarmClock: # player: Optional wake_time: time current_state: AlarmState = AlarmState.DEACTIVATED def set_alarm(self, wake_time: time) -> time: print(f"SETTING ALARM to: {wake_time}") self.current_state = AlarmState.SET self.wake_time = wake_time return self.wake_time def start_alarm(self, check_frequency: int = 1): print("STARTING ALARM") self.current_state = AlarmState.RUNNING # now = datetime.now().time() # if now >= self.wake_time: # return False # sleep_time_amount = max(check_frequency, 1) # while now < self.wake_time: # # Sleep for some time # sleep(sleep_time_amount) # now = datetime.now().time() # self.sound_alarm() # return True def sound_alarm(self): print("SOUNDING ALARM") self.current_state = AlarmState.PLAYING # if sound is not None: # self.player.set_media(sound) # self.player.audio_set_volume(volume) # self.player.play() def snooze_alarm(self, snooze_time: int = SNOOZE_SEC): print("SNOOZING ALARM") self.current_state = AlarmState.SNOOZED # self.player.pause() # Maybe make this async later sleep(snooze_time) # self.player.play() if self.current_state is AlarmState.SNOOZED: self.sound_alarm() def stop_alarm(self, deactivate: bool = True): print("STOPPING ALARM") if self.current_state is AlarmState.PLAYING: print("STOPPED PLAYING ALARM") # self.player.stop() self.current_state = AlarmState.DEACTIVATED if deactivate else AlarmState.SET def alarm_check_reached(self, current_time = datetime.now().time()) -> bool: result = current_time >= self.wake_time if self.current_state is AlarmState.RUNNING else False print(f"{result = }") return result def simple_alarm_mode(alarm_time): alarm_clock = BaseAlarmClock(alarm_time) alarm_clock.start_alarm() while not alarm_clock.alarm_check_reached(): print(f"ALARM SLEEPING @: {datetime.now().time()}") sleep(1) alarm_clock.sound_alarm() while alarm_clock.current_state is not AlarmState.DEACTIVATED: with keyboard.Events() as events: for event in events: if event.key == ALARM_OFF_KEY: alarm_clock.stop_alarm() break elif event.key == SNOOZE_KEY: alarm_clock.snooze_alarm() break if __name__ == '__main__': simple_alarm_mode(ALARM_TIME)