When I try to do what you’re attempting, it fails Config Check. The stated error message always indicates it’s expecting the option’s data to be in “HH:MM” format (not a template).
But no, if you mean this: Invalid config for [binary_sensor.tod]: Invalid time specified: '{{ (as_timestamp(states.sun.sun.attributes.next_rising) + states.input_number.sunrise_offset.state | float * 3600) | timestamp_custom("%H:%M") }}' for dictionary value @ data['after']. Got '\'{{ (as_timestamp(states.sun.sun.attributes.next_rising) + states.input_number.sunrise_offset.state | float * 3600) | timestamp_custom("%H:%M") }}\'\n' Invalid time specified: '{{ (as_timestamp(states.sun.sun.attributes.next_setting) + states.input_number.sunset_offset.state | float * 3600) | timestamp_custom("%H:%M") }}' for dictionary value @ data['before']. Got '\'{{ (as_timestamp(states.sun.sun.attributes.next_setting) + states.input_number.sunset_offset.state | float * 3600) | timestamp_custom("%H:%M") }}\'\n'. (See ?, line ?). Please check the docs at https://home-assistant.io/components/binary_sensor.tod/
But the docs says:
Configuration Variables
name
(string)(Required)Name of the sensor.
before
(string or time)(Required)The absolute local time value or sun event for beginning of the time range.
before_offset
(time)(Optional)The time offset of the beginning time range.
after
(string or time)(Required)The absolute local time value or sun event for ending of the time range.
after_offset
(time)(Optional)The time offset of the beginning time range.
In other words, before and after could be either string or time. My template returns a string.
By supplying the option with a template, you’re assuming the option is able to recognize it’s a template, evaluate the template, and then use the result of the evaluation.
Templates are not supported by all options. If you examine the source code for the Time of Day binary_sensor, you’ll see that it simply reads its options directly from the configuration file. I see nothing in the code that assumes it might receive a template and be required to evaluate it first.
Here’s the line of code where the after option is read directly from the configuration. You’ll notice it expects it to be a valid time.
Ok, I understand. Thanks for the info. I will have to find another way to have a daylight sensor that I can adjust dynamically from the UI. A simple time offset from sunrise and sunset won’t cut it as it changes through the seasons. I find it awkward to edit a yaml-file every time I want to adjust it.
I’m intrigued by what you are trying to accomplish.
The Time of Day Sensor can be used to specify a day-period which can automatically adjust itself according sunrise/sunset. You want to influence its calculation using an input_number. Effectively, you want to manually shorten/lengthen the day-period, on demand.
What is your intended application for a day-period that can be manually adjusted?
Let me explain.
Daylight is a relative thing when you consider luminance. I would like to have a sensor that gives me a good and reliable daylight reading to turn on/off lights in the house. I know, there are luminance sensors, but I haven’t got any of those to work reliably as their readings often vary significantly over short periods of time, thereby triggering lights due to a dark cloud passing by.
My idea now is to create a sensor based on sunrise/sunset, but adjusted for the seasons, e.g. in the summer there is daylight maybe 1-1½ hours before sunrise, while as during the winter it could still be dark an hour after sunrise.
To complicate it a bit further, I would also like to adjust the timings dependent on if the weather is sunny or cloudy. It makes a lot of difference.
Here’s what I’ve been using for almost ten years (I use another home automation software):
I have one light sensor outdoors and another indoors.
Both have thresholds indicating when it is dark.
The thresholds were determined by experimentation and have been set to my preference.
Both sensors must agree it is dark before any automations are triggered.
The combination of the two sensors is used to turn on lights in the morning and in the evening.
For late afternoon/evening, there are two automations controlling the interior lights :
A scheduled automation runs 2.5 hours before sunset. If the indoor and outdoor light sensors indicate it is dark, the interior lights are turned on.
An automation is triggered when the indoor and outdoor light sensors indicate it is dark. If the current time is less than 2.5 hours from sunset, the interior lights are turned on.
This offset prevents the lights from being turned on during the middle of the day in the event of a passing storm. For your purposes, the 2.5 hour offset could be set by an input_number.
For early morning, there is only one automation controlling the interior lights:
A scheduled automation runs at 6:45 AM. If the indoor and outdoor light sensors indicate it is dark, the interior lights are turned on
Albeit I live on the front end of Sweden, I can sympathise with your dillemma. I am trying the same thing, but want to throw in the workday sensor as well, so I can have time of day for weekdays and weekends differentiated easily.
Edit: The workday binary sensor is not a valid source for a template within the tod sensor
I have an Aeotec MultiSensor 6 I use for luminance that controls my lights on the front of the house. I use a slightly different technique: The lights will only change if they haven’t changed for 30 minutes. This way even a manual turn on or off of the lights won’t get immediately overridden by the automation.
- alias: House Front
trigger:
- platform: state
entity_id: sensor.house_front_luminance
- platform: state
entity_id: switch.house_front_lights
to: 'on'
for: '00:30:00'
- platform: state
entity_id: switch.house_front_lights
to: 'off'
for: '00:30:00'
- platform: event
event_type: DELAYED_HOMEASSISTANT_START
condition:
- condition: template
value_template: >
{% set turn_on = states('sensor.house_front_luminance')|int < 50 %}
{% set is_on = is_state('switch.house_front_lights', 'on') %}
{{ (turn_on and not is_on or not turn_on and is_on) and
(trigger.platform == 'event' or
states('sensor.uptime')|int < 30 or
(now() - states.switch.house_front_lights.last_changed)
.total_seconds() >= 30*60) }}
action:
- service: switch.toggle
entity_id: switch.house_front_lights
Thomas,
I appreciate that people can understand time before sunset (or after) as it’s easier to get your head around.
However, you are looking at luminance and (assuming a volcano has not erupted or you get particularly bad weather) that’s related to sun position in the sky relative to your global position and elevation.
Why not use regular binary sensors to detect a particular sun elevation derived from an angular sun.sun.elevation offset passed by an input_number ? eg civilian dusk (valid HA option, dusk) is 6° below horizon (but pick any number, careful if the sun never reaches that declination (closer to the poles)). Condition this with if the sun is rising or falling and you will be able to hit it with a bit of trial and error.
I’ve just spent an hour trying to get TOD to work with a template (and even to accept a name to use as an entity_id)
So vanilla binary sensors for me tomorrow : - S
Cheers
Guys,
I’ve had a play with this and have something that seems to work. I’m hoping that as this would seem a resonable function, some more people can test it, see if there are any faults/issues and polish this up a bit.
What I use it for is to turn on my floodlights, they consume (according to my metering) 0.7W and 0.6W each (2 off them) in the standby state and 48W each when they fire up having detected movement.
I have a double switch (consumes 0.96W on it’s own so I can’t claim I’m saving much energy (or any at all)) But it’s about interupting the flood if I step out side (patio or porch light goes on) and choosing the enable period for the porch light to come on when I get home or if I just open the relevant door.
This is written as a package so you may need to adjust for your installation.
Ended up I didn’t need binary_sensors, just used templates
input_boolean:
ib_light_floodr1_timeslot_enable:
name: Time Slot Enable
#initial: on
icon: mdi:clock-outline
ib_light_floods2_timeslot_enable:
name: Time Slot Enable
#initial: on
icon: mdi:clock-outline
ib_global_darkslot: # usually lives elsewhere (globals) as I can use this for other things
name: Time Slot - Dark
#initial: off
icon: mdi:weather-night
input_number:
in_light_flood_on_elev_offset:
name: Switch On ( ° offset from horizon)
#initial: 0
min: -12
max: 12
step: 0.1
mode: box
icon: mdi:clock-start
in_light_flood_off_elev_offset:
name: Switch Off ( ° offset from horizon)
#initial: 0
min: -12
max: 12
step: 0.1
mode: box
icon: mdi:clock-end
# ''{{ (states.sun.sun.attributes.elevation <= states.input_number.in_light_flood_on_elev_offset.state | float) and not (states.sun.sun.attributes.rising) }}'
# '{{ (states.sun.sun.attributes.elevation <= states.input_number.in_light_flood_off_elev_offset.state | float) and (states.sun.sun.attributes.rising) }}'
automation:
#name: Light Flood Dark
- alias: au_switch_flood_dark
trigger:
- platform: template
value_template: '{{ (states.sun.sun.attributes.elevation <= states.input_number.in_light_flood_on_elev_offset.state | float) and not (states.sun.sun.attributes.rising) }}'
action:
- service: input_boolean.turn_on
entity_id: input_boolean.ib_global_darkslot
#name: Light Flood Light
- alias: au_switch_flood_light
trigger:
- platform: template
value_template: '{{ (states.sun.sun.attributes.elevation <= states.input_number.in_light_flood_off_elev_offset.state | float) and (states.sun.sun.attributes.rising) }}'
action:
- service: input_boolean.turn_off
entity_id: input_boolean.ib_global_darkslot
#name: Light Flood Rear Control On
- alias: au_switch_floodr1_on
trigger:
- platform: state
entity_id: input_boolean.ib_global_darkslot
to: 'on'
condition:
- condition: state
entity_id: input_boolean.ib_light_floodr1_timeslot_enable
state: 'on'
action:
- service: switch.turn_on
entity_id: switch.fib_fgs223dblrly_fld1_sw1
#name: Light Flood Rear Control Off
- alias: au_switch_floodr1_off
trigger:
- platform: state
entity_id: input_boolean.ib_global_darkslot
to: 'off'
condition:
- condition: state
entity_id: input_boolean.ib_light_floodr1_timeslot_enable
state: 'on'
action:
- service: switch.turn_off
entity_id: switch.fib_fgs223dblrly_fld1_sw1
#name: Light Flood Side Control On
- alias: au_switch_floods2_on
trigger:
- platform: state
entity_id: input_boolean.ib_global_darkslot
to: 'on'
condition:
- condition: state
entity_id: input_boolean.ib_light_floods2_timeslot_enable
state: 'on'
action:
- service: switch.turn_on
entity_id: switch.fib_fgs223dblrly_fld2_sw2
#name: Light Flood Side Control Off
- alias: au_switch_floods2_off
trigger:
- platform: state
entity_id: input_boolean.ib_global_darkslot
to: 'off'
condition:
- condition: state
entity_id: input_boolean.ib_light_floods2_timeslot_enable
state: 'on'
action:
- service: switch.turn_off
entity_id: switch.fib_fgs223dblrly_fld2_sw2
#name: Light Flood Rear Control Off Overide
- alias: au_switch_floodr1_off_bcpatio
trigger:
- platform: state
entity_id: light.fib_fgd212dim2_prch_level
to: 'on'
condition:
- condition: state
entity_id: input_boolean.ib_light_floodr1_timeslot_enable
state: 'on'
- condition: state
entity_id: input_boolean.ib_global_darkslot
state: 'on'
action:
- service: switch.turn_off
entity_id: switch.fib_fgs223dblrly_fld1_sw1
#name: Light Flood Rear Control On Overide
- alias: au_switch_floodr1_on_bcpatio
trigger:
- platform: state
entity_id: light.fib_fgd212dim2_prch_level
to: 'off'
condition:
- condition: state
entity_id: input_boolean.ib_light_floodr1_timeslot_enable
state: 'on'
- condition: state
entity_id: input_boolean.ib_global_darkslot
state: 'on'
action:
- service: switch.turn_on
entity_id: switch.fib_fgs223dblrly_fld1_sw1
Basically it assumes that if the sun is a given number of degrees below the horizon, it then reaches the threshold for you to want external lights ‘on’ (as a rule of thumb), the limits have been set +/- 12° from the horizon, adjust as you require (12° is military dusk/dawn, 6° is civilian dusk/dawn).
When the light reaches your desired level, note the sun elevation and off you go.
It allows you to set a different limit on mornings to evenings as it checks the limit against whether the sun is rising or falling.
You can then use the input_number’s, as variables, to adjust the offset via the interface.
Any feedback welcome.