live.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import requests, json
  2. from os import getenv
  3. from flask import Flask, request, abort
  4. # consts
  5. metric_map = {
  6. "spots": "free_slots",
  7. "bikes": "avl_bikes",
  8. "capacity": "total_slots",
  9. "location": "coordinates"
  10. }
  11. url = "https://vancouver-ca.smoove.pro/api-public/stations"
  12. #with open('live_dump.json') as f:
  13. # old_data = json.load(f)
  14. # data = old_data
  15. # init globals
  16. data = None
  17. app = Flask(__name__)
  18. def refresh_data():
  19. global data
  20. # try to get new data
  21. try:
  22. new = requests.get(url)
  23. except requests.exceptions.RequestException:
  24. app.logger.error("failed to get data")
  25. data = None
  26. else:
  27. data = new.json()["result"]
  28. # main function to get data from api
  29. def get_bikes(station, metric):
  30. refresh_data()
  31. # if refresh failed, return 404
  32. if not data:
  33. return 502
  34. # find the station
  35. match = False
  36. for each in data:
  37. split = each['name'].split(' ', 1)
  38. id = split[0]
  39. name = split[1]
  40. if station == id or station == name:
  41. match = each
  42. break
  43. # return 404 if no match
  44. if not match:
  45. return 404
  46. if metric == "both":
  47. result = "Spots: " + str(match["avl_bikes"]) + '<br/>'
  48. result += "Bikes: " + str(match["free_slots"])
  49. return result
  50. return(str(match[metric]))
  51. # interprets REST requests at a given location
  52. # you can get /api/station/metric to get just one metric w/o formatting
  53. @app.route('/api/<string:station>/<string:metric>', methods=['GET'])
  54. def get_metric_info(station, metric):
  55. try:
  56. metric_map[metric]
  57. except KeyError:
  58. abort(404, description="Sorry, that metric does not exist")
  59. result = get_bikes(station, metric_map[metric])
  60. if result == 404:
  61. abort(404, description="Sorry, that station does not exist")
  62. elif result == 502:
  63. abort(502, description="Sorry, the API server isn't responding right now")
  64. else:
  65. return result
  66. # interprets REST requests at a given location
  67. # get /api/station (can be a number or name) returns bikes+slots available
  68. @app.route('/api/<string:station>/', methods=['GET'])
  69. def get_station_info(station):
  70. result = get_bikes(station, "both")
  71. if result == 404:
  72. abort(404, description="Sorry, that station does not exist")
  73. elif result == 502:
  74. abort(502, description="Sorry, the API server isn't responding right now")
  75. else:
  76. return result