Skip to content

Commit

Permalink
feat: add node filtering and centralize config handling
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
fernandodpr committed Nov 27, 2024
1 parent 84a170c commit 8ff29ac
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 21 deletions.
65 changes: 47 additions & 18 deletions GPXTracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -17,30 +35,39 @@ 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)

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)
Expand All @@ -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)."""
Expand Down
10 changes: 7 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,25 @@ 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:
gpxtracker:
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.

0 comments on commit 8ff29ac

Please sign in to comment.