|
1 |
| -## Coming soon! |
| 1 | +################################################################################### |
| 2 | +#### |
| 3 | +#### Title: VicRoads Bluetooth Links API to AWS S3 Bucket |
| 4 | +#### |
| 5 | +#### Description: This Python script is developed to be used in an AWS Lambda to |
| 6 | +#### get Bluetooth travel time and congestion data from the VicRoads API |
| 7 | +#### on a scheduled (cron) basis. http://api.vicroads.vic.gov.au/ |
| 8 | +#### |
| 9 | +#### AWS Lambda settings: |
| 10 | +#### trigger: setup a CloudWatch event on a scheduled basis, say every 5/10/15/30/60 minutes etc |
| 11 | +#### runtime: Python 2.7 |
| 12 | +#### handler: vicroads_api_bluetooth_links_to_aws_s3.save_to_bucket |
| 13 | +#### |
| 14 | +################################################################################### |
| 15 | + |
| 16 | +import boto3 |
| 17 | +import csv |
| 18 | +import json |
| 19 | +import logging |
| 20 | +from botocore.vendored import requests ## Boto requests (URL request) library |
| 21 | +from datetime import datetime |
| 22 | +from datetime import timedelta |
| 23 | + |
| 24 | +def save_to_bucket(event, context): |
| 25 | + ## Get date-time in current time zone |
| 26 | + time_zone = 11 #Melbourne UTC +11:00 hours |
| 27 | + date_time_now = datetime.now() + timedelta(hours=time_zone) |
| 28 | + date_time_now_str = str(date_time_now) |
| 29 | + |
| 30 | + ## Re-format the date-time |
| 31 | + dt_str = date_time_now_str[:16] |
| 32 | + dt_str = dt_str.replace(' ','') |
| 33 | + dt_str = dt_str.replace(':','') |
| 34 | + dt_str = dt_str.replace('-','') #Fomrat: yyyymmddhhmm |
| 35 | + |
| 36 | + ## VicRoads API key |
| 37 | + vicroads_api_key = "YOUR_API_KEY" |
| 38 | + |
| 39 | + ## Construct URL to query |
| 40 | + """ |
| 41 | + Docs: http://api.vicroads.vic.gov.au/#examples |
| 42 | + ---- |
| 43 | + http://api.vicroads.vic.gov.au/vicroads/wfs? |
| 44 | + service=wfs& |
| 45 | + version=2.0.0& - 1.1.0 or 2.0.0 are most widely used |
| 46 | + request=GetFeature& |
| 47 | + typeNames=vicroads:bluetooth_links& - Layer name, separate multiple with comma |
| 48 | + outputformat=application/json& - Also supports 'csv', 'shape-zip' (Shapefile), 'GML2', 'GML3' |
| 49 | + srsname=EPSG:4326& |
| 50 | + bbox=144.87,-38.64,145.64,-37.71& - Optional bounding box filter |
| 51 | + cql_filter=congestion>5& - Optional attribute or spatial filter using CQL |
| 52 | + sortby=reportedtime+D& - Optional sort, +D (Descending) or +A (Ascending) |
| 53 | + count=10 - Optional, leave it off to return everything |
| 54 | + """ |
| 55 | + url_to_query = 'http://api.vicroads.vic.gov.au/vicroads/wfs?' |
| 56 | + url_to_query += 'service=wfs&' |
| 57 | + url_to_query += 'version=2.0.0&' # 1.1.0 or 2.0.0 are most widely used |
| 58 | + url_to_query += 'request=GetFeature&' |
| 59 | + url_to_query += 'typeNames=vicroads:bluetooth_links&' # Layer name, separate multiple with comma |
| 60 | + url_to_query += 'outputformat=application/json&' # Supports 'application/json' 'csv', 'shape-zip' (Shapefile), 'GML2', 'GML3' |
| 61 | + url_to_query += 'srsname=EPSG:4326&' |
| 62 | + #url_to_query += 'bbox=144.87,-38.64,145.64,-37.71&' #Optional bounding box filter |
| 63 | + #url_to_query += 'cql_filter=congestion>5&' # Optional attribute or spatial filter using CQL |
| 64 | + #url_to_query += 'sortby=reportedtime+D&' # Optional sort, +D (Descending) or +A (Ascending) |
| 65 | + #url_to_query += 'count=4&' # Optional, leave it off to return everything |
| 66 | + url_to_query += 'AUTH=' + vicroads_api_key |
| 67 | + |
| 68 | + ## CloudWatch Logger |
| 69 | + logger = logging.getLogger() |
| 70 | + logger.setLevel(logging.INFO) |
| 71 | + logger.info('url_to_query: {}'.format(url_to_query)) |
| 72 | + |
| 73 | + ## Query (request) the URL |
| 74 | + result = requests.get(url_to_query) |
| 75 | + |
| 76 | + ## Get JSON Response |
| 77 | + jsonstr = result.content |
| 78 | + jsonobj = json.loads(jsonstr) |
| 79 | + |
| 80 | + ## Parse out elements... |
| 81 | + jsonobj_features = jsonobj['features'] |
| 82 | + string = "timestamp,linkid,name,direction,congestion,delay,excess_delay,travel_time,score,trend\n" |
| 83 | + for feature in jsonobj_features: |
| 84 | + timestamp = feature['properties']['timestamp'] |
| 85 | + linkid = feature['properties']['linkid'] |
| 86 | + name = feature['properties']['name'] |
| 87 | + name = name.replace(",","") |
| 88 | + direction = feature['properties']['direction'] |
| 89 | + congestion = feature['properties']['congestion'] |
| 90 | + delay = feature['properties']['delay'] |
| 91 | + excess_delay = feature['properties']['excess_delay'] |
| 92 | + travel_time = feature['properties']['travel_time'] |
| 93 | + score = feature['properties']['score'] |
| 94 | + trend = feature['properties']['trend'].replace(",","|") #NB has commas in it so replace |
| 95 | + ## Concatenate the CSV string.. |
| 96 | + string += str(timestamp) + ',' |
| 97 | + string += str(linkid) + ',' |
| 98 | + string += str(name) + ',' |
| 99 | + string += str(direction) + ',' |
| 100 | + string += str(congestion) + ',' |
| 101 | + string += str(delay) + ',' |
| 102 | + string += str(excess_delay) + ',' |
| 103 | + string += str(travel_time) + ',' |
| 104 | + string += str(score) + ',' |
| 105 | + string += str(trend) + ',' |
| 106 | + string += "\n" |
| 107 | + |
| 108 | + encoded_string = string.encode("utf-8") |
| 109 | + |
| 110 | + ## S3 Bucket Details |
| 111 | + bucket_name = "S3_BUCKET_NAME" # Update with your bucket name |
| 112 | + file_name = "bt_data_"+ str(dt_str) +".csv" |
| 113 | + s3_folder = "vicroads_api/bluetooth_links/" # Update with your S3 folder |
| 114 | + s3_path = s3_folder + file_name |
| 115 | + |
| 116 | + ## Connect to S3 Bucket |
| 117 | + s3 = boto3.resource("s3") |
| 118 | + s3.Bucket(bucket_name).put_object(Key=s3_path, Body=encoded_string) |
| 119 | + |
| 120 | + ## Return a response |
| 121 | + return { |
| 122 | + "statusCode": 200, |
| 123 | + "body": string |
| 124 | + } |
| 125 | + |
0 commit comments