From b7567ac33ea5e42ae89b40a539362987295c7dda Mon Sep 17 00:00:00 2001 From: DJ2LS Date: Sat, 3 Feb 2024 11:02:41 +0100 Subject: [PATCH] version update --- modem/message_system_db_beacon.py | 124 ++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 modem/message_system_db_beacon.py diff --git a/modem/message_system_db_beacon.py b/modem/message_system_db_beacon.py new file mode 100644 index 00000000..df69458b --- /dev/null +++ b/modem/message_system_db_beacon.py @@ -0,0 +1,124 @@ +from message_system_db_manager import DatabaseManager +from sqlalchemy import create_engine +from sqlalchemy.orm import scoped_session, sessionmaker +from threading import local +from message_system_db_model import Base, Beacon, Station, Status, Attachment, P2PMessage +from datetime import timezone, timedelta, datetime +import json +import structlog +import helpers + + +class DatabaseManagerBeacon(DatabaseManager): + def __init__(self, uri): + super().__init__(uri) + + def add_beacon(self, timestamp, callsign, snr, gridsquare): + session = None + try: + session = self.get_thread_scoped_session() + # Ensure the station exists or create it, and get the station object + station = self.get_or_create_station(callsign, session) + # Initialize location as an empty dict if None + if not station.location: + station.location = {} + + # Now, check and update the station's location with gridsquare if it has changed + if station.location.get('gridsquare') != gridsquare: + self.log(f"Updating location for {callsign}") + station.location['gridsquare'] = gridsquare # Update directly without re-serialization + session.flush() + + # Now, add the beacon + new_beacon = Beacon(timestamp=timestamp, snr=snr, callsign=callsign) + session.add(new_beacon) + session.commit() + self.log(f"Added beacon for {callsign}") + + except Exception as e: + self.log(f"An error occurred while adding beacon for {callsign}: {e}", isWarning=True) + if session: + session.rollback() + finally: + if session and not session.is_active: + session.remove() + + def get_beacons_by_callsign(self, callsign): + session = self.get_thread_scoped_session() + try: + # Query the station by callsign + station = session.query(Station).filter_by(callsign=callsign).first() + if station: + # Access the beacons directly thanks to the back_populated relationship + beacons = station.beacons + # Convert beacon objects to a dictionary if needed, or directly return the list + beacons_data = [{ + 'id': beacon.id, + 'timestamp': beacon.timestamp.isoformat(), + 'snr': beacon.snr, + 'gridsquare': station.location.get('gridsquare') if station.location else None + } for beacon in beacons] + return beacons_data + else: + self.log(f"No station found with callsign {callsign}") + return [] + except Exception as e: + self.log(f"An error occurred while fetching beacons for callsign {callsign}: {e}", isWarning=True) + return [] + finally: + session.remove() + + def get_all_beacons(self): + session = None + try: + session = self.get_thread_scoped_session() + # Query all beacons + beacons_query = session.query(Beacon).all() + + # Optionally format the result for easier consumption + beacons_list = [] + for beacon in beacons_query: + # Fetch the associated station for each beacon to get the 'gridsquare' information + station = session.query(Station).filter_by(callsign=beacon.callsign).first() + gridsquare = station.location.get('gridsquare') if station and station.location else None + + beacons_list.append({ + 'id': beacon.id, + 'timestamp': beacon.timestamp.isoformat(), + 'snr': beacon.snr, + 'callsign': beacon.callsign, + 'gridsquare': gridsquare + }) + + return beacons_list + + except Exception as e: + self.log(f"An error occurred while fetching all beacons: {e}", isWarning=True) + return [] # Return an empty list or handle the error as appropriate + finally: + if session and not session.is_active: + session.remove() + + def beacon_cleanup_older_than_days(self, days): + session = None + try: + session = self.get_thread_scoped_session() + # Calculate the threshold timestamp + older_than_timestamp = datetime.now(timezone.utc) - timedelta(days=days) + + # Query and delete beacons older than the calculated timestamp + delete_query = session.query(Beacon).filter(Beacon.timestamp < older_than_timestamp) + deleted_count = delete_query.delete(synchronize_session='fetch') + session.commit() + + self.log(f"Deleted {deleted_count} beacons older than {days} days") + return deleted_count + + except Exception as e: + self.log(f"An error occurred during beacon cleanup: {e}", isWarning=True) + if session: + session.rollback() + return 0 # Return 0 or handle the error as appropriate + finally: + if session and not session.is_active: + session.remove() \ No newline at end of file