Calculate bearing between zones (or zone and device tracker)

How can I calculate the bearing between the coordinates of two zones?

(using a template sensor, not Python)

Background:

I travel to work by bike. My plan is to show a card with information for my daily commute. One of the entities that I want to show (sensor, binary sensor, I don’t know yet) is to show if there is an average headwind, tailwind or sidewind (or no wind, if the speed is below a treshold).

To determine this, I need to calculate a bearing between my home zone and my work zone. Both have coordinates in my config. I will then compare the bearing with the wind direction.

Unless your work and/or home change regularly, I recommend simply hard-coding this bearing into your template sensors.

You’re going to have a hard time calculating this without using advanced math. You basically need to use 2d vector mathematics to compare 2 vectors. This pretty much will require python if you want the math to be short.

That’s one way of doing it. :smile:

But I was thinking of learning something. A more generic approach would allow me to use the method for a device tracker as well (bearing from device location to home).

The proximity component has some potential, too. If that would have bearing as an attribute I could use that.

The bearing calculation requires trig or vectors.

start = x1, y1
end = x2, y2

y = sin(y2-y1)*cos(x2)
x = cos(x1)*sin(x2) - sin(x1)*cos(x2)*cos(y2-y1)
bearing = atan2(y, x)*180/pi

Good luck implementing it, I don’t think templates can handle trig.

You might be able to do it in a python script that you call occassionally. https://docs.python.org/3/library/math.html#trigonometric-functions

If they allow importing of the math library. Last I checked, you can’t import in the python_script component.

If that’s the case, then to appdaemon with you @metbril!

If you haven’t used it before, I think you’ll get a lot of learning out of this exercise. :laughing:

1 Like

I agree AppDaemon would be the way forward for more complex automations like trig. On the other hand, extending an existing component or developing a custom one is a challenge as well.

An additional attribute ‘bearing’ to a device tracker or the proximity component sound the most generic.

The math itself isn’t overly complex, so I’ll give all options a good thought.

More suggestions are welcome, of course.

Bearing only works with 2 points though, so adding it to a device tracker would do nothing because you only have half the information. It would need to be a component where you specify the start entity and end entity. Honestly, I don’t think the component would be that hard to make if you know python because it would just use existing home assistant items. It’s not like it’s communicating with an api.

Here’s a little help if you get around to adding the home assistant stuff.

import math
def get_location(attributes): 
    if 'latitude' in attributes.keys() and 'longitude' in attributes.keys():
        return [ attributes['latitude'], attributes['longitude'] ]
    else
        return None

def calc_bearing(start_entity_attributes, end_entity_attributes):
    s = get_location(start_entity_attributes)
    e = get_location(end_entity_attributes)
    
    if s and e:
        sx, sy = s
        ex, ey = e
      
        y = math.sin(ey-sy)*math.cos(ex)
        x = math.cos(sx)*math.sin(ex) - math.sin(sx)*math.cos(ex)*math.cos(ey-sy)
        return math.atan2(y, x)*180/math.pi
    else:
        return None
2 Likes

I would add the bearing from the current gps coordinates of the device tracker to the home location.

This would be an attribute to the tracker or a new component. I already have some design specs in mind. Will need to write these down.

My approach will be to add a ‘bearing’ attribute to the proximity platform.
This is the most generic and future proof solution.
I will keep you updated.

1 Like

Bumping this…

I’d like to have a bearing attribute to the proximity integration. Who cares / dares to create a PR?

Create a feature request…

1 Like