Skip to content
Snippets Groups Projects
Commit 6be57aa8 authored by Dónal Murray's avatar Dónal Murray
Browse files

Merge branch 'master' of https://github.com/hev-sw/hev-sw

parents 9de51f3f bfecead7
Branches
No related merge requests found
...@@ -9,20 +9,19 @@ import sys ...@@ -9,20 +9,19 @@ import sys
import time import time
import argparse import argparse
import sqlite3 import sqlite3
from random import random
from datetime import datetime from datetime import datetime
import threading import threading
from hevclient import HEVClient from hevclient import HEVClient
from commsConstants import dataFormat
SQLITE_FILE = 'database/HEC_monitoringDB.sqlite' # name of the sqlite database file SQLITE_FILE = 'database/HEC_monitoringDB.sqlite' # name of the sqlite database file
TABLE_NAME = 'hec_monitor' # name of the table to be created TABLE_NAME = 'hec_monitor' # name of the table to be created
def get_temperature(): def getList(dict):
""" return [*dict]
Returns a random number to simulate data obtained from a sensor
""" # List of data variables in the data packet from the Arduino
return random() * 20 data_format = getList(dataFormat().getDict())
def database_setup(): def database_setup():
...@@ -36,28 +35,19 @@ def database_setup(): ...@@ -36,28 +35,19 @@ def database_setup():
try: try:
# Connecting to the database file # Connecting to the database file
conn = sqlite3.connect(SQLITE_FILE) conn = sqlite3.connect(SQLITE_FILE)
conn.execute('''CREATE TABLE IF NOT EXISTS ''' + TABLE_NAME + ''' (
created_at INTEGER NOT NULL, exec_string = "created_at INTEGER NOT NULL, "
alarms STRING NOT NULL, for var in data_format:
version FLOAT NOT NULL, exec_string += var + " FLOAT NOT NULL, "
fsm_state FLOAT NOT NULL, exec_string += "alarms STRING NOT NULL "
pressure_air_supply FLOAT NOT NULL,
pressure_air_regulated FLOAT NOT NULL, # Setting the maximum size of the DB to 100 MB
pressure_o2_supply FLOAT NOT NULL, conn.execute("PRAGMA max_page_count = 204800")
pressure_o2_regulated FLOAT NOT NULL, conn.execute("PRAGMA page_size = 512")
pressure_buffer FLOAT NOT NULL,
pressure_inhale FLOAT NOT NULL, conn.execute('''CREATE TABLE IF NOT EXISTS {tn} ({ex_str});'''
pressure_patient FLOAT NOT NULL, .format(tn=TABLE_NAME, ex_str=exec_string))
temperature_buffer FLOAT NOT NULL,
pressure_diff_patient FLOAT NOT NULL,
readback_valve_air_in FLOAT NOT NULL,
readback_valve_o2_in FLOAT NOT NULL,
readback_valve_inhale FLOAT NOT NULL,
readback_valve_exhale FLOAT NOT NULL,
readback_valve_purge FLOAT NOT NULL,
readback_mode FLOAT NOT NULL
);'''
)
conn.commit() conn.commit()
conn.close() conn.close()
except sqlite3.Error as err: except sqlite3.Error as err:
...@@ -72,7 +62,6 @@ def monitoring(source_address): ...@@ -72,7 +62,6 @@ def monitoring(source_address):
# Instantiating the client # Instantiating the client
hevclient = HEVClient() hevclient = HEVClient()
print(hevclient.send_cmd("CMD_START"))
epoch = datetime(1970, 1, 1) epoch = datetime(1970, 1, 1)
...@@ -94,46 +83,26 @@ def monitoring(source_address): ...@@ -94,46 +83,26 @@ def monitoring(source_address):
data_alarms = ','.join(data_alarms) data_alarms = ','.join(data_alarms)
else: else:
data_alarms = "none" data_alarms = "none"
data_packet = { el : data_receiver[el] for el in data_format}
data_packet = { data_packet.update({"time" : timestamp})
'time' : timestamp, data_packet.update({"alarms" : data_alarms})
'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 ...") print("Writing to database ...")
try: try:
exec_string = "( :time, "
for el in data_format:
exec_string += ":" + el + ", "
exec_string += ":alarms) "
cursor.execute( cursor.execute(
'INSERT INTO {tn} VALUES ' 'INSERT INTO {tn} VALUES {ex_str} '
'(:time, :alarms, :version, ' .format(tn=TABLE_NAME, ex_str=exec_string), data_packet
':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)'
.format(tn=TABLE_NAME), data_packet
) )
conn.commit() conn.commit()
except sqlite3.Error as err: except sqlite3.Error as err:
raise Exception("sqlite3 error. Insert into database failed: {}".format(str(err))) raise Exception("sqlite3 error. Insert into database failed: {}".format(str(err)))
finally: finally:
......
#!/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)
No preview for this file type
No preview for this file type
var chart_pressure;
var chart_flow;
var chart_volume;
var time_value = 0 ;
/**
* Request data from the server, add it to the graph and set a timeout
* to request again
*/
function requestChartVar() {
$.ajax({
url: '/live-data',
success: function(point) {
if(chart_pressure.data.datasets[0].data.length > 30){
chart_pressure.data.labels.shift();
chart_pressure.data.datasets[0].data.shift();
}
if(chart_flow.data.datasets[0].data.length > 30){
chart_flow.data.labels.shift();
chart_flow.data.datasets[0].data.shift();
}
if(chart_volume.data.datasets[0].data.length > 30){
chart_volume.data.labels.shift();
chart_volume.data.datasets[0].data.shift();
}
// Convert epoch timestamp into seconds
var date = new Date(point.created_at);
var seconds = date.getSeconds();
// Show the time that has passed
chart_pressure.data.labels.push(-(60-seconds));
chart_pressure.data.datasets[0].data.push(point["pressure_buffer"]);
// add the point
chart_flow.data.labels.push(point.created_at);
chart_flow.data.datasets[0].data.push(point["pressure_inhale"]);
// add the point
chart_volume.data.labels.push(point.created_at);
chart_volume.data.datasets[0].data.push(point["temperature_buffer"]);
chart_pressure.update();
chart_flow.update();
chart_volume.update();
},
cache: false
});
// call it again after one second
setTimeout(requestChartVar, 1000);
}
$(document).ready(function() {
var ctx_pressure = document.getElementById('pressure_chart');
chart_pressure = new Chart(ctx_pressure, {
type: 'line',
data: {
labels: [],
datasets: [{
data: [],
label: "Var1",
borderColor: "#3e95cd",
fill: false
}
]
},
options: {
responsive: true,
title: {
display: false,
text: 'Pressure [mbar]'
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true
},
//type: 'time',
time: {
unit: 'second',
displayFormat: 'second'
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
suggestedMax: 25
},
scaleLabel: {
display: true,
labelString: 'Pressure [mbar]'
}
}]
},
legend : {
display: false}
},
plugins: {
streaming: {
duration: 20000,
refresh: 1000,
delay: 2000,
onRefresh: requestChartVar()
}
}
});
});
$(document).ready(function() {
var ctx_flow = document.getElementById('flow_chart');
chart_flow = new Chart(ctx_flow, {
type: 'line',
data: {
labels: [],
datasets: [{
data: [],
label: "Var1",
borderColor: "#3e95cd",
fill: false
}
]
},
options: {
title: {
display: false,
text: 'Variable 1'
},
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'second',
displayFormat: 'second'
}
}]
},
legend : {
display: false}
}
});
//requestChartVar("pressure_inhale");
});
$(document).ready(function() {
var ctx_volume = document.getElementById('volume_chart');
chart_volume = new Chart(ctx_volume, {
type: 'line',
data: {
labels: [],
datasets: [{
data: [],
label: "Var1",
borderColor: "#3e95cd",
fill: false
}
]
},
options: {
title: {
display: false,
text: 'Variable 1'
},
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'second',
displayFormat: 'second'
}
}]
},
legend : {
display: false}
}
});
//requestChartVar("temperature_buffer");
});
var chart_pressure;
var chart_flow;
var chart_volume;
var time_value = 0 ;
/**
* Request data from the server, add it to the graph and set a timeout
* to request again
*/
function requestChartVar1() {
$.ajax({
url: '/live-data',
success: function(point) {
if(chart_pressure.data.datasets[0].data.length > 10){
chart_pressure.data.labels.shift();
chart_pressure.data.datasets[0].data.shift();
}
// add the point
chart_pressure.data.labels.push(point.created_at);
time_value = point.created_at;
console.log(time_value)
chart_pressure.data.datasets[0].data.push(point[var1]);
// add the point
chart_flow.data.labels.push(point.created_at);
chart_flow.data.datasets[0].data.push(point[var1]);
chart_pressure.update();
},
cache: false
});
// call it again after one second
setTimeout(requestChartVar1, 1000);
}
$(document).ready(function() {
var ctx_pressure = document.getElementById('pressure_chart');
chart_pressure = new Chart(ctx_pressure, {
type: 'line',
data: {
labels: [],
datasets: [{
data: [],
label: "Var1",
borderColor: "#3e95cd",
fill: false
}
]
},
options: {
title: {
display: false,
text: 'Variable 1'
},
scales: {
xAxes: [{
time: {
unit: 'second',
displayFormat: 'second'
}
}]
},
legend : {
display: false}
}
});
requestChartVar1("pressure_buffer");
});
function requestChartVar2(var1) {
$.ajax({
url: '/live-data',
success: function(point) {
if(chart_flow.data.datasets[0].data.length > 10){
chart_flow.data.labels.shift();
chart_flow.data.datasets[0].data.shift();
}
// add the point
chart_flow.data.labels.push(point.created_at);
chart_flow.data.datasets[0].data.push(point[var1]);
chart_flow.update();
},
cache: false
});
// call it again after one second
setTimeout(requestChartVar2, 1000, var1);
}
$(document).ready(function() {
var ctx_flow = document.getElementById('flow_chart');
chart_flow = new Chart(ctx_flow, {
type: 'line',
data: {
labels: [],
datasets: [{
data: [],
label: "Var1",
borderColor: "#3e95cd",
fill: false
}
]
},
options: {
title: {
display: false,
text: 'Variable 1'
},
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'second',
displayFormat: 'second'
}
}]
},
legend : {
display: false}
}
});
requestChartVar2("pressure_inhale");
});
function requestChartVar3(var1) {
$.ajax({
url: '/live-data',
success: function(point) {
if(chart_volume.data.datasets[0].data.length > 10){
chart_volume.data.labels.shift();
chart_volume.data.datasets[0].data.shift();
}
// add the point
chart_volume.data.labels.push(point.created_at);
chart_volume.data.datasets[0].data.push(point[var1]);
chart_volume.update();
},
cache: false
});
// call it again after one second
setTimeout(requestChartVar3, 1000, var1);
}
$(document).ready(function() {
var ctx_volume = document.getElementById('volume_chart');
chart_volume = new Chart(ctx_volume, {
type: 'line',
data: {
labels: [],
datasets: [{
data: [],
label: "Var1",
borderColor: "#3e95cd",
fill: false
}
]
},
options: {
title: {
display: false,
text: 'Variable 1'
},
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'second',
displayFormat: 'second'
}
}]
},
legend : {
display: false}
}
});
requestChartVar3("temperature_buffer");
});
...@@ -73,6 +73,7 @@ ...@@ -73,6 +73,7 @@
<script src="{{ url_for('static', filename='js/moment.js') }}"></script> <script src="{{ url_for('static', filename='js/moment.js') }}"></script>
<script src="{{ url_for('static', filename='js/Chart.js') }}"></script> <script src="{{ url_for('static', filename='js/Chart.js') }}"></script>
<script src="{{ url_for('static', filename='js/Chart-plot.js') }}"></script> <script src="{{ url_for('static', filename='js/Chart-plot.js') }}"></script>
<script src="{{ url_for('static', filename='js/Chart-display.js') }}"></script>
<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js') }}"></script> <script src="{{ url_for('static', filename='js/jquery.dataTables.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/dataTables.bootstrap4.min.js') }}"></script> <script src="{{ url_for('static', filename='js/dataTables.bootstrap4.min.js') }}"></script>
......
...@@ -11,94 +11,34 @@ ...@@ -11,94 +11,34 @@
<div class = "row"> <div class = "row">
<div class = "col-md-7 py-0"> <div class = "col-md-10 py-0">
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="card mb-6"> <div class="card mb-6">
<div class="card-chart-header small ">Variable number 1</div> <div class="card-chart-header small ">Pressure [mbar]</div>
<div class="card-body px-0 py-0"><canvas id="pressure_air_supply" width="200%" height="40"></canvas></div> <div class="card-body px-0 py-0"><canvas id="pressure_chart" width="200%" height="30"></canvas></div>
</div> </div>
</div> </div>
</div> </div>
<div class = "row"> <div class = "row">
<div class="col-md-12"> <div class="col-md-12">
<div class="card mb-6 px-0 py-0"> <div class="card mb-6 px-0 py-0">
<div class="card-chart-header small">Variable number 2</div> <div class="card-chart-header small">Flow [mL/min]</div>
<div class="card-body px-0 py-0"><canvas id="variable2" width="200%" height="40"></canvas></div> <div class="card-body px-0 py-0"><canvas id="flow_chart" width="200%" height="30"></canvas></div>
</div> </div>
</div> </div>
</div> </div>
<div class = "row"> <div class = "row">
<div class="col-md-12"> <div class="col-md-12">
<div class="card mb-6 px-0 py-0"> <div class="card mb-6 px-0 py-0">
<div class="card-chart-header small ">Variable number 3</div> <div class="card-chart-header small ">Volume [mL]</div>
<div class="card-body px-0 py-0"><canvas id="chart_variable3" width="200%" height="40"></canvas></div> <div class="card-body px-0 py-0"><canvas id="volume_chart" width="200%" height="30"></canvas></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class = "col-md-5 py-0 px-0 mr-0">
<div class="row">
<div class="col-xl-5b px-1 py-0 mr-0">
<div class="card bg-primary text-dark mb-2">
<div class="card-header d-flex align-items-center justify-content-between">
<a class="small text-dark stretched-link" href="#">Temperature</a>
</div>
<div class="card-body"><span class = "reading" id="temperature">000.00</span> &#8451;</div>
</div>
</div>
<div class="col-xl-5b px-1 py-0 mr-0">
<div class="card bg-primary text-dark mb-2">
<div class="card-header d-flex align-items-center justify-content-between">
<a class="small text-dark stretched-link" href="#">Pressure</a>
</div>
<div class="card-body"><span class = "reading" id = "pressure">000.00</span> Pa</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xl-5b col-md-8 px-1 py-0">
<div class="card bg-primary text-dark mb-2">
<div class="card-header d-flex align-items-center justify-content-between">
<a class="small text-dark stretched-link" href="#">variable3</a>
</div>
<div class="card-body"><span class = "reading" id = "variable3">000.00</span> &#8451;</div>
</div>
</div>
<div class="col-xl-5b px-1 py-0 col-md-8">
<div class="card bg-primary text-dark mb-2">
<div class="card-header d-flex align-items-center justify-content-between">
<a class="small text-dark stretched-link" href="#">variable4</a>
</div>
<div class="card-body"><span class = "reading" id = "variable4">000.00</span> Pa</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xl-5b col-md-8 px-1 py-0">
<div class="card bg-primary text-dark mb-2">
<div class="card-header d-flex align-items-center justify-content-between">
<a class="small text-dark stretched-link" href="#">variable5</a>
</div>
<div class="card-body"><span class = "reading" id = "variable5">000.00</span> &#8451;</div>
</div>
</div>
<div class="col-xl-5b px-1 py-0 col-md-8">
<div class="card bg-primary text-dark mb-2">
<div class="card-header d-flex align-items-center justify-content-between">
<a class="small text-dark stretched-link" href="#">variable6</a>
</div>
<div class="card-body"><span class = "reading" id = "variable6">000.00</span> Pa</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment