431 lines
20 KiB
Python
431 lines
20 KiB
Python
from server.trackdirect.common.Repository import Repository
|
|
from server.trackdirect.objects.Packet import Packet
|
|
from server.trackdirect.database.PacketTableCreator import PacketTableCreator
|
|
from server.trackdirect.exceptions.TrackDirectMissingTableError import TrackDirectMissingTableError
|
|
from server.trackdirect.database.DatabaseObjectFinder import DatabaseObjectFinder
|
|
|
|
|
|
class PacketRepository(Repository):
|
|
"""The PacketRepository class contains different methods that create Packet instances."""
|
|
|
|
def __init__(self, db):
|
|
"""Initialize PacketRepository with a database connection."""
|
|
super().__init__(db)
|
|
self.packet_table_creator = PacketTableCreator(self.db)
|
|
self.packet_table_creator.disable_create_if_missing()
|
|
self.db_object_finder = DatabaseObjectFinder(db)
|
|
|
|
def get_object_by_id(self, id):
|
|
"""Return a Packet object based on the specified id in the database."""
|
|
with self.db.cursor() as cursor:
|
|
cursor.execute("SELECT * FROM packet WHERE id = %s", (id,))
|
|
record = cursor.fetchone()
|
|
return self.get_object_from_record(record)
|
|
|
|
def get_object_by_id_and_timestamp(self, id, timestamp):
|
|
"""Return a Packet object based on the specified id and timestamp."""
|
|
try:
|
|
packet_table = self.packet_table_creator.get_table(timestamp)
|
|
with self.db.cursor() as cursor:
|
|
cursor.execute(f"SELECT * FROM {packet_table} WHERE id = %s", (id,))
|
|
record = cursor.fetchone()
|
|
return self.get_object_from_record(record)
|
|
except TrackDirectMissingTableError:
|
|
return self.create()
|
|
|
|
def get_object_by_station_id_and_timestamp(self, station_id, timestamp):
|
|
"""Return a Packet object based on the specified station_id and timestamp."""
|
|
try:
|
|
packet_table = self.packet_table_creator.get_table(timestamp)
|
|
with self.db.cursor() as cursor:
|
|
cursor.execute(f"""
|
|
SELECT * FROM {packet_table}
|
|
WHERE station_id = %s AND timestamp = %s
|
|
ORDER BY id LIMIT 1
|
|
""", (station_id, timestamp))
|
|
record = cursor.fetchone()
|
|
return self.get_object_from_record(record)
|
|
except TrackDirectMissingTableError:
|
|
return self.create()
|
|
|
|
def get_latest_object_list_by_station_id_list_and_time_interval(self, station_id_list, min_packet_timestamp, max_packet_timestamp, only_confirmed=True):
|
|
"""Return an array of the latest Packet objects specified by station ids."""
|
|
if not station_id_list:
|
|
return []
|
|
|
|
result = []
|
|
found_station_id_list = []
|
|
packet_tables = self.packet_table_creator.get_tables(min_packet_timestamp, max_packet_timestamp)
|
|
map_id_list = [1, 2, 12] if only_confirmed else [1, 2, 5, 7, 9, 12]
|
|
|
|
with self.db.cursor() as cursor:
|
|
for packet_table in reversed(packet_tables):
|
|
station_id_list_to_find = tuple(set(station_id_list) - set(found_station_id_list))
|
|
if station_id_list_to_find:
|
|
cursor.execute(f"""
|
|
SELECT * FROM {packet_table} packet
|
|
WHERE id IN (
|
|
SELECT MAX(id)
|
|
FROM {packet_table} packet
|
|
WHERE map_id IN %s
|
|
AND station_id IN %s
|
|
AND timestamp > %s
|
|
AND timestamp <= %s
|
|
GROUP BY station_id
|
|
)
|
|
ORDER BY packet.marker_id DESC, packet.id DESC
|
|
""", (tuple(map_id_list), station_id_list_to_find, min_packet_timestamp, max_packet_timestamp))
|
|
|
|
for record in cursor:
|
|
if record and record['station_id'] not in found_station_id_list:
|
|
result.append(self.get_object_from_record(record))
|
|
found_station_id_list.append(record['station_id'])
|
|
|
|
if len(found_station_id_list) >= len(station_id_list):
|
|
break
|
|
|
|
return result
|
|
|
|
def get_object_list_by_station_id_list_and_time_interval(self, station_id_list, min_packet_timestamp, max_packet_timestamp):
|
|
"""Return an array of Packet objects specified by station ids."""
|
|
if not station_id_list:
|
|
return []
|
|
|
|
result = []
|
|
packet_tables = self.packet_table_creator.get_tables(min_packet_timestamp, max_packet_timestamp)
|
|
|
|
with self.db.cursor() as cursor:
|
|
for packet_table in packet_tables:
|
|
cursor.execute(f"""
|
|
SELECT * FROM {packet_table} packet
|
|
WHERE map_id IN (1, 2, 5, 7, 9, 12)
|
|
AND station_id IN %s
|
|
AND timestamp > %s
|
|
AND timestamp <= %s
|
|
ORDER BY packet.marker_id, packet.id
|
|
""", (tuple(station_id_list), min_packet_timestamp, max_packet_timestamp))
|
|
|
|
for record in cursor:
|
|
if record:
|
|
result.append(self.get_object_from_record(record))
|
|
|
|
cursor.execute(f"""
|
|
SELECT * FROM {packet_table} packet
|
|
WHERE map_id = 12
|
|
AND station_id IN %s
|
|
AND position_timestamp <= %s
|
|
AND timestamp > %s
|
|
ORDER BY packet.marker_id, packet.id
|
|
""", (tuple(station_id_list), max_packet_timestamp, min_packet_timestamp))
|
|
|
|
for record in cursor:
|
|
if record:
|
|
result.append(self.get_object_from_record(record))
|
|
|
|
return result
|
|
|
|
def get_object_list_by_station_id_list(self, station_id_list, min_packet_timestamp):
|
|
"""Return an array of Packet objects specified by station ids."""
|
|
if not station_id_list:
|
|
return []
|
|
|
|
result = []
|
|
packet_tables = self.packet_table_creator.get_tables(min_packet_timestamp)
|
|
|
|
with self.db.cursor() as cursor:
|
|
for packet_table in packet_tables:
|
|
cursor.execute(f"""
|
|
SELECT * FROM {packet_table} packet
|
|
WHERE map_id IN (1, 5, 7, 9)
|
|
AND station_id IN %s
|
|
AND timestamp > %s
|
|
ORDER BY packet.marker_id, packet.id
|
|
""", (tuple(station_id_list), min_packet_timestamp))
|
|
|
|
for record in cursor:
|
|
if record:
|
|
result.append(self.get_object_from_record(record))
|
|
|
|
return result
|
|
|
|
def get_latest_object_by_station_id_and_position(self, station_id, latitude, longitude, map_id_list, symbol=None, symbol_table=None, min_timestamp=0):
|
|
"""Return a Packet object specified by station id and position."""
|
|
packet_tables = self.packet_table_creator.get_tables(min_timestamp)
|
|
|
|
with self.db.cursor() as cursor:
|
|
for packet_table in reversed(packet_tables):
|
|
cursor.execute(f"""
|
|
SELECT * FROM {packet_table}
|
|
WHERE station_id = %s
|
|
AND latitude = %s
|
|
AND longitude = %s
|
|
AND map_id IN %s
|
|
AND timestamp > %s
|
|
{f"AND symbol = %s" if symbol else ""}
|
|
{f"AND symbol_table = %s" if symbol_table else ""}
|
|
ORDER BY marker_id DESC, id DESC LIMIT 1
|
|
""", (station_id, latitude, longitude, tuple(map_id_list), min_timestamp, symbol, symbol_table))
|
|
|
|
record = cursor.fetchone()
|
|
if record:
|
|
return self.get_object_from_record(record)
|
|
|
|
return self.create()
|
|
|
|
def get_latest_confirmed_moving_object_by_station_id(self, station_id, min_timestamp=0):
|
|
"""Return the latest confirmed moving Packet specified by station id."""
|
|
packet_tables = self.packet_table_creator.get_tables(min_timestamp)
|
|
|
|
with self.db.cursor() as cursor:
|
|
for packet_table in reversed(packet_tables):
|
|
cursor.execute(f"""
|
|
SELECT * FROM {packet_table}
|
|
WHERE station_id = %s
|
|
AND is_moving = 1
|
|
AND map_id = 1
|
|
AND timestamp > %s
|
|
ORDER BY marker_id DESC, id DESC LIMIT 1
|
|
""", (station_id, min_timestamp))
|
|
|
|
record = cursor.fetchone()
|
|
if record:
|
|
return self.get_object_from_record(record)
|
|
|
|
return self.create()
|
|
|
|
def get_latest_moving_object_by_station_id(self, station_id, min_timestamp=0):
|
|
"""Return the latest moving Packet specified by station id."""
|
|
packet_tables = self.packet_table_creator.get_tables(min_timestamp)
|
|
|
|
with self.db.cursor() as cursor:
|
|
for packet_table in reversed(packet_tables):
|
|
cursor.execute(f"""
|
|
SELECT * FROM {packet_table} packet
|
|
WHERE station_id = %s
|
|
AND is_moving = 1
|
|
AND map_id IN (1, 7)
|
|
AND timestamp > %s
|
|
ORDER BY marker_id DESC, id DESC LIMIT 1
|
|
""", (station_id, min_timestamp))
|
|
|
|
record = cursor.fetchone()
|
|
if record:
|
|
return self.get_object_from_record(record)
|
|
|
|
return self.create()
|
|
|
|
def get_latest_confirmed_object_by_station_id(self, station_id, min_timestamp=0):
|
|
"""Return the latest confirmed Packet object specified by station id."""
|
|
with self.db.cursor() as cursor:
|
|
cursor.execute("""
|
|
SELECT * FROM station
|
|
WHERE id = %s
|
|
""", (station_id,))
|
|
record = cursor.fetchone()
|
|
|
|
if record and record["latest_confirmed_packet_timestamp"] is not None and record["latest_confirmed_packet_timestamp"] >= min_timestamp:
|
|
return self.get_object_by_id_and_timestamp(record["latest_confirmed_packet_id"], record["latest_confirmed_packet_timestamp"])
|
|
return self.create()
|
|
|
|
def get_latest_object_by_station_id(self, station_id, min_timestamp=0):
|
|
"""Return the latest Packet specified by station id."""
|
|
with self.db.cursor() as cursor:
|
|
cursor.execute("""
|
|
SELECT * FROM station
|
|
WHERE id = %s
|
|
""", (station_id,))
|
|
record = cursor.fetchone()
|
|
|
|
if record and record["latest_location_packet_timestamp"] is not None and record["latest_location_packet_timestamp"] >= min_timestamp:
|
|
return self.get_object_by_id_and_timestamp(record["latest_location_packet_id"], record["latest_location_packet_timestamp"])
|
|
return self.create()
|
|
|
|
def get_most_recent_confirmed_object_list_by_station_id_list(self, station_id_list, min_timestamp):
|
|
"""Return an array of the most recent confirmed Packet objects specified by station ids."""
|
|
if not station_id_list:
|
|
return []
|
|
|
|
result = []
|
|
packet_tables = self.packet_table_creator.get_tables(min_timestamp)
|
|
|
|
with self.db.cursor() as cursor:
|
|
for packet_table in packet_tables:
|
|
cursor.execute(f"""
|
|
SELECT * FROM {packet_table}
|
|
WHERE station_id IN %s
|
|
AND timestamp > %s
|
|
AND is_moving = 0
|
|
AND map_id = 1
|
|
""", (tuple(station_id_list), min_timestamp))
|
|
|
|
for record in cursor:
|
|
if record:
|
|
result.append(self.get_object_from_record(record))
|
|
|
|
for station_id in station_id_list:
|
|
packet = self.get_latest_confirmed_moving_object_by_station_id(station_id, min_timestamp)
|
|
if packet.is_existing_object():
|
|
result.append(packet)
|
|
|
|
return result
|
|
|
|
def get_most_recent_confirmed_object_list_by_station_id_list_and_time_interval(self, station_id_list, min_timestamp, max_timestamp):
|
|
"""Return an array of the most recent confirmed Packet objects specified by station ids."""
|
|
if not station_id_list:
|
|
return []
|
|
|
|
result = []
|
|
found_stationary_marker_hash_list = []
|
|
found_moving_marker_station_id_list = []
|
|
packet_tables = self.packet_table_creator.get_tables(min_timestamp, max_timestamp)
|
|
|
|
with self.db.cursor() as cursor:
|
|
for packet_table in reversed(packet_tables):
|
|
cursor.execute(f"""
|
|
SELECT * FROM {packet_table} packet
|
|
WHERE id IN (
|
|
SELECT MAX(id)
|
|
FROM {packet_table} packet
|
|
WHERE station_id IN %s
|
|
AND timestamp > %s
|
|
AND timestamp <= %s
|
|
AND is_moving = 0
|
|
AND map_id IN (1, 2, 12)
|
|
GROUP BY station_id, latitude, longitude, symbol, symbol_table
|
|
)
|
|
""", (tuple(station_id_list), min_timestamp, max_timestamp))
|
|
|
|
for record in cursor:
|
|
if record:
|
|
marker_hash = hash(f"{record['station_id']};{record['latitude']};{record['longitude']};{record['symbol']};{record['symbol_table']}")
|
|
if marker_hash not in found_stationary_marker_hash_list:
|
|
found_stationary_marker_hash_list.append(marker_hash)
|
|
result.append(self.get_object_from_record(record))
|
|
|
|
cursor.execute(f"""
|
|
SELECT packet.* FROM {packet_table} packet
|
|
WHERE id IN (
|
|
SELECT MAX(id)
|
|
FROM {packet_table} packet
|
|
WHERE station_id IN %s
|
|
AND map_id IN (1, 2, 12)
|
|
AND timestamp > %s
|
|
AND timestamp <= %s
|
|
AND is_moving = 1
|
|
GROUP BY station_id
|
|
)
|
|
""", (tuple(station_id_list), min_timestamp, max_timestamp))
|
|
|
|
for record in cursor:
|
|
if record and record['station_id'] not in found_moving_marker_station_id_list:
|
|
found_moving_marker_station_id_list.append(record['station_id'])
|
|
result.append(self.get_object_from_record(record))
|
|
|
|
return result
|
|
|
|
def get_latest_confirmed_object_list_by_station_id_list(self, station_id_list, min_timestamp=0):
|
|
"""Return an array of the latest confirmed Packet objects specified by station ids."""
|
|
if not station_id_list:
|
|
return []
|
|
|
|
result = []
|
|
if min_timestamp == 0:
|
|
for station_id in station_id_list:
|
|
packet = self.get_latest_confirmed_object_by_station_id(station_id)
|
|
if packet.is_existing_object():
|
|
result.append(packet)
|
|
else:
|
|
packet_tables = self.packet_table_creator.get_tables(min_timestamp)
|
|
|
|
with self.db.cursor() as cursor:
|
|
for packet_table in reversed(packet_tables):
|
|
cursor.execute(f"""
|
|
SELECT packet.* FROM {packet_table} packet, station
|
|
WHERE station.id IN %s
|
|
AND station.latest_confirmed_packet_id = packet.id
|
|
AND station.latest_confirmed_packet_timestamp = packet.timestamp
|
|
AND station.latest_confirmed_packet_timestamp > %s
|
|
ORDER BY packet.marker_id, packet.id
|
|
""", (tuple(station_id_list), min_timestamp))
|
|
|
|
for record in cursor:
|
|
if record:
|
|
result.append(self.get_object_from_record(record))
|
|
|
|
if len(result) >= len(station_id_list):
|
|
break
|
|
|
|
return result
|
|
|
|
def get_latest_object_list_by_station_id_list(self, station_id_list, min_timestamp=0):
|
|
"""Return an array of the latest Packet objects specified by station ids."""
|
|
if not station_id_list:
|
|
return []
|
|
|
|
result = []
|
|
if min_timestamp == 0:
|
|
for station_id in station_id_list:
|
|
packet = self.get_latest_object_by_station_id(station_id)
|
|
if packet.is_existing_object():
|
|
result.append(packet)
|
|
else:
|
|
packet_tables = self.packet_table_creator.get_tables(min_timestamp)
|
|
|
|
with self.db.cursor() as cursor:
|
|
for packet_table in reversed(packet_tables):
|
|
cursor.execute(f"""
|
|
SELECT packet.* FROM {packet_table} packet, station
|
|
WHERE station.id IN %s
|
|
AND station.latest_location_packet_id = packet.id
|
|
AND station.latest_confirmed_packet_timestamp = packet.timestamp
|
|
AND station.latest_location_packet_timestamp > %s
|
|
""", (tuple(station_id_list), min_timestamp))
|
|
|
|
for record in cursor:
|
|
if record:
|
|
result.append(self.get_object_from_record(record))
|
|
|
|
if len(result) >= len(station_id_list):
|
|
break
|
|
|
|
return result
|
|
|
|
def get_object_from_record(self, record):
|
|
"""Return a Packet object from a database record."""
|
|
db_object = self.create()
|
|
if record:
|
|
db_object.id = record["id"]
|
|
db_object.station_id = int(record["station_id"])
|
|
db_object.sender_id = int(record["sender_id"])
|
|
db_object.packet_type_id = record["packet_type_id"]
|
|
db_object.timestamp = int(record["timestamp"])
|
|
db_object.latitude = float(record["latitude"]) if record["latitude"] is not None else None
|
|
db_object.longitude = float(record["longitude"]) if record["longitude"] is not None else None
|
|
db_object.posambiguity = record['posambiguity']
|
|
db_object.symbol = record["symbol"]
|
|
db_object.symbol_table = record["symbol_table"]
|
|
db_object.map_sector = record["map_sector"]
|
|
db_object.related_map_sectors = record["related_map_sectors"]
|
|
db_object.map_id = record["map_id"]
|
|
db_object.source_id = record["source_id"]
|
|
db_object.marker_id = record["marker_id"]
|
|
db_object.speed = record["speed"]
|
|
db_object.course = record["course"]
|
|
db_object.altitude = record["altitude"]
|
|
db_object.is_moving = record['is_moving']
|
|
db_object.reported_timestamp = int(record["reported_timestamp"]) if record["reported_timestamp"] is not None else None
|
|
db_object.position_timestamp = int(record["position_timestamp"]) if record["position_timestamp"] is not None else None
|
|
db_object.packet_tail_timestamp = record.get('packet_tail_timestamp', db_object.timestamp)
|
|
db_object.marker_counter = record.get('marker_counter', 1)
|
|
db_object.comment = record.get('comment')
|
|
db_object.raw_path = record.get('raw_path')
|
|
db_object.raw = record.get('raw')
|
|
db_object.phg = record.get('phg')
|
|
db_object.rng = record.get('rng')
|
|
db_object.latest_phg_timestamp = record.get('latest_phg_timestamp')
|
|
db_object.latest_rng_timestamp = record.get('latest_rng_timestamp')
|
|
return db_object
|
|
|
|
def create(self):
|
|
"""Create an empty Packet."""
|
|
return Packet(self.db) |