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.
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.
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.
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.
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
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.