Skip to content

Instantly share code, notes, and snippets.

@ConnorGriffin
Last active December 17, 2025 04:52
Show Gist options
  • Select an option

  • Save ConnorGriffin/2e6646bd7295ce06122ee0fe447eee05 to your computer and use it in GitHub Desktop.

Select an option

Save ConnorGriffin/2e6646bd7295ce06122ee0fe447eee05 to your computer and use it in GitHub Desktop.
HomeAssistant Plot for Brightness Curve
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
def brightness_at_time(t, sunrise, sunset,
pre_sunrise=120, morning_ramp=90,
pre_sunset=60, evening_ramp=240,
min_brightness=20, max_brightness=100):
# Adjusted ramp times
ramp_up_start = sunrise - timedelta(minutes=pre_sunrise)
ramp_up_end = ramp_up_start + timedelta(minutes=morning_ramp)
ramp_down_start = sunset - timedelta(minutes=pre_sunset)
ramp_down_end = ramp_down_start + timedelta(minutes=evening_ramp)
if ramp_up_start <= t < ramp_up_end:
ramp = (t - ramp_up_start).total_seconds() / (morning_ramp*60)
return int(min_brightness + ramp * (max_brightness - min_brightness))
elif ramp_up_end <= t < ramp_down_start:
return max_brightness
elif ramp_down_start <= t < ramp_down_end:
ramp = (t - ramp_down_start).total_seconds() / (evening_ramp*60)
return int(max_brightness - ramp * (max_brightness - min_brightness))
else:
return min_brightness
# Sunrise and sunset
sunrise = datetime.strptime("07:23", "%H:%M")
sunset = datetime.strptime("17:23", "%H:%M")
# Ramp offsets/durations
pre_sunrise = 120
morning_ramp = 150
pre_sunset = 30
evening_ramp = 330
min_brightness = 20
max_brightness = 100
# Calculate key times
morning_start = sunrise - timedelta(minutes=pre_sunrise)
morning_end = morning_start + timedelta(minutes=morning_ramp)
evening_start = sunset - timedelta(minutes=pre_sunset)
evening_end = evening_start + timedelta(minutes=evening_ramp)
# Generate times
times = [morning_start.replace(hour=0, minute=0) + timedelta(minutes=i) for i in range(0, 24*60, 5)]
brightness_values = [brightness_at_time(t, sunrise, sunset,
pre_sunrise=pre_sunrise, morning_ramp=morning_ramp,
pre_sunset=pre_sunset, evening_ramp=evening_ramp,
min_brightness=min_brightness, max_brightness=max_brightness)
for t in times]
# Plot
plt.figure(figsize=(15,8))
plt.plot(times, brightness_values, label="Brightness")
# Add padding for annotations
plt.ylim(min_brightness - 5, max_brightness + 15) # extra space above max
# Annotate sunrise/sunset
plt.axvline(sunrise, color='orange', linestyle='--', label="Sunrise")
plt.axvline(sunset, color='red', linestyle='--', label="Sunset")
# Annotate ramp min/max points
for t_point, label_text in [
(morning_start, f"Morning min {morning_start.strftime('%H:%M')}"),
(morning_end, f"Morning max {morning_end.strftime('%H:%M')}"),
(evening_start, f"Evening max {evening_start.strftime('%H:%M')}"),
(evening_end, f"Evening min {evening_end.strftime('%H:%M')}")
]:
brightness = brightness_at_time(t_point, sunrise, sunset,
pre_sunrise=pre_sunrise, morning_ramp=morning_ramp,
pre_sunset=pre_sunset, evening_ramp=evening_ramp,
min_brightness=min_brightness, max_brightness=max_brightness)
plt.scatter(t_point, brightness, color='blue')
plt.text(t_point, brightness + 5, label_text, rotation=45, fontsize=9)
plt.xlabel("Time")
plt.ylabel("Brightness")
plt.title("Light Brightness Over the Day with Key Points")
plt.xticks(rotation=45)
plt.grid(True)
plt.legend()
plt.show()
# Jinja code for HA in use as a templated value for brightness_pct:
{# Force sunrise/sunset times onto today's date #}
{% set sr = today_at((state_attr('sun.sun', 'next_rising') | as_datetime | as_local).strftime('%H:%M')) %}
{% set ss = today_at((state_attr('sun.sun', 'next_setting') | as_datetime | as_local).strftime('%H:%M')) %}
{# Ramp settings #}
{% set pre_sunrise = 120 %} {# minutes before sunrise to start ramp up #}
{% set morning_ramp = 150 %} {# ramp duration in minutes #}
{% set pre_sunset = 30 %} {# minutes before sunset to start ramp down #}
{% set evening_ramp = 360 %} {# ramp duration in minutes #}
{% set min_brightness = 20 %}
{% set max_brightness = 100 %}
{% set t = now() %}
{# Compute ramp start/end times #}
{% set ramp_up_start = sr - timedelta(minutes=pre_sunrise) %}
{% set ramp_up_end = ramp_up_start + timedelta(minutes=morning_ramp) %}
{% set ramp_down_start = ss - timedelta(minutes=pre_sunset) %}
{% set ramp_down_end = ramp_down_start + timedelta(minutes=evening_ramp) %}
{# Determine brightness #}
{% if ramp_up_start <= t < ramp_up_end %}
{{ (min_brightness + ((t - ramp_up_start).total_seconds() / (morning_ramp*60)) * (max_brightness - min_brightness)) | int }}
{% elif ramp_up_end <= t < ramp_down_start %}
{{ max_brightness }}
{% elif ramp_down_start <= t < ramp_down_end %}
{{ (max_brightness - ((t - ramp_down_start).total_seconds() / (evening_ramp*60)) * (max_brightness - min_brightness)) | int }}
{% else %}
{{ min_brightness }}
{% endif %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment