Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 184 additions & 0 deletions database_access/DatabaseHandler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import requests
import os
import json
import time
from pathlib import Path
from urllib3 import Retry
from requests.adapters import HTTPAdapter
import dotenv

class DatabaseHandler:
"""
Class for handling usage of the database functions

Attributes
----------
session : requests.Session
Session object for accessing

Methods
------------
uploadMeasurement(filepath_raw: str, filepath_clean: str):
Uploads chosen measurement into the remote database.

downloadMeasurement():
Downloads measurements fitting the criteria from the database into a configured zip archive.

deleteMeasurement():
Deletes chosen measurement from database using its ID.
"""

def __init__(self):
dotenv.load_dotenv(".env")
self._session = requests.Session()
retries = Retry(total=5, backoff_factor=0.5, status_forcelist=[500,502,503,504])
adapter = HTTPAdapter(max_retries=retries)
headers = {"CF-Access-Client-Id": os.getenv("ACCESS_CLIENT_ID"), "CF-Access-Client-Secret": os.getenv("ACCESS_CLIENT_SECRET")}
self._session.headers.update(headers)
self._session.mount("https://", adapter)

def uploadMeasurement(self, filepath_raw: str, filepath_clean: str):
"""
Upload measurement files into the database for future use.

Parameters
----------
filepath_raw : str
String containing the path (absolute or relative) to a file containing raw BRV data.
filepath_clean : str
String containing the path (absolute or relative) to a file containing corresponding cleaned BRV data.

Returns
-------
none

Side Effects
------------
This function will result in a files being uploaded into the database and creation of a record corresponding to them.
"""

form_data = {}
#TODO: MOVE UI TO AN APP/WEBPAGE
print("Fill measurement metadata:")
form_data["person_id"] = str(input("Person ID (currently email): "))


with open(filepath_clean, "rb") as workMeasurementFileHook:
jsonlines = workMeasurementFileHook.readlines()
jsonlines = jsonlines[::-1]
parsed_line = json.loads(jsonlines[0])

form_data["duration_ms"] = parsed_line["timestamp"]
form_data["timestamp"] = time.time()

print("Fill in labels for the measurement:")

labels = {}

activity = input("Activity: ")
labels["activity"] = activity

age = int(input("Age (from 0 to 100): "))
gender = input("Biological gender (male/female): ")
health = input("Health condition: ")
condition = input("Athletic condition: ")

labels["bio"] = {"age": age, "gender": gender, "health": health, "condition": condition}

form_data["labels"] = json.dumps(labels)

with open(filepath_raw, "rb") as file_raw, open(filepath_clean, "rb") as file_clean:
files = {"measurement_file_raw": file_raw, "measurement_file_clean": file_clean}
r = self._session.post('https://brics-api.electimore.xyz/measurement/upload', files=files, data=form_data)

r.raise_for_status()
print(r.status_code)
print(r.text)
return

def downloadMeasurement(self):
"""
Download measurement files from the database with accordance to the query.

Parameters
----------
none

Returns
-------
none

Side Effects
------------
This function will result in a zip archive being created in the user's Downloads directory, if it exists.
"""


#TODO: MOVE UI TO AN APP/WEBPAGE
print("Fill measurement download query parameters")

person_id = input("Person ID (currently email): ").strip() or None

length_min = int(input("Minimum length in minutes: ").strip() or 0)
length_max = int(input("Maximum length in minutes: ").strip() or 24*60) # default value - 1 day

age_min = int(input("Minimum age of subject: ").strip() or 0)
age_max = int(input("Maximum age of subject: ").strip() or 100)

level = input("Enter acceptable levels (raw/clean) seperated by space or press enter for all").strip().split() or None
gender = input("Enter genders (male/female) seperated by space or skip for all").strip().split() or None
activity = input("Enter activities seperated by space or skip or all").strip().split() or None
condition = input("Enter conditions seperated by space or skip or all").strip().split() or None
health = input("Enter health statuses seperated by space or skip or all").strip().split() or None

query_data = {
"person_id": person_id,
"length_min": length_min * 60000, #length kept in db in milliseconds
"length_max": length_max * 60000,
"age_min": age_min,
"age_max": age_max,
"level": level,
"gender": gender,
"activity": activity,
"condition": condition,
"health": health
}

r = self._session.get('https://brics-api.electimore.xyz/measurement/download', params=query_data)

path = Path.home() / "Downloads" / "measurements_dataset.zip"
if r.status_code == 200:
with open(path, "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)

r.raise_for_status()
print(r.status_code)
return

def deleteMeasurement(self):
"""
Delete measurement record and files from database using it's ID.

Parameters
----------
none

Returns
-------
none

Side Effects
------------
This function will result in a measurement record and files being permamently deleted, if they exist.
"""
query_data = {}
measurement_id = input("Fill id of measurement to delete: ")

query_data["measurement_id"] = measurement_id
r = self._session.delete('https://brics-api.electimore.xyz/measurement/delete', params=query_data, timeout=30)

r.raise_for_status()
print(r.status_code)
print(r.text)
160 changes: 0 additions & 160 deletions database_access/requests.py

This file was deleted.

5 changes: 3 additions & 2 deletions db_download.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import sys
sys.path.append("utils")
from config import *
from database_access.requests import *
from database_access.DatabaseHandler import *

def main():
dotenv.load_dotenv()
downloadMeasurement()
dbh = DatabaseHandler()
dbh.downloadMeasurement()

if __name__ == "__main__":
main()