diff --git a/scripts/sunset.py b/scripts/sunset.py index ce0426d..577c939 100755 --- a/scripts/sunset.py +++ b/scripts/sunset.py @@ -2,6 +2,7 @@ """Sets the monitor temperature based on the current time using Hyprsunset""" from datetime import datetime from os import environ +from pathlib import Path from socket import AF_UNIX, SOCK_STREAM, socket @@ -24,29 +25,65 @@ def day_elapsed(hours: int = 0, minutes: int = 0, seconds: int = 0) -> float: return ((((hours * 60) + minutes) * 60) + seconds) / 86400 -def main(sunrise: Range, sunset: Range, temp_range: Range) -> None: - """Adjusts the monitor temperature based on the current time""" +def now_elapsed() -> float: + """How far through the day it is""" now = datetime.now() - elapsed = day_elapsed(now.hour, now.minute, now.second) + return day_elapsed(now.hour, now.minute, now.second) + +def calculate_temperature(sunrise: Range, sunset: Range, temperature_range: Range) -> float: + """What temperature the monitor should be""" + elapsed = now_elapsed() if elapsed <= sunrise[0]: - temperature = temp_range[0] + return temperature_range[0] elif elapsed < sunrise[1]: - temperature = smoothstep(lerped_amount(elapsed, sunrise), temp_range) + return smoothstep(lerped_amount(elapsed, sunrise), temperature_range) elif elapsed <= sunset[0]: - temperature = temp_range[1] + return temperature_range[1] elif elapsed < sunset[1]: - temperature = smoothstep(lerped_amount(elapsed, sunset), (temp_range[1], temp_range[0])) + return smoothstep(lerped_amount(elapsed, sunset), (temperature_range[1], temperature_range[0])) else: - temperature = temp_range[0] + return temperature_range[0] + +def setup_socket() -> socket: + """Connects to the Hyprsunset socket""" hyprsunset = socket(AF_UNIX, SOCK_STREAM) # In theory I should use $XDG_RUNTIME_DIR, but for me it's always `/run/user/1000/` - hyprsunset.connect(f"/run/user/1000/hypr/{environ["HYPRLAND_INSTANCE_SIGNATURE"]}/.hyprsunset.sock") - # In theory the message might not send in one go, but in practice it does do I won't bother handling it + hyprsunset.connect(f"{environ["XDG_RUNTIME_DIR"]}/hypr/{environ["HYPRLAND_INSTANCE_SIGNATURE"]}/.hyprsunset.sock") + return hyprsunset + + +def get_temperature(hyprsunset: socket) -> int: + """Retrieves the current screen temperature""" + # In theory the message might not send in one go, but in practice it does so I won't bother handling the error + _ = hyprsunset.send(b"temperature") + # 4 bytes should be enough but why not 8 for comfort + # Just raise an error if it's not a number, nothing special to do here + return int(hyprsunset.recv(8)) + + +def set_temperature(hyprsunset: socket, temperature: float) -> None: + # In theory the message might not send in one go, but in practice it does so I won't bother handling the error _ = hyprsunset.send(f"temperature {temperature:.1f}".encode()) +def on_steam() -> bool: + """Whether the Steam PID is in use""" + pid_file = Path("~/.steampid").expanduser().resolve(strict=True) + pid = pid_file.read_text().strip() + pid_dir = Path("/proc") / pid + return pid_dir.is_dir() + + +def main(sunrise: Range, sunset: Range, temperature_range: Range) -> None: + """Adjusts the monitor temperature based on the current time""" + hyprsunset = setup_socket() + temperature = int(calculate_temperature(sunrise, sunset, temperature_range)) + if temperature != get_temperature(hyprsunset) and not on_steam(): + set_temperature(hyprsunset, temperature) + + if __name__ == "__main__": main( (day_elapsed(5), day_elapsed(7)),