From 55567815eff296046f7e830892643a01932ec842 Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Thu, 23 Oct 2025 11:57:55 -0700 Subject: [PATCH] map to csv --- mesh_bot.py | 1 + modules/README.md | 34 +++++++++++++++++++ modules/locationdata.py | 73 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/mesh_bot.py b/mesh_bot.py index a2d51c5..2de3236 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -68,6 +68,7 @@ def auto_response(message, snr, rssi, hop, pkiStatus, message_from_id, channel_n "leaderboard": lambda: get_mesh_leaderboard(message, message_from_id, deviceID), "lemonstand": lambda: handleLemonade(message, message_from_id, deviceID), "lheard": lambda: handle_lheard(message, message_from_id, deviceID, isDM), + "map": lambda: mapHandler(message_from_id, deviceID, channel_number), "mastermind": lambda: handleMmind(message, message_from_id, deviceID), "messages": lambda: handle_messages(message, deviceID, channel_number, msg_history, publicChannel, isDM), "moon": lambda: handle_moon(message_from_id, deviceID, channel_number), diff --git a/modules/README.md b/modules/README.md index abf11bf..58da162 100644 --- a/modules/README.md +++ b/modules/README.md @@ -160,6 +160,40 @@ Enable in `[checklist]` section of `config.ini`. Configure in `[location]` section of `config.ini`. +Certainly! Here’s a README help section for your `mapHandler` command, suitable for users of your meshbot: + +--- + +## 📍 Map Command + +The `map` command allows you to log your current GPS location with a custom description. This is useful for mapping mesh nodes, events, or points of interest. + +### Usage + +- **Show Help** + ``` + map help + ``` + Displays usage instructions for the map command. + +- **Log a Location** + ``` + map + ``` + Example: + ``` + map Found a new mesh node near the park + ``` + This will log your current location with the description "Found a new mesh node near the park". + +### How It Works + +- The bot records your user ID, latitude, longitude, and your description in a CSV file (`data/map_data.csv`). +- If your location data is missing or invalid, you’ll receive an error message. +- You can view or process the CSV file later for mapping or analysis. + +**Tip:** Use `map help` at any time to see these instructions in the bot. + --- ## EAS & Emergency Alerts diff --git a/modules/locationdata.py b/modules/locationdata.py index 3fad995..9c9631b 100644 --- a/modules/locationdata.py +++ b/modules/locationdata.py @@ -10,9 +10,10 @@ import xml.dom.minidom from datetime import datetime from modules.log import * import math +import csv -trap_list_location = ("whereami", "wx", "wxa", "wxalert", "rlist", "ea", "ealert", "riverflow", "valert", "earthquake", "howfar") +trap_list_location = ("whereami", "wx", "wxa", "wxalert", "rlist", "ea", "ealert", "riverflow", "valert", "earthquake", "howfar", "map",) def where_am_i(lat=0, lon=0, short=False, zip=False): whereIam = "" @@ -1054,3 +1055,73 @@ def get_openskynetwork(lat=0, lon=0): aircraft_report = aircraft_report[:-1] aircraft_report = abbreviate_noaa(aircraft_report) return aircraft_report if aircraft_report else NO_ALERTS + +def log_locationData_toMap(userID, location, message): + """ + Logs location data to a CSV file for meshing purposes. + Returns True if successful, False otherwise. + """ + lat, lon = location + if lat is None or lon is None or lat == 0.0 or lon == 0.0: + logger.warning(f"Invalid GPS data for user {userID}: {location}") + return False + + # Set default directory to ../data/ + default_dir = os.path.join(os.path.dirname(__file__), "..", "data") + os.makedirs(default_dir, exist_ok=True) + map_filepath = os.path.join(default_dir, "map_data.csv") + + # Check if the file exists to determine if we need to write headers + write_header = not os.path.isfile(map_filepath) or os.path.getsize(map_filepath) == 0 + + try: + with open(map_filepath, mode='a', newline='') as csvfile: + fieldnames = ['userID', 'Latitude', 'Longitude', 'Description'] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + + # Write headers only if the file did not exist before or is empty + if write_header: + writer.writeheader() + + writer.writerow({ + 'userID': userID, + 'Latitude': lat, + 'Longitude': lon, + 'Description': message if message else "" + }) + + logger.debug(f"Logged location for {userID} to {map_filepath}") + return True + except Exception as e: + logger.error(f"Failed to log location for {userID}: {e}") + return False + +def mapHandler(command, userID, location): + """ + Handles 'map' commands from meshbot. + Usage: + map - Log current location with description + """ + command = str(command) # Ensure command is always a string + + if command.strip().lower() == "?": + return ( + "Usage:\n" + " 🗺️map - Log your current location with a description\n" + "Example:\n" + " 🗺️map Found a new mesh node near the park" + ) + + description = command.strip() + if not description: + return "Please provide a description. Type 'map help' for usage." + + # location should be a tuple: (lat, lon) + if not location or len(location) != 2: + return "🚫Location data is missing or invalid." + + success = log_locationData_toMap(userID, location, description) + if success: + return f"📍Location logged " + else: + return "🚫Failed to log location. Please try again."