Загрузил файл
This commit is contained in:
parent
2da5e566d3
commit
7f57819f0e
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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())
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
__version__ = "1.0"
|
||||
__author__ = "Per Qvarforth"
|
||||
Loading…
Reference in New Issue