app.py 6.6 KB

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