Enhanced Sun component

By using it directly I meant in a template trigger, as opposed to creating a template binary sensor from it and then using that in a state trigger.

How about:

trigger:
  platform: template
  value_template: >
    {% set noon = state_attr('sensor.astral_solar_noon', 'today') %}
    {{ noon is not none and now() > noon }}
1 Like

yes, that would do it, much better.

the binary sensor template I made above would have triggered twice probably, but this will only fire once, so I can use it in an automation that should trigger on date change, and at solar noon.
If you have an extra spare moment, might I ask you to check the challenge I need this for?

not in a hurry, but I’d appreciate your expertise in the matter

Sorry, I’m not sure I’m following you here. The template trigger I suggested will only fire once a day, when it changes from False to True, which happens when the current time surpasses the day’s solar noon. At midnight the solar noon sensor will update and the template will change from evaluating as True to False, which will not cause the trigger to fire.

BTW, you can change > to >=, which is slightly more appropriate, but in practice probably won’t have much of an effect.

Um, I read it briefly, but I couldn’t easily wrap my head around what you’re trying to do. If the question is, how to cause something to happen at change of day, why not have an automation with a time trigger that triggers at 00:00:00, with appropriate conditions?

yes, thats what I was trying to say, and what was the benefit over it compared to a binary template sensor I made, which triggers twice a day (and needs the extra to: 'on' because of that)

no it wasn’t the issue of triggering at daystart…
the challenge was/is to check whether the conditionas are met for the pond pumps to alternate (opposed to both of them being always on)

they need to be alternating either when it is below 6 degrees, or when the sun is down. And survive restarts.

