mirror of
https://github.com/SpudGunMan/meshing-around.git
synced 2026-06-30 23:11:20 +02:00
Merge branch 'main' of https://github.com/SpudGunMan/meshing-around
This commit is contained in:
@@ -138,6 +138,7 @@ git clone https://github.com/spudgunman/meshing-around
|
||||
| `readnews` | returns the contents of a file (news.txt, by default) via the chunker on air | ✅ |
|
||||
| `satpass` | returns the pass info from API for defined NORAD ID in config or Example: `satpass 25544,33591`| |
|
||||
| `wiki:` | Searches Wikipedia and returns the first few sentences of the first result if a match. Example: `wiki: lora radio` |
|
||||
| `howfar` | returns the distance you have traveled since your last HowFar. `howfar reset` to start over | ✅ |
|
||||
|
||||
### CheckList
|
||||
| Command | Description | |
|
||||
|
||||
+26
@@ -61,6 +61,7 @@ def auto_response(message, snr, rssi, hop, pkiStatus, message_from_id, channel_n
|
||||
"hangman": lambda: handleHangman(message, message_from_id, deviceID),
|
||||
"hfcond": hf_band_conditions,
|
||||
"history": lambda: handle_history(message, message_from_id, deviceID, isDM),
|
||||
"howfar": lambda: handle_howfar(message, message_from_id, deviceID, isDM),
|
||||
"joke": lambda: tell_joke(message_from_id),
|
||||
"lemonstand": lambda: handleLemonade(message, message_from_id, deviceID),
|
||||
"lheard": lambda: handle_lheard(message, message_from_id, deviceID, isDM),
|
||||
@@ -311,6 +312,31 @@ def handle_wxalert(message_from_id, deviceID, message):
|
||||
weatherAlert = weatherAlert[0]
|
||||
return weatherAlert
|
||||
|
||||
def handle_howfar(message, message_from_id, deviceID, isDM):
|
||||
msg = ''
|
||||
location = get_node_location(message_from_id, deviceID)
|
||||
lat = location[0]
|
||||
lon = location[1]
|
||||
# if ? in message
|
||||
if "?" in message.lower():
|
||||
return "command returns the distance you have traveled since your last HowFar-command. Add 'reset' to reset your starting point."
|
||||
|
||||
# if no GPS location return
|
||||
if lat == latitudeValue and lon == longitudeValue:
|
||||
logger.debug(f"System: HowFar: No GPS location for {message_from_id}")
|
||||
return "No GPS location available"
|
||||
|
||||
if "reset" in message.lower():
|
||||
msg = distance(lat,lon,message_from_id, reset=True)
|
||||
else:
|
||||
msg = distance(lat,lon,message_from_id)
|
||||
|
||||
# if not a DM add the username to the beginning of msg
|
||||
if not useDMForResponse and not isDM:
|
||||
msg = "@" + get_name_from_number(message_from_id, 'short', deviceID) + " " + msg
|
||||
|
||||
return msg
|
||||
|
||||
def handle_wiki(message, isDM):
|
||||
# location = get_node_location(message_from_id, deviceID)
|
||||
msg = "Wikipedia search function. \nUsage example:📲wiki: travelling gnome"
|
||||
|
||||
+121
-1
@@ -8,8 +8,10 @@ import requests # pip install requests
|
||||
import bs4 as bs # pip install beautifulsoup4
|
||||
import xml.dom.minidom
|
||||
from modules.log import *
|
||||
import math
|
||||
|
||||
trap_list_location = ("whereami", "wx", "wxa", "wxalert", "rlist", "ea", "ealert", "riverflow", "valert", "earthquake")
|
||||
|
||||
trap_list_location = ("whereami", "wx", "wxa", "wxalert", "rlist", "ea", "ealert", "riverflow", "valert", "earthquake", "howfar")
|
||||
|
||||
def where_am_i(lat=0, lon=0, short=False, zip=False):
|
||||
whereIam = ""
|
||||
@@ -811,3 +813,121 @@ def checkUSGSEarthQuake(lat=0, lon=0):
|
||||
return NO_ALERTS
|
||||
else:
|
||||
return f"{quake_count} quakes in last {history} days within {radius}km of you largest was {largest_mag}. {description_text}"
|
||||
|
||||
howfarDB = {}
|
||||
def distance(lat=0,lon=0,nodeID=0, reset=False):
|
||||
# part of the howfar function, calculates the distance between two lat/lon points
|
||||
msg = ""
|
||||
if lat == 0 and lon == 0:
|
||||
return NO_DATA_NOGPS
|
||||
if nodeID == 0:
|
||||
return "No NodeID provided"
|
||||
|
||||
if reset:
|
||||
if nodeID in howfarDB:
|
||||
del howfarDB[nodeID]
|
||||
|
||||
if nodeID not in howfarDB:
|
||||
#register first point NodeID, lat, lon, time, point
|
||||
howfarDB[nodeID] = [{'lat': lat, 'lon': lon, 'time': datetime.now()}]
|
||||
if reset:
|
||||
return "Tracking reset, new starting point registered🗺️"
|
||||
else:
|
||||
return "Starting point registered🗺️"
|
||||
else:
|
||||
#de-dupe points if same as last point
|
||||
if howfarDB[nodeID][-1]['lat'] == lat and howfarDB[nodeID][-1]['lon'] == lon:
|
||||
return "📍No movement detected yet"
|
||||
# calculate distance from last point in howfarDB
|
||||
last_point = howfarDB[nodeID][-1]
|
||||
lat1 = math.radians(last_point['lat'])
|
||||
lon1 = math.radians(last_point['lon'])
|
||||
lat2 = math.radians(lat)
|
||||
lon2 = math.radians(lon)
|
||||
dlon = lon2 - lon1
|
||||
dlat = lat2 - lat1
|
||||
a = math.sin(dlat / 2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2)**2
|
||||
c = 2 * math.asin(math.sqrt(a))
|
||||
r = 6371 # Radius of earth in kilometers
|
||||
distance_km = c * r
|
||||
if use_metric:
|
||||
msg += f"{distance_km:.2f} km"
|
||||
else:
|
||||
distance_miles = distance_km * 0.621371
|
||||
msg += f"{distance_miles:.2f} miles"
|
||||
|
||||
# calculate the speed if time difference is more than 1 minute
|
||||
time_diff = datetime.now() - last_point['time']
|
||||
if time_diff.total_seconds() > 60:
|
||||
hours = time_diff.total_seconds() / 3600
|
||||
if use_metric:
|
||||
speed = distance_km / hours
|
||||
speed_str = f"{speed:.2f} km/h"
|
||||
else:
|
||||
speed_mph = (distance_km * 0.621371) / hours
|
||||
speed_str = f"{speed_mph:.2f} mph"
|
||||
msg += f", travel time: {int(time_diff.total_seconds()//60)} min, Speed: {speed_str}"
|
||||
|
||||
#calculate bearing
|
||||
x = math.sin(dlon) * math.cos(lat2)
|
||||
y = math.cos(lat1) * math.sin(lat2) - (math.sin(lat1) * math.cos(lat2) * math.cos(dlon))
|
||||
initial_bearing = math.atan2(x, y)
|
||||
initial_bearing = math.degrees(initial_bearing)
|
||||
compass_bearing = (initial_bearing + 360) % 360
|
||||
msg += f", Bearing from last point: {compass_bearing:.2f}°"
|
||||
|
||||
# if points 3+ are within 30 meters of the first point add the area of the polygon
|
||||
if len(howfarDB[nodeID]) >= 3:
|
||||
points = []
|
||||
# loop the howfarDB to get all the points except the current nodeID
|
||||
for key in howfarDB:
|
||||
if key != nodeID:
|
||||
points.append((howfarDB[key][-1]['lat'], howfarDB[key][-1]['lon']))
|
||||
# loop the howfarDB[nodeID] to get the points
|
||||
for point in howfarDB[nodeID]:
|
||||
points.append((point['lat'], point['lon']))
|
||||
# close the polygon by adding the first point to the end
|
||||
points.append((howfarDB[nodeID][0]['lat'], howfarDB[nodeID][0]['lon']))
|
||||
# calculate the area of the polygon
|
||||
area = 0.0
|
||||
for i in range(len(points)-1):
|
||||
lat1 = math.radians(points[i][0])
|
||||
lon1 = math.radians(points[i][1])
|
||||
lat2 = math.radians(points[i+1][0])
|
||||
lon2 = math.radians(points[i+1][1])
|
||||
area += (lon2 - lon1) * (2 + math.sin(lat1) + math.sin(lat2))
|
||||
area = area * (6378137 ** 2) / 2.0
|
||||
area = abs(area) / 1e6 # convert to square kilometers
|
||||
|
||||
if use_metric:
|
||||
msg += f", Area Sq.Km: {area:.2f} sq.km (approx)"
|
||||
else:
|
||||
area_miles = area * 0.386102
|
||||
msg += f", Area Sq.Miles: {area_miles:.2f} sq.mi (approx)"
|
||||
|
||||
#calculate the centroid of the polygon
|
||||
x = 0.0
|
||||
y = 0.0
|
||||
z = 0.0
|
||||
for point in points[:-1]:
|
||||
lat_rad = math.radians(point[0])
|
||||
lon_rad = math.radians(point[1])
|
||||
x += math.cos(lat_rad) * math.cos(lon_rad)
|
||||
y += math.cos(lat_rad) * math.sin(lon_rad)
|
||||
z += math.sin(lat_rad)
|
||||
total_points = len(points) - 1
|
||||
x /= total_points
|
||||
y /= total_points
|
||||
z /= total_points
|
||||
lon_centroid = math.atan2(y, x)
|
||||
hyp = math.sqrt(x * x + y * y)
|
||||
lat_centroid = math.atan2(z, hyp)
|
||||
lat_centroid = math.degrees(lat_centroid)
|
||||
lon_centroid = math.degrees(lon_centroid)
|
||||
msg += f", Centroid: {lat_centroid:.5f}, {lon_centroid:.5f}"
|
||||
|
||||
|
||||
# update the last point in howfarDB
|
||||
howfarDB[nodeID].append({'lat': lat, 'lon': lon, 'time': datetime.now()})
|
||||
|
||||
return msg
|
||||
+13
-13
@@ -128,21 +128,21 @@ def get_moon(lat=0, lon=0):
|
||||
illum = moon.phase # 0 = new, 50 = first/last quarter, 100 = full
|
||||
|
||||
if illum < 1.0:
|
||||
moon_phase = 'New Moon🌑'
|
||||
moon_phase = 'New Moon 🌑'
|
||||
elif illum < 49:
|
||||
moon_phase = 'Waxing Crescent🌒'
|
||||
moon_phase = 'Waxing Crescent 🌒'
|
||||
elif 49 <= illum < 51:
|
||||
moon_phase = 'First Quarter🌓'
|
||||
moon_phase = 'First Quarter 🌓'
|
||||
elif illum < 99:
|
||||
moon_phase = 'Waxing Gibbous🌔'
|
||||
moon_phase = 'Waxing Gibbous 🌔'
|
||||
elif illum >= 99:
|
||||
moon_phase = 'Full Moon🌕'
|
||||
moon_phase = 'Full Moon 🌕'
|
||||
elif illum > 51:
|
||||
moon_phase = 'Waning Gibbous🌖'
|
||||
moon_phase = 'Waning Gibbous 🌖'
|
||||
elif 51 >= illum > 49:
|
||||
moon_phase = 'Last Quarter🌗'
|
||||
moon_phase = 'Last Quarter 🌗'
|
||||
else:
|
||||
moon_phase = 'Waning Crescent🌘'
|
||||
moon_phase = 'Waning Crescent 🌘'
|
||||
|
||||
moon_table['phase'] = moon_phase
|
||||
moon_table['illumination'] = moon.phase
|
||||
@@ -167,9 +167,9 @@ def get_moon(lat=0, lon=0):
|
||||
moon_table['next_full_moon'] = local_next_full_moon.strftime('%a %b %d %I:%M%p')
|
||||
moon_table['next_new_moon'] = local_next_new_moon.strftime('%a %b %d %I:%M%p')
|
||||
|
||||
moon_data = "MoonRise:" + moon_table['rise_time'] + "\nSet:" + moon_table['set_time'] + \
|
||||
"\nPhase:" + moon_table['phase'] + " @:" + str('{0:.2f}'.format(moon_table['illumination'])) + "%" \
|
||||
+ "\nFullMoon:" + moon_table['next_full_moon'] + "\nNewMoon:" + moon_table['next_new_moon']
|
||||
moon_data = "MoonRise: " + moon_table['rise_time'] + "\nSet: " + moon_table['set_time'] + \
|
||||
"\nPhase: " + moon_table['phase'] + " @: " + str('{0:.2f}'.format(moon_table['illumination'])) + "%" \
|
||||
+ "\nFullMoon: " + moon_table['next_full_moon'] + "\nNewMoon: " + moon_table['next_new_moon']
|
||||
|
||||
# if moon is in the sky, add azimuth and altitude
|
||||
if moon_table['altitude'] > 0:
|
||||
@@ -206,7 +206,7 @@ def getNextSatellitePass(satellite, lat=0, lon=0):
|
||||
pass_startAzCompass = pass_json['passes'][0]['startAzCompass']
|
||||
pass_set_time = datetime.fromtimestamp(pass_time + pass_duration).strftime('%a %d %I:%M%p')
|
||||
pass__endAzCompass = pass_json['passes'][0]['endAzCompass']
|
||||
pass_data = f"{satname} @{pass_rise_time} Az:{pass_startAzCompass} for{getPrettyTime(pass_duration)}, MaxEl:{pass_maxEl}° Set@{pass_set_time} Az:{pass__endAzCompass}"
|
||||
pass_data = f"{satname} @{pass_rise_time} Az: {pass_startAzCompass} for{getPrettyTime(pass_duration)}, MaxEl: {pass_maxEl}° Set @{pass_set_time} Az: {pass__endAzCompass}"
|
||||
elif pass_json['info']['passescount'] == 0:
|
||||
satname = pass_json['info']['satname']
|
||||
pass_data = f"{satname} has no upcoming passes"
|
||||
@@ -215,5 +215,5 @@ def getNextSatellitePass(satellite, lat=0, lon=0):
|
||||
pass_data = ERROR_FETCHING_DATA
|
||||
except Exception as e:
|
||||
logger.warning(f"System: User supplied value {satellite} unknown or invalid")
|
||||
pass_data = "Provide NORAD# example use:🛰️satpass 25544,33591"
|
||||
pass_data = "Provide NORAD# example use: 🛰️ satpass 25544,33591"
|
||||
return pass_data
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ if enableCmdHistory:
|
||||
if location_enabled:
|
||||
from modules.locationdata import * # from the spudgunman/meshing-around repo
|
||||
trap_list = trap_list + trap_list_location
|
||||
help_message = help_message + ", whereami, wx, rlist"
|
||||
help_message = help_message + ", whereami, wx, rlist, howfar"
|
||||
if enableGBalerts and not enableDEalerts:
|
||||
from modules.globalalert import * # from the spudgunman/meshing-around repo
|
||||
logger.warning(f"System: GB Alerts not functional at this time need to find a source API")
|
||||
|
||||
Reference in New Issue
Block a user