tomvanswam / compass-card

A Lovelace card that shows a directional indicator on a compass for Home Assistant
MIT License
174 stars 19 forks source link

Home Assistant Sensor Example for "Friends" location #41

Closed Haringstad closed 4 years ago

Haringstad commented 4 years ago

Is your feature request related to a problem? Please describe. I would like to know, how I can create the sensor "sensor.friends_direction", that you mention in the example.

type: custom:compass-card entity: sensor.friends_direction secondary_entity: sensor.friends_distance

Describe the solution you'd like Please provide an example of the sensor or template you use for this?

Describe alternatives you've considered I've been trying already for days to get this work, and it drives me bonkers :-)

Additional context NONE

tomvanswam commented 4 years ago

To be honest, the friends indicator is just a placeholder to show the outward indicator. I don't have it working in my own Home Assistant setup.

However, I don't want to leave you driving yourself bonkers, so here's what I made up:

Home Assistant itself has a great templating function for calculating distances, so I used that one for the secondary entity value. The direction is calculated with the formula I found here. The big catch is that the trigonometry functions in the template engine require the input parameter to be in radians as unit, not in degrees, so a conversion is needed to get a correct outcome of the calculation.

In the configuration example I used 2 zones to simulate the locations to get the directions between. You could use anything as long as you get a latitude and longitude in degrees from somewhere (adjust template accordingly).

