app.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #!/usr/bin/env python
  2. import json
  3. import os
  4. import subprocess
  5. from flask import Flask, Response, request
  6. from json import JSONEncoder
  7. from aman.AMAN import AMAN
  8. from aman.config.AirportSequencing import AirportSequencing
  9. from aman.config.RunwaySequencing import RunwaySequencing
  10. class InboundEncoder(JSONEncoder):
  11. def default(self, o):
  12. pta = str(o.PlannedArrivalTime)
  13. delimiter = pta.find('.')
  14. if -1 == delimiter:
  15. delimiter = pta.find('+')
  16. return { 'callsign' : o.Callsign, 'fixed' : o.FixedSequence, 'runway' : o.PlannedRunway.Name, 'pta' : pta[0:delimiter] }
  17. class RunwaySequencingEncoder(JSONEncoder):
  18. def default(self, o):
  19. return { 'runway' : o.Runway.Name, 'spacing' : o.Spacing }
  20. if 'AMAN_PATH' not in os.environ:
  21. os.environ['AMAN_PATH'] = 'C:\\Repositories\VATSIM\\AMAN\\aman-sys\\aman'
  22. if 'AMAN_CONFIG_PATH' not in os.environ:
  23. os.environ['AMAN_CONFIG_PATH'] = 'C:\\Repositories\\VATSIM\\AMAN\\config'
  24. aman = AMAN()
  25. app = Flask('AMAN')
  26. version = '0.0.0'
  27. with open(os.path.join(os.environ['AMAN_PATH'], 'VERSION')) as file:
  28. version = file.readline()
  29. if __name__ == '__main__':
  30. app.run()
  31. @app.route('/aman/airports')
  32. def airports():
  33. # get the airports
  34. retval = []
  35. for airport in aman.Workers:
  36. retval.append(airport.Icao)
  37. data = json.dumps({ 'version' : version, 'airports' : retval }, ensure_ascii=True)
  38. return Response(data, status=200, mimetype='application/json')
  39. @app.route('/aman/newuser')
  40. def newUser():
  41. toolpath = os.path.join(os.path.join(os.environ['AMAN_PATH'], 'tools'), 'KeyPairCreator.py')
  42. serverKeypath = os.path.join(os.path.join(os.path.join(AMAN.findConfigPath(), 'keys'), 'server'), 'server.key')
  43. clientKeypath = os.path.join(os.path.join(AMAN.findConfigPath(), 'keys'), 'clients')
  44. cmd = ['python', toolpath, '--directory=' + clientKeypath, '--publickey=' + serverKeypath]
  45. stdout = subprocess.check_output(cmd)
  46. keys = stdout.splitlines()
  47. server = keys[0].decode('ascii')
  48. public = keys[1].decode('ascii')
  49. private = keys[2].decode('ascii')
  50. dictionary = {
  51. 'server' : server,
  52. 'public' : public,
  53. 'private' : private,
  54. }
  55. data = json.dumps(dictionary, ensure_ascii=True)
  56. return Response(data, status=200, mimetype='application/json')
  57. @app.route('/aman/configuration/<icao>')
  58. def configuration(icao):
  59. airport = aman.findAirport(icao.upper())
  60. if None == airport:
  61. return Response('{}', status=404, mimetype='application/json')
  62. config = airport.SequencingConfiguration
  63. dependencies = []
  64. for dependency in config.RunwayDependencies:
  65. rwy0 = config.runway(dependency[0])
  66. rwy1 = config.runway(dependency[1])
  67. cand1 = [ rwy0.Name, rwy1.Name ]
  68. cand2 = [ rwy1.Name, rwy0.Name ]
  69. found = False
  70. for dep in dependencies:
  71. if cand1 == dep or cand2 == dep:
  72. found = True
  73. break
  74. if False == found:
  75. dependencies.append(cand1)
  76. dictionary = {
  77. 'airport' : airport.Icao,
  78. 'useShallShouldMay' : config.UseShallShouldMay,
  79. 'activeRunways' : config.ActiveArrivalRunways,
  80. 'dependentRunways' : dependencies
  81. }
  82. data = json.dumps(dictionary, ensure_ascii=True, cls=RunwaySequencingEncoder)
  83. return Response(data, status=200, mimetype='application/json')
  84. @app.route('/aman/sequence/<icao>')
  85. def sequence(icao):
  86. airport = aman.findAirport(icao.upper())
  87. if None == airport:
  88. return Response('{}', status=404, mimetype='application/json')
  89. # convert the timestamp
  90. stamp = str(airport.SequencingConfiguration.LastUpdateTimestamp)
  91. delimiter = stamp.find('.')
  92. if -1 == delimiter:
  93. delimiter = stamp.find('+')
  94. dictionary = {
  95. 'airport': airport.Icao,
  96. 'lastConfigurationUpdate': stamp[0:delimiter],
  97. 'sequence': airport.inboundSequence()
  98. }
  99. data = json.dumps(dictionary, ensure_ascii=True, cls=InboundEncoder)
  100. return Response(data, status=200, mimetype='application/json')
  101. @app.route('/aman/configure', methods=['POST'])
  102. def configure():
  103. data = request.get_json()
  104. # validate that the airport exists
  105. if 'airport' not in data:
  106. return Response('{}', status=404, mimetype='application/json')
  107. airport = aman.findAirport(data['airport'].upper())
  108. if None == airport:
  109. return Response('{}', status=404, mimetype='application/json')
  110. # check that all top-level information are available
  111. if 'useShallShouldMay' not in data or 'activeRunways' not in data or 'dependentRunways' not in data:
  112. return Response('{}', status=404, mimetype='application/json')
  113. if False == isinstance(data['useShallShouldMay'], bool) or 0 == len(data['activeRunways']):
  114. return Response('{}', status=404, mimetype='application/json')
  115. # create the toplevel information
  116. config = AirportSequencing(airport.Icao)
  117. config.Airport = data['airport'].upper()
  118. config.UseShallShouldMay = data['useShallShouldMay']
  119. # parse the active runways
  120. for activeRunway in data['activeRunways']:
  121. if 'runway' not in activeRunway or 'spacing' not in activeRunway:
  122. return Response('{}', status=404, mimetype='application/json')
  123. if False == isinstance(activeRunway['runway'], str) or False == isinstance(activeRunway['spacing'], int):
  124. return Response('{}', status=404, mimetype='application/json')
  125. gngRunway = None
  126. for runway in airport.Configuration.GngData.Runways[airport.Icao]:
  127. if runway.Name == activeRunway['runway']:
  128. gngRunway = runway
  129. break
  130. # could not find the runway
  131. if None == gngRunway:
  132. return None
  133. runway = RunwaySequencing(gngRunway)
  134. runway.Spacing = activeRunway['spacing']
  135. config.activateRunway(runway)
  136. # parse the dependent runways
  137. for dependency in data['dependentRunways']:
  138. if 2 != len(dependency) or False == isinstance(dependency[0], str) or False == isinstance(dependency[1], str):
  139. return Response('{}', status=404, mimetype='application/json')
  140. if False == config.addDependency(dependency[0], dependency[1]):
  141. return Response('{}', status=404, mimetype='application/json')
  142. airport.Configuration.assignmentUpdate(config)
  143. airport.configure(config)
  144. return Response('{}', status=200, mimetype='application/json')