import sys import datetime import subprocess def hex_to_rgb(hex_color): """ Converts a hexadecimal color string to an RGB tuple. Args: hex_color (str): Hexadecimal color string. Returns: tuple: Tuple representing the RGB color. """ if len(hex_color) != 6: raise ValueError("Hex color must be 6 characters long.") return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) def calculate_color(start_color, end_color, ratio): """ Calculates the interpolated color between two colors. Args: start_color (str): Start color in hex format. end_color (str): End color in hex format. ratio (float): Interpolation ratio (0 to 1). Returns: str: Interpolated color in hex format. """ start_rgb = hex_to_rgb(start_color) end_rgb = hex_to_rgb(end_color) current_rgb = [round(start + (end - start) * ratio) for start, end in zip(start_rgb, end_rgb)] return ''.join(f"{value:02x}" for value in current_rgb) def get_current_period(current_time, color_times): """ Determines the current time period and returns the corresponding colors. Args: current_time (datetime.time): The current time. color_times (dict): A dictionary linking time periods (as a string in 'HH:MM' format) with pairs of colors. Returns: tuple: A tuple of the start and end color (as hex codes) for the current period. """ sorted_periods = sorted(color_times.items()) for i, (period_start_str, colors) in enumerate(sorted_periods): period_start_time = datetime.datetime.strptime(period_start_str, "%H:%M").time() if current_time <= period_start_time: return sorted_periods[i - 1 if i > 0 else -1][1] return sorted_periods[0][1] def calculate_transition_ratio(current_time, start_time, end_time): """ Calculates the transition ratio for a color transition. Args: current_time (datetime.time): The current time. start_time (datetime.time): The start time of the current color period. end_time (datetime.time): The end time of the current color period. Returns: float: The transition ratio between 0 and 1. """ # Use the current date for timestamp calculation today = datetime.datetime.now().date() # Calculate timestamps for the start and end of the current period start_timestamp = datetime.datetime.combine(today, start_time).timestamp() end_timestamp = datetime.datetime.combine(today, end_time).timestamp() # If start and end times are the same, return 0 to indicate no transition if start_timestamp == end_timestamp: return 0 # Calculate the current timestamp current_timestamp = datetime.datetime.combine(today, current_time).timestamp() # Calculate the transition ratio transition_duration = end_timestamp - start_timestamp time_since_start = current_timestamp - start_timestamp # Ratio as the proportion of time elapsed in the total transition duration return time_since_start / transition_duration def change_keyboard_color(color, device_id): """ Changes the keyboard color using an external command. Args: color (str): Color in hex format. device_id (str): Vendor and product ID for the keyboard. """ command = ["msi-perkeyrgb", "--model", "GS65", "-s", color, "--id", device_id] try: subprocess.run(command, check=True) print(f"Keyboard color changed to #{color}.") except subprocess.CalledProcessError as e: print(f"Error setting keyboard color: {e}") sys.exit(1) def main(vendor_and_product_id): color_times = { "22:00": ("990000", "990000"), # Night "21:00": ("0000ff", "990000"), # Evening Blue to Night "20:00": ("fdbe51", "0000ff"), # Evening Golden to Blue "19:30": ("ff4500", "fdbe51"), # Sunset to Golden "12:00": ("ffffff", "ff4500"), # Noon to Sunset "07:30": ("ffd700", "ffffff"), # Sunrise to Noon "07:00": ("f9c80e", "ffd700"), # Morning Golden to Sunrise "06:00": ("ff7f00", "f9c80e"), # Dawn to Golden "05:00": ("5bc0eb", "ff7f00"), # Morning Blue to Dawn "04:00": ("990000", "5bc0eb"), # Night to Blue } current_time = datetime.datetime.now().time() start_color, end_color = get_current_period(current_time, color_times) sorted_times = sorted(color_times.keys()) for time_str in sorted_times + [sorted_times[0]]: next_start_time_obj = datetime.datetime.strptime(time_str, "%H:%M").time() if current_time < next_start_time_obj: break current_period_start_time_str = [time for time, colors in color_times.items() if colors == (start_color, end_color)][0] current_period_start_time_obj = datetime.datetime.strptime(current_period_start_time_str, "%H:%M").time() transition_ratio = calculate_transition_ratio(current_time, current_period_start_time_obj, next_start_time_obj) current_color = calculate_color(start_color, end_color, transition_ratio) change_keyboard_color(current_color, vendor_and_product_id) if __name__ == "__main__": if len(sys.argv) < 2: print("Error: Vendor and product ID is missing.") print("Usage: python keyboard_color.py ") sys.exit(1) vendor_and_product_id = sys.argv[1] main(vendor_and_product_id)