Calculate hours between sun.elevation values possible?

I just woke up that morning and had that question in my head, as i saw an degree of the sun above the horizon and the “right” power to optimal power my solar panels sufficiently.
As i said before, it was just out of curiosity, so maybe i will be the only one asking this for a loooong time :wink:

Nevertheless, thank you for your contibution to this and if it develops into an “really urgent” case, i will definitely try this out!

For the time being, the mentioned template quite at the start of this thread is working quite well and good for me now. :slight_smile:

Yes, my sun2 integration uses the same astral package that HA uses. FWIW, I was aware of that time_at_elevation method, and I tried using it at first, but it’s not very precise. The result can vary quite a bit from what the elevation method returns (around the same time.) I.e., if you map the values elevation returns over a given period of time, then use time_at_elevation to find the time for one of those values, they generally won’t agree. So I used a kind of brute force search method instead.

But, if you’re not looking for a very accurate result, time_at_elevation is definitely a lot easier/faster to use.

2 Likes

Thanks for the insight into the function’s accuracy (and thank you for going the extra distance to improve upon it, using an iterative technique, in your sun2 component).

FWIW, the only reason I mentioned it was because Mutt needed proof of its existence. Beyond that, I don’t have an application for it. However, I can see how it could be useful for applications such solar power generation and controlling blinds and other covers.

This is indeed proof, but of the use of an iterative method (my point NOT yours !)

You said : -

AND this whole thread, goes through the fact that there aren’t. The ‘models’ we have of the solar system are based on actual observations and they are all predetermined by the time as the base factor.
So calculations to solve for time, HAVE to be algorithms not equations.
And just to be clear : -

An Equation expresses the relation between several variables. An equation is a proposition that asserts the equality of two quantities, whereas an algorithm is a set of steps to get from some initial quantities to some desired output. Therefore they cannot be used interchangeably.

This is quite a common statement for distinction.
Moon - Fun Fact 1 - Katherine Johnson, was employed as a ‘computer’ given the repetitive nature of these calculations used in the algorithms and the precision required.
Moon - Fun Fact 2 - There were no seats in the Eagle Lander, the first men on the moon landed standing up.

Are you 6 ?

I am surprised to see that you replied to the thread (i.e. notification) rather than to me given my reduction in attendance, (for much the same reasons as Marc’s), so either sloppy - or perhaps deliberate ???

Edit: Actually I could (for a given location and sun elevation) derive a couple of 5th order polynominals to give the times in UTC, which could be coverted to a span, but this would only be accurate to about the nearest minute. These could be put into a template equation, but would over a number of years drift - require updating.

Technically incorrect usage but : - “Over and Out”

Pnbruckner employed an iterative method because the existing function in the astral library was found to be imprecise. However, that shouldn’t be considered proof that the same function in all other libraries is equally imprecise. The point is you were adamant that such a function cannot exist at all, yet there it is; plug in numbers, get a result. How the function works internally, I leave for you to investigate.

Could be what astral’s function does as well but, like I said, I leave that for you to explore.

Ha Ha Ha !

You are joking right ?

You think that if I use iterative methods, based on time, to determine the times of the day where the sun elevation is 24° for a single location on the planet.
Then by looking at those results derive a set of (it actually fits better with a 6th order) polynomial equations to give time. - Then that is a valid example of an equation solution ? Assuming just ‘an equation’ for each degree of latitude and longitude on the planet you’d need 129,600 equations - then Mutiply that by whatever ‘elevation’ is required. Oh and I was wrong, the calculations would need to be updated for every year as the calculation centres around the summer equinox for the selected year only.

I just set a tracker running on the number of calculations required and it’s over 221,816 (and those ignore the many comparision steps) - but I’m sure you had an equation for that.

I also love the fact that you know next to nothing about the calculations in use but with supreme confidence say : - "There’s an equation for that - but the proof is beneath me"

:rofl: :rofl: :rofl: :rofl: :rofl:

It’s true, I know next to nothing about the equations in use. Nevertheless, that’s true for most everyone who uses a library function (such as astral’s time_at_elevation). However, it’s a safe bet the functions employ mathematical equations and not the Oracle of Delphi.

I made no claim that the “proof is beneath me”. You said:

I described a library function that implements it so now you are free to explore the function’s code. The so-called “proof” lies within the code. There may be other libraries (implemented in other programming languages) that can provide you with additional, possibly better, examples.

Okay, we’ve seen that ‘astral’ determination (via package) is a bit of a finger in the air.
The best way to do this is via an iterative algorhithm that we just can’t process via Jinja2
So I did the full calcs for the location as specified (well Berlin as in 52.52° North and 13.4° East)
This gave me the exact times of the sun elevation at 24° through the year.
I then got another algorhithm to look at that real data and produce a 6th order polynominal (well 2 actually) by looking at that data to try to reproduce the same results.

The output is based on day of the year so can be repeated year after year (though variations will occur due to both the 4 and 100 year UTC matching) The formulas give correlation factors (R2) of 0.9995 and 0.9996 and comparisons against properly calculated figures give maximum errors of 1 minute 08 seconds at ‘one’ part (but as the sensors given below only have a resolution of 1 minute …

So I can’t say I’d use these myself (it just offends the OCD in me) but they are what they are.
I have given the sensor for the time ‘bracket’ (i.e. time between 24° in the morning and 24° in the afternoon) but you can copy and adjust (with the commented out sections) for the bracket ‘start time’ or the ‘stop time’.
This is incase you want to start an action when the slot starts or when it stops. Use a template trigger : -

"{{ states('sensor.time') == states('sensor.s_berlin_elev24') }}"

But you ‘may’ have to prevent triggers at midnight with a condition when the sun in winter does not reach 24°

The sensor(s) : -

sensor:
  - platform: template
    sensors:
      s_berlin_elev24:
        friendly_name: Sun Elevation Bracket
        value_template: >
          {% set tdy = as_local(states.sensor.date.last_updated).strftime('%j') | int %}
          {% set tstdy = as_timestamp(states.sensor.date.last_changed.replace(hour=0,minute=0,second=0,microsecond=0)) %}
          {% set strt = (0.00000000252469998477268*(tdy**6) - 0.00000251059967892875*(tdy**5) + 0.000993142676065872*(tdy**4) - 0.200203193424386*(tdy**3) + 22.711821494624*(tdy**2) - 1541.2614147067*tdy + 79570.0417881012) | int %}
          {% set stop = (0 - 0.00000000258919433582163*(tdy**6) + 0.00000276855794001385*(tdy**5) - 0.00118433434658982*(tdy**4) + 0.256722704303684*(tdy**3) - 30.2558065308257*(tdy**2) + 1962.38214886188*tdy + 1143.75953197479) | int %}
          {% set bracket = stop - strt %}
          {% set dytst = 0 if (tdy < 44 or tdy > 301 or strt > 43200 or stop < 43200) else 1 %}
          {#{ (tstdy + dytst*strt) | timestamp_custom("%H:%M", false) }#}
          {{ (tstdy + dytst*bracket) | timestamp_custom("%H:%M", false) }}
          {#{ (tstdy + dytst*stop) | timestamp_custom("%H:%M", false) }#}
        icon_template: "{% if is_state('sensor.s_berlin_elev24', '00:00') %}mdi:weather-sunny-off{% else %}mdi:weather-sunny{% endif %}"

This is written for inclusion in a package file so may need adjusting according to your storage preferences.
It is supplied as is (and has been fully tested), it will not be adjusted/corrected for others use. And to show that even an OCD’s best efforts can not substitute for real calculations.
Having said that. given for the ‘day’ to ‘day’ variation (due to Solar Analema) this should be more accurate than just serving up yesterday’s values.
It also does not require any additional ‘helpers’ to store data.

Any ammendments will be made at your own risk (i.e. I won’t help you fix it)

Additional Information : I found that Jinja2 does not seem to like negative mantissa’s so had to subtract a positive one from zero. There ‘may’ be a better way of doing it.

You will also need sensor.date (and sensor.time, if you want time triggers) set up

Edit : Thinking about this further, The Duration of the ‘bracket’ will always be correct but the start and stop times may be related to UTC (ie not DST) . So the ‘tigger time’ formulas may need ‘adjustment’

{{ (tstdy + dytst*strt) | timestamp_custom("%H:%M", false) }}
becomes something like : -
{{ (tstdy + dytst*strt + local_dst_adjustment) | timestamp_custom("%H:%M", false) }}
[ i.e. - determine if DST is applied to set the adjustment, else 0 ]
Or it may be as simple as : -
{{ (tstdy + dytst*strt) | timestamp_custom("%H:%M", true) }}

Suck it and see ...

oh my, this is getting ugly :laughing: