Загрузил файл

This commit is contained in:
Batareiken 2024-02-28 23:37:50 +00:00
parent 2da5e566d3
commit 7f57819f0e
4 changed files with 307 additions and 0 deletions

View File

@ -0,0 +1,169 @@
import datetime, time, calendar
from trackdirect.repositories.PacketRepository import PacketRepository
from trackdirect.repositories.StationRepository import StationRepository
from trackdirect.parser.policies.MapSectorPolicy import MapSectorPolicy
class MissingPacketsQuery() :
"""This query class is used to find a packet for all stations that we are missing a packet for (when we rely need a packet for them)
Note:
If no packet are found we will simulate them
"""
def __init__(self, state, db) :
"""The __init__ method.
Args:
state (WebsocketConnectionState): The current state for a websocket connection
db (psycopg2.Connection): Database connection
"""
self.state = state
self.db = db
self.packetRepository = PacketRepository(db)
self.stationRepository = StationRepository(db)
self.simulateEmptyStation = False
def enableSimulateEmptyStation(self) :
"""Enable simulation even if we have no packet from station at all
"""
self.simulateEmptyStation = True
def getMissingPackets(self, stationIds, foundPackets) :
"""Fetch latest packets for stations that has no packet in foundPackets
Args:
stationIds (array): An array of all stations we should filter on
foundPackets (array): Packets that we have found
Returns:
array
"""
foundMissingPackets = []
for stationId in stationIds :
foundStationPacket = False
for packet in foundPackets :
if packet.stationId == stationId :
foundStationPacket = True
break # will go to next stationId
# Get latest packet for this station
if (not foundStationPacket) :
missingPacket = self._getLatestPacket(stationId)
if (missingPacket is not None) :
foundMissingPackets.append(missingPacket)
def getSortKey(item) :
return item.timestamp
return sorted(foundMissingPackets, key = getSortKey)
def _getLatestPacket(self, stationId) :
"""This method tries to find a packet for the specified station, in worst case a packet will be simulated based on old data
Args:
stationId (int): Stations id that we need a packet for
Returns:
Packet
"""
if (self.state.latestTimeTravelRequest is not None) :
ts = int(self.state.latestTimeTravelRequest) - (30*24*60*60) # For time travelers we need a limit
olderPackets = self.packetRepository.getLatestObjectListByStationIdListAndTimeInterval([stationId], ts, self.state.latestTimeTravelRequest)
else :
olderPackets = self.packetRepository.getLatestConfirmedObjectListByStationIdList([stationId], 0)
if (len(olderPackets) > 0) :
return olderPackets[0] # The lastet is the first in array
else :
# Lets try not confirmed packets
if (self.state.latestTimeTravelRequest is not None) :
ts = int(self.state.latestTimeTravelRequest) - (30*24*60*60) # For time travelers we need a limit
olderNonConfirmedPackets = self.packetRepository.getLatestObjectListByStationIdListAndTimeInterval([stationId], ts, self.state.latestTimeTravelRequest, False)
else :
olderNonConfirmedPackets = self.packetRepository.getLatestObjectListByStationIdList([stationId], 0)
if (len(olderNonConfirmedPackets) > 0) :
# Make this ghost-packet visible...
packet = olderNonConfirmedPackets[0]
packet.mapId = 1
packet.sourceId = 0 #simulated
return packet
else :
# We still do not have packets for this station, just get what we have from the station-table
return self._getSimulatedPacket(stationId)
return None
def _getSimulatedPacket(self, stationId) :
"""Creates a simulated packet based on data saved in the station table
Args:
stationId (int): The station that we want a packet from
Returns:
Packet
"""
station = self.stationRepository.getObjectById(stationId)
if (station.isExistingObject()
and (station.latestConfirmedPacketId is not None
or self.simulateEmptyStation)) :
packet = self.packetRepository.create()
packet.stationId = station.id
packet.senderId = station.latestSenderId
packet.sourceId = station.sourceId
packet.ogn_sender_address = station.latestOgnSenderAddress
if (station.latestConfirmedPacketId is not None) :
packet.id = station.latestConfirmedPacketId
else :
packet.id = -station.id # simulate a packet id that is uniqe
if (station.latestConfirmedMarkerId is not None) :
packet.markerId = station.latestConfirmedMarkerId
else :
packet.markerId = -station.id # simulate a marker id
packet.isMoving = 0
packet.packetTypeId = 1 # Assume it was a position packet...
if (station.latestConfirmedLatitude is not None and station.latestConfirmedLongitude is not None) :
packet.latitude = station.latestConfirmedLatitude
packet.longitude = station.latestConfirmedLongitude
else :
packet.latitude = float(0.0)
packet.longitude = float(0.0)
if (self.state.latestTimeTravelRequest is not None) :
packet.timestamp = 0 # don't know anything better to set here...
elif (station.latestConfirmedPacketTimestamp is not None) :
packet.timestamp = station.latestConfirmedPacketTimestamp
else :
packet.timestamp = 0
packet.reportedTimestamp = None
packet.positionTimestamp = packet.timestamp
packet.posambiguity = 0
if (station.latestConfirmedSymbol is not None and station.latestConfirmedSymbolTable is not None) :
packet.symbol = station.latestConfirmedSymbol
packet.symbolTable = station.latestConfirmedSymbolTable
else :
packet.symbol = None
packet.symbolTable = None
mapSectorPolicy = MapSectorPolicy()
packet.mapSector = mapSectorPolicy.getMapSector(packet.latitude, packet.longitude)
packet.relatedMapSectors = []
packet.mapId = 1
packet.speed = None
packet.course = None
packet.altitude = None
packet.packetTailTimestamp = packet.timestamp
packet.comment = None
packet.rawPath = None
packet.raw = None
return packet
return None