# Add this to your configuration.yaml
sensor:
  - platform: template
    sensors:
      friend_distance:
        friendly_name: Friend Distance
        icon_template: mdi:map-marker-distance
        value_template: "{{ distance('zone.me', 'zone.you') | round(0) | int }}"
        unit_of_measurement: km
      friend_direction:
        friendly_name: Friend Direction
        icon_template: mdi:compass-outline
        value_template: >
          {# Use the latitude and longitude from a zone, app location sensor or any other source #}
          {% set originLatDeg = state_attr('zone.me', 'latitude') %}
          {% set originLonDeg = state_attr('zone.me', 'longitude') %}
          {% set destLatDeg = state_attr('zone.you', 'latitude') %}
          {% set destLonDeg = state_attr('zone.you', 'longitude') %}

          {# Trigonometry function use radians instead of degrees #}
          {# Convert everything we need for the calucation in radians #}
          {% set RadDegFactor = (180/pi) %}
          {% set dLonRad = (destLonDeg - originLonDeg) / RadDegFactor %}
          {% set dLatRad = (destLatDeg - originLatDeg) / RadDegFactor %}
          {% set originLatRad = originLatDeg / RadDegFactor %}
          {% set originLonRad = originLonDeg / RadDegFactor %}
          {% set destLatRad = destLatDeg / RadDegFactor %}
          {% set destLonRad = destLonDeg / RadDegFactor %}

          {# Calculate the direction #}
          {% set aTan2x = (sin(dLonRad)*cos(destLatRad)) %}
          {% set aTan2y = ((cos(originLatRad)*sin(destLatRad))-(sin(originLatRad) * cos(destLatRad) * cos(dLonRad))) %}
          {% set rDir = atan2(aTan2x, aTan2y ) %}

          {# Convert result back to degrees, and make sure we get a positive result between 0 and 360 #}
          {% set dDir = rDir * RadDegFactor %}
          {% if dDir < 0 %}
            {{ (dDir + ((((dDir / 360)| round(0, floor)) | abs) + 1) * 360) | round(0) }}
          {% else %}
            {{ (dDir % 360) | round(0) | int }}
          {% endif %}
        unit_of_measurement: "°"
# This is the acompanying card config
type: 'custom:compass-card'
entity: sensor.friend_direction
secondary_entity: sensor.friend_distance
name: Friends direction
compass:
  indicator: arrow_outward

Hope this helps out keeping you sane ;-)

I'll link this issue in the README, for easy access for anyone else.

Haringstad commented 4 years ago

Tom, That should actually work with a person set too. Because both should have the LAT/LON information too, if they have trackers. I'll give it a try tomorrow! Thanks again!

Regards, Jacco

On Sun, Sep 6, 2020 at 2:36 PM Tom van Swam notifications@github.com wrote:

To be honest, the friends inidcator is just a placeholder to show the outward indicator. I don't have it working in my own Home Assistant setup.

However, I don't want to leave you driving yourself bonkers, so here's what I made up:

Home Assistant itself has a great templating function https://www.home-assistant.io/docs/configuration/templating/#distance for calculating distances, so I used that one for the secondary entity value. The direction is calculated with the formula I found here https://www.omnicalculator.com/other/azimuthhttps://www.omnicalculator.com/other/azimuth. The big catch is that the trigonometry functions in the template engine require the input parameter to be in radians as unit, not in degrees, so a conversion is needed to get a correct outcome of the calculation.

In the configuration example I used 2 zones to simulate the locations to get the directions between. You could use anything as long as you get a latitude and longitude in degrees from somewhere (adjust template accordingly).

Add this to your configuration.yaml

sensor:

  • platform: template

    sensors:

    friend_distance:

    friendly_name: Friend Distance
    
    icon_template: mdi:map-marker-distance
    
    value_template: "{{ distance('zone.me', 'zone.you') | round(0) | int }}"
    
    unit_of_measurement: km

    friend_direction:

    friendly_name: Friend Direction
    
    icon_template: mdi:compass-outline
    
    value_template: >
      {# Use the latitude and longitude from a zone, app location sensor or any other source #}
      {% set originLatDeg = state_attr('zone.me', 'latitude') %}
      {% set originLonDeg = state_attr('zone.me', 'longitude') %}
      {% set destLatDeg = state_attr('zone.you', 'latitude') %}
      {% set destLonDeg = state_attr('zone.you', 'longitude') %}
    
      {# Trigonometry function use radians instead of degrees #}
      {# Convert everything we need for the calucation in radians #}
      {% set RadDegFactor = (180/pi) %}
      {% set dLonRad = (destLonDeg - originLonDeg) / RadDegFactor %}
      {% set dLatRad = (destLatDeg - originLatDeg) / RadDegFactor %}
      {% set originLatRad = originLatDeg / RadDegFactor %}
      {% set originLonRad = originLonDeg / RadDegFactor %}
      {% set destLatRad = destLatDeg / RadDegFactor %}
      {% set destLonRad = destLonDeg / RadDegFactor %}
    
      {# Calculate the direction #}
      {% set aTan2x = (sin(dLonRad)*cos(destLatRad)) %}
      {% set aTan2y = ((cos(originLatRad)*sin(destLatRad))-(sin(originLatRad) * cos(destLatRad) * cos(dLonRad))) %}
      {% set rDir = atan2(aTan2x, aTan2y ) %}
    
      {# Convert result back to degrees, and make sure we get a positive result between 0 and 360 #}
      {% set dDir = rDir * RadDegFactor %}
      {% if dDir < 0 %}
        {{ (dDir + ((((dDir / 360)| round(0, floor)) | abs) + 1) * 360) | round(0) }}
      {% else %}
        {{ (dDir % 360) | round(0) | int }}
      {% endif %}
    unit_of_measurement: "°"

This is the acompanying card config

type: 'custom:compass-card' entity: sensor.friend_direction secondary_entity: sensor.friend_distance name: Friends direction compass:

indicator: arrow_outward

Hope this helps out keeping you sane ;-)

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/tomvanswam/compass-card/issues/41#issuecomment-687778460, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB3YEZWECYXFZ7ESWOCE2N3SEN64DANCNFSM4Q3F3KYA .

DeFlanko commented 8 months ago

@tomvanswam Is there a way to A) use Miles 'Mi' and if 'Mi' < 0 convert to 'ft' for more granularity? i plan on incorporating this in to our pet's tracking collar.

tomvanswam commented 8 months ago

Did you set the Setings->General->Unit System to Fahrenheit, pounds? I'm not sure, but I would suspect that selecting that should change all length measurements to your desired settings. Otherwise you'd need some formula to include in the template to do the converting for you.

DeFlanko commented 8 months ago

Did you set the Settings->General->Unit System to Fahrenheit, pounds? I'm not sure, but I would suspect that selecting that should change all length measurements to your desired settings. Otherwise you'd need some formula to include in the template to do the converting for you.

Yes my system default is imperial measurements as i'm in the US.

but what i'm trying to do is for those values less than 0 shown here, convert to feet Using your code from above in post image

tomvanswam commented 3 months ago

Appologies for the long wait. Imperial units are not my forte. However I think with something like this is the best you can do:

        value_template:  {{ distance('zone.me', 'zone.you') | float }}

This wil give you a decimals after the 0, instead of just 0. Problem is, the template sensor does not support dynamic units. So while it could be possible to display feet when distance < 1 mile, the unit will still show miles.