range-testing/helper_functions.py

122 lines
3.3 KiB
Python
Raw Permalink Normal View History

import json
import math
import re
def calculate_distance(point1: dict, point2: dict) -> float:
"""
Calculate the distance in meters between two geographic points with altitude.
:param point1: A dictionary with 'latitude', 'longitude', and optional 'altitude'.
:param point2: A dictionary with 'latitude', 'longitude', and optional 'altitude'.
:return: Distance in meters as a float.
"""
try:
# Extract latitude, longitude, and altitude
lat1, lon1, alt1 = (
point1["latitude"],
point1["longitude"],
point1.get("altitude", 0),
)
lat2, lon2, alt2 = (
point2["latitude"],
point2["longitude"],
point2.get("altitude", 0),
)
except KeyError:
return "Points were not properly set"
# Convert latitude and longitude from degrees to radians
lat1, lon1, lat2, lon2 = map(math.radians, [lat1, lon1, lat2, lon2])
# Radius of the Earth in meters
R = 6369500
# Compute deltas
delta_lat = lat2 - lat1
delta_lon = lon2 - lon1
# Haversine formula for horizontal distance
a = (
math.sin(delta_lat / 2) ** 2
+ math.cos(lat1) * math.cos(lat2) * math.sin(delta_lon / 2) ** 2
)
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
horizontal_distance = R * c
# Altitude difference
delta_alt = alt2 - alt1
# Total 3D distance
distance = math.sqrt(horizontal_distance**2 + delta_alt**2)
return distance
# Split string by commas, if there are commas
def comma_split(string: str):
if "," in string:
return string.split(",")
else:
return string
# Extract stats from strings
def extract_numbers(string):
pattern = r"-?\d+\.\d+|-?\d+"
numbers = re.findall(pattern, string)
numbers = [float(num) if "." in num else int(num) for num in numbers]
return numbers
# Parse the latitude or longitude from the NMEA format
def parse_lat_lon(value: str, direction: str) -> float:
"""
Parses latitude or longitude from NMEA format.
Args:
value (str): The raw NMEA latitude or longitude value.
direction (str): Direction indicator ('N', 'S', 'E', 'W').
Returns:
float: The parsed latitude or longitude as a decimal degree.
"""
if not value or not direction:
return None
degrees = int(value[:2])
minutes = float(value[2:])
decimal = degrees + minutes / 60
if direction in ["S", "W"]:
decimal = -decimal
return decimal
# Convert RSSI to DBM
def rssi_to_dbm(rssi):
if rssi == 99:
return "Unknown"
else:
# Convert RSSI to dBm
return -113 + 2 * rssi
# Save data to JSON file
def save_data_to_json(data, filename):
try:
# Load existing data
try:
with open(filename, "r") as file:
existing_data = json.load(file)
except FileNotFoundError:
# If file doesn't exist, start with an empty list
existing_data = []
# Append new data
existing_data.append(data)
# Save updated data back to the file
with open(filename, "w") as file:
json.dump(existing_data, file, indent=4)
except Exception as e:
print(f"Error saving data to JSON: {e}")