152 lines
5.4 KiB
Python
152 lines
5.4 KiB
Python
#!/usr/bin/env python
|
|
|
|
import ctypes
|
|
import glob
|
|
import os
|
|
import sys
|
|
import time
|
|
|
|
import zmq
|
|
import zmq.auth
|
|
|
|
from aman.com import AircraftReport_pb2
|
|
from aman.com import Communication_pb2
|
|
from aman.config.Server import Server
|
|
from threading import Thread, _active
|
|
|
|
class ReceiverThread(Thread):
|
|
def __init__(self, socket, aman):
|
|
Thread.__init__(self)
|
|
self.Socket = socket
|
|
self.AMAN = aman
|
|
|
|
def run(self):
|
|
while True:
|
|
try:
|
|
msg = self.Socket.recv(zmq.NOBLOCK)
|
|
|
|
# parse the received message
|
|
report = AircraftReport_pb2.AircraftReport()
|
|
report.ParseFromString(msg)
|
|
|
|
# try to associate the received aircraft to an airport
|
|
self.AMAN.updateAircraftReport(report)
|
|
|
|
except zmq.ZMQError as error:
|
|
if zmq.EAGAIN == error.errno:
|
|
time.sleep(0.5)
|
|
continue
|
|
else:
|
|
return
|
|
|
|
def threadId(self):
|
|
if hasattr(self, '_thread_id'):
|
|
return self._thread_id
|
|
for id, thread in _active.items():
|
|
if thread is self:
|
|
return id
|
|
|
|
def stopThread(self):
|
|
id = self.threadId()
|
|
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(id, ctypes.py_object(SystemExit))
|
|
if 1 < res:
|
|
ctypes.pythonapi.PyThreadState_SetAsyncExc(id, 0)
|
|
|
|
# @brief Receives and sends messages to EuroScope plugins
|
|
class Euroscope:
|
|
def __init__(self):
|
|
self.Context = None
|
|
self.ReceiverSocket = None
|
|
self.ReceiverThread = None
|
|
self.NotificationSocket = None
|
|
|
|
def __del__(self):
|
|
self.release()
|
|
|
|
# @brief Initializes the ZMQ socket
|
|
# @param[in] config The server configuration
|
|
def acquire(self, configPath : str, config : Server, aman):
|
|
self.Context = zmq.Context()
|
|
|
|
# find the key directories
|
|
serverKeyPath = os.path.join(os.path.join(configPath, 'keys'), 'server')
|
|
if False == os.path.isdir(serverKeyPath):
|
|
sys.stderr.write('No directory for the server key found')
|
|
sys.exit(-1)
|
|
print('Path to the server key: ' + serverKeyPath)
|
|
|
|
clientKeyPath = os.path.join(os.path.join(configPath, 'keys'), 'clients')
|
|
if False == os.path.isdir(clientKeyPath):
|
|
sys.stderr.write('No directory for the client keys found')
|
|
sys.exit(-1)
|
|
print('Path to the client keys: ' + clientKeyPath)
|
|
|
|
# read the certificates
|
|
keyPairPath = glob.glob(os.path.join(serverKeyPath, '*.key_secret'))
|
|
if 1 != len(keyPairPath):
|
|
sys.stderr.write('No public-private keypair found for the server certificate')
|
|
sys.exit(-1)
|
|
keyPair = zmq.auth.load_certificate(keyPairPath[0])
|
|
|
|
# initialize the receiver
|
|
self.ReceiverSocket = zmq.Socket(self.Context, zmq.SUB)
|
|
self.ReceiverSocket.setsockopt(zmq.CURVE_PUBLICKEY, keyPair[0])
|
|
self.ReceiverSocket.setsockopt(zmq.CURVE_SECRETKEY, keyPair[1])
|
|
self.ReceiverSocket.setsockopt(zmq.CURVE_SERVER, True)
|
|
self.ReceiverSocket.bind('tcp://' + config.Address + ':' + str(config.PortReceiver))
|
|
self.ReceiverSocket.setsockopt(zmq.SUBSCRIBE, b'')
|
|
self.ReceiverThread = ReceiverThread(self.ReceiverSocket, aman)
|
|
self.ReceiverThread.start()
|
|
print('Listening to tcp://' + config.Address + ':' + str(config.PortReceiver))
|
|
|
|
# initialize the notification
|
|
self.NotificationSocket = zmq.Socket(self.Context, zmq.PUB)
|
|
self.NotificationSocket.setsockopt(zmq.CURVE_PUBLICKEY, keyPair[0])
|
|
self.NotificationSocket.setsockopt(zmq.CURVE_SECRETKEY, keyPair[1])
|
|
self.NotificationSocket.setsockopt(zmq.CURVE_SERVER, True)
|
|
self.NotificationSocket.bind('tcp://' + config.Address + ':' + str(config.PortNotification))
|
|
print('Publishing to tcp://' + config.Address + ':' + str(config.PortNotification))
|
|
|
|
def release(self):
|
|
if None != self.ReceiverThread:
|
|
self.ReceiverThread.stopThread()
|
|
self.ReceiverThread.join()
|
|
self.ReceiverThread = None
|
|
|
|
if None != self.ReceiverSocket:
|
|
self.ReceiverSocket.close()
|
|
self.ReceiverSocket = None
|
|
|
|
if None != self.NotificationSocket:
|
|
self.NotificationSocket.close()
|
|
self.NotificationSocket = None
|
|
|
|
self.Context = None
|
|
|
|
def sendSequence(self, airport : str, inbounds):
|
|
if None == self.NotificationSocket:
|
|
return
|
|
|
|
sequence = Communication_pb2.AircraftSequence()
|
|
sequence.airport = airport
|
|
|
|
for inbound in inbounds:
|
|
entry = sequence.sequence.add()
|
|
entry.callsign = inbound.Callsign
|
|
entry.arrivalRoute = inbound.PlannedStar.Name
|
|
entry.arrivalRunway = inbound.PlannedRunway.Name
|
|
|
|
for waypoint in inbound.PlannedArrivalRoute:
|
|
wp = entry.waypoints.add()
|
|
wp.name = waypoint.Waypoint.Name
|
|
|
|
pta = str(waypoint.PTA)
|
|
delimiter = pta.find('.')
|
|
if -1 == delimiter:
|
|
delimiter = pta.find('+')
|
|
|
|
wp.pta = pta[0:delimiter]
|
|
|
|
message = sequence.SerializeToString()
|
|
self.NotificationSocket.send(message)
|