From 8ff29ac20e64eefc356624c54fe6cfdbe15086eb Mon Sep 17 00:00:00 2001 From: fernandodpr Date: Thu, 28 Nov 2024 00:35:47 +0100 Subject: [PATCH] feat: add node filtering and centralize config handling - Introduced node filtering using `allowed_device_ids` from the plugin configuration. - Dynamically load `allowed_device_ids` and `gpx_directory` from the configuration in `__init__()`. - Ensured the GPX directory is created during initialization. - Updated the README to document the new node filtering feature and configuration options. --- GPXTracker.py | 65 +++++++++++++++++++++++++++++++++++++-------------- readme.md | 10 +++++--- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/GPXTracker.py b/GPXTracker.py index 7e03647..7cd4095 100644 --- a/GPXTracker.py +++ b/GPXTracker.py @@ -6,6 +6,24 @@ class Plugin(BasePlugin): plugin_name = "gpxtracker" + + def __init__(self, config_file='config.yaml'): + super().__init__() + # Load configuration options + self.allowed_device_ids = self.config.get('allowed_device_ids', []) + self.gpx_directory = self.config.get('gpx_directory', './data/gpx_data') + + + # Warn if no allowed device IDs are set + if not self.allowed_device_ids: + self.logger.warning("[CONFIG_WARNING] Allowed device IDs list is empty. No locations will be logged.") + + # Ensure the GPX directory exists + try: + os.makedirs(self.gpx_directory, exist_ok=True) + except Exception as e: + self.logger.error(f"Failed to prepare GPX directory '{self.gpx_directory}': {e}") + async def handle_meshtastic_message(self, packet, formatted_message, longname, meshnet_name): """ Handles Meshtastic messages and updates the GPX file for the corresponding device. @@ -17,9 +35,16 @@ async def handle_meshtastic_message(self, packet, formatted_message, longname, m if not decoded or decoded.get("portnum") != "POSITION_APP" or not position or "precisionBits" not in position: return - # Extract relevant data - device_id_raw = packet.get("fromId", "") - device_id_hex = device_id_raw.lstrip("!") + # Extract device ID + device_id_raw = packet.get("fromId", "") + device_id_hex = device_id_raw.lstrip("!") + + # Check if the device is allowed or if wildcard is enabled + if "*" not in self.allowed_device_ids and device_id_hex not in self.allowed_device_ids: + self.logger.debug(f"Device ID {device_id_hex} sent a location but is not in the allowed list. Ignoring message.") + return + + # Extract position data latitude = position.get("latitude") longitude = position.get("longitude") altitude = position.get("altitude", 0) @@ -27,20 +52,22 @@ async def handle_meshtastic_message(self, packet, formatted_message, longname, m now = datetime.now(tz=timezone.utc) track_name = now.strftime("%Y-%m-%d") - # Log processed data - self.logger.info(f"Processed data: Latitude={latitude}, Longitude={longitude}, Altitude={altitude}, track_name={track_name}, Device={device_id_hex}") + # Create GPX file path + gpx_file_path = os.path.join(self.gpx_directory, f"{device_id_hex}.gpx") - # Create directory and GPX file - gpx_directory = "./data/gpx_data" - os.makedirs(gpx_directory, exist_ok=True) # Create directory if it doesn't exist - gpx_file_path = os.path.join(gpx_directory, f"{device_id_hex}.gpx") + # Log processed data + self.logger.info(f"Processed data from Device={device_id_hex}: Latitude={latitude}, Longitude={longitude}, Altitude={altitude}, track_name={track_name}, Path={gpx_file_path}") # Load or create GPX file - if os.path.exists(gpx_file_path): - with open(gpx_file_path, "r") as gpx_file: - gpx = gpxpy.parse(gpx_file) - else: - gpx = gpxpy.gpx.GPX() + try: + if os.path.exists(gpx_file_path): + with open(gpx_file_path, "r") as gpx_file: + gpx = gpxpy.parse(gpx_file) + else: + gpx = gpxpy.gpx.GPX() + except Exception as e: + self.logger.error(f"Error loading or creating GPX file {gpx_file_path}: {e}") + return # Create or find the track for the current day track = next((t for t in gpx.tracks if t.name == track_name), None) @@ -58,11 +85,13 @@ async def handle_meshtastic_message(self, packet, formatted_message, longname, m segment.points.append(point) # Save the GPX file - with open(gpx_file_path, "w") as gpx_file: - gpx_file.write(gpx.to_xml()) + try: + with open(gpx_file_path, "w") as gpx_file: + gpx_file.write(gpx.to_xml()) + self.logger.debug(f"Data saved in {gpx_file_path} for device {device_id_hex}") + except Exception as e: + self.logger.error(f"Error saving GPX file {gpx_file_path}: {e}") - # Confirm data saved - self.logger.info(f"Data saved in {gpx_file_path} for device {device_id_hex}") async def handle_room_message(self, room, event, full_message): """Placeholder for Matrix messages (if needed).""" diff --git a/readme.md b/readme.md index 4e2f31c..a11f107 100644 --- a/readme.md +++ b/readme.md @@ -8,7 +8,7 @@ The GPX Tracker plugin for Meshtastic allows you to log location data from your - Compatible with GPX visualization tools for further analysis and mapping. ## Usage -Simply add the plugin to your Meshtastic setup, and it will automatically handle incoming location data from the network. GPX files will be stored in a directory called `gpx_data`. +Simply add the plugin to your Meshtastic setup, and it will automatically handle incoming location data from the network. ```yaml community-plugins: @@ -16,13 +16,17 @@ community-plugins: active: true repository: https://github.com/fernandodpr/MMR-GPXTRacker.git tag: main + gpx_directory: "./data/gpx_data" + allowed_device_ids: + - "fd3e19c2" # Example (randome ID) + - "*" # To save all location messages that are received. ``` ## Ethical and Legal Considerations -Be aware that tracking and logging location data from Meshtastic devices without the explicit consent of all network users may be a violation of privacy laws or ethical guidelines in your jurisdiction. Always ensure that all parties are informed and have given their consent to the use of this plugin. +Be aware that tracking and logging location data from Meshtastic devices without the explicit consent of users may be a violation of privacy laws or ethical guidelines in your jurisdiction. Always ensure that all parties are informed and have given their consent to the use of this plugin. ## Upcoming Features -The next release will include filters for nodes, allowing users to specify which devices are tracked, providing greater control and flexibility. +We welcome your suggestions! Please share your ideas in the Issues section. ## License See the LICENSE file for more details.