You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

63 lines
2.5KB

  1. #!/usr/bin/python3
  2. import requests
  3. import sys
  4. import textwrap
  5. import pprint
  6. from pathlib import Path
  7. try:
  8. from simplejson.errors import JSONDecodeError
  9. except ImportError:
  10. from json.decoder import JSONDecodeError
  11. api = 'http://parkering.linkoping.se/'
  12. key = Path('key-parking').read_text().strip()
  13. # Fetch JSON from url and run it through transform, pretty printing errors
  14. # and the data worked on as exhaustively as possible.
  15. def json_query(url, transform, params={}):
  16. try:
  17. result = requests.get(url, params)
  18. except requests.exceptions.ConnectionError:
  19. print("Network connection error.")
  20. sys.exit(1)
  21. try:
  22. data = result.json()
  23. except JSONDecodeError as err:
  24. print('Error when decoding JSON:\nFrom endpoint ' + url + ':\n' + str(err) + '\n' + str(result) + '\n')
  25. sys.exit(1)
  26. try:
  27. return transform(data)
  28. except (IndexError, KeyError) as err:
  29. print('Error when traversing JSON:\nFrom endpoint ' + url + ':\n' + str(err))
  30. pprint.PrettyPrinter(indent=2).pprint(data)
  31. sys.exit(1)
  32. # Get parking lots from the municipal server.
  33. # The timestamp part of this API does not work as expected, if non-zero it will return all computer parking terminal lots
  34. # in ParkingAreaUpdateList regardless of their status, up to a timestamp of less than one hour into the future, after which it will return nothing.
  35. def get_parking_lots():
  36. return json_query(api + 'Parkeringsdata/ParkeringsdataV1.svc/GetParkeringsytaList/' + key + '/0', lambda data: data['ParkingAreaNewList'], {})
  37. # The key ParkingSpacesAvailable is only present for those lots that are tracked by computer parking terminals.
  38. # All other lots only have static information available.
  39. def computerized(lot):
  40. return 'ParkingSpacesAvailable' in lot
  41. # The parking type '4' means handicap spots, whoever organized this put handicap spots as separate lots with duplicate names.
  42. def only_has_handicap_spots(lot):
  43. return lot['ParkingTypes'] == [4]
  44. # The downtown parking lots are equipped with electric charging stations and the API has a parking type for this
  45. # but the lot data has not been updated to reflect this, so this function always returns False.
  46. def electric_car_lot(lot):
  47. return 3 in lot['ParkingTypes']
  48. def main():
  49. print('Parking spaces available:')
  50. for lot in sorted(get_parking_lots(), key=lambda lot: lot['Name']):
  51. if computerized(lot) and not only_has_handicap_spots(lot):
  52. print("{Name}: {ParkingSpacesAvailable}/{ParkingSpaces}".format(**lot))
  53. if __name__ == '__main__':
  54. main()