More precise time for morning, day, evening and night

Hi all geniuses!
Is there anyone who can help me with the time for volume in below script?
I would like a more precise time for morning, day, evening and night

#coffeemaker
    coffeemaker:
        sequence:
          - service: light.turn_on
            data:
              entity_id: light.kitchen_sink,light.kitchen_sink_two #brighten lights
              brightness: 254
          - service: script.turn_on
            data:
              entity_id: script.coffee_on
          - delay: 00:00:01
          - service: media_player.turn_on
            data:
              entity_id: media_player.kitchen
          - service: media_player.volume_set
            data:
              entity_id: media_player.kitchen
              volume_level: >
               {% if now().strftime("%H")|int < 12 %}
               '0.3'
               {% elif now().strftime("%H")|int < 18 %}
               '0.5'
               {% else %}
               '0.3'
               {% endif %}              
          - service: tts.amazon_polly_say #google_say
            data_template:
              entity_id: media_player.kitchen
              message: >
               {% if now().strftime("%H")|int < 12 %}
               {{["Insert coffee to begin this day.",
               "Coffee. Creative lighter fluid.",
               "A morning without coffee is like sleep.",
               "Drink coffee! Do Stupid Things Faster with More Energy.",
               "Every morning I long to hold you…I need you, I want you, I have to have you…your warmth, your smell, your taste…ohhh coffee, I love you.",
               "Even bad coffee is better… than no Coffee at all.",
               "Life’s too short to drink cheap coffee.",
               "The road to success is paved in coffee.",
               "I don’t have a problem with caffeine. I have a problem without it.",
               "With this coffee and many, many refills... we will overcome this day",
               "I'm sorry, Dave. I'm afraid I can't do that.... Oh sorry i thought you where Dave. But now i see you are not Dave so i will definitely make you some coffee",
               "Todays good mood is sponsored by Coffee",
               "I will start working when my coffee does",
               "Patience is the time between drinking a cup of coffee and the motivation to begin your day",
               "You should know that before 10am, no matter what the question is, my answer is always coffee",
               "Coffee, because it’s too early for wine",
               "When life gives you lemons, trade them for coffee",
               "Humanity runs on coffee.",
               "Todays todolist. one make coffee. two drink coffee. three make ore coffee",
               "Nothing is like coffee on a cold day. Or a mild day. Or a hot day.",
               "Keep calm. Coffee is on the way",
               "I like big cups and i cannot lie",
               "Planning to take over the world today. Just need some coffee first.",
               "Insert coffee to begin.",
               "Wake up and smell the coffee.",
               "Life begins after coffee.",
               "Start your day with coffee. End your day with wine.",
               "If you think that by threatening me you can get me to do what you want... Well, that's where you're right. But - and I am only saying that because I care - there's a lot of decaffeinated brands on the market that are just as tasty as the real thing.",
               "If I'm not back in five minutes, just wait longer.",
               "Alright, alright alright.",
               "Try not. Do, or do not. There is no try",
               "After very careful consideration, I've come to the conclusion that you need coffee",
               "The answer to the Ultimate Question of Life, the Universe, and Everything is 42 if you ask Douglas Adams. But if you ask me the answer is coffee",
               "All you really need to know for the moment is that the universe is a lot more complicated than you might think, even if you start from a position of thinking it’s pretty damn complicated in the first place."
               ] | random}} ...
               {% elif now().strftime("%H")|int < 18 %}
               {{["When life gives you lemons, trade them for coffee",
               "Water is the most essential element of life, because without water, you can't make coffee"
               "Todays good mood is sponsored by Coffee",
               "Life is what happens between coffee and wine",
               "Sometimes I go hours without drinking coffee…it’s called sleeping",
               "Sometimes you gotta drink some coffee, put on some rock n’ roll, and handle your business",
               "Coffee is a hug in a mug",
               "Coffee, because crack is bad for you",
               "I put coffee in my coffee",
               "Keep calm and drink more coffee.",
               "A day without coffee is like something without something.",
               "You had me at hot coffee.",
               "It's time for coffee.",
               "I never drink coffee at lunch. I find it keeps me awake for the afternoon.",
               "Do you know how helpless you feel if you have a full cup of coffee in your hand and you start to sneeze?",
               "I survive my days with coffee."
               ] | random}} ...
               {% else %}
               {{["I’ve had so much coffee today I can see noises",
               "Coffee is always a good idea",
               "Grab life by the beans.",
               "Caffeine-The other Vitamin C.",
               "Caffeine isn’t a drug, it’s a vitamin.",
               "Deja Brew: The feeling that you’ve had this coffee before.",
               "Coffee gives strength to get things done",
               "Caffeine is the foundation of the food pyramid.",
               "Everybody should believe in something. I believe in coffee",
               "Way too much coffee. But if it weren't for the coffee, I'd have no identifiable personality whatsoever."] | random}} ...
               {% endif %}
               {{ speech_message | replace("\n","") | replace("   ","") | replace("  "," ") }}

You could add something like this at the beginning of your templates:

{% set t = now() %}
{% set t = (t.hour*60+t.minute)*60+t.second %}

