diff --git a/aman/AMAN.py b/aman/AMAN.py index 5cce43c..3a9cb57 100644 --- a/aman/AMAN.py +++ b/aman/AMAN.py @@ -30,6 +30,7 @@ class AMAN: def __init__(self): # default initialization of members + configPath = AMAN.findConfigPath() self.SystemConfig = None self.AircraftPerformance = None self.Receiver = None @@ -37,15 +38,6 @@ class AMAN: self.WebUi = None self.Workers = [] - # initialize the random number generator - random.seed(time.time()) - - def __del__(self): - self.release() - - def aquire(self): - configPath = AMAN.findConfigPath() - # read all system relevant configuration files self.SystemConfig = System(os.path.join(configPath, 'System.ini')) print('Parsed System.ini') @@ -58,13 +50,10 @@ class AMAN: else: print('Parsed PerformanceData.ini. Extracted ' + str(len(self.AircraftPerformance.Aircrafts)) + ' aircrafts') - self.Weather = Weather() - self.Weather.acquire(self.SystemConfig.Weather) - self.WebUi = WebUI() - self.WebUi.acquire(self.SystemConfig.Server, self) + # create the communication syb + self.Weather = Weather(self.SystemConfig.Weather) + self.Receiver = Euroscope(configPath, self.SystemConfig.Server, self) - # create the EuroScope receiver - self.Receiver = Euroscope() # find the airport configurations and create the workers airportsPath = os.path.join(os.path.join(configPath, 'airports'), '*.ini') @@ -75,31 +64,13 @@ class AMAN: airportConfig = Airport(file, icao) # initialize the worker thread - worker = Worker() - worker.acquire(icao, airportConfig, self.Weather, self.AircraftPerformance, self.WebUi, self.Receiver) + worker = Worker(icao, airportConfig, self.Weather, self.AircraftPerformance, self.Receiver) self.Workers.append(worker) print('Started worker for ' + icao) - # initialize the receiver - self.Receiver.acquire(configPath, self.SystemConfig.Server, self) - def release(self): - if None != self.Workers: - for worker in self.Workers: - worker.release() - self.Workers = None - if None != self.Receiver: - self.Receiver.release() - self.Receiver = None - if None != self.Weather: - self.Weather.release() - self.Weather = None - - if None != self.WebUi: - self.WebUi.release() - self.WebUi = None def updateAircraftReport(self, report : AircraftReport_pb2.AircraftReport): # find the correct worker for the inbound diff --git a/aman/com/Euroscope.py b/aman/com/Euroscope.py index 5d5f9df..017ffff 100644 --- a/aman/com/Euroscope.py +++ b/aman/com/Euroscope.py @@ -40,33 +40,13 @@ class ReceiverThread(Thread): 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): + def __init__(self, configPath : str, config : Server, aman): 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 @@ -97,6 +77,7 @@ class Euroscope: self.ReceiverSocket.bind('tcp://' + config.Address + ':' + str(config.PortReceiver)) self.ReceiverSocket.setsockopt(zmq.SUBSCRIBE, b'') self.ReceiverThread = ReceiverThread(self.ReceiverSocket, aman) + self.ReceiverThread.setDaemon(True) self.ReceiverThread.start() print('Listening to tcp://' + config.Address + ':' + str(config.PortReceiver)) @@ -108,22 +89,6 @@ class Euroscope: 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, weather): if None == self.NotificationSocket: return diff --git a/aman/com/Weather.py b/aman/com/Weather.py index 9c288cc..5f2cacc 100644 --- a/aman/com/Weather.py +++ b/aman/com/Weather.py @@ -11,15 +11,9 @@ from aman.com.DwdCrawler import DwdCrawler import aman.config.Weather class Weather(Thread): - def __init__(self): + def __init__(self, config : aman.config.Weather.Weather): Thread.__init__(self) - self.NextUpdate = None - self.LastUpdateTried = None - self.StopThread = False - self.Provider = None - - def acquire(self, config : aman.config.Weather.Weather): self.NextUpdate = dt.utcfromtimestamp(int(time.time())) self.LastUpdateTried = None self.StopThread = False @@ -31,12 +25,9 @@ class Weather(Thread): sys.stderr.write('Invalid or unknown weather-provider defined') sys.exit(-1) + self.setDaemon(True) self.start() - def release(self): - self.StopThread = True - self.join() - def currentClock(): clock = dt.utcfromtimestamp(int(time.time())).replace(tzinfo = pytz.UTC) return clock diff --git a/aman/sys/Worker.py b/aman/sys/Worker.py index ec21c50..dc61a36 100644 --- a/aman/sys/Worker.py +++ b/aman/sys/Worker.py @@ -17,27 +17,13 @@ from aman.types.Inbound import Inbound from aman.types.PerformanceData import PerformanceData class Worker(Thread): - def __init__(self): + def __init__(self, icao : str, configuration : Airport, weather : Weather, + performance : PerformanceData, euroscope : Euroscope): Thread.__init__(self) self.StopThread = None - self.Icao = None - self.Configuration = None - self.PerformanceData = None - self.UpdateLock = None - self.ReportQueue = {} - self.WeatherModel = None - self.RecedingHorizonControl = None - self.WebUi = None - - def __del__(self): - self.release() - - def acquire(self, icao : str, configuration : Airport, weather : Weather, - performance : PerformanceData, webui : WebUI, euroscope : Euroscope): - self.StopThread = None self.Icao = icao self.Configuration = configuration - self.sequencingConfiguration = configuration.DefaultSequencing + self.SequencingConfiguration = configuration.DefaultSequencing self.PerformanceData = performance self.UpdateLock = Lock() self.ReportQueue = {} @@ -68,16 +54,13 @@ class Worker(Thread): sys.exit(-1) break + self.setDaemon(True) self.start() def acquireLock(self): if None != self.UpdateLock: self.UpdateLock.acquire() - def release(self): - self.StopThread = True - self.join() - def releaseLock(self): if None != self.UpdateLock: self.UpdateLock.release() @@ -107,7 +90,7 @@ class Worker(Thread): if 0 != report.distanceToIAF and '' != report.initialApproachFix: inbound = Inbound(report, self.PerformanceData) - Node(inbound, inbound.ReportTime, self.WeatherModel, self.Configuration.GngData, self.sequencingConfiguration) + Node(inbound, inbound.ReportTime, self.WeatherModel, self.Configuration.GngData, self.SequencingConfiguration) if None != inbound.InitialArrivalTime: self.RecedingHorizonControl.updateReport(inbound) else: @@ -123,13 +106,13 @@ class Worker(Thread): # get the last landing aircrafts per runway before the RHC stage to check for constraints # this is required to handle the overlap between windows preceedingInbounds = {} - for runway in self.sequencingConfiguration.ActiveArrivalRunways: + for runway in self.SequencingConfiguration.ActiveArrivalRunways: inbound = self.RecedingHorizonControl.lastFixedInboundOnRunway(runway.Runway.Name) if None != inbound: preceedingInbounds[runway.Runway.Name] = inbound # configure the ACO run - acoConfig = Configuration(constraints = self.sequencingConfiguration, nav = self.Configuration.GngData, + acoConfig = Configuration(constraints = self.SequencingConfiguration, nav = self.Configuration.GngData, earliest = earliestArrivalTime, weather = self.WeatherModel, preceeding = None if 0 == len(preceedingInbounds) else preceedingInbounds, ants = 5 * len(relevantInbounds), generations = 5 * len(relevantInbounds))