#!/usr/bin/env python import json import os import subprocess from flask import Flask, Response, request from json import JSONEncoder from aman.AMAN import AMAN from aman.config.AirportSequencing import AirportSequencing from aman.config.RunwaySequencing import RunwaySequencing class InboundEncoder(JSONEncoder): def default(self, o): pta = str(o.PlannedArrivalTime) delimiter = pta.find('.') if -1 == delimiter: delimiter = pta.find('+') return { 'callsign' : o.Callsign, 'fixed' : o.FixedSequence, 'runway' : o.PlannedRunway.Name, 'pta' : pta[0:delimiter] } class RunwaySequencingEncoder(JSONEncoder): def default(self, o): return { 'runway' : o.Runway.Name, 'spacing' : o.Spacing } if 'AMAN_PATH' not in os.environ: os.environ['AMAN_PATH'] = 'C:\\Repositories\VATSIM\\AMAN\\aman-sys\\aman' if 'AMAN_CONFIG_PATH' not in os.environ: os.environ['AMAN_CONFIG_PATH'] = 'C:\\Repositories\\VATSIM\\AMAN\\config' aman = AMAN() app = Flask('AMAN') version = '0.0.0' with open(os.path.join(os.environ['AMAN_PATH'], 'VERSION')) as file: version = file.readline() if __name__ == '__main__': app.run() @app.route('/aman/airports') def airports(): # get the airports retval = [] for airport in aman.Workers: retval.append(airport.Icao) data = json.dumps({ 'version' : version, 'airports' : retval }, ensure_ascii=True) return Response(data, status=200, mimetype='application/json') @app.route('/aman/newuser') def newUser(): toolpath = os.path.join(os.path.join(os.environ['AMAN_PATH'], 'tools'), 'KeyPairCreator.py') serverKeypath = os.path.join(os.path.join(os.path.join(AMAN.findConfigPath(), 'keys'), 'server'), 'server.key') clientKeypath = os.path.join(os.path.join(AMAN.findConfigPath(), 'keys'), 'clients') cmd = ['python', toolpath, '--directory=' + clientKeypath, '--publickey=' + serverKeypath] stdout = subprocess.check_output(cmd) keys = stdout.splitlines() server = keys[0].decode('ascii') public = keys[1].decode('ascii') private = keys[2].decode('ascii') dictionary = { 'server' : server, 'public' : public, 'private' : private, } data = json.dumps(dictionary, ensure_ascii=True) return Response(data, status=200, mimetype='application/json') @app.route('/aman/configuration/') def configuration(icao): airport = aman.findAirport(icao.upper()) if None == airport: return Response('{}', status=404, mimetype='application/json') config = airport.SequencingConfiguration dependencies = [] for dependency in config.RunwayDependencies: rwy0 = config.runway(dependency[0]) rwy1 = config.runway(dependency[1]) cand1 = [ rwy0.Name, rwy1.Name ] cand2 = [ rwy1.Name, rwy0.Name ] found = False for dep in dependencies: if cand1 == dep or cand2 == dep: found = True break if False == found: dependencies.append(cand1) dictionary = { 'airport' : airport.Icao, 'useShallShouldMay' : config.UseShallShouldMay, 'activeRunways' : config.ActiveArrivalRunways, 'dependentRunways' : dependencies } data = json.dumps(dictionary, ensure_ascii=True, cls=RunwaySequencingEncoder) return Response(data, status=200, mimetype='application/json') @app.route('/aman/sequence/') def sequence(icao): airport = aman.findAirport(icao.upper()) if None == airport: return Response('{}', status=404, mimetype='application/json') # convert the timestamp stamp = str(airport.SequencingConfiguration.LastUpdateTimestamp) delimiter = stamp.find('.') if -1 == delimiter: delimiter = stamp.find('+') dictionary = { 'airport': airport.Icao, 'lastConfigurationUpdate': stamp[0:delimiter], 'sequence': airport.inboundSequence() } data = json.dumps(dictionary, ensure_ascii=True, cls=InboundEncoder) return Response(data, status=200, mimetype='application/json') @app.route('/aman/configure', methods=['POST']) def configure(): data = request.get_json() # validate that the airport exists if 'airport' not in data: return Response('{}', status=404, mimetype='application/json') airport = aman.findAirport(data['airport'].upper()) if None == airport: return Response('{}', status=404, mimetype='application/json') # check that all top-level information are available if 'useShallShouldMay' not in data or 'activeRunways' not in data or 'dependentRunways' not in data: return Response('{}', status=404, mimetype='application/json') if False == isinstance(data['useShallShouldMay'], bool) or 0 == len(data['activeRunways']): return Response('{}', status=404, mimetype='application/json') # create the toplevel information config = AirportSequencing(airport.Icao) config.Airport = data['airport'].upper() config.UseShallShouldMay = data['useShallShouldMay'] # parse the active runways for activeRunway in data['activeRunways']: if 'runway' not in activeRunway or 'spacing' not in activeRunway: return Response('{}', status=404, mimetype='application/json') if False == isinstance(activeRunway['runway'], str) or False == isinstance(activeRunway['spacing'], int): return Response('{}', status=404, mimetype='application/json') gngRunway = None for runway in airport.Configuration.GngData.Runways[airport.Icao]: if runway.Name == activeRunway['runway']: gngRunway = runway break # could not find the runway if None == gngRunway: return None runway = RunwaySequencing(gngRunway) runway.Spacing = activeRunway['spacing'] config.activateRunway(runway) # parse the dependent runways for dependency in data['dependentRunways']: if 2 != len(dependency) or False == isinstance(dependency[0], str) or False == isinstance(dependency[1], str): return Response('{}', status=404, mimetype='application/json') if False == config.addDependency(dependency[0], dependency[1]): return Response('{}', status=404, mimetype='application/json') airport.Configuration.assignmentUpdate(config) airport.configure(config) return Response('{}', status=200, mimetype='application/json')