Now you’ve got the number of seconds since midnight that you can use in comparisons. E.g.:

{% if t < (13*60+15)*60 %}

would compare if it’s before 13:15:00.

Or you could just do something like:

{% set t = now() %}
{% if t.hour < 13 or t.hour == 13 and now().minute < 15 %}

That seem to be really neat :+1:

Is there a way to have different volume_level between?

For example if i want to have
22:00 - 07:00 : 0.3
07:00 - 12:00 : 0.4
12:00 - 18:00 : 0.5
18:00 - 22:00 : 0.4

many ways to set a period of day :slight_smile:

  day_phase:
    friendly_name: 'Day Phase'
    entity_id: sensor.time
    value_template: >
      {% if now() > now().replace(hour=5).replace(minute=0).replace(second=0) and
        now() < now().replace(hour=7).replace(minute=0).replace(second=0) %}
          Morning
      {% elif states('sun.sun') == 'above_horizon' or
        now() > now().replace(hour=5).replace(minute=0).replace(second=0) and
        now() < now().replace(hour=12).replace(minute=0).replace(second=0) %}
          Day
      {% elif now() < now().replace(hour=21).replace(minute=45).replace(second=0) and
        now() > now().replace(hour=5).replace(minute=0).replace(second=0) %}
          Evening
      {% else %}
          Night
      {% endif %}
    icon_template: >
      {% if now() > now().replace(hour=5).replace(minute=0).replace(second=0) and
        now() < now().replace(hour=7).replace(minute=0).replace(second=0) %}
        mdi:weather-sunset-up
      {% elif states('sun.sun') == 'above_horizon' or
        now() > now().replace(hour=5).replace(minute=0).replace(second=0) and
        now() < now().replace(hour=12).replace(minute=0).replace(second=0) %}
        mdi:weather-sunny
      {% elif now() < now().replace(hour=21).replace(minute=45).replace(second=0) and
        now() > now().replace(hour=5).replace(minute=0).replace(second=0) %}
        mdi:weather-sunset-down
      {% else %}
        mdi:weather-night
      {% endif %}

  period_of_day:
    friendly_name: 'Period of the day'
    value_template: >
      {% if (as_timestamp(state_attr('sun.sun','next_dusk'))) - 
            (as_timestamp(state_attr('sun.sun','next_setting'))) < 0 %}
        Dusk
      {% elif (as_timestamp(state_attr('sun.sun','next_rising'))) - 
              (as_timestamp(state_attr('sun.sun','next_dawn'))) < 0 %}
        Dawn
      {% elif (state_attr('sun.sun', 'elevation')) < 0 %}
        night
      {% else %}
        Day
      {% endif %}
    icon_template: >
      {% if (as_timestamp(state_attr('sun.sun','next_dusk'))) - 
            (as_timestamp(state_attr('sun.sun','next_setting'))) < 0 %}
        mdi:weather-sunset-down
      {% elif (as_timestamp(state_attr('sun.sun','next_rising'))) - 
              (as_timestamp(state_attr('sun.sun','next_dawn'))) < 0 %}
        mdi:weather-sunset-up
      {% elif (state_attr('sun.sun', 'elevation')) < 0 %}
        mdi:weather-night
      {% else %}
        mdi:weather-sunny
      {% endif %}

  part_of_day:
    friendly_name: 'Part of Day'
    entity_id: sensor.time
    value_template: >
      {% if now().hour in range(0, 6) %}
        Midnight
      {% elif now().hour in range(6, 12) %}
        Morning
      {% elif now().hour in range(12, 18) %}
        Afternoon
      {% else %}
        Evening
      {% endif %}
    icon_template: >
      {% if now().hour in range(0, 6) %}
        mdi:weather-night
      {% elif now().hour in range(6, 12) %}
        mdi:weather-sunset-up
      {% elif now().hour in range(12, 18) %}
        mdi:weather-sunny
      {% else %}
        mdi:weather-sunset-down
      {% endif %} 

you could use one of these, and use the state if that sensor in your audio_volume services {% if is_state('sensor.part_of_day','Midnight') %} '0.2'

added advantage of this is you can use the sensor in all of you HA setup, and not need to program if for each automation or template.

I’ll add @pnbruckner s format which is even shorter than the ones I had up to now . cool.

So i guess i can use the sensor looking like this then

  part_of_day:
    friendly_name: 'Part of Day'
    entity_id: sensor.time
    value_template: >
      {% if now().hour in range(22, 7) %}
        Midnight
      {% elif now().hour in range(7, 12) %}
        Morning
      {% elif now().hour in range(12, 18) %}
        Afternoon
      {% else %}
        Evening
      {% endif %}
    icon_template: >
      {% if now().hour in range(22, 7) %}
        mdi:weather-night
      {% elif now().hour in range(7, 12) %}
        mdi:weather-sunset-up
      {% elif now().hour in range(12, 18) %}
        mdi:weather-sunny
      {% else %}
        mdi:weather-sunset-down
      {% endif %}

And for the script:

      - service: media_player.volume_set
        data:
          entity_id: media_player.kitchen
          volume_level: >
           {% if is_state('sensor.part_of_day','Midnight') %} 
           '0.3'
           {% elif is_state('sensor.part_of_day','Morning') %}
           '0.4'
           {% elif is_state('sensor.part_of_day','Afternoon') %} 
           '0.5'
           {% else %} 
           0.4
           {% endif %}

yep. think you need data_template.
Ive noticed these daytime templates, which were created some time ago could be bettered like this:

  part_of_day:
    friendly_name: 'Part of Day'
    entity_id: sensor.time
    value_template: >
      {% if now().hour in range(0, 6) %}
        Midnight
      {% elif now().hour in range(6, 12) %}
        Morning
      {% elif now().hour in range(12, 18) %}
        Afternoon
      {% else %}
        Evening
      {% endif %}
    icon_template: >
      {% if is_state('sensor.part_of_day','Midnight') %} mdi:weather-night
      {% elif is_state('sensor.part_of_day','Morning') %} mdi:weather-sunset-up
      {% elif is_state('sensor.part_of_day','Afternoon') %} mdi:weather-sunny
      {% else %} mdi:weather-sunset-down
      {% endif %}

No need to repeat the same template for value and icon templates, now using the value of the sensor itself for the icon_template. Haven’t found a way to refer to the sensor directly with state == 'Midnight' etc, and this seems to be the only way to do so.

Very nice! I never would have thought of using the sensor’s state in its icon_template. :slight_smile:

I would make a change, though. In any given template I would only reference now() once, otherwise the value it returns for each call will be slightly different, even if only a few microseconds. If that happens right near an hour or day boundary, that could cause the template to behave differently than you expect. If there’s anything I’ve learned in 40 years of programming, if something can happen, it will happen, no matter how unlikely, and usually drive you nuts trying to figure out what went wrong! :wink:

Also I’d use regular comparisons to make it easier to read and understand. E.g., many people don’t understand that the second value in the range function isn’t included in the range, so range(0, 6) is 0…5, not 0…6, although you used it correctly here.

So, per the above and using @dawnlord’s original time periods…

  part_of_day:
    friendly_name: 'Part of Day'
    entity_id: sensor.time
    value_template: >
      {% set hour = now().hour %}
      {% if 7 <= hour < 12 %}    Morning
      {% elif 12 <= hour < 18 %} Afternoon
      {% elif 18 <= hour < 22 %} Evening
      {% else %}                 Midnight
      {% endif %}
    icon_template: >
      {% if is_state('sensor.part_of_day', 'Morning') %}     mdi:weather-sunset-up
      {% elif is_state('sensor.part_of_day', 'Afternoon') %} mdi:weather-sunny
      {% elif is_state('sensor.part_of_day', 'Evening') %}   mdi:weather-sunset-down
      {% else %}                                             mdi:weather-night
      {% endif %}

And for the script, as @Mariusthvdb said you need to use data_template, and remove the quotes around the numbers. Otherwise '0.3' will actually result in "'0.3'". So…

      - service: media_player.volume_set
        entity_id: media_player.kitchen
        data_template:
          volume_level: >
            {% if is_state('sensor.part_of_day', 'Midnight') %}    0.3
            {% elif is_state('sensor.part_of_day', 'Morning') %}   0.4
            {% elif is_state('sensor.part_of_day', 'Afternoon') %} 0.5
            {% else %}                                             0.4
            {% endif %}

But you could make this simpler using a dictionary:

      - service: media_player.volume_set
        entity_id: media_player.kitchen
        data_template:
          volume_level: >
            {% set map = {'Midnight': 0.3, 'Afternoon': 0.5} %}
            {{ map.get(states('sensor.part_of_day'), 0.4) }}
3 Likes

clever!

especially the else 0,4, also used for Morning :wink:

I tend to make maps only when it results fewer lines (including the conditions). In this case the Morning line makes the difference :+1:
rewriting templates now…

sure, and appreciated, still, kind of liked the in range technique.

    value_template: >
      {% set hour = now().hour %}
      {% if hour in range(0,6) %} Midnight
      {% elif hour in range(6,12) %} Morning
      {% elif hour in range(12,18) %} Afternoon
      {% else %} Evening
      {% endif %}

not sure about the <= you use, and I miss. Haven’t seen it fail yet, but I understand the difference. copied your version in comments into the package and cookbook.

Yep, there’s often multiple ways to implement something, so usually comes down to personal preference. BTW, never said or suggested using in range would fail.

It just means less than or equal to. So 7 <= hour < 12 is true if 7 is less than or equal to hour (or to express that a more useful way, hour is greater than or equal to 7) and hour is less than 12; basically it’s between 7:00 and 12:00.

Thank you @Mariusthvdb and @pnbruckner for all help!

lol. no that’s no secret ;=_)
it’s just that I wasn’t sure if the same was accomplished with my range() technique

Gotcha. Yep, for ints, A <= x < B is equivalent to x in range(A, B). But, the former takes only 10 characters, whereas the latter takes 16 characters, so just for that reason alone you should prefer the first way. :wink: LOL