diff --git a/parking b/parking new file mode 100755 index 0000000..494f8b1 --- /dev/null +++ b/parking @@ -0,0 +1,62 @@ +#!/usr/bin/python3 +import requests +import sys +import textwrap +import pprint +from pathlib import Path +try: + from simplejson.errors import JSONDecodeError +except ImportError: + from json.decoder import JSONDecodeError + +api = 'http://parkering.linkoping.se/' +key = Path('key-parking').read_text().strip() + +# Fetch JSON from url and run it through transform, pretty printing errors +# and the data worked on as exhaustively as possible. +def json_query(url, transform, params={}): + try: + result = requests.get(url, params) + except requests.exceptions.ConnectionError: + print("Network connection error.") + sys.exit(1) + try: + data = result.json() + except JSONDecodeError as err: + print('Error when decoding JSON:\nFrom endpoint ' + url + ':\n' + str(err) + '\n' + str(result) + '\n') + sys.exit(1) + try: + return transform(data) + except (IndexError, KeyError) as err: + print('Error when traversing JSON:\nFrom endpoint ' + url + ':\n' + str(err)) + pprint.PrettyPrinter(indent=2).pprint(data) + sys.exit(1) + +# Get parking lots from the municipal server. +# The timestamp part of this API does not work as expected, if non-zero it will return all computer parking terminal lots +# in ParkingAreaUpdateList regardless of their status, up to a timestamp of less than one hour into the future, after which it will return nothing. +def get_parking_lots(): + return json_query(api + 'Parkeringsdata/ParkeringsdataV1.svc/GetParkeringsytaList/' + key + '/0', lambda data: data['ParkingAreaNewList'], {}) + +# The key ParkingSpacesAvailable is only present for those lots that are tracked by computer parking terminals. +# All other lots only have static information available. +def computerized(lot): + return 'ParkingSpacesAvailable' in lot + +# The parking type '4' means handicap spots, whoever organized this put handicap spots as separate lots with duplicate names. +def only_has_handicap_spots(lot): + return lot['ParkingTypes'] == [4] + +# The downtown parking lots are equipped with electric charging stations and the API has a parking type for this +# but the lot data has not been updated to reflect this, so this function always returns False. +def electric_car_lot(lot): + return 3 in lot['ParkingTypes'] + +def main(): + print('Parking spaces available:') + for lot in sorted(get_parking_lots(), key=lambda lot: lot['Name']): + if computerized(lot) and not only_has_handicap_spots(lot): + print("{Name}: {ParkingSpacesAvailable}/{ParkingSpaces}".format(**lot)) + +if __name__ == '__main__': + main()