diff --git a/aprsd/cmds/webchat.py b/aprsd/cmds/webchat.py
index e090787..1900b95 100644
--- a/aprsd/cmds/webchat.py
+++ b/aprsd/cmds/webchat.py
@@ -1,7 +1,6 @@
import datetime
import json
import logging
-import math
import signal
import sys
import threading
@@ -14,13 +13,14 @@ from flask_httpauth import HTTPBasicAuth
from flask_socketio import Namespace, SocketIO
from geopy.distance import geodesic
from oslo_config import cfg
+import timeago
from werkzeug.security import check_password_hash, generate_password_hash
import wrapt
import aprsd
-from aprsd import (
- cli_helper, client, packets, plugin_utils, stats, threads, utils,
-)
+from aprsd import cli_helper, client, packets, plugin_utils, stats, threads
+from aprsd import utils
+from aprsd import utils as aprsd_utils
from aprsd.client import client_factory, kiss
from aprsd.main import cli
from aprsd.threads import aprsd as aprsd_threads
@@ -131,47 +131,6 @@ def verify_password(username, password):
return username
-def calculate_initial_compass_bearing(point_a, point_b):
- """
- Calculates the bearing between two points.
- The formulae used is the following:
- θ = atan2(sin(Δlong).cos(lat2),
- cos(lat1).sin(lat2) − sin(lat1).cos(lat2).cos(Δlong))
- :Parameters:
- - `pointA: The tuple representing the latitude/longitude for the
- first point. Latitude and longitude must be in decimal degrees
- - `pointB: The tuple representing the latitude/longitude for the
- second point. Latitude and longitude must be in decimal degrees
- :Returns:
- The bearing in degrees
- :Returns Type:
- float
- """
- if (type(point_a) is not tuple) or (type(point_b) is not tuple):
- raise TypeError("Only tuples are supported as arguments")
-
- lat1 = math.radians(point_a[0])
- lat2 = math.radians(point_b[0])
-
- diff_long = math.radians(point_b[1] - point_a[1])
-
- x = math.sin(diff_long) * math.cos(lat2)
- y = math.cos(lat1) * math.sin(lat2) - (
- math.sin(lat1)
- * math.cos(lat2) * math.cos(diff_long)
- )
-
- initial_bearing = math.atan2(x, y)
-
- # Now we have the initial bearing but math.atan2 return values
- # from -180° to + 180° which is not what we want for a compass bearing
- # The solution is to normalize the initial bearing as shown below
- initial_bearing = math.degrees(initial_bearing)
- compass_bearing = (initial_bearing + 360) % 360
-
- return compass_bearing
-
-
def _build_location_from_repeat(message):
# This is a location message Format is
# ^ld^callsign:latitude,longitude,altitude,course,speed,timestamp
@@ -188,16 +147,19 @@ def _build_location_from_repeat(message):
course = float(b[3])
speed = float(b[4])
time = int(b[5])
+ compass_bearing = aprsd_utils.degrees_to_cardinal(course)
data = {
"callsign": callsign,
"lat": lat,
"lon": lon,
"altitude": alt,
"course": course,
+ "compass_bearing": compass_bearing,
"speed": speed,
"lasttime": time,
+ "timeago": timeago.format(time),
}
- LOG.warning(f"Location data from REPEAT {data}")
+ LOG.debug(f"Location data from REPEAT {data}")
return data
@@ -208,25 +170,32 @@ def _calculate_location_data(location_data):
alt = location_data["altitude"]
speed = location_data["speed"]
lasttime = location_data["lasttime"]
+ timeago_str = location_data.get(
+ "timeago",
+ timeago.format(lasttime),
+ )
# now calculate distance from our own location
distance = 0
if CONF.webchat.latitude and CONF.webchat.longitude:
our_lat = float(CONF.webchat.latitude)
our_lon = float(CONF.webchat.longitude)
distance = geodesic((our_lat, our_lon), (lat, lon)).kilometers
- bearing = calculate_initial_compass_bearing(
+ bearing = aprsd_utils.calculate_initial_compass_bearing(
(our_lat, our_lon),
(lat, lon),
)
+ compass_bearing = aprsd_utils.degrees_to_cardinal(bearing)
return {
"callsign": location_data["callsign"],
"lat": lat,
"lon": lon,
"altitude": alt,
"course": f"{bearing:0.1f}",
+ "compass_bearing": compass_bearing,
"speed": speed,
"lasttime": lasttime,
- "distance": f"{distance:0.3f}",
+ "timeago": timeago_str,
+ "distance": f"{distance:0.1f}",
}
diff --git a/aprsd/utils/__init__.py b/aprsd/utils/__init__.py
index e3ca433..6998d82 100644
--- a/aprsd/utils/__init__.py
+++ b/aprsd/utils/__init__.py
@@ -174,14 +174,29 @@ def load_entry_points(group):
print(traceback.format_exc(), file=sys.stderr)
-def calculate_initial_compass_bearing(start, end):
- if (type(start) != tuple) or (type(end) != tuple): # noqa: E721
+def calculate_initial_compass_bearing(point_a, point_b):
+ """
+ Calculates the bearing between two points.
+ The formulae used is the following:
+ θ = atan2(sin(Δlong).cos(lat2),
+ cos(lat1).sin(lat2) − sin(lat1).cos(lat2).cos(Δlong))
+ :Parameters:
+ - `pointA: The tuple representing the latitude/longitude for the
+ first point. Latitude and longitude must be in decimal degrees
+ - `pointB: The tuple representing the latitude/longitude for the
+ second point. Latitude and longitude must be in decimal degrees
+ :Returns:
+ The bearing in degrees
+ :Returns Type:
+ float
+ """
+ if (type(point_a) != tuple) or (type(point_b) != tuple): # noqa: E721
raise TypeError("Only tuples are supported as arguments")
- lat1 = math.radians(float(start[0]))
- lat2 = math.radians(float(end[0]))
+ lat1 = math.radians(float(point_a[0]))
+ lat2 = math.radians(float(point_b[0]))
- diff_long = math.radians(float(end[1]) - float(start[1]))
+ diff_long = math.radians(float(point_b[1]) - float(point_a[1]))
x = math.sin(diff_long) * math.cos(lat2)
y = math.cos(lat1) * math.sin(lat2) - (
diff --git a/aprsd/web/chat/static/js/send-message.js b/aprsd/web/chat/static/js/send-message.js
index dfd7d88..f93d1a8 100644
--- a/aprsd/web/chat/static/js/send-message.js
+++ b/aprsd/web/chat/static/js/send-message.js
@@ -17,25 +17,24 @@ function reload_popovers() {
}
function build_location_string(msg) {
- dt = new Date(parseInt(msg['lasttime']) * 1000);
- loc = "Last Location Update: " + dt.toLocaleString();
- loc += "
Latitude: " + msg['lat'] + "
Longitude: " + msg['lon'];
- loc += "
" + "Altitude: " + msg['altitude'] + " m";
- loc += "
" + "Speed: " + msg['speed'] + " kph";
- loc += "
" + "Bearing: " + msg['course'] + "°";
- loc += "
" + "distance: " + msg['distance'] + " km";
- return loc;
+ dt = new Date(parseInt(msg['lasttime']) * 1000);
+ loc = "Last Location Update: " + dt.toLocaleString();
+ loc += "
Latitude: " + msg['lat'] + "
Longitude: " + msg['lon'];
+ loc += "
" + "Altitude: " + msg['altitude'] + " m";
+ loc += "
" + "Speed: " + msg['speed'] + " kph";
+ loc += "
" + "Bearing: " + msg['compass_bearing'];
+ loc += "
" + "distance: " + msg['distance'] + " km";
+ return loc;
}
function build_location_string_small(msg) {
-
- dt = new Date(parseInt(msg['lasttime']) * 1000);
-
+ dt = new Date(parseInt(msg['lasttime']) * 1000);
loc = "" + msg['distance'] + "km";
//loc += "Lat " + msg['lat'] + " Lon " + msg['lon'];
- loc += "@" + msg['course'] + "°";
+ loc += " " + msg['compass_bearing'];
//loc += " Distance " + msg['distance'] + " km";
- loc += " " + dt.toLocaleString();
+ //loc += " " + dt.toLocaleString();
+ loc += " " + msg['timeago'];
return loc;
}
@@ -346,9 +345,9 @@ function create_callsign_tab_content(callsign, active=false) {
item_html += '