an automation with a ‘while’ construct I made at first doesn’t survive restarts, so now I use these 3 small automations:
1 to set alternating mode, and turn-off 1 switch (so the next automation only needs a toggle service, triggered by the binary sensor checking the temperature and daylight condition
2 to actually toggle, and is triggered by the day change and your noon template (needed in longer periods of cold)
3 to leave alternating mode and turn on both of them again

btw, your suggestion to use
state_attr('sensor.astral_solar_noon', 'today') works fine, and I am trying to understand why it is better than using states('sensor.astral_solar_noon') which renders the same result, only without the T.

Having seen several other issues with that resulting in incorrect frontend representation of the timestamp, we had to cure that adding .isoformat(), making it a true datetime.datetime object

I ask because the states show the attributes With the T…

while the templates show:

and yes, adding that to the {{state_attr('sensor.astral_solar_noon','today')}} results in the correct time with the T

      solar_noon:
        value_template: >
          {{states('sensor.astral_solar_noon')}}
        device_class: timestamp
      solar_noon_today:
        value_template: >
          {{state_attr('sensor.astral_solar_noon','today')}}
        device_class: timestamp
      solar_noon_today_iso:
        value_template: >
          {{state_attr('sensor.astral_solar_noon','today').isoformat()}}
        device_class: timestamp

in frontend (atop is the astral sensor from your integration):

Because that is not the only difference. The today attribute is a Python datetime object, just like what is returned by the now() function, so they can be compared directly. The state, however, is, of course, like all states, a string, which is more difficult to compare to a Python datetime object. (I.e., you need to use as_timestamp(), etc.)

Regarding the rest of your comment, the state will always show as it is, because it’s a string. It doesn’t need any further formatting when displayed. However, how a Python datetime object (attribute) is displayed depends on how/where it’s being displayed. But, no matter how it’s displayed, it’s still a Python datetime object and can be used as such. (And, yeah, by “datetime” I mean “datetime.datetime”.)

thanks Phil, ive adapted it all, and working fine now.

I do need your assistance on a couple of template sensors calculating the remains daylights time. Before I used the extra attributes your now archived Sun integration added to the core sun.sun and the templates.

      daylight_remaining_min:
        friendly_name: Daylight remaining minutes
        value_template: >
          {{((as_timestamp(state_attr('sun.sun','next_setting')) - now().timestamp())/60)|int}}
        unit_of_measurement: min

      daylight_remaining_hm:
        friendly_name: 'Daylight remaining hh:mm'
        value_template: >
          {{(as_timestamp(state_attr('sun.sun','next_setting')) - now().timestamp())
             |timestamp_custom('%H:%M',false)}}

because I had checked these during daytime only thus far, I hadn’t noticed they show strange states in the evening, when there of course is no more remaining daylight at all… still:

It is a bit silly to show20 hours of remaining daylight, at 23:07 ? Of course it simply calculates the time until the next setting… which would make it only a naming issue, unless I miss something you did I the archived integration.

Im struggling to make that a more adaptive sensor, showing 0 when the sun is down, (no more remaining daylight that day, or on the next day until sunrise, showing the true remaining daylight calculated from that days sunrise tilll sunset…

{% if is_state('sun.sun','above_horizon') %}
{{((as_timestamp(state_attr('sun.sun','next_setting')) - now().timestamp())/60)|int}}
{% else %} 
{{state_attr('sensor.astral_daylight','tomorrow')}}
{% endif %}

would this pass the correct day changes? I need to use the new Sun enhanced integration’ ‘astral’ sensors

{{state_attr('sensor.astral_daylight','tomorrow')}} and {{state_attr('sensor.astral_daylight','today')}} in a better way.

Use the sunset option for sun2. Then:

{{ [0, (state_attr('sensor.astral_sunset', 'today') - now()).total_seconds()]|max }}

That is in seconds. If you want it shown elsewise, then adjust accordingly.

EDIT: Actually, I need to also take into account if it’s before sunrise, so…

EDIT 2: Ok, try this on for size:

{% set nw = now() %}
{% set sr = state_attr('sensor.astral_sunrise', 'today') %}
{% set ss = state_attr('sensor.astral_sunset', 'today') %}
{% if nw < sr %}
  {{ (ss - sr).total_seconds() }}
{% elif nw < ss %}
  {{ (ss - nw).total_seconds() }}
{% else %}
  0
{% endif %}
1 Like

thanks Phil,
making that use aH:M:S format:

{% set nw = now() %}
{% set sr = state_attr('sensor.astral_sunrise', 'today') %}
{% set ss = state_attr('sensor.astral_sunset', 'today') %}
{% if nw < sr %}
  {{ (ss - sr).total_seconds()|timestamp_custom('%-H:%M:%S',false) }}
{% elif nw < ss %}
  {{ (ss - nw).total_seconds()|timestamp_custom('%-H:%M:%S',false) }}
{% else %}
  0
{% endif %}

will see what happens tonight…

If that’s what you want, then no need to convert to seconds and reformat. Just let it use the default datetime.timedelta display format:

{% set nw = now().replace(microsecond=0) %}
{% set sr = state_attr('sensor.astral_sunrise', 'today') %}
{% set ss = state_attr('sensor.astral_sunset', 'today') %}
{% if nw < sr %}
  {{ ss - sr }}
{% elif nw < ss %}
  {{ ss - nw }}
{% else %}
  0:00:00
{% endif %}
1 Like

And knowing how you like everything “guarded” :wink:

{% set nw = now().replace(microsecond=0) %}
{% set sr = state_attr('sensor.astral_sunrise', 'today') %}
{% set ss = state_attr('sensor.astral_sunset', 'today') %}
{% if sr is none or ss is none %}
  unknown
{% elif nw < sr %}
  {{ ss - sr }}
{% elif nw < ss %}
  {{ ss - nw }}
{% else %}
  0:00:00
{% endif %}
2 Likes

Right, need guards! Haha, thanks. Glad you helped me out.

still, this is not as expected, or maybe I should say, as intended? it is utterly dark right now, and definitely before sunrise, and yet is shows the remaining daylight. One could philosophize on the correctness of that (it is after all the remaining time of daylight for today), yet I would have hoped your words

would have accounted for this?

guess I was looking for:

{% if sr is none or ss is none %}
  unknown
{% elif sr < nw < ss %}
  {{ ss - nw }}
{% else %}
  0
{% endif %}

Exactly. That’s what I intended and what I thought you wanted. If something else, then adjust accordingly. Your last template seems like it will do what you want.

getting back on the guard, what are your thoughts on the availability_template?

something like:

availability_template: >
  {% set sr = state_attr('sensor.astral_sunrise', 'today') %}
  {% set ss = state_attr('sensor.astral_sunset', 'today') %}
  {{ sr not is none and ss not is none }}

I ask because I have several automations triggering on comparable template (binary_)sensors, and these tend to trigger on reload of the template entities. Preventing that has been a struggle here and there, and either adding these conditions to the automation, or the availability_template to the template sensors is the advised way to go, though not always successful.

That looks reasonable. I did look briefly into what availability_template does when I first became aware of it, but I don’t remember the details. I think it basically just causes the entity’s state to change to 'unavailable' (when the template evaluates to something other than true.)

I’m guessing that is causing the entities to be deleted and recreated. Which means their states are changing from something to none, and then from none to something. I.e., if you had a state trigger set up to listen to a template sensor, when the template sensor is reloaded, you’ll get (possibly, depending on how you have to: & from: configured) two trigger events. The first with trigger.to_state is none, and the second with trigger.from_state is none. I don’t think availability_template will have any affect with respect to this.

yes, you’re right, the availability sensor on my binary_sensor vijverpompen doesnt help.
And yes, they are being recreated (show yellow in the frontend and state entity is unavailable)

The set of conditions doesnt help either. I’ve only been able to prevent this automation from triggering by adding the additional condition in the action block:

  - alias: Vijverpompen aan
    id: Vijverpompen aan
    trigger:
      platform: state
      entity_id: binary_sensor.vijverpompen
      from: 'off'
      to: 'on'
    condition:
      - >
          {{trigger.to_state.state != 'None'}}
      - >
          {{trigger.from_state is not none and
            trigger.to_state is not none and
            trigger.to_state.state != trigger.from_state.state}}
    action:
      - condition: state
        entity_id: input_boolean.vijverpompen_alterneren
        state: 'on'
      - service: input_boolean.turn_off
        entity_id: input_boolean.vijverpompen_alterneren

this being the binary:

    vijverpompen:
      friendly_name: Vijverpompen
      value_template: >
        {{states('sensor.pond_tools_buiten_sensor_calibrated_temperature')|float > 6 and
          is_state('binary_sensor.outside_daylight_sensor','on')}}
      delay_off:
        minutes: 60

this is straying form the threads topic though, sorry.

There’s a few things about this that don’t make sense.

First, you’re specifying both from: & to: in the trigger, so this should not trigger when the sensor gets deleted or added (i.e., at startup, at shutdown, or when the template sensor is reloaded.)

Second, because of the trigger, it will only fire when trigger.from_state.state is 'off' and trigger.to_state.state is 'on', so none of the conditions are needed.

Lastly, this certainly doesn’t help (and probably hurts):

      - >
          {{trigger.to_state.state != 'None'}}

If trigger.to_state is none (which, of course, can’t happen per the above, but in general, if it could be), then trigger.to_state.state doesn’t make sense and probably causes an error.

But, yes, I think we’ve strayed off topic a bit.

Looks like HA will be updating the astral package from 1.10.1 to 2.2 in an upcoming release (presumably 2021.4.) See PR #48573. That change breaks this custom integration. (E.g., it broke using a HA dev checkout.) See Issue #32.

I think I’ve fixed it so that it will continue to work ok with current and previous HA releases (that use astral 1.10.1), as well as newer releases (that use 2.2.) See PR #33. I’ve tested it with a HA dev checkout, as well as with 2021.3.4. If anyone else could give it a try, either with a current HA release, and/or with a dev checkout, it would be greatly appreciated!

1 Like

What should one do? :slight_smile:

If you know how to use the code from github, then by all means, give it a try. If not, then I plan to release a new version before the next HA release, and then you can just update the custom integration at that time. If all goes well you shouldn’t run into any problems (as long as you update the custom integration before updating HA to the new version that uses the new version of the astral package.)