#!/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()