app.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import uuid
  2. import threading
  3. import time
  4. import queue
  5. import os
  6. from flask import Flask
  7. from flask import render_template
  8. from flask import request
  9. from flask import json, jsonify
  10. from MAVProxy.modules.mavproxy_map import srtm
  11. from terrain_gen import makeTerrain
  12. # The output folder for all zipped terrain requests
  13. app = Flask(__name__,static_url_path='/terrain', static_folder='outputTer',)
  14. def clamp(n, smallest, largest):
  15. return max(smallest, min(n, largest))
  16. class TerGenThread(threading.Thread):
  17. # This is the terrain generator. It will check the queue
  18. # for new requests.
  19. def __init__(self):
  20. threading.Thread.__init__(self)
  21. self.event = threading.Event()
  22. # SRTM downloader. Single instance passed to terrain generator
  23. self.downloader = srtm.SRTMDownloader(debug=False, cachedir='./srtmcache')
  24. self.downloader.loadFileList()
  25. self.terStats = {}
  26. self.terQ = queue.Queue()
  27. def addStatus(self, uuidkey, value):
  28. self.terStats[uuidkey] = value
  29. def run(self):
  30. print("Starting Terrain Generator")
  31. while not self.event.is_set():
  32. time.sleep(0.01)
  33. if not self.terQ.empty():
  34. (radius, lat, lon, spacing, uuidkey, outfolder) = self.terQ.get()
  35. print("Starting request: " + str(uuidkey))
  36. self.terStats[uuidkey] = "Processing"
  37. makeTerrain(self.downloader, radius, lat, lon, spacing, uuidkey, outfolder)
  38. del self.terStats[uuidkey]
  39. print("Exiting Terrain Generator")
  40. # Terrain generator checker
  41. x = TerGenThread()
  42. x.start()
  43. def queueStatus():
  44. return len(x.terStats)
  45. def wholeStat():
  46. return str(x.terStats)
  47. def shutdown():
  48. x.event.set()
  49. x.join()
  50. @app.route('/')
  51. def index():
  52. return render_template('index.html')
  53. @app.route('/generate', methods = ['GET', 'POST'])
  54. def generate():
  55. if request.method == 'POST':
  56. # parse and sanitise the input
  57. try:
  58. # request.form['username']
  59. lat = float(request.form['lat'])
  60. lon = float(request.form['long'])
  61. radius = int(request.form['radius'])
  62. spacing = int(request.form['spacing'])
  63. assert lat < 90
  64. assert lon < 180
  65. assert lat > -90
  66. assert lon > -180
  67. radius = clamp(radius, 1, 400)
  68. spacing = clamp(spacing, 50, 500)
  69. except:
  70. print("Bad data")
  71. return render_template('generate.html', error = "Error with input")
  72. # UUID for this terrain generation
  73. uuidkey = str(uuid.uuid1())
  74. # Add this job to the processing queue
  75. x.terQ.put((radius, lat, lon, spacing, uuidkey, 'outputTer'))
  76. #x.terStats[uuidkey] = "In Queue, pos={0}".format(terQ.qsize())
  77. x.addStatus(uuidkey, "In Queue, pos={0}".format(x.terQ.qsize()))
  78. return render_template('generate.html', urlkey="/terrain/" + uuidkey + ".zip", waittime=x.terQ.qsize()+1, uuidkey=uuidkey)
  79. else:
  80. print("Bad get")
  81. return render_template('generate.html', error = "Need to use POST, not GET")
  82. @app.route('/status/<uuid:uuidkey>')
  83. def status(uuidkey):
  84. if not uuidkey:
  85. return jsonify(status = 'Error: incorrect UUID')
  86. elif str(uuidkey) in x.terStats:
  87. return jsonify(status = 'success', data = str(x.terStats[str(uuidkey)]))
  88. elif os.path.exists(os.path.join('.', 'outputTer', str(uuidkey) + ".zip")):
  89. return jsonify(status = 'success', data = "ready")
  90. else:
  91. return jsonify(status = 'Error: bad UUID ' + str(os.path.join('.', 'outputTer', str(uuidkey) + ".zip")))