Refactored we pages
Former-commit-id: a64def61acdcbf63bf4792b9084a48dded9eb41a
This commit is contained in:
parent
c669cca664
commit
84fd5adb5e
12 changed files with 421 additions and 424 deletions
|
|
@ -5,6 +5,7 @@ import se.koc.hal.deamon.DataAggregatorDaemon;
|
|||
import se.koc.hal.deamon.DataSynchronizationClient;
|
||||
import se.koc.hal.deamon.DataSynchronizationDaemon;
|
||||
import se.koc.hal.deamon.HalDaemon;
|
||||
import se.koc.hal.page.HalHttpPage;
|
||||
import se.koc.hal.page.PCConfigureHttpPage;
|
||||
import se.koc.hal.page.PCHeatMapHttpPage;
|
||||
import se.koc.hal.page.PCOverviewHttpPage;
|
||||
|
|
@ -24,6 +25,7 @@ public class PowerChallenge {
|
|||
|
||||
|
||||
private static HalDaemon[] daemons;
|
||||
private static HalHttpPage[] pages;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// init logging
|
||||
|
|
@ -47,12 +49,18 @@ public class PowerChallenge {
|
|||
for(HalDaemon daemon : daemons){
|
||||
daemon.initiate(daemonTimer);
|
||||
}
|
||||
|
||||
|
||||
pages = new HalHttpPage[]{
|
||||
new PCOverviewHttpPage(),
|
||||
new PCHeatMapHttpPage(),
|
||||
new PCConfigureHttpPage()
|
||||
};
|
||||
HttpServer http = new HttpServer(HalContext.getIntegerProperty("http_port"));
|
||||
http.setDefaultPage(new HttpFilePage(FileUtil.find("web-resource/")));
|
||||
http.setPage("/", new PCOverviewHttpPage());
|
||||
http.setPage("/configure", new PCConfigureHttpPage());
|
||||
http.setPage("/heatmap", new PCHeatMapHttpPage());
|
||||
http.setPage("/", pages[0]);
|
||||
for(HalHttpPage page : pages){
|
||||
http.setPage(page.getURL(), page);
|
||||
}
|
||||
http.start();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
70
src/se/koc/hal/page/HalHttpPage.java
Executable file
70
src/se/koc/hal/page/HalHttpPage.java
Executable file
|
|
@ -0,0 +1,70 @@
|
|||
package se.koc.hal.page;
|
||||
|
||||
import se.koc.hal.HalContext;
|
||||
import se.koc.hal.struct.Sensor;
|
||||
import se.koc.hal.struct.User;
|
||||
import zutil.db.DBConnection;
|
||||
import zutil.io.file.FileUtil;
|
||||
import zutil.net.http.HttpHeaderParser;
|
||||
import zutil.net.http.HttpPage;
|
||||
import zutil.net.http.HttpPrintStream;
|
||||
import zutil.parser.Templator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Ziver on 2015-12-10.
|
||||
*/
|
||||
public abstract class HalHttpPage implements HttpPage{
|
||||
|
||||
private static ArrayList<HalHttpPage> pages = new ArrayList<>();
|
||||
|
||||
private final String name;
|
||||
private final String id;
|
||||
|
||||
public HalHttpPage(String name, String id){
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
pages.add(this);
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
public String getId(){
|
||||
return id;
|
||||
}
|
||||
public String getURL(){
|
||||
return "/" + this.id;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void respond(HttpPrintStream out, HttpHeaderParser client_info,
|
||||
Map<String, Object> session, Map<String, String> cookie,
|
||||
Map<String, String> request) throws IOException {
|
||||
|
||||
try {
|
||||
DBConnection db = HalContext.getDB();
|
||||
|
||||
Templator tmpl = new Templator(FileUtil.find("web-resource/index.tmpl"));
|
||||
tmpl.set("user", User.getLocalUser(db));
|
||||
tmpl.set("navigation", pages);
|
||||
tmpl.set("content", httpRespond(session, cookie, request));
|
||||
out.print(tmpl.compile());
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract Templator httpRespond(
|
||||
Map<String, Object> session,
|
||||
Map<String, String> cookie,
|
||||
Map<String, String> request)
|
||||
throws Exception;
|
||||
}
|
||||
|
|
@ -14,26 +14,30 @@ import zutil.net.http.HttpPage;
|
|||
import zutil.net.http.HttpPrintStream;
|
||||
import zutil.parser.Templator;
|
||||
|
||||
public class PCConfigureHttpPage implements HttpPage {
|
||||
public class PCConfigureHttpPage extends HalHttpPage {
|
||||
|
||||
public PCConfigureHttpPage() {
|
||||
super("Configuration", "config");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Templator httpRespond(
|
||||
Map<String, Object> session,
|
||||
Map<String, String> cookie,
|
||||
Map<String, String> request)
|
||||
throws Exception{
|
||||
|
||||
@Override
|
||||
public void respond(HttpPrintStream out, HttpHeaderParser client_info,
|
||||
Map<String, Object> session, Map<String, String> cookie,
|
||||
Map<String, String> request) throws IOException {
|
||||
|
||||
try {
|
||||
DBConnection db = HalContext.getDB();
|
||||
|
||||
Templator tmpl = new Templator(FileUtil.find("web-resource/configure.html"));
|
||||
Templator tmpl = new Templator(FileUtil.find("web-resource/configure.tmpl"));
|
||||
tmpl.set("user", User.getLocalUser(db));
|
||||
tmpl.set("localSensor", Sensor.getLocalSensors(db));
|
||||
tmpl.set("extUsers", User.getExternalUsers(db));
|
||||
tmpl.set("extSensor", Sensor.getExternalSensors(db));
|
||||
out.print(tmpl.compile());
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
return tmpl;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,15 +9,21 @@ import zutil.net.http.HttpPage;
|
|||
import zutil.net.http.HttpPrintStream;
|
||||
import zutil.parser.Templator;
|
||||
|
||||
public class PCHeatMapHttpPage implements HttpPage {
|
||||
public class PCHeatMapHttpPage extends HalHttpPage {
|
||||
|
||||
public PCHeatMapHttpPage() {
|
||||
super("Heatmap", "map");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void respond(HttpPrintStream out, HttpHeaderParser client_info,
|
||||
Map<String, Object> session, Map<String, String> cookie,
|
||||
Map<String, String> request) throws IOException {
|
||||
public Templator httpRespond(
|
||||
Map<String, Object> session,
|
||||
Map<String, String> cookie,
|
||||
Map<String, String> request)
|
||||
throws Exception{
|
||||
|
||||
Templator tmpl = new Templator(FileUtil.find("web-resource/heatmap.html"));
|
||||
out.print(tmpl.compile());
|
||||
Templator tmpl = new Templator(FileUtil.find("web-resource/heatmap.tmpl"));
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,75 +18,80 @@ import zutil.net.http.HttpPage;
|
|||
import zutil.net.http.HttpPrintStream;
|
||||
import zutil.parser.Templator;
|
||||
|
||||
public class PCOverviewHttpPage implements HttpPage {
|
||||
public class PCOverviewHttpPage extends HalHttpPage {
|
||||
|
||||
public PCOverviewHttpPage() {
|
||||
super("Overview", "overview");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Templator httpRespond(
|
||||
Map<String, Object> session,
|
||||
Map<String, String> cookie,
|
||||
Map<String, String> request)
|
||||
throws Exception{
|
||||
|
||||
|
||||
DBConnection db = HalContext.getDB();
|
||||
|
||||
PreparedStatement stmt = db.getPreparedStatement(
|
||||
"SELECT user.username as username,"
|
||||
+ " sensor_data_aggr.timestamp_start as timestamp_start,"
|
||||
+ " sensor_data_aggr.timestamp_end as timestamp_end,"
|
||||
+ " sensor_data_aggr.data as data,"
|
||||
+ " sensor_data_aggr.confidence as confidence,"
|
||||
+ DataAggregatorDaemon.FIVE_MINUTES_IN_MS + " as period_length"
|
||||
+ " FROM sensor_data_aggr, user, sensor"
|
||||
+ " WHERE sensor.id = sensor_data_aggr.sensor_id"
|
||||
+ " AND user.id = sensor.user_id"
|
||||
+ " AND timestamp_end-timestamp_start == ?"
|
||||
+ " AND timestamp_start > ?"
|
||||
+ " ORDER BY timestamp_start ASC");
|
||||
stmt.setLong(1, DataAggregatorDaemon.FIVE_MINUTES_IN_MS-1);
|
||||
stmt.setLong(2, (System.currentTimeMillis() - DataAggregatorDaemon.DAY_IN_MS) );
|
||||
ArrayList<PowerData> minDataList = DBConnection.exec(stmt , new SQLPowerDataBuilder());
|
||||
|
||||
stmt = db.getPreparedStatement(
|
||||
"SELECT user.username as username,"
|
||||
+ " sensor_data_aggr.timestamp_start as timestamp_start,"
|
||||
+ " sensor_data_aggr.timestamp_end as timestamp_end,"
|
||||
+ " sensor_data_aggr.data as data,"
|
||||
+ " sensor_data_aggr.confidence as confidence,"
|
||||
+ DataAggregatorDaemon.HOUR_IN_MS + " as period_length"
|
||||
+ " FROM sensor_data_aggr, user, sensor"
|
||||
+ " WHERE sensor.id = sensor_data_aggr.sensor_id"
|
||||
+ " AND user.id = sensor.user_id"
|
||||
+ " AND timestamp_end-timestamp_start == ?"
|
||||
+ " AND timestamp_start > ?"
|
||||
+ " ORDER BY timestamp_start ASC");
|
||||
stmt.setLong(1, DataAggregatorDaemon.HOUR_IN_MS-1);
|
||||
stmt.setLong(2, (System.currentTimeMillis() - 3*DataAggregatorDaemon.DAY_IN_MS) );
|
||||
ArrayList<PowerData> hourDataList = DBConnection.exec(stmt, new SQLPowerDataBuilder());
|
||||
|
||||
stmt = db.getPreparedStatement(
|
||||
"SELECT user.username as username,"
|
||||
+ " sensor_data_aggr.timestamp_start as timestamp_start,"
|
||||
+ " sensor_data_aggr.timestamp_end as timestamp_end,"
|
||||
+ " sensor_data_aggr.data as data,"
|
||||
+ " sensor_data_aggr.confidence as confidence,"
|
||||
+ DataAggregatorDaemon.DAY_IN_MS + " as period_length"
|
||||
+ " FROM sensor_data_aggr, user, sensor"
|
||||
+ " WHERE sensor.id = sensor_data_aggr.sensor_id"
|
||||
+ " AND user.id = sensor.user_id"
|
||||
+ " AND timestamp_end-timestamp_start == ?"
|
||||
+ " ORDER BY timestamp_start ASC");
|
||||
stmt.setLong(1, DataAggregatorDaemon.DAY_IN_MS-1);
|
||||
ArrayList<PowerData> dayDataList = DBConnection.exec(stmt, new SQLPowerDataBuilder());
|
||||
|
||||
|
||||
Templator tmpl = new Templator(FileUtil.find("web-resource/overview.tmpl"));
|
||||
tmpl.set("minData", minDataList);
|
||||
tmpl.set("hourData", hourDataList);
|
||||
tmpl.set("dayData", dayDataList);
|
||||
tmpl.set("username", new String[]{"Ziver", "Daniel"});
|
||||
|
||||
return tmpl;
|
||||
|
||||
@Override
|
||||
public void respond(HttpPrintStream out, HttpHeaderParser client_info, Map<String, Object> session, Map<String, String> cookie, Map<String, String> request) throws IOException {
|
||||
|
||||
try {
|
||||
DBConnection db = HalContext.getDB();
|
||||
|
||||
PreparedStatement stmt = db.getPreparedStatement(
|
||||
"SELECT user.username as username,"
|
||||
+ " sensor_data_aggr.timestamp_start as timestamp_start,"
|
||||
+ " sensor_data_aggr.timestamp_end as timestamp_end,"
|
||||
+ " sensor_data_aggr.data as data,"
|
||||
+ " sensor_data_aggr.confidence as confidence,"
|
||||
+ DataAggregatorDaemon.FIVE_MINUTES_IN_MS + " as period_length"
|
||||
+ " FROM sensor_data_aggr, user, sensor"
|
||||
+ " WHERE sensor.id = sensor_data_aggr.sensor_id"
|
||||
+ " AND user.id = sensor.user_id"
|
||||
+ " AND timestamp_end-timestamp_start == ?"
|
||||
+ " AND timestamp_start > ?"
|
||||
+ " ORDER BY timestamp_start ASC");
|
||||
stmt.setLong(1, DataAggregatorDaemon.FIVE_MINUTES_IN_MS-1);
|
||||
stmt.setLong(2, (System.currentTimeMillis() - DataAggregatorDaemon.DAY_IN_MS) );
|
||||
ArrayList<PowerData> minDataList = DBConnection.exec(stmt , new SQLPowerDataBuilder());
|
||||
|
||||
stmt = db.getPreparedStatement(
|
||||
"SELECT user.username as username,"
|
||||
+ " sensor_data_aggr.timestamp_start as timestamp_start,"
|
||||
+ " sensor_data_aggr.timestamp_end as timestamp_end,"
|
||||
+ " sensor_data_aggr.data as data,"
|
||||
+ " sensor_data_aggr.confidence as confidence,"
|
||||
+ DataAggregatorDaemon.HOUR_IN_MS + " as period_length"
|
||||
+ " FROM sensor_data_aggr, user, sensor"
|
||||
+ " WHERE sensor.id = sensor_data_aggr.sensor_id"
|
||||
+ " AND user.id = sensor.user_id"
|
||||
+ " AND timestamp_end-timestamp_start == ?"
|
||||
+ " AND timestamp_start > ?"
|
||||
+ " ORDER BY timestamp_start ASC");
|
||||
stmt.setLong(1, DataAggregatorDaemon.HOUR_IN_MS-1);
|
||||
stmt.setLong(2, (System.currentTimeMillis() - 3*DataAggregatorDaemon.DAY_IN_MS) );
|
||||
ArrayList<PowerData> hourDataList = DBConnection.exec(stmt, new SQLPowerDataBuilder());
|
||||
|
||||
stmt = db.getPreparedStatement(
|
||||
"SELECT user.username as username,"
|
||||
+ " sensor_data_aggr.timestamp_start as timestamp_start,"
|
||||
+ " sensor_data_aggr.timestamp_end as timestamp_end,"
|
||||
+ " sensor_data_aggr.data as data,"
|
||||
+ " sensor_data_aggr.confidence as confidence,"
|
||||
+ DataAggregatorDaemon.DAY_IN_MS + " as period_length"
|
||||
+ " FROM sensor_data_aggr, user, sensor"
|
||||
+ " WHERE sensor.id = sensor_data_aggr.sensor_id"
|
||||
+ " AND user.id = sensor.user_id"
|
||||
+ " AND timestamp_end-timestamp_start == ?"
|
||||
+ " ORDER BY timestamp_start ASC");
|
||||
stmt.setLong(1, DataAggregatorDaemon.DAY_IN_MS-1);
|
||||
ArrayList<PowerData> dayDataList = DBConnection.exec(stmt, new SQLPowerDataBuilder());
|
||||
|
||||
|
||||
Templator tmpl = new Templator(FileUtil.find("web-resource/index.html"));
|
||||
tmpl.set("minData", minDataList);
|
||||
tmpl.set("hourData", hourDataList);
|
||||
tmpl.set("dayData", dayDataList);
|
||||
tmpl.set("username", new String[]{"Ziver", "Daniel"});
|
||||
|
||||
out.print(tmpl.compile());
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PowerData{
|
||||
|
|
|
|||
|
|
@ -1,136 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
|
||||
<title>Power;Challenge</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="css/main.css" rel="stylesheet">
|
||||
|
||||
<script src="js/jquery-1.11.3.min.js"></script>
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="#">Power;Challenge</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="#">Ziver</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-md-2 sidebar">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li><a href="/">Overview</a></li>
|
||||
<li><a href="heatmap">Heat Map</a></li>
|
||||
<li><a href="#">Statistics</a></li>
|
||||
<li class="active"><a href="configure">Configuration <span class="sr-only">(current)</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
|
||||
<h1 class="page-header">Configuration</h1>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Profile Information</div>
|
||||
<div class="panel-body">
|
||||
<form>
|
||||
<hidden id="id" value="{{user.getId()}}">
|
||||
<div class="form-group col-md-4">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" class="form-control" id="username" value="{{user.username}}">
|
||||
</div>
|
||||
<div class="form-group col-md-8">
|
||||
<label for="address">Address</label>
|
||||
<input type="text" class="form-control" id="username" value="{{user.address}}">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<button type="submit" class="btn btn-default">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Local Sensors</div>
|
||||
<div class="panel-body">
|
||||
This is a local list of sensors connected to this node.
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Configuration</th>
|
||||
</tr>
|
||||
{{#localSensor}}
|
||||
<tr>
|
||||
<td>{{.name}}</td>
|
||||
<td>{{.type}}</td>
|
||||
<td>{{.config}}</td>
|
||||
</tr>
|
||||
{{/localSensor}}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">External Users</div>
|
||||
<div class="panel-body">
|
||||
Add or remove users that you want to synchronized data with.
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<th>Address</th>
|
||||
<th>Hostname</th>
|
||||
<th>Port</th>
|
||||
</tr>
|
||||
{{#extUsers}}
|
||||
<tr>
|
||||
<td>{{.username}}</td>
|
||||
<td>{{.address}}</td>
|
||||
<td>{{.hostname}}</td>
|
||||
<td>{{.port}}</td>
|
||||
</tr>
|
||||
{{/extUsers}}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">External Sensors</div>
|
||||
<div class="panel-body">
|
||||
This is a read only list of synchronized sensors from external users.
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Configuration</th>
|
||||
</tr>
|
||||
{{#extSensor}}
|
||||
<tr>
|
||||
<td>{{.name}}</td>
|
||||
<td>{{.type}}</td>
|
||||
<td>{{.config}}</td>
|
||||
</tr>
|
||||
{{/extSensor}}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
86
web-resource/configure.tmpl
Executable file
86
web-resource/configure.tmpl
Executable file
|
|
@ -0,0 +1,86 @@
|
|||
<h1 class="page-header">Configuration</h1>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Profile Information</div>
|
||||
<div class="panel-body">
|
||||
<form>
|
||||
<hidden id="id" value="{{user.getId()}}">
|
||||
<div class="form-group col-md-4">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" class="form-control" id="username" value="{{user.username}}">
|
||||
</div>
|
||||
<div class="form-group col-md-8">
|
||||
<label for="address">Address</label>
|
||||
<input type="text" class="form-control" id="address" value="{{user.address}}">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<button type="submit" class="btn btn-default">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Local Sensors</div>
|
||||
<div class="panel-body">
|
||||
This is a local list of sensors connected to this node.
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Configuration</th>
|
||||
</tr>
|
||||
{{#localSensor}}
|
||||
<tr>
|
||||
<td>{{.name}}</td>
|
||||
<td>{{.type}}</td>
|
||||
<td>{{.config}}</td>
|
||||
</tr>
|
||||
{{/localSensor}}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">External Users</div>
|
||||
<div class="panel-body">
|
||||
Add or remove users that you want to synchronized data with.
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<th>Address</th>
|
||||
<th>Hostname</th>
|
||||
<th>Port</th>
|
||||
</tr>
|
||||
{{#extUsers}}
|
||||
<tr>
|
||||
<td>{{.username}}</td>
|
||||
<td>{{.address}}</td>
|
||||
<td>{{.hostname}}</td>
|
||||
<td>{{.port}}</td>
|
||||
</tr>
|
||||
{{/extUsers}}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">External Sensors</div>
|
||||
<div class="panel-body">
|
||||
This is a read only list of synchronized sensors from external users.
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Configuration</th>
|
||||
</tr>
|
||||
{{#extSensor}}
|
||||
<tr>
|
||||
<td>{{.name}}</td>
|
||||
<td>{{.type}}</td>
|
||||
<td>{{.config}}</td>
|
||||
</tr>
|
||||
{{/extSensor}}
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
|
||||
<title>Power;Challenge</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="css/main.css" rel="stylesheet">
|
||||
|
||||
<script src="js/jquery-1.11.3.min.js"></script>
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
<script src="http://maps.googleapis.com/maps/api/js"></script>
|
||||
|
||||
<script>
|
||||
function initialize() {
|
||||
var mapProp = {
|
||||
center:new google.maps.LatLng(59.329323,18.068581),
|
||||
zoom:12,
|
||||
mapTypeId:google.maps.MapTypeId.ROADMAP
|
||||
};
|
||||
var map=new google.maps.Map(document.getElementById("googleMap"),mapProp);
|
||||
|
||||
var home = new google.maps.Circle({
|
||||
center: {lat: 59.365954, lng: 17.975351},
|
||||
radius:2000,
|
||||
strokeColor:"#00FF00",
|
||||
strokeOpacity:0.8,
|
||||
strokeWeight:2,
|
||||
fillColor:"#00FF00",
|
||||
fillOpacity:0.4,
|
||||
map: map
|
||||
});
|
||||
|
||||
var external = new google.maps.Circle({
|
||||
center: {lat: 59.275638, lng: 18.024362},
|
||||
radius:2000,
|
||||
strokeColor:"#FF0000",
|
||||
strokeOpacity:0.8,
|
||||
strokeWeight:2,
|
||||
fillColor:"#FF0000",
|
||||
fillOpacity:0.4,
|
||||
map: map
|
||||
});
|
||||
}
|
||||
google.maps.event.addDomListener(window, 'load', initialize);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="#">Power;Challenge</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="#">Ziver</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-md-2 sidebar">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li><a href="/">Overview</a></li>
|
||||
<li class="active"><a href="heatmap">Heat Map <span class="sr-only">(current)</span></a></li>
|
||||
<li><a href="#">Statistics</a></li>
|
||||
<li><a href="configure">Configuration</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
|
||||
<h1 class="page-header">Heat Map</h1>
|
||||
|
||||
<div id="googleMap" style="width: 95%;height: 800px;"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
39
web-resource/heatmap.tmpl
Executable file
39
web-resource/heatmap.tmpl
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
<h1 class="page-header">Heat Map</h1>
|
||||
|
||||
<div id="googleMap" style="width: 95%;height: 800px;"></div>
|
||||
|
||||
|
||||
<script src="http://maps.googleapis.com/maps/api/js"></script>
|
||||
<script>
|
||||
function initialize() {
|
||||
var mapProp = {
|
||||
center:new google.maps.LatLng(59.329323,18.068581),
|
||||
zoom:12,
|
||||
mapTypeId:google.maps.MapTypeId.ROADMAP
|
||||
};
|
||||
var map=new google.maps.Map(document.getElementById("googleMap"),mapProp);
|
||||
|
||||
var home = new google.maps.Circle({
|
||||
center: {lat: 59.365954, lng: 17.975351},
|
||||
radius:2000,
|
||||
strokeColor:"#00FF00",
|
||||
strokeOpacity:0.8,
|
||||
strokeWeight:2,
|
||||
fillColor:"#00FF00",
|
||||
fillOpacity:0.4,
|
||||
map: map
|
||||
});
|
||||
|
||||
var external = new google.maps.Circle({
|
||||
center: {lat: 59.275638, lng: 18.024362},
|
||||
radius:2000,
|
||||
strokeColor:"#FF0000",
|
||||
strokeOpacity:0.8,
|
||||
strokeWeight:2,
|
||||
fillColor:"#FF0000",
|
||||
fillOpacity:0.4,
|
||||
map: map
|
||||
});
|
||||
}
|
||||
google.maps.event.addDomListener(window, 'load', initialize);
|
||||
</script>
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
|
||||
<title>Power;Challenge</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="css/main.css" rel="stylesheet">
|
||||
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
|
||||
<script src="js/jquery-1.11.3.min.js"></script>
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
<script src="js/morris.min.js"></script>
|
||||
|
||||
<script>
|
||||
$(function(){
|
||||
chartData("min-power-chart",
|
||||
[
|
||||
{ y: (Date.now()-24*60*60*1000) },
|
||||
{{#minData}}
|
||||
{ y: {{.timestamp}}, {{.username}}: {{.data}} },
|
||||
{{/minData}}
|
||||
{ y: Date.now() }
|
||||
]
|
||||
);
|
||||
chartData("hour-power-chart",
|
||||
[
|
||||
{ y: (Date.now()-3*24*60*60*1000) },
|
||||
{{#hourData}}
|
||||
{ y: {{.timestamp}}, {{.username}}: {{.data}} },
|
||||
{{/hourData}}
|
||||
{ y: (Date.now()-24*60*60*1000) }
|
||||
]
|
||||
);
|
||||
chartData("day-power-chart",
|
||||
[{{#dayData}}
|
||||
{ y: {{.timestamp}}, {{.username}}: {{.data}} },
|
||||
{{/dayData}}
|
||||
{ y: (Date.now()-3*24*60*60*1000) }
|
||||
]
|
||||
);
|
||||
});
|
||||
var userArray = [ {{#username}} '{{.}}', {{/username}} ];
|
||||
function chartData(elementId, data){
|
||||
Morris.Line({
|
||||
element: elementId,
|
||||
data: data,
|
||||
xkey: 'y',
|
||||
ykeys: userArray,
|
||||
labels: userArray,
|
||||
continuousLine: false,
|
||||
pointSize: 1,
|
||||
postUnits: 'kWh',
|
||||
resize: true
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="#">Power;Challenge</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="#">Ziver</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-md-2 sidebar">
|
||||
<ul class="nav nav-sidebar">
|
||||
<li class="active"><a href="/">Overview <span class="sr-only">(current)</span></a></li>
|
||||
<li><a href="heatmap">Heat Map</a></li>
|
||||
<li><a href="#">Statistics</a></li>
|
||||
<li><a href="configure">Configuration</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
|
||||
<h1 class="page-header">Overview</h1>
|
||||
|
||||
<div class="row placeholders">
|
||||
<H1>Last 24 hours (kWh/5min)</H1>
|
||||
<div id="min-power-chart" style="height:450px;"></div>
|
||||
</div>
|
||||
<div class="row placeholders">
|
||||
<H1>Previous two days (kWh/h)</H1>
|
||||
<div id="hour-power-chart" style="height:450px;"></div>
|
||||
</div>
|
||||
<div class="row placeholders">
|
||||
<H1>Long term (kWh/day)</H1>
|
||||
<div id="day-power-chart" style="height:450px;"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
51
web-resource/index.tmpl
Executable file
51
web-resource/index.tmpl
Executable file
|
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
|
||||
<title>Power;Challenge</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="css/main.css" rel="stylesheet">
|
||||
|
||||
<script src="js/jquery-1.11.3.min.js"></script>
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="#">Power;Challenge</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="#">{{user.username}}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-md-2 sidebar">
|
||||
<ul class="nav nav-sidebar">
|
||||
<!-- <li class="active"><a href="/">Overview</a></li> -->
|
||||
{{#navigation}}
|
||||
<li><a href="{{.getURL()}}">{{.getName()}}</a></li>
|
||||
{{/navigation}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
|
||||
{{content}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
63
web-resource/overview.tmpl
Executable file
63
web-resource/overview.tmpl
Executable file
|
|
@ -0,0 +1,63 @@
|
|||
<h1 class="page-header">Overview</h1>
|
||||
|
||||
<div class="row placeholders">
|
||||
<H1>Last 24 hours (kWh/5min)</H1>
|
||||
<div id="min-power-chart" style="height:450px;"></div>
|
||||
</div>
|
||||
<div class="row placeholders">
|
||||
<H1>Previous two days (kWh/h)</H1>
|
||||
<div id="hour-power-chart" style="height:450px;"></div>
|
||||
</div>
|
||||
<div class="row placeholders">
|
||||
<H1>Long term (kWh/day)</H1>
|
||||
<div id="day-power-chart" style="height:450px;"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="js/raphael-min.js"></script>
|
||||
<script src="js/morris.min.js"></script>
|
||||
|
||||
<script>
|
||||
$(function(){
|
||||
chartData("min-power-chart",
|
||||
[
|
||||
{ y: (Date.now()-24*60*60*1000) },
|
||||
{{#minData}}
|
||||
{ y: {{.timestamp}}, {{.username}}: {{.data}} },
|
||||
{{/minData}}
|
||||
{ y: Date.now() }
|
||||
]
|
||||
);
|
||||
chartData("hour-power-chart",
|
||||
[
|
||||
{ y: (Date.now()-3*24*60*60*1000) },
|
||||
{{#hourData}}
|
||||
{ y: {{.timestamp}}, {{.username}}: {{.data}} },
|
||||
{{/hourData}}
|
||||
{ y: (Date.now()-24*60*60*1000) }
|
||||
]
|
||||
);
|
||||
chartData("day-power-chart",
|
||||
[{{#dayData}}
|
||||
{ y: {{.timestamp}}, {{.username}}: {{.data}} },
|
||||
{{/dayData}}
|
||||
{ y: (Date.now()-3*24*60*60*1000) }
|
||||
]
|
||||
);
|
||||
});
|
||||
var userArray = [ {{#username}} '{{.}}', {{/username}} ];
|
||||
function chartData(elementId, data){
|
||||
Morris.Line({
|
||||
element: elementId,
|
||||
data: data,
|
||||
xkey: 'y',
|
||||
ykeys: userArray,
|
||||
labels: userArray,
|
||||
continuousLine: false,
|
||||
pointSize: 1,
|
||||
postUnits: 'kWh',
|
||||
resize: true
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue