diff --git a/modem/command_ping.py b/modem/command_ping.py index 01edd438..58ab6337 100644 --- a/modem/command_ping.py +++ b/modem/command_ping.py @@ -1,5 +1,7 @@ from command import TxCommand import api_validations +from message_system_db_manager import DatabaseManager + class PingCommand(TxCommand): @@ -8,6 +10,9 @@ class PingCommand(TxCommand): if not api_validations.validate_freedata_callsign(self.dxcall): self.dxcall = f"{self.dxcall}-0" + # update callsign database... + DatabaseManager(self.event_manager).get_or_create_station(self.dxcall) + return super().set_params_from_api(apiParams) def build_frame(self): diff --git a/modem/frame_handler.py b/modem/frame_handler.py index d11ba742..66ef2811 100644 --- a/modem/frame_handler.py +++ b/modem/frame_handler.py @@ -5,6 +5,7 @@ from queue import Queue import structlog import time, uuid from codec2 import FREEDV_MODE +from message_system_db_manager import DatabaseManager TESTMODE = False @@ -105,6 +106,7 @@ class FrameHandler(): ) def make_event(self): + event = { "type": "frame-handler", "received": self.details['frame']['frame_type'], @@ -115,6 +117,10 @@ class FrameHandler(): } if 'origin' in self.details['frame']: event['dxcallsign'] = self.details['frame']['origin'] + + if 'origin_crc' in self.details['frame']: + event['dxcallsign'] = DatabaseManager(self.event_manager).get_callsign_by_checksum(self.details['frame']['origin_crc']) + return event def emit_event(self): diff --git a/modem/message_system_db_manager.py b/modem/message_system_db_manager.py index 7061ccf9..fad51cce 100644 --- a/modem/message_system_db_manager.py +++ b/modem/message_system_db_manager.py @@ -8,6 +8,7 @@ from message_system_db_model import Base, Station, Status, Attachment, P2PMessag from datetime import datetime import json import structlog +import helpers class DatabaseManager: def __init__(self, event_manger, uri='sqlite:///freedata-messages.db'): @@ -57,13 +58,49 @@ class DatabaseManager: self.thread_local.session = scoped_session(self.session_factory) return self.thread_local.session - def get_or_create_station(self, session, callsign): - station = session.query(Station).filter_by(callsign=callsign).first() - if not station: - station = Station(callsign=callsign) - session.add(station) - session.flush() # To get the callsign immediately - return station + def get_or_create_station(self, callsign, session=None): + own_session = False + if not session: + session = self.get_thread_scoped_session() + own_session = True + + try: + station = session.query(Station).filter_by(callsign=callsign).first() + if not station: + self.log(f"Updating station list with {callsign}") + station = Station(callsign=callsign, checksum=helpers.get_crc_24(callsign).hex()) + session.add(station) + session.flush() + + if own_session: + session.commit() # Only commit if we created the session + + return station + + except Exception as e: + + if own_session: + session.rollback() + + finally: + if own_session: + session.remove() + + def get_callsign_by_checksum(self, checksum): + session = self.get_thread_scoped_session() + try: + station = session.query(Station).filter_by(checksum=checksum).first() + if station: + self.log(f"Found callsign [{station.callsign}] for checksum [{station.checksum}]") + return station.callsign + else: + self.log(f"No callsign found for [{checksum}]") + return None + except Exception as e: + self.log(f"Error fetching callsign for checksum {checksum}: {e}", isWarning=True) + return {'status': 'failure', 'message': str(e)} + finally: + session.remove() def get_or_create_status(self, session, status_name): status = session.query(Status).filter_by(name=status_name).first() @@ -77,8 +114,8 @@ class DatabaseManager: session = self.get_thread_scoped_session() try: # Create and add the origin and destination Stations - origin = self.get_or_create_station(session, message_data['origin']) - destination = self.get_or_create_station(session, message_data['destination']) + origin = self.get_or_create_station(message_data['origin'], session) + destination = self.get_or_create_station(message_data['destination'], session) # Create and add Status if provided if status: diff --git a/modem/message_system_db_model.py b/modem/message_system_db_model.py index 6388e52e..9174ccde 100644 --- a/modem/message_system_db_model.py +++ b/modem/message_system_db_model.py @@ -8,9 +8,17 @@ Base = declarative_base() class Station(Base): __tablename__ = 'station' callsign = Column(String, primary_key=True) + checksum = Column(String, nullable=True) location = Column(JSON, nullable=True) info = Column(JSON, nullable=True) + def to_dict(self): + return { + 'callsign': self.callsign, + 'checksum': self.checksum, + 'location': self.location, + 'info': self.info, + } class Status(Base): __tablename__ = 'status' id = Column(Integer, primary_key=True) diff --git a/tests/test_protocols.py b/tests/test_protocols.py index 6b820225..41a5b826 100755 --- a/tests/test_protocols.py +++ b/tests/test_protocols.py @@ -51,7 +51,7 @@ class TestProtocols(unittest.TestCase): def testPingWithAck(self): # Run ping command - api_params = { "dxcall": "XX1XXX-7"} + api_params = { "dxcall": "XX1XXX-6"} ping_cmd = PingCommand(self.config, self.state_manager, self.event_manager, api_params) #ping_cmd.run(self.event_queue, self.modem) frame = ping_cmd.test(self.event_queue)