Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
API - initial commit
  • Loading branch information
mrd14005 committed Feb 27, 2019
1 parent 3246702 commit 4b4c1ac
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 0 deletions.
40 changes: 40 additions & 0 deletions API/DataObjects.py
@@ -0,0 +1,40 @@
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String, Binary, Float
from sqlalchemy.orm import relationship, sessionmaker, deferred
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext.declarative import declarative_base

from datetime import datetime

Base = declarative_base()

class LocationData(Base):
"""
Location Data for HuskyTrack
Attributes:
uuid: The Location Data's universally unique identifier
uid: The user ID of the user this data belongs to
latitude: The latitude of the device when this measurement was taken
longitude: The longitude of the device when this measurement was taken
accuracy: The accuracy of the measurement as reported by the device
speed: The speed of the device when this measurement was taken
heading: The heading of the device when this measurement was taken
altitude: The altitude of the device when this measurement was taken
timestamp: The time at which this measurement was taken [ISO-8601 UTC]
"""

__tablename__ = 'location_data'

uuid = Column('uuid', String, primary_key=True)
uid = Column('uid', String, nullable=False)
latitude = Column('latitude', Float, nullable=False)
longitude = Column('longitude', Float, nullable=False)
accuracy = Column('accuracy', Float, nullable=False)
speed = Column('speed', Float, nullable=False)
heading = Column('heading', Float, nullable=False)
altitude = Column('altitude', Float, nullable=False)
timestamp = Column('timestamp', String, nullable=False)

def __repr__(self):
return self.uuid
Binary file added API/DataObjects.pyc
Binary file not shown.
Binary file added API/__pycache__/DataObjects.cpython-36.pyc
Binary file not shown.
146 changes: 146 additions & 0 deletions API/api.py
@@ -0,0 +1,146 @@
import configparser
import sys
import json
from datetime import datetime

from flask import Flask, request

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 = Session()
return session

except Exception as e:
print("Unable to configure database connection. Error:", e)
sys.exit()

@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()
location = raw_location_data["location"]
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"]
uid = "1"
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:
try:
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)
except Exception as e:
print(e)
return json.dumps([[l.uuid, l.latitude, l.longitude, l.timestamp] for l in session.query(LocationData).all()])

if __name__ == '__main__':
app.run(debug=True)
7 changes: 7 additions & 0 deletions API/config.ini
@@ -0,0 +1,7 @@
[database]
type = sqlite
host = C:\Users\demel\Documents\GitHub\GPS-Tracking-of-On-Campus-Walking-Project\API\db\test.db
username = mason
pass = mason
port = 3306
database = mason
14 changes: 14 additions & 0 deletions API/db/init_sqlite.sql
@@ -0,0 +1,14 @@
BEGIN TRANSACTION;
DROP TABLE IF EXISTS `location_data`;
CREATE TABLE IF NOT EXISTS `location_data` (
`uuid` TEXT NOT NULL PRIMARY KEY UNIQUE,
`uid` TEXT NOT NULL,
`latitude` REAL NOT NULL,
`longitude` REAL NOT NULL,
`accuracy` REAL NOT NULL,
`speed` REAL NOT NULL,
`heading` REAL NOT NULL,
`altitude` REAL NOT NULL,
`timestamp` TEXT NOT NULL
);
COMMIT;
Binary file added API/db/test.db
Binary file not shown.
44 changes: 44 additions & 0 deletions API/post_test.py
@@ -0,0 +1,44 @@
import json
import urllib2
import uuid
import datetime

data = {
"location": {
"coords": {
"latitude": 1.5,
"longitude": 1.5,
"accuracy": 1.5,
"speed": 1.5,
"heading": 1.5,
"altitude": 1.5
},
"extras": {
"foo": "bar"
},
"activity": {
"type": "still",
"confidence": 100
},
"geofence": {
"identifier": "identifier",
"action": "ENTER"
},
"battery": {
"level": 1.5,
"is_charging": True
},
"timestamp": str(datetime.datetime.now().replace(microsecond=0).isoformat()),
"uuid": str(uuid.uuid4()),
"event": "EVENT",
"is_moving": 1.0,
"odometer": 1.0
}
}

req = urllib2.Request('http://127.0.0.1:5000/api/locationdata')
req.add_header('Content-Type', 'application/json')

response = urllib2.urlopen(req, json.dumps(data))

print(response.read())

0 comments on commit 4b4c1ac

Please sign in to comment.