Simon Bruder
939df6ae2a
The time is already stored in the journal, so it does not need to be logged. Only logging changed values makes the log less polluted once a fixed value has been reached ((3, 3, 3) or (3, 0, 0)):
89 lines
2.6 KiB
Python
Executable file
89 lines
2.6 KiB
Python
Executable file
#!/usr/bin/env python3
|
||
|
||
# SPDX-FileCopyrightText: 2021 Simon Bruder <simon@sbruder.de>
|
||
#
|
||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||
|
||
from astral.location import Location, LocationInfo
|
||
from math import cos, pi
|
||
from time import sleep
|
||
import datetime
|
||
import os
|
||
import paho.mqtt.client as mqtt
|
||
import sys
|
||
|
||
|
||
def time_as_float_hours(time: datetime.time) -> float:
|
||
return time.hour + time.minute / 60 + time.second / 3600
|
||
|
||
|
||
def set_color(client: mqtt.Client, red: int, green: int, blue: int, retain=True):
|
||
client.reconnect()
|
||
# my wordclock’s red and green LEDs seem to be switched
|
||
client.publish("wordclock/color/red", green, retain=True)
|
||
client.publish("wordclock/color/green", red, retain=True)
|
||
client.publish("wordclock/color/blue", blue, retain=True)
|
||
|
||
|
||
def get_color_for_time(time: datetime.time, base=(60, 60, 60)) -> (int, int, int):
|
||
if time.hour >= 22 or time.hour < 7:
|
||
# night mode: dim red
|
||
return (3, 0, 0)
|
||
else:
|
||
# day mode: calculated depending on sun (https://www.desmos.com/calculator/nrseefnaom)
|
||
now = time_as_float_hours(time)
|
||
|
||
# returns at least (3, 3, 3)
|
||
min_factors = (3 / base[0], 3 / base[1], 3 / base[2])
|
||
|
||
rate = 5
|
||
|
||
location_info = LocationInfo(
|
||
timezone="Europe/Berlin", latitude=49.52, longitude=10.18
|
||
)
|
||
location = Location(location_info)
|
||
sunrise = time_as_float_hours(location.sunrise().time())
|
||
sunset = time_as_float_hours(location.sunset().time())
|
||
|
||
factors = []
|
||
for min_factor in min_factors:
|
||
factor = min_factor
|
||
if now > sunrise and now < sunset:
|
||
factor = 1 - (
|
||
(1 - min_factor) * cos((pi / (sunrise - sunset)) * (now - sunset))
|
||
) ** (2 * rate)
|
||
factors.append(factor)
|
||
|
||
return (
|
||
round(base[0] * factors[0]),
|
||
round(base[1] * factors[1]),
|
||
round(base[2] * factors[2]),
|
||
)
|
||
|
||
|
||
client = mqtt.Client("wordclock.py")
|
||
|
||
user = os.environ["WORDCLOCK_MQTT_USER"]
|
||
try:
|
||
password = os.environ["WORDCLOCK_MQTT_PASSWORD"]
|
||
except KeyError:
|
||
with open(os.environ["WORDCLOCK_MQTT_PASSWORD_FILE"]) as f:
|
||
password = f.read().rstrip()
|
||
host = os.environ["WORDCLOCK_MQTT_HOST"]
|
||
|
||
client.username_pw_set(user, password)
|
||
client.connect(host, 1883, 60)
|
||
|
||
color = (0, 0, 0)
|
||
|
||
while True:
|
||
time = datetime.datetime.now().time()
|
||
new_color = get_color_for_time(time)
|
||
if new_color != color:
|
||
color = new_color
|
||
print(f"setting color to {color}")
|
||
sys.stdout.flush()
|
||
set_color(client, *color)
|
||
|
||
sleep(300)
|