app.py 5.6 KB

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