Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Merge pull request #6 from mrd14005/master
API Changes
- Loading branch information
Showing
5 changed files
with
216 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<VirtualHost *> | ||
ServerName sdp40.cse.uconn.edu | ||
|
||
LoadModule wsgi_module "/var/www/api/env/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so" | ||
|
||
WSGIDaemonProcess HuskyTrackAPI threads=1 | ||
WSGIProcessGroup HuskyTrackAPI | ||
WSGIScriptAlias /api /var/www/api/HuskyTrackAPI.wsgi process-group=HuskyTrackAPI application-group=%{GLOBAL} | ||
<Directory /var/www/api> | ||
Order allow,deny | ||
Allow from all | ||
</Directory> | ||
</VirtualHost> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
import configparser | ||
import sys | ||
import json | ||
from datetime import datetime | ||
|
||
from flask import Flask, request, g | ||
|
||
from DataObjects import LocationData | ||
from sqlalchemy import create_engine | ||
from sqlalchemy.orm import sessionmaker | ||
|
||
from collections import defaultdict | ||
|
||
app = Flask(__name__) | ||
|
||
ISO8601 = "%Y%m%dT%H%M%S" | ||
ISO8601_O = "%Y-%m-%d %H:%M:%S" | ||
|
||
|
||
def get_config(): | ||
""" | ||
Get the configuration data for the application | ||
""" | ||
try: | ||
config = configparser.SafeConfigParser() | ||
config.read('config.ini') | ||
return config | ||
except Exception as e: | ||
print("No configuration file found.", e) | ||
sys.exit() | ||
|
||
def get_session(config): | ||
""" | ||
Attempt to initialize the database session, quit if the | ||
program cannot find the database. | ||
""" | ||
try: | ||
# Collect Configuration | ||
dao_type = config.get('database', 'type').lower() | ||
username = config.get('database', 'username') | ||
password = config.get('database', 'pass') | ||
host = config.get('database', 'host') | ||
port = config.get('database', 'port') | ||
database = config.get('database', 'database') | ||
|
||
# Build URL | ||
if dao_type == 'sqlite': | ||
url = dao_type + ":///" + host | ||
else: | ||
url = dao_type + "://" + username +\ | ||
":" + password + "@" + host + \ | ||
":" + port + "/" + database | ||
|
||
# Create session | ||
engine = create_engine(url) | ||
Session = sessionmaker(bind=engine) | ||
session = getattr(g, '_session', None) | ||
if session is None: | ||
session = Session() | ||
return session | ||
|
||
except Exception as e: | ||
print("Unable to configure database connection. Error:", e) | ||
sys.exit() | ||
|
||
@app.route('/', methods=('GET', 'POST')) | ||
def test(): | ||
if request.method == 'POST': | ||
print (request.get_json()) | ||
return "Success" | ||
|
||
@app.route('/api') | ||
def api(): | ||
""" | ||
Returns the version for compatibility/availability checks" | ||
""" | ||
return 'v0.1' | ||
|
||
@app.route('/api/locationdata', methods=('GET', 'POST')) | ||
def location_data(): | ||
""" | ||
Request or post location data | ||
""" | ||
session = get_session(get_config()) | ||
if request.method == 'POST': | ||
if request.is_json: | ||
try: | ||
raw_location_data = request.get_json() | ||
locations = raw_location_data["location"] | ||
uid = raw_location_data["user_id"] | ||
for location in locations: | ||
coords = location["coords"] | ||
lat = coords["latitude"] | ||
lng = coords["longitude"] | ||
acc = coords["accuracy"] | ||
spd = coords["speed"] | ||
hed = coords["heading"] | ||
alt = coords["altitude"] | ||
tim = location["timestamp"] | ||
uuid = location["uuid"] | ||
locationData = LocationData(uuid = uuid, | ||
uid = uid, | ||
latitude = lat, | ||
longitude = lng, | ||
accuracy = acc, | ||
speed = spd, | ||
heading = hed, | ||
altitude = alt, | ||
timestamp = tim) | ||
session.add(locationData) | ||
session.commit() | ||
return "Success" | ||
except Exception as e: | ||
session.rollback() | ||
return ("Fail", str(e)) | ||
else: | ||
return "NOT JSON" | ||
else: | ||
if 'start' and 'end' in request.args: | ||
start = request.args.get('start') | ||
end = request.args.get('end') | ||
|
||
start = datetime.strptime(start, ISO8601) | ||
end = datetime.strptime(end, ISO8601) | ||
|
||
print(str([str(start), str(end)])) | ||
query_results = session.query(LocationData).filter(LocationData.timestamp > start, LocationData.timestamp < end).all() | ||
|
||
dataPoints = defaultdict(list) | ||
for result in query_results: | ||
dataPoints[result.uid].append(result) | ||
|
||
result = [] | ||
for user in dataPoints: | ||
print(user) | ||
json_entry = json.loads('{}') | ||
json_entry['user_id'] = user | ||
json_entry['start_time'] = min(dataPoints[user], key=lambda x:x.timestamp).timestamp | ||
json_entry['end_time'] = max(dataPoints[user], key=lambda x:x.timestamp).timestamp | ||
json_entry['locations'] = [] | ||
for location in dataPoints[user]: | ||
json_location = json.loads('{}') | ||
json_location['latitude'] = location.latitude | ||
json_location['longitude'] = location.longitude | ||
json_location['timestamp'] = location.timestamp | ||
json_entry['locations'].append(json_location) | ||
result.append(json_entry) | ||
|
||
return json.dumps(result) | ||
else: | ||
return json.dumps([[l.uuid, l.latitude, l.longitude, l.timestamp] for l in session.query(LocationData).all()]) | ||
|
||
@app.teardown_appcontext | ||
def close_connection(exception): | ||
session = getattr(g, '_session', None) | ||
if session is not None: | ||
session.close() | ||
|
||
if __name__ == '__main__': | ||
app.run(host='0.0.0.0', port=44) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters