diff --git a/raspberry-backend/app.py b/raspberry-backend/app.py index a578ac1079669c0a6bf07110614e5470be5064f6..cbf058454bc5d2f2f78945b7e3fa93f1fe76ef83 100755 --- a/raspberry-backend/app.py +++ b/raspberry-backend/app.py @@ -12,6 +12,7 @@ import sqlite3 from flask import json import chardet from hevclient import HEVClient +from commsConstants import dataFormat WEBAPP = Flask(__name__) @@ -20,6 +21,9 @@ WEBAPP = Flask(__name__) hevclient = HEVClient() +def getList(dict): + return [*dict] + @WEBAPP.route('/', methods=['GET', 'POST']) def hello_world(): return render_template('index.html', result=live_data()) @@ -94,15 +98,9 @@ def live_data(): Output in json format """ - list_variables = ['created_at', 'version' , - 'fsm_state' , 'pressure_air_supply' , - 'pressure_air_regulated' , 'pressure_o2_supply' , - 'pressure_o2_regulated' , 'pressure_buffer' , - 'pressure_inhale' , 'pressure_patient' , - 'temperature_buffer' , 'pressure_diff_patient' , - 'readback_valve_air_in' , 'readback_valve_o2_in' , - 'readback_valve_inhale' , 'readback_valve_exhale' , - 'readback_valve_purge' , 'readback_mode' ] + list_variables = [] + list_variables.append("created_at") + list_variables.extend(getList(dataFormat().getDict())) data = {key: None for key in list_variables} diff --git a/raspberry-backend/arduino_recorder_V2.py b/raspberry-backend/arduino_recorder_V2.py new file mode 100755 index 0000000000000000000000000000000000000000..5a0785d99ba4486007262e51fa856d5acbb89394 --- /dev/null +++ b/raspberry-backend/arduino_recorder_V2.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 + +# HEV monitoring application +# USAGE: python3 arduino_recorder.py +# +# Last update: April 4, 2020 + +import sys +import time +import argparse +import sqlite3 +from random import random +from datetime import datetime +import threading +from hevclient import HEVClient +from commsConstants import dataFormat + +SQLITE_FILE = 'database/HEC_monitoringDB.sqlite' # name of the sqlite database file +TABLE_NAME = 'hec_monitor' # name of the table to be created + +def getList(dict): + return [*dict] + +data_format = getList(dataFormat().getDict()) +print(data_format) +print(len(data_format)) + +def get_temperature(): + """ + Returns a random number to simulate data obtained from a sensor + """ + return random() * 20 + + +def database_setup(): + ''' + This function creates the sqlite3 table with the timestamp column + and the columns for the arduino packet data + ''' + print('Creating ' + TABLE_NAME + ' table..' ) + + # Create the table if it does not exist + try: + # Connecting to the database file + conn = sqlite3.connect(SQLITE_FILE) + conn.execute('''CREATE TABLE IF NOT EXISTS ''' + TABLE_NAME + ''' ( + created_at INTEGER NOT NULL, + alarms STRING NOT NULL, + {} FLOAT NOT NULL + );'''.format(*( _ for _ in data_format)) + ) + conn.commit() + conn.close() + except sqlite3.Error as err: + raise Exception("sqlite3 Error. Create failed: {}".format(str(err))) + finally: + print('Table ' + TABLE_NAME + ' created successfully!') + +def monitoring(source_address): + ''' + Store arduino data in the sqlite3 table. + ''' + + # Instantiating the client + hevclient = HEVClient() + + epoch = datetime(1970, 1, 1) + + with sqlite3.connect(SQLITE_FILE) as conn: + cursor = conn.cursor() + while True: + current_time = datetime.now() + + # Computing the time in seconds since the epoch because easier to manipulate. + timestamp = (current_time -epoch).total_seconds() * 1000 + + data_receiver = hevclient.get_values() + data_alarms = hevclient.get_alarms() + + if data_receiver != None: + + # data alarms can have length of 6, joining all the strings + if data_alarms != None: + data_alarms = ','.join(data_alarms) + else: + data_alarms = "none" + + + data_packet = { + 'time' : timestamp, + 'alarms' : data_alarms, + 'version': data_receiver["version"], + 'fsm_state': data_receiver["fsm_state"], + 'pressure_air_supply': data_receiver["pressure_air_supply"], + 'pressure_air_regulated': data_receiver["pressure_air_regulated"], + 'pressure_o2_supply': data_receiver["pressure_o2_supply"], + 'pressure_o2_regulated': data_receiver["pressure_o2_regulated"], + 'pressure_buffer': data_receiver["pressure_buffer"], + 'pressure_inhale': data_receiver["pressure_inhale"], + 'pressure_patient': data_receiver["pressure_patient"], + 'temperature_buffer': data_receiver["temperature_buffer"], + 'pressure_diff_patient': data_receiver["pressure_diff_patient"], + 'readback_valve_air_in': data_receiver["readback_valve_air_in"], + 'readback_valve_o2_in': data_receiver["readback_valve_o2_in"], + 'readback_valve_inhale': data_receiver["readback_valve_inhale"], + 'readback_valve_exhale': data_receiver["readback_valve_exhale"], + 'readback_valve_purge': data_receiver["readback_valve_purge"], + 'readback_mode': data_receiver["readback_mode"] + } + + print("Writing to database ...") + try: + cursor.execute( + 'INSERT INTO hec_monitor VALUES ' + '( :time, :alarms, :{var} ' + .format(var=( _ for _ in data_format)), data_packet + ) + conn.commit() + except sqlite3.Error as err: + raise Exception("sqlite3 error. Insert into database failed: {}".format(str(err))) + finally: + sys.stdout.flush() + time.sleep(1) + +def progress(status, remaining, total): + print(f'Copied {total-remaining} of {total} pages...') + + +def db_backup(backup_time): + threading.Timer(backup_time, db_backup, [backup_time]).start() + print("Executing DB backup") + try: + # Existing DB + sqliteCon = sqlite3.connect(SQLITE_FILE) + # Backup DB + backupCon = sqlite3.connect("database/HEC_monitoringDB_backup.sqlite") + with backupCon: + sqliteCon.backup(backupCon, pages=5, progress=progress) + print("Backup successful") + except sqlite3.Error as err: + raise Exception("sqlite3 error. Error during backup: {}".format(str(err))) + finally: + if(backupCon): + backupCon.close() + sqliteCon.close() + + +def parse_args(): + parser = argparse.ArgumentParser(description='Python script monitorign Arduino data') + parser.add_argument('--source', default='ttys0 or similar') + parser.add_argument('--backup_time', type=int, default=600) + return parser.parse_args() + +if __name__ == "__main__": + ARGS = parse_args() + database_setup() + db_backup(ARGS.backup_time) + monitoring(ARGS.source) diff --git a/raspberry-backend/commsConstants.py b/raspberry-backend/commsConstants.py new file mode 120000 index 0000000000000000000000000000000000000000..0f24c112273123ee7e69dacdeb5f76fcebda0c2a --- /dev/null +++ b/raspberry-backend/commsConstants.py @@ -0,0 +1 @@ +../raspberry-dataserver/commsConstants.py \ No newline at end of file diff --git a/raspberry-backend/database/HEC_monitoringDB.sqlite b/raspberry-backend/database/HEC_monitoringDB.sqlite index 342d1ba5101f60ab192ea946d5f2590179fa8e2a..ab59e60190dbc5286c1a6eba31873099f3d398d8 100644 Binary files a/raspberry-backend/database/HEC_monitoringDB.sqlite and b/raspberry-backend/database/HEC_monitoringDB.sqlite differ diff --git a/raspberry-backend/static/js/Chart-plot.js b/raspberry-backend/static/js/Chart-plot.js index ffaaaca7d2dadc615219edb69626ca7b6b961dd7..e56d6fc1d6b07b70481ab729abf6928affc231ee 100644 --- a/raspberry-backend/static/js/Chart-plot.js +++ b/raspberry-backend/static/js/Chart-plot.js @@ -101,7 +101,8 @@ $(document).ready(function() { type: 'time', time: { unit: 'second', - displayFormat: 'second' + displayFormat: 'second', + type: 'realtime' }, ticks: { maxTicksLimit: 5, @@ -116,7 +117,15 @@ $(document).ready(function() { id: 'B', type: 'linear', position: 'right', - }] + },{ + ticks: { + min: 0, + max: 200, + stepSize: 20 + } + + +}] }, legend : { display: true}