Hello all
New to HA, and this is my first attempt at an automation/blueprint.
Also given I’m NOT a programmer, this script was written entirely with the help of ChatGPT.
Premiss of the project: Fully automate lighting and heating of my grow room. (heating script to come).
Or you can visit GitHub
blueprint:
name: Grow Lights – Solar Noon Cycle
description: >
Automatically controls grow lights based on a grow start date.
Veg weeks 1–4 run 18/6, Flower week 5+ runs 12/12.
Lights are centered on solar noon with safe fallback to clock noon.
This automation requires helper input_datetime.grow_start_date.
Set the date you started your grow. Grow is based on a 12 week cycle.
Select the light switch you wish to control.
domain: automation
input:
grow_start_date:
name: Grow Start Date
selector:
entity:
domain: input_datetime
grow_light_switch:
name: Grow Light Switch
selector:
entity:
domain: switch
mode: single
trigger:
- platform: time_pattern
minutes: "/1"
- platform: homeassistant
event: start
variables:
start_date: !input grow_start_date
light_switch: !input grow_light_switch
now_ts: "{{ now().timestamp() }}"
prev_noon: "{{ state_attr('sun.sun','previous_noon') }}"
next_noon: "{{ state_attr('sun.sun','next_noon') }}"
noon_ts: >
{% if prev_noon is not none and next_noon is not none %}
{{ as_timestamp(prev_noon if now_ts < as_timestamp(next_noon) else next_noon) }}
{% else %}
{{ as_timestamp(today_at('12:00')) }}
{% endif %}
grow_days: >
{% if states(start_date) not in ['unknown','unavailable',''] %}
{{ (now().date()
- strptime(states(start_date).split(' ')[0], '%Y-%m-%d').date()).days }}
{% else %}
-1
{% endif %}
grow_week: "{{ (grow_days // 7) + 1 if grow_days >= 0 else 0 }}"
light_hours: "{{ 18 if grow_week < 5 else 12 }}"
half_window: "{{ (light_hours / 2) * 3600 }}"
lights_on_ts: "{{ noon_ts - half_window }}"
lights_off_ts: "{{ noon_ts + half_window }}"
action:
- choose:
# Turn lights ON
- conditions:
- condition: template
value_template: >
{{ now_ts >= lights_on_ts and now_ts < lights_off_ts }}
sequence:
- service: switch.turn_on
target:
entity_id: !input grow_light_switch
# Turn lights OFF
- conditions:
- condition: template
value_template: >
{{ now_ts < lights_on_ts or now_ts >= lights_off_ts }}
sequence:
- service: switch.turn_off
target:
entity_id: !input grow_light_switch
Helper required:
input_datetime.grow_start_date
Also ensure you have sun.sun installed (found this out by accident).
To configure the automation simply select your date helper and the light switch you wish to control. Everything else is done for you.
Grow cycles are based on a 12 week cycle. 4 veg and 8 flower.
The lighting cycle is centered on midday. So a 18/6 cycle is 0300-2100 and a 12/12 cycle is 0600-1800.
Here are a couple of templates that may also be helpful.
These should be added to your templates.yaml
Show grow week
# ───────────── Grow Week ─────────────
- name: "Grow Week"
icon: mdi:calendar-week
state: >
{% set start = states('input_datetime.grow_start_date') %}
{% if start not in ['unknown','unavailable',''] %}
{% set start_date = strptime(start.split(' ')[0], '%Y-%m-%d') %}
{% set days = (now().date() - start_date.date()).days %}
{{ (days // 7) + 1 if days >= 0 else 0 }}
{% else %}
unknown
{% endif %}
Grow light countdown. Show how far away the next lighting cycle is.
# ───────────── Grow Lights Countdown ─────────────
- name: "Grow Lights – Countdown"
icon: mdi:timer-outline
state: >
{% set start_date = states('input_datetime.grow_start_date') %}
{% set light_state = states('switch.relayboard_lights') %}
{% if start_date in ['unknown','unavailable',''] or light_state in ['unknown','unavailable'] %}
unavailable
{% else %}
{% set now_ts = as_timestamp(now()) %}
{# Use fixed local noon today #}
{% set noon = now().replace(hour=12, minute=0, second=0, microsecond=0) %}
{% set noon_ts = as_timestamp(noon) %}
{% set grow_days = (now().date() - strptime(start_date.split(' ')[0], '%Y-%m-%d').date()).days %}
{% set grow_week = (grow_days // 7) + 1 if grow_days >= 0 else 0 %}
{% set light_hours = 18 if grow_week < 5 else 12 %}
{% set half_window = (light_hours / 2) * 3600 %}
{% set lights_on_ts = noon_ts - half_window %}
{% set lights_off_ts = noon_ts + half_window %}
{% if light_state == 'on' %}
{% set remaining = max(0, lights_off_ts - now_ts) %}
{% else %}
{% if now_ts < lights_on_ts %}
{% set remaining = lights_on_ts - now_ts %}
{% else %}
{% set remaining = (lights_on_ts + 24*3600) - now_ts %}
{% endif %}
{% endif %}
{% set hours = (remaining // 3600) | int %}
{% set minutes = ((remaining % 3600) // 60) | int %}
{{ "%02d:%02d" | format(hours, minutes) }}
{% endif %}
I hope that someone finds this helpful.
Regards
Fred