View File

@ -0,0 +1,59 @@
import datetime, time, calendar
from trackdirect.repositories.PacketRepository import PacketRepository
from trackdirect.websocket.queries.MissingPacketsQuery import MissingPacketsQuery
class MostRecentPacketsQuery() :
"""This query class returnes the latest packet for moving stations and the latest packet for every uniqe position for stationary stations.
Note:
If no packet are found we will simulate them
"""
def __init__(self, state, db) :
"""The __init__ method.
Args:
state (WebsocketConnectionState): The current state for a websocket connection
db (psycopg2.Connection): Database connection
"""
self.state = state
self.db = db
self.packetRepository = PacketRepository(db)
self.simulateEmptyStation = False
def enableSimulateEmptyStation(self) :
"""Enable simulation even if we have no packet from station at all
"""
self.simulateEmptyStation = True
def getPackets(self, stationIds) :
"""Fetch the most recent packets for the specified stations.
Returns the latest packet for moving stations and the latest packet for every uniqe position for stationary stations.
Args:
stationIds (array): An array of all stations we want packets for
Returns:
array
"""
if (self.state.latestTimeTravelRequest is not None) :
timestamp = int(self.state.latestTimeTravelRequest) - (int(self.state.latestMinutesRequest)*60)
packets = self.packetRepository.getMostRecentConfirmedObjectListByStationIdListAndTimeInterval(stationIds, timestamp, self.state.latestTimeTravelRequest)
else :
timestamp = int(time.time()) - (int(self.state.latestMinutesRequest)*60)
packets = self.packetRepository.getMostRecentConfirmedObjectListByStationIdList(stationIds, timestamp)
if (len(packets) < len(stationIds)) :
# If we have no recent markers we just send the latest that we have
query = MissingPacketsQuery(self.state, self.db)
if (self.simulateEmptyStation) :
query.enableSimulateEmptyStation()
foundMissingPackets = query.getMissingPackets(stationIds, packets)
if (foundMissingPackets) :
foundMissingPackets.extend(packets)
packets = foundMissingPackets
return packets

View File

@ -0,0 +1,77 @@
import datetime, time, calendar
from trackdirect.database.DatabaseObjectFinder import DatabaseObjectFinder
class StationIdByMapSectorQuery() :
"""A query class used to find station ids in a map sector
"""
def __init__(self, db) :
"""The __init__ method.
Args:
db (psycopg2.Connection): Database connection
"""
self.db = db
self.dbObjectFinder = DatabaseObjectFinder(db)
def getStationIdListByMapSector(self, mapSector, startPacketTimestamp, endPacketTimestamp) :
"""Returns a list station ids based on the specified map sector and time interval
Args:
mapSector (int): Map sector integer
startPacketTimestamp (int): Min unix timestamp
endPacketTimestamp (int): Max unix timestamp
Returns:
array
"""
result = {}
selectCursor = self.db.cursor()
# Create list of packet tables to look in
# After testing I have realized that this query is faster if you query one child table at the time
if (endPacketTimestamp is None):
endPacketTimestamp = int(time.time())
endDateTime = datetime.datetime.utcfromtimestamp(int(endPacketTimestamp))
endDateTime = endDateTime.replace(hour=0, minute=0, second=0, microsecond=0) + datetime.timedelta(days=1)
endTimestamp = calendar.timegm(endDateTime.timetuple())
packetTables = []
ts = startPacketTimestamp
while (ts < endTimestamp) :
date = datetime.datetime.utcfromtimestamp(int(ts)).strftime('%Y%m%d')
datePacketTable = 'packet' + date
if (self.dbObjectFinder.checkTableExists(datePacketTable)) :
packetTables.append(datePacketTable)
ts = ts + 86400 # 1 day in seconds
# Go through packet tables and search for stations
for packetTable in reversed(packetTables) :
sql1 = selectCursor.mogrify("""select distinct station_id id
from """ + packetTable + """
where map_sector = %s
and timestamp > %s
and timestamp <= %s
and map_id in (1,5,7,9)""", (mapSector, startPacketTimestamp, endPacketTimestamp))
selectCursor.execute(sql1)
for record in selectCursor :
if (record is not None) :
result[int(record["id"])] = True
sql2 = selectCursor.mogrify("""select distinct station_id id
from """ + packetTable + """
where map_sector = %s
and position_timestamp <= %s
and timestamp > %s
and map_id in (12)""", (mapSector, endPacketTimestamp, startPacketTimestamp))
selectCursor.execute(sql2)
for record in selectCursor :
if (record is not None) :
result[int(record["id"])] = True
selectCursor.close()
return list(result.keys())

View File

@ -0,0 +1,2 @@
__version__ = "1.0"
__author__ = "Per Qvarforth"