Commit 0d72f305 authored by Vladislav Rykov's avatar Vladislav Rykov
Browse files

device view integrated

parent 190a1137
from psycopg2 import sql from psycopg2 import sql
from app.helpers.misc import with_psql, utc_roundhour, utc_roundday from app.helpers.misc import with_psql, utc_roundhour, utc_roundday, utc_local_diff
import app.dao.application.application as ad import app.dao.application.application as ad
import app.dao.device.device as dd import app.dao.device.device as dd
...@@ -146,7 +146,7 @@ def get_recent_activity(cur, username, n=5): ...@@ -146,7 +146,7 @@ def get_recent_activity(cur, username, n=5):
for d in devs[1]: for d in devs[1]:
query += """ query += """
(SELECT timedate, appname, devname, data, utc from (SELECT timedate, appname, devname, data, utc from
(SELECT utc, timedate, data from dev_{}_{} limit 5) AS utc, (SELECT utc, timedate, data from dev_{}_{} ORDER BY utc DESC limit 5) AS utc,
(SELECT '{}' as appname) AS appname, (SELECT '{}' as appname) AS appname,
(SELECT '{}' as devname) AS devname) (SELECT '{}' as devname) AS devname)
UNION ALL""".format(a[1],d[1], a[0],d[0]) UNION ALL""".format(a[1],d[1], a[0],d[0])
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -150,3 +150,6 @@ def local_hour(hour_offset): ...@@ -150,3 +150,6 @@ def local_hour(hour_offset):
def local_weekday(day_offset = 0): def local_weekday(day_offset = 0):
d = {0:'Mo',1:'Tu',2:'We',3:'Th',4:'Fr',5:'Sa',6:'Su'} d = {0:'Mo',1:'Tu',2:'We',3:'Th',4:'Fr',5:'Sa',6:'Su'}
return (d[((datetime.now().weekday() - day_offset) % 7)]) return (d[((datetime.now().weekday() - day_offset) % 7)])
def utc_local_diff():
return abs((datetime.now() - datetime.utcnow()).total_seconds())
...@@ -83,12 +83,12 @@ ...@@ -83,12 +83,12 @@
<!-- Navigation --> <!-- Navigation -->
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="nav-item active "> <li class="nav-item active ">
<a class="nav-link active " href="./index.html"> <a class="nav-link active " href="/">
<i class="ni ni-tv-2 text-primary"></i> Dashboard <i class="ni ni-tv-2 text-primary"></i> Dashboard
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link " href="./examples/applications.html"> <a class="nav-link " href="/applications">
<i class="ni ni-air-baloon text-yellow"></i> Applications <i class="ni ni-air-baloon text-yellow"></i> Applications
</a> </a>
</li> </li>
...@@ -169,6 +169,8 @@ ...@@ -169,6 +169,8 @@
<div class="container-fluid"> <div class="container-fluid">
<!-- Brand --> <!-- Brand -->
{% block location %} {% endblock %} {% block location %} {% endblock %}
<!-- Form for layout control-->
<form class="navbar-search navbar-search-dark form-inline mr-3 d-none d-md-flex ml-lg-auto"></form>
<!-- User --> <!-- User -->
<ul class="navbar-nav align-items-center d-none d-md-flex"> <ul class="navbar-nav align-items-center d-none d-md-flex">
<li class="nav-item dropdown"> <li class="nav-item dropdown">
...@@ -214,6 +216,15 @@ ...@@ -214,6 +216,15 @@
</nav> </nav>
<!-- End Navbar --> <!-- End Navbar -->
<!-- Header -->
<div class="header bg-gradient-primary pb-8 pt-5 pt-md-8">
<div class="container-fluid">
<div class="header-body">
<!-- Card stats -->
{% block stats %} {% endblock %}
</div>
</div>
</div>
{% block body %} {% endblock %} {% block body %} {% endblock %}
</div> </div>
......
...@@ -201,10 +201,8 @@ ...@@ -201,10 +201,8 @@
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="../index.html">Application Name</a> <a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="../index.html">Application Name</a>
<p class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block"> &nbsp;-&nbsp; </p> <p class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block"> &nbsp;-&nbsp; </p>
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="../index.html">Device Name</a> <a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="../index.html">Device Name</a>
<!-- Form --> <!-- Form for layout control-->
<form class="navbar-search navbar-search-dark form-inline mr-3 d-none d-md-flex ml-lg-auto"> <form class="navbar-search navbar-search-dark form-inline mr-3 d-none d-md-flex ml-lg-auto"></form>
</form>
<!-- User --> <!-- User -->
<ul class="navbar-nav align-items-center d-none d-md-flex"> <ul class="navbar-nav align-items-center d-none d-md-flex">
<li class="nav-item dropdown"> <li class="nav-item dropdown">
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
{% block title %} HPC&amp;A IoT - {{ app[1] }} {% endblock %} {% block title %} HPC&amp;A IoT - {{ app[1] }} {% endblock %}
{% block location %} {% block location %}
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="./applications">Applications</a> <a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/applications">Applications</a>
<p class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block"> &nbsp;-&nbsp; </p> <p class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block"> &nbsp;-&nbsp; </p>
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="./application/{{ app[1] }}">{{ app[0] }}</a> <a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/application/{{ app[1] }}">{{ app[0] }}</a>
{% endblock %} {% endblock %}
{% block stats %} {% block stats %}
......
{% extends 'logged_layout.html' %}
{% block title %} HPC&amp;A IoT - {{ app[1] }} - Devices {% endblock %}
{% block header %}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
{% endblock %}
{% block location %}
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/applications">Applications</a>
<p class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block"> &nbsp;-&nbsp; </p>
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/application/{{ app[1] }}">{{ app[0] }}</a>
<p class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block"> &nbsp;-&nbsp; </p>
<a class="h4 mb-0 text-white text-uppercase d-none d-lg-inline-block" href="/application/{{ app[1] }}/device/{{ dev[1] }}">{{ dev[0] }}</a>
{% endblock %}
{% block stats %}
<!-- Header -->
<div class="row">
<div class="col-xl-4 col-lg-6">
<div class="card card-stats mb-4 mb-xl-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="card-title text-uppercase text-muted mb-0">Name</h5>
<span class="h2 font-weight-bold mb-0">{{ dev[0] }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-4 col-lg-6">
<div class="card card-stats mb-4 mb-xl-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="card-title text-uppercase text-muted mb-0">Device ID</h5>
<span class="h2 font-weight-bold mb-0">{{ dev[1] }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-4 col-lg-6">
<div class="card card-stats mb-4 mb-xl-0">
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="card-title text-uppercase text-muted mb-0">Last time up</h5>
<span class="h2 font-weight-bold mb-0">{{ ltup }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block body %}
<!-- Page content -->
<div class="container-fluid mt--7">
<!-- Table -->
<div class="row">
<div class="col">
<div class="card shadow">
<div class="card-header bg-transparent">
<h3 class="mb-0">Details</h3>
</div>
<div class="card-body">
<div class="col-lg-12 col-md-6" style="margin-bottom : 30px;">
<div class="card" style="margin-bottom : 15px;">
<div class="card-body">
<h5 class="card-title">Description</h5>
<p class="card-text">{{ dev[2] }}</p>
</div>
</div>
</div>
<div>
<ul class="nav nav-pills" id="pills-tab" role="tablist">
{% for k in data[0][2] %}
<li class="nav-item col-lg-3 col-md-6" role="presentation">
<a class="nav-link" id="tab_{{ k }}" data-toggle="pill" href="#{{ k }}" role="tab" aria-controls="{{ k }}" aria-selected="true" onclick="display_data('{{ k }}')">{{ k }}</a>
</li>
{% endfor %}
</ul>
<div class="tab-content" id="pills-tabContent">
{% for k in data[0][2] %}
<div class="tab-pane fade card" id="{{ k }}" style="margin-top: 30px;" role="tabpanel" aria-labelledby="tab_{{ k }}">
<div class="card-body">
<h3 class="mb-0 card-header">Last 24 hours data</h3>
<center>
<div id="curve_chart_{{ k }}"></div>
</center>
<p> Total: <strong> {{ total }} </strong> messages. </p>
<table class="table" id="table_{{ k }}">
<thead>
<th> Time </th>
<th> {{ k }} </th>
</thead>
<tbody id="table_{{ k }}_body">
</tbody>
</table>
<center><a href="javascript:void(0);" onclick="return table_load_more('{{ k }}');">Load more</a></center>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="row" style="margin-top: 30px;">
<div class="col-lg-4">
<button type="submit" class="btn btn-primary btn-block">Configure</button>
</div>
<div class="col-lg-4">
<button type="submit" class="btn btn-primary btn-block">Download CSV</button>
</div>
<div class="col-lg-4">
<button type="submit" class="btn btn-primary btn-block">Settings</button>
</div>
<!-- put inside settings
<div class="col-lg-3">
<button type="button" class="btn btn-danger btn-block" data-toggle="modal" data-target="#exampleModal">Delete</button>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
Modal Body ....
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-danger">Delete Application</button>
</div>
</div>
</div>
</div>
</div>
-->
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(show_first_page);
function init_scroll() {
var ts = {
{% for k in data[0][2] %}
{{ k }} : 1,
{% endfor %}
};
return ts;
}
var tscroll = init_scroll();
function drawChart(dname, ddata) {
var data = google.visualization.arrayToDataTable(ddata);
var options = {
title: '{{ dev[0] }} > '+dname,
curveType: 'function',
hAxis: {
format: 'dd/MM hh:mm'
},
vAxis: {
format: 'decimal',
scaleType: 'linear',
textPosition: 'out'
},
legend: { position: 'none' },
height: 600,
/* width: 900, */
// interpolateNulls: true,
chartArea: { left: '5%', width: '90%', height: '80%' }
};
var container = document.getElementById('curve_chart_'+dname);
var chart = new google.visualization.LineChart(container);
chart.draw(data, options);
}
function display_data(dname) {
// Declare all variables
var i, tabcontent, tablinks;
// Get all elements with class="tabcontent" and hide them
//tabcontent = document.getElementsByClassName("tab-content");
//for (i = 0; i < tabcontent.length; i++) {
// tabcontent[i].style.display = "none";
//}
// Get all elements with class="tablinks" and remove the class "active"
//tablinks = document.getElementsByClassName("tablinks");
//for (i = 0; i < tablinks.length; i++) {
// tablinks[i].className = tablinks[i].className.replace(" active", "");
//}
// Show the current tab, and add an "active" class to the button that opened the tab
//document.getElementById(dname).style.display = "block";
//evt.currentTarget.className += " active";
tscroll = init_scroll();
fetch('/application/{{ app[1] }}/device/{{ dev[1] }}/data/'+dname+'/graph/1').then(res => res.text()).then(data => drawChart(dname, eval(data)));
fetch('/application/{{ app[1] }}/device/{{ dev[1] }}/data/'+dname+'/table/'+tscroll[dname]).then(res => res.text()).then(data => $('#table_'+dname+'_body').html(data));
/*
window.onscroll = function (ev) {
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
tscroll[dname] += 1;
fetch(window.origin+'/dev-data/'+dname+'/table/'+tscroll[dname]).then(res => res.text()).then(data => $('#table_'+dname+'_body').append(data));
}
};
*/
}
function show_first_page() {
document.getElementById("tab_{{ data[0][2] | first }}").click();
}
function table_load_more(dname) {
tscroll[dname] += 1;
fetch('/application/{{ app[1] }}/device/{{ dev[1] }}/data/'+dname+'/table/'+tscroll[dname]).then(res => res.text()).then(data => $('#table_'+dname+'_body').append(data));
fetch('/application/{{ app[1] }}/device/{{ dev[1] }}/data/'+dname+'/table/'+tscroll[dname]).then(res => res.text()).then(data => console.log(data));
}
</script>
{% endblock %}
...@@ -34,11 +34,7 @@ def index(): ...@@ -34,11 +34,7 @@ def index():
total_activity = md.get_user_data_count(session['name'])[1][0] total_activity = md.get_user_data_count(session['name'])[1][0]
last_activity = md.get_user_data_count_per_day(session['name'])[1][0] last_activity = md.get_user_data_count_per_day(session['name'])[1][0]
recent_activity = md.get_recent_activity(session['name'])[1] recent_activity = md.get_recent_activity(session['name'])[1]
print (recent_activity)
#print('created_apps', created_apps)
#print('active_devices', active_devices)
#print('total_activity', total_activity)
#print('last_activity', last_activity)
info = [created_apps, active_devices, total_activity, last_activity] info = [created_apps, active_devices, total_activity, last_activity]
day_chart_values = md.get_user_data_count_per_hour_period(session['name'], 11)[1] day_chart_values = md.get_user_data_count_per_hour_period(session['name'], 11)[1]
...@@ -53,16 +49,16 @@ def index(): ...@@ -53,16 +49,16 @@ def index():
return render_template('new/public/dashboard.html', info=info, recent_activity=recent_activity, day_chart=day_chart, week_chart=week_chart) return render_template('new/public/dashboard.html', info=info, recent_activity=recent_activity, day_chart=day_chart, week_chart=week_chart)
#apps = ad.get_list(session['name'])
#session.pop('appkey', None)
#if apps[0]:
# return render_template('old/public/index.html', apps=apps[1], users_signup=app.config['USERS_SIGNUP'])
#else:
# return render_template('old/public/index.html', feedback=apps[1], users_signup=app.config['USERS_SIGNUP'])
else: else:
return render_template('new/public/login.html', users_signup=app.config['USERS_SIGNUP']) return render_template('new/public/login.html', users_signup=app.config['USERS_SIGNUP'])
@app.route('/chart-update')
def chart_update():
day_chart_values = md.get_user_data_count_per_hour_period(session['name'], 11)[1]
day_chart_values = [x[0] for x in day_chart_values]
day_chart_labels = [misc.local_hour(x) for x in range(11,-1,-1)]
day_chart = [day_chart_labels, day_chart_values]
return "{}".format(day_chart)
@app.route('/register', methods=['GET', 'POST']) @app.route('/register', methods=['GET', 'POST'])
...@@ -131,13 +127,60 @@ def login(): ...@@ -131,13 +127,60 @@ def login():
return redirect(url_for('index')) return redirect(url_for('index'))
@app.route('/logout') @app.route('/logout')
def logout(): def logout():
session.clear() session.clear()
return redirect(url_for('index')) return redirect(url_for('index'))
@app.route('/applications')
def applications():
if 'name' in session:
apps = ad.get_list(session['name'])
session.pop('appkey', None)
return render_template('new/public/applications.html', apps=apps[1])
else:
return redirect(url_for('login', users_signup=app.config['USERS_SIGNUP']))
@app.route('/application/<appkey>')
def application(appkey):
if 'name' in session:
ap = list(ad.get(appkey)[1])
ap[5] = misc.skey_b64_to_hex(ap[5])
devs = dd.get_list(ap[1])[1]
return render_template('new/public/application.html', app=ap, devs=devs)
else:
return redirect(url_for('login', users_signup=app.config['USERS_SIGNUP']))
@app.route('/application/<appkey>/device/<devid>')
def app_device(appkey, devid):
if 'name' in session:
ap = ad.get(appkey)
if session['role'] == 'admin' or session['name'] == ap[1][2]:
dev = dd.get(appkey, devid)
session['devid'] = int(dev[1][1])
session['devname'] = dev[1][0]
ld = data.get_last_range(appkey, devid, [MAX_PG_ENTRIES_DATA, 0])
cnt = data.get_count(appkey, devid)
print(ld)
ltup = 'Device have not any sent data yet'
if ld[0] and ld[1][0] != []:
ltup = ld[1][0][1]
return render_template('new/public/device.html', dev=dev[1], app=ap[1], ltup=ltup, data=ld[1], total=cnt[1][0])
else:
return redirect(url_for('login'))
@app.route('/new-app') @app.route('/new-app')
def new_application(): def new_application():
...@@ -147,7 +190,6 @@ def new_application(): ...@@ -147,7 +190,6 @@ def new_application():
return redirect(url_for('index')) return redirect(url_for('index'))
@app.route('/app', methods=['GET', 'POST']) @app.route('/app', methods=['GET', 'POST'])
def app_(): def app_():
if 'name' in session: if 'name' in session:
...@@ -155,8 +197,9 @@ def app_(): ...@@ -155,8 +197,9 @@ def app_():
session['appkey'] = request.args.get('appkey') session['appkey'] = request.args.get('appkey')
ap = ad.get(session['appkey']) ap = ad.get(session['appkey'])
print(ap)
devs = dd.get_list(ap[1][1]) devs = dd.get_list(ap[1][1])
print(devs)
session['appname'] = ap[1][0] session['appname'] = ap[1][0]
if session['role'] == 'admin' or session['name'] == ap[1][2]: if session['role'] == 'admin' or session['name'] == ap[1][2]:
...@@ -529,6 +572,26 @@ def dev_data(var, dest, page): ...@@ -529,6 +572,26 @@ def dev_data(var, dest, page):
return t return t
@app.route('/application/<appkey>/device/<devid>/data/<var>/<dest>/<page>')
def new_dev_data(appkey, devid, var, dest, page):
if dest == 'graph':
last = data.get_last_hours(appkey, devid, MAX_PG_ENTRIES_GRAPH_HOURS, int(page))
arr = '[["Time", "{}"],'.format(var)
if last[0]:
for d in last[1]:
arr += '[new Date('+str(d[0])+'*1000),'+str(d[2][var])+'],'
arr += ']'
return arr
elif dest == 'table':
# for table <cnt> is in items
last = data.get_last_range(appkey, devid, [MAX_PG_ENTRIES_DATA, (int(page)-1)*MAX_PG_ENTRIES_DATA])
t = ''
if last[0]:
for d in last[1]:
t += '<tr><th>'+d[1]+'</th><th>'+str(d[2][var])+'</th></tr>'
return t
@app.route('/alerts') @app.route('/alerts')
def alerts(): def alerts():
if 'name' in session: if 'name' in session:
......
Supports Markdown
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