How to get planet constellation data (azimuth & elevation) into HA

Since I’ve seen this great card here I’m trying to create the same for my dashboard.

For the card I would need the constellation data (azimuth & elevation) of all visible planets.

For the sun I can get the data via state_attr(‘sun.sun’, ‘azimuth’) and state_attr(‘sun.sun’, ‘elevation’).

For the moon I can get the same via Lunar Phase (or via Moon Astro).

For planets I found ha_skyfield which is only for displaying the planets, not for providing raw-data.

My question is now, how I get the planet information into an HA-sensor?

Search here is a wonderful tool.

I’m not sure how this could solve my issue.

Here is the template sensor code I’m using for the sun.

- sensor:
    - name: "Sun Azimuth"
      unique_id: 8eb9eec1-409c-447e-ad60-aeb3d6d043d4
      icon: mdi:sun-compass
      unit_of_measurement: "°"
      state_class: measurement
      state: "{{ state_attr('sun.sun', 'azimuth') }}"
- sensor:
    - name: "Sun Elevation"
      unique_id: cb321e75-73e1-45a3-84f2-d3306bb579f4
      icon: mdi:sun-angle
      unit_of_measurement: "°"
      state_class: measurement
      state: "{{ state_attr('sun.sun', 'elevation') }}"

It’s working fine, but for creating such a template sensor also for planet data, I would need the planet data first.

I could not help on the planet data feeds, but am curious: What kind of automation would you need the planet data for?

It’s not an automation, it’s a very nice card showing the movement of sun & moon and the positions of the planets.

I am using this one in combination with compass-card: Astronomy API - Free To Use, Astronomy API For Developers

this is the sensor from which I can use it in the card…with jq one can bend/squeeze/fold more if/where needed of course

command_line:
  - sensor:
        name: Planetary Positions
        command: >
            curl -X GET 'https://api.astronomyapi.com/api/v2/bodies/positions?longitude=YOURLON&latitude=YOURLAT&elevation=50&from_date={{ now().date() }}&to_date={{ now().date() }}&time={{ now().strftime('%H:%M:%m') }}' -H 'Authorization: Basic YOURAPIKEY' | jq '{"planets": .[].table.rows}'
        value_template: "{{ now() }}"
        json_attributes:
            - planets
        scan_interval: 600
1 Like

At the risk of being shouted down here, I find the separate app Heavens Above is up to date, knows my current orientation in all four dimensions, and even has night mode and search abilities for when I actually venture outside to see a new passing comet. Highly recommended.

Now back to trying to squeeze all the stars into your display, and have it update in real time, and add random star music in the background…

You want it for when? Yesterday, tomorrow? 2038? Music too?

A beautiful sympathy for you if you missed out on the lovely aurora display the other evening. [Not my video - done in 2018 - click through for the back story - actually time lapse, not direct video]

I have seen a most wonderful aurora display around 30 years ago in unexpected latitudes that reminds me of this. Enjoy the beautifully haunting music too.

For Sun and Moon data, you can that from the following integration:

And from the same author, there is the UpTonight scripts to get the planet data but it looks a little more involved to get setup.

Thanks a lot for this command_line sensor, this was exactly the solution I was searching for - and it’s already working.

Keep going - once you have the Right Ascension and Declination for the Moon and Sun, you can create all kinds of fun template sensors for the moon - like the phase - as an angle, an icon, a character, or an image, and percent illumination, and even parallactic angle for your location (to rotate your moon phase daily image).

Here is a sample definition for the Moon Phase Angle (moonphase.jinja, store it in your custom_templates directory on your server), just replace the sensor names with yours:

{% macro phaseangle() %}
    {% set Ds = float(state_attr('sensor.planet_sun','Dec'),0) * pi/180 %}
    {% set RAs = float(state_attr('sensor.planet_sun','RA'),0) * pi/180 %}
    {% set Dm = float(state_attr('sensor.planet_moon','Dec'),0) * pi/180 %}
    {% set RAm = float(state_attr('sensor.planet_moon','RA'),0) * pi/180 %}
    {% set SinA = sin(Dm) * sin(Ds) %}
    {% set CosA =  cos(Dm) * cos(Ds) * cos(RAm - RAs) %}
    {% set phase_angle = acos(SinA + CosA) %}
    {{ ((phase_angle*180/pi) | round(2)) }}
{% endmacro %}

And reference it in your configuration.yaml:

template:
  - sensor:
    # moon phase angle
      - name: "Moon Phase Angle 2"
        unique_id: moon_phase_angle_2
        state: >
          {% from 'moonphaseangle.jinja' import phaseangle %}
          {{ phaseangle() }}
        unit_of_measurement: "°"

I also wanted that Plotly card to show a different character for the moon for each moon phase. You can do that by changing the annotation for the text field to a sensor:

  annotations:
    - x: $ex hass.states["sensor.planet_moon_az"].state
      "y": $ex hass.states["sensor.planet_moon_alt"].state
      text: $ex hass.states["sensor.planet_moon_phase_icon_char"].state

Where the sensor.planet_moon_phase_icon_char is defined in a custom template:

{% macro phaseiconchar() %}
  {% set illumination = float(states('number.moon_percent_illumination'),0) %}
  {% if float(state_attr('sensor.planet_moon','RA'),0) > float(state_attr('sensor.planet_sun','RA'),0) %}
    {% if illumination < 5 %}🌑
    {% elif illumination < 45 %}🌒
    {% elif illumination < 55 %}🌓
    {% elif illumination < 98 %}🌔
    {% else %}🌕{% endif %}
  {% else %}
    {% if illumination > 98 %}🌕
    {% elif illumination > 55 %}🌖
    {% elif illumination > 45 %}🌗
    {% elif illumination > 5 %}🌘
    {% else %}🌑{% endif %}
  {% endif %}
{% endmacro %}

The limits for the different phases are reasonable arbitrary: I like the phases to stick around for a bit, so i widened First Quarter (50% Illumination) to 45-55.

And Illumination is defined in a Template helper as

{% set phase_angle = float(states('sensor.moon_phase_angle_2'),0) * pi/180 %}
{% set illumination_fraction = (1 - cos(phase_angle)) / 2 %}
{# comment convert illumination_fraction from fraction to percent #}
{{ (illumination_fraction * 100 ) | round(2)}}

Now, the plotly card of the Moon looks like this:

1 Like

Looks really nice indeed, does plotly allow to use locally stored pictures too? I am using this one right now with ref. to some I found on the net.
Other yaml‐configuration examples · tomvanswam/compass-card Wiki

Unfortunately, no. Plotly can only show text, which is why I defined the phase icon character template to use a moon “character” for each moon phase. I found the moon characters on the net, and they look reasonably similar to the small moon images that you use on your compass card dynamic style element (thanks for that!).

In a similar way, I also use the moon age as an index for a picture entity card that shows a daily larger moon image (thanks, Nasa), and card-mod to rotate it by the parallactic angle so that it rotates during the day:

I stored the 30 daily moon images in a folder under the www directory, just like for the compass card.

To calculate the Age of the Moon in days from the last New Moon.
It takes about 29.5 days for the Moon to go through a full cycle. Or, exactly 29.530588853 days, or 12.190749117535045° per day.
We can use the difference between the RA of the Moon and Sun (adjusted to range from 0° to 360°), divided by 29.530588853 days.

Example Moon-Sun Right Ascension Separation Angle Template Number Helper

{% set as = float(state_attr('sensor.planet_moon','RA'),0) - float(state_attr('sensor.planet_sun','RA'),0) %}
{% if as < 0 %}
{% set as = as + 360 %}
{% endif %}
{{ as }}

This gives us a simple formula for calculating the Age of the moon:

Example Calculation of Age of Moon in a Template Helper

{{ (float(states('sensor.moon_sun_separation')) / 12.190749117535045) | int(0) }}

Daily Moon Image

E.g. Place 30 daily images (named from Moon0 to Moon29) in your www/MoonPhaseImages folder on your Home Assistant server, and reference them as follows:

Example Daily Image Template Image in configuration.yaml

template:
  - image:
      - name: Moon Phase Daily Image
        unique_id: moon_phase_daily_image
        url: "http://homeassistant.local/local/MoonPhaseImages/Moon{{ states('number.age_of_moon') | int(0) | string }}.jpg"
        verify_ssl: False

And finally the parallactic angle and the rotating daily moon image. (You need your latitude and longitude for this formula - you can get it from zone.home if you have that defined:

{% set my_lat = state_attr('zone.home', 'latitude') %}
{% set my_long = state_attr('zone.home', 'longitude') %}

Moon Parallactic Angle

The Moon Parallactic Angle is the angle of the moon measured clockwise from the zenith (celestial North).
This is why you see the moon tilted in the sky, and it moves between moonrise and moonset.
The formula for the moon parallactic angle is:

Moon Parallactic Angle Formula

Q = atan(sinH/(tanphi * cosdelta - sindelta * cosH))

where:
    Q is the parallactic angle of the moon
    H is the Moon Hour Angle (in radians) at the observer longitude
    phi is the observer latitude (in radians)
    delta is the declination of the Moon (in radians)

As a Template Number:

Example definition of moon parallactic angle in a Template Number Helper

{% set daySs = 60*60*24 %}
{% set J1970 = 2440588 %}
{% set J2000 = 2451545 %}
{% set my_latitude = 44.2307 %}
{% set my_longitude = -76.4813 %}

{% set julian_date = ( as_timestamp(now()) / daySs )  - 0.5 + J1970 %}
{% set gmst_deg = (280.46061837 + 360.98564736629 * (jd - J2000)) % 360 %}
{% set GMST = (gmst_deg / 15) %}
{% set longitude_hrs = my_longitude / 15 %}
{% set latitude_radians = my_latitude * pi/180 %}
{% set LST = (GMST + longitude_hrs)  %}
{% set MLH = float(state_attr('sensor.planet_moon','RA'),0) / 15 %}
{% set H = (((LST - MLH) )/24) * 360 %}
{% set sinH = sin(H*pi/180) %}
{% set tanphi = tan(latitude_radians) %}
{% set Dm = float(state_attr('sensor.planet_moon','Dec'),0) * pi/180 %}
{% set cosdelta = cos(Dm) %}
{% set sindelta = sin(Dm) %}
{% set cosH = cos(H*pi/180) %}
{% set Q = atan(sinH/(tanphi * cosdelta - sindelta * cosH)) %}
{{ ( Q * 180/pi) | round(2) }}

Card-mod image rotation

Card-mod can be used to modify a picture entity card to rotate the image.

Card-mod example to rotate an image in a picture entity card configuration

    - type: picture-entity
      entity: image.moon_phase_daily_image
      card_mod:
        style: |
          ha-card {
            {% set angle = states('number.moon_parallactic_angle')|string + "deg" %}
            transform: rotate({{angle}});
            border: none
          }
2 Likes