Created Json endpoints and separated json stuff from http pages, moved chart JS to common file.
This commit is contained in:
parent
969f089a9e
commit
92f402a07b
12 changed files with 348 additions and 279 deletions
2
Hal.iml
2
Hal.iml
|
|
@ -8,7 +8,7 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/resource" type="java-resource" relativeOutputPath="resource" />
|
<sourceFolder url="file://$MODULE_DIR$/resource" type="java-resource" relativeOutputPath="resource" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="module-library" exported="">
|
<orderEntry type="module-library" exported="">
|
||||||
<library name="lib">
|
<library name="lib">
|
||||||
|
|
|
||||||
|
|
@ -44,3 +44,80 @@ $.fn.relTimestamp = function() {
|
||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////// Hal functions
|
||||||
|
|
||||||
|
////////////// Chart functions
|
||||||
|
function createChart(elementId, url, updateTime=-1){
|
||||||
|
var tickConf = {count: 20};
|
||||||
|
if (updateTime < 60*60*1000)
|
||||||
|
tickConf['format'] = '%H:%M';
|
||||||
|
else if (updateTime < 24*60*60*1000)
|
||||||
|
tickConf['format'] = '%Y-%m-%d %H:%M';
|
||||||
|
else
|
||||||
|
tickConf['format'] = '%Y-%m-%d';
|
||||||
|
|
||||||
|
|
||||||
|
var chart = c3.generate({
|
||||||
|
bindto: elementId,
|
||||||
|
data: {json: []}, // set empty data, data will be loaded later
|
||||||
|
axis : {
|
||||||
|
x : {
|
||||||
|
type : 'timeseries',
|
||||||
|
label: 'Timestamp',
|
||||||
|
tick: tickConf,
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
label: 'Power (kWh)',
|
||||||
|
min: 0,
|
||||||
|
},
|
||||||
|
y2: {
|
||||||
|
show: true,
|
||||||
|
label: 'Temperature (C)',
|
||||||
|
min: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
y: {show: true}
|
||||||
|
},
|
||||||
|
point: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
updateChart(chart, url, updateTime);;
|
||||||
|
}
|
||||||
|
function updateChart(chart, url, updateTime){
|
||||||
|
$.getJSON(url, function(json){
|
||||||
|
chart.load(getChartData(json));
|
||||||
|
});
|
||||||
|
if (updateTime > 0)
|
||||||
|
setTimeout(function(){ updateChart(chart, url, updateTime); }, updateTime);
|
||||||
|
}
|
||||||
|
function getChartData(json){
|
||||||
|
var dataXaxis = {};
|
||||||
|
var dataYaxis = {};
|
||||||
|
var data = [];
|
||||||
|
var labels = [];
|
||||||
|
json.forEach(function(sensor, i) {
|
||||||
|
var index = 'data'+i;
|
||||||
|
labels[index] = sensor.user +": "+ sensor.name;
|
||||||
|
dataXaxis[index] = 'data'+i+'x';
|
||||||
|
data.push([index+'x'].concat(sensor.timestamps));
|
||||||
|
data.push([index].concat(sensor.data));
|
||||||
|
|
||||||
|
if (sensor.type == "PowerConsumptionSensorData")
|
||||||
|
dataYaxis[index] = 'y';
|
||||||
|
else //if (sensor.type == "TemperatureSensorData")
|
||||||
|
dataYaxis[index] = 'y2';
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
xs: dataXaxis,
|
||||||
|
columns: data,
|
||||||
|
names: labels,
|
||||||
|
type: 'spline',
|
||||||
|
axes: dataYaxis,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -136,7 +136,7 @@
|
||||||
|
|
||||||
function drawMap(){
|
function drawMap(){
|
||||||
// Get map data
|
// Get map data
|
||||||
$.getJSON("?json&action=getdata", function(json){
|
$.getJSON("/data/map?action=getdata", function(json){
|
||||||
// reset map
|
// reset map
|
||||||
svg.clear();
|
svg.clear();
|
||||||
|
|
||||||
|
|
@ -183,7 +183,7 @@
|
||||||
$.ajax({
|
$.ajax({
|
||||||
async: false,
|
async: false,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
url: "?json",
|
url: "/data/map?",
|
||||||
data: {
|
data: {
|
||||||
action: "save",
|
action: "save",
|
||||||
id: element.attr("device-id"),
|
id: element.attr("device-id"),
|
||||||
|
|
|
||||||
|
|
@ -20,83 +20,10 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
$(function(){
|
$(function(){
|
||||||
initChart("#minute-power-chart", "?json&data=minute", 5*60*1000);
|
createChart("#minute-power-chart", "/data/sensor?aggr=minute", 5*60*1000);
|
||||||
initChart("#hour-power-chart", "?json&data=hour", 60*60*1000);
|
createChart("#hour-power-chart", "/data/sensor?aggr=hour", 60*60*1000);
|
||||||
initChart("#day-power-chart", "?json&data=day", 24*60*60*1000);
|
createChart("#day-power-chart", "/data/sensor?aggr=day", 24*60*60*1000);
|
||||||
initChart("#week-power-chart", "?json&data=week", 7*24*60*60*1000);
|
createChart("#week-power-chart", "/data/sensor?aggr=week", 7*24*60*60*1000);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function initChart(elementId, url, updateTime){
|
|
||||||
var tickConf = {count: 20};
|
|
||||||
if (updateTime < 60*60*1000)
|
|
||||||
tickConf['format'] = '%H:%M';
|
|
||||||
else if (updateTime < 24*60*60*1000)
|
|
||||||
tickConf['format'] = '%Y-%m-%d %H:%M';
|
|
||||||
else
|
|
||||||
tickConf['format'] = '%Y-%m-%d';
|
|
||||||
|
|
||||||
|
|
||||||
var chart = c3.generate({
|
|
||||||
bindto: elementId,
|
|
||||||
data: {json: []}, // set empty data, data will be loaded later
|
|
||||||
axis : {
|
|
||||||
x : {
|
|
||||||
type : 'timeseries',
|
|
||||||
label: 'Timestamp',
|
|
||||||
tick: tickConf,
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
label: 'Power (kWh)',
|
|
||||||
min: 0,
|
|
||||||
},
|
|
||||||
y2: {
|
|
||||||
show: true,
|
|
||||||
label: 'Temperature (C)',
|
|
||||||
min: 0,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
y: {show: true}
|
|
||||||
},
|
|
||||||
point: {
|
|
||||||
show: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
updateChart(chart, url, updateTime);;
|
|
||||||
}
|
|
||||||
function updateChart(chart, url, updateTime){
|
|
||||||
$.getJSON(url, function(json){
|
|
||||||
chart.load(getChartData(json));
|
|
||||||
});
|
|
||||||
setTimeout(function(){ updateChart(chart, url, updateTime); }, updateTime);
|
|
||||||
}
|
|
||||||
function getChartData(json){
|
|
||||||
var dataXaxis = {};
|
|
||||||
var dataYaxis = {};
|
|
||||||
var data = [];
|
|
||||||
var labels = [];
|
|
||||||
json.forEach(function(sensor, i) {
|
|
||||||
var index = 'data'+i;
|
|
||||||
labels[index] = sensor.user +": "+ sensor.name;
|
|
||||||
dataXaxis[index] = 'data'+i+'x';
|
|
||||||
data.push([index+'x'].concat(sensor.timestamps));
|
|
||||||
data.push([index].concat(sensor.data));
|
|
||||||
|
|
||||||
if (sensor.type == "PowerConsumptionSensorData")
|
|
||||||
dataYaxis[index] = 'y';
|
|
||||||
else //if (sensor.type == "TemperatureSensorData")
|
|
||||||
dataYaxis[index] = 'y2';
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
xs: dataXaxis,
|
|
||||||
columns: data,
|
|
||||||
names: labels,
|
|
||||||
type: 'spline',
|
|
||||||
axes: dataYaxis,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,5 @@
|
||||||
<h1 class="page-header">Details for <a href="#">{{sensor.getName()}}</a></h1>
|
<h1 class="page-header">Details for <a href="#">{{sensor.getName()}}</a></h1>
|
||||||
|
|
||||||
<script>
|
|
||||||
$(function(){
|
|
||||||
Morris.Line({
|
|
||||||
element: "chart",
|
|
||||||
data: [
|
|
||||||
{ x: (Date.now()-24*60*60*1000) },
|
|
||||||
{{#aggregation}}
|
|
||||||
{ x: {{.timestamp}}, data: {{.data}} },
|
|
||||||
{{/aggregation}}
|
|
||||||
{ x: Date.now() }
|
|
||||||
],
|
|
||||||
xkey: 'x',
|
|
||||||
ykeys: ['data'],
|
|
||||||
labels: ['Data'],
|
|
||||||
continuousLine: false,
|
|
||||||
resize: true,
|
|
||||||
hideHover: 'auto',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="panel panel-default drop-shadow">
|
<div class="panel panel-default drop-shadow">
|
||||||
<div class="panel-heading">Last 24 hours</div>
|
<div class="panel-heading">Last 24 hours</div>
|
||||||
|
|
@ -29,7 +8,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script>
|
||||||
|
$(function(){
|
||||||
|
createChart("#chart", "/data/sensor?aggr=minute&sensor_id={{sensor.getID()}}", 5*60*1000);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
<div class="panel panel-default drop-shadow">
|
<div class="panel panel-default drop-shadow">
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import zutil.io.file.FileUtil;
|
||||||
import zutil.net.http.HttpHeader;
|
import zutil.net.http.HttpHeader;
|
||||||
import zutil.net.http.HttpPage;
|
import zutil.net.http.HttpPage;
|
||||||
import zutil.net.http.HttpPrintStream;
|
import zutil.net.http.HttpPrintStream;
|
||||||
import zutil.parser.DataNode;
|
|
||||||
import zutil.parser.Templator;
|
import zutil.parser.Templator;
|
||||||
import zutil.parser.json.JSONWriter;
|
import zutil.parser.json.JSONWriter;
|
||||||
import zutil.ui.Navigation;
|
import zutil.ui.Navigation;
|
||||||
|
|
@ -44,15 +43,6 @@ public abstract class HalHttpPage implements HttpPage{
|
||||||
Map<String, String> request) throws IOException {
|
Map<String, String> request) throws IOException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(this instanceof HalJsonPage &&
|
|
||||||
(("application/json").equals(header.getHeader("ContentType")) ||
|
|
||||||
request.containsKey("json"))){
|
|
||||||
out.setHeader("Content-Type", "application/json");
|
|
||||||
JSONWriter writer = new JSONWriter(out);
|
|
||||||
writer.write(((HalJsonPage)this).jsonResponse(session,cookie, request));
|
|
||||||
writer.close();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
DBConnection db = HalContext.getDB();
|
DBConnection db = HalContext.getDB();
|
||||||
|
|
||||||
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
|
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
|
||||||
|
|
@ -68,7 +58,6 @@ public abstract class HalHttpPage implements HttpPage{
|
||||||
tmpl.set("alerts", HalAlertManager.getInstance().generateAlerts());
|
tmpl.set("alerts", HalAlertManager.getInstance().generateAlerts());
|
||||||
tmpl.set("content", httpRespond(session, cookie, request));
|
tmpl.set("content", httpRespond(session, cookie, request));
|
||||||
out.print(tmpl.compile());
|
out.print(tmpl.compile());
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
|
|
@ -95,13 +84,4 @@ public abstract class HalHttpPage implements HttpPage{
|
||||||
Map<String, String> request)
|
Map<String, String> request)
|
||||||
throws Exception;
|
throws Exception;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public interface HalJsonPage{
|
|
||||||
DataNode jsonResponse(
|
|
||||||
Map<String, Object> session,
|
|
||||||
Map<String, String> cookie,
|
|
||||||
Map<String, String> request)
|
|
||||||
throws Exception;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
58
src/se/hal/intf/HalJsonPage.java
Executable file
58
src/se/hal/intf/HalJsonPage.java
Executable file
|
|
@ -0,0 +1,58 @@
|
||||||
|
package se.hal.intf;
|
||||||
|
|
||||||
|
import zutil.net.http.HttpHeader;
|
||||||
|
import zutil.net.http.HttpPage;
|
||||||
|
import zutil.net.http.HttpPrintStream;
|
||||||
|
import zutil.parser.DataNode;
|
||||||
|
import zutil.parser.Templator;
|
||||||
|
import zutil.parser.json.JSONWriter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A interface defining a Hal json endpoint
|
||||||
|
*/
|
||||||
|
public abstract class HalJsonPage extends HalHttpPage{
|
||||||
|
|
||||||
|
|
||||||
|
public HalJsonPage(String id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void respond(HttpPrintStream out,
|
||||||
|
HttpHeader headers,
|
||||||
|
Map<String, Object> session,
|
||||||
|
Map<String, String> cookie,
|
||||||
|
Map<String, String> request) throws IOException {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
out.setHeader("Content-Type", "application/json");
|
||||||
|
JSONWriter writer = new JSONWriter(out);
|
||||||
|
try{
|
||||||
|
writer.write(jsonRespond(session, cookie, request));
|
||||||
|
} catch (Exception e){
|
||||||
|
DataNode root = new DataNode(DataNode.DataType.Map);
|
||||||
|
root.set("error", e.getMessage());
|
||||||
|
writer.write(root);
|
||||||
|
}
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Templator httpRespond(
|
||||||
|
Map<String, Object> session,
|
||||||
|
Map<String, String> cookie,
|
||||||
|
Map<String, String> request) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected abstract DataNode jsonRespond(
|
||||||
|
Map<String, Object> session,
|
||||||
|
Map<String, String> cookie,
|
||||||
|
Map<String, String> request) throws Exception;
|
||||||
|
}
|
||||||
|
|
@ -2,10 +2,6 @@ package se.hal.page;
|
||||||
|
|
||||||
import se.hal.HalContext;
|
import se.hal.HalContext;
|
||||||
import se.hal.intf.HalHttpPage;
|
import se.hal.intf.HalHttpPage;
|
||||||
import se.hal.struct.AbstractDevice;
|
|
||||||
import se.hal.struct.Event;
|
|
||||||
import se.hal.struct.Sensor;
|
|
||||||
import zutil.db.DBConnection;
|
|
||||||
import zutil.io.file.FileUtil;
|
import zutil.io.file.FileUtil;
|
||||||
import zutil.net.http.HttpHeader;
|
import zutil.net.http.HttpHeader;
|
||||||
import zutil.net.http.HttpPrintStream;
|
import zutil.net.http.HttpPrintStream;
|
||||||
|
|
@ -14,7 +10,6 @@ import zutil.net.http.multipart.MultipartFileField;
|
||||||
import zutil.net.http.multipart.MultipartParser;
|
import zutil.net.http.multipart.MultipartParser;
|
||||||
import zutil.parser.Base64Decoder;
|
import zutil.parser.Base64Decoder;
|
||||||
import zutil.parser.Base64Encoder;
|
import zutil.parser.Base64Encoder;
|
||||||
import zutil.parser.DataNode;
|
|
||||||
import zutil.parser.Templator;
|
import zutil.parser.Templator;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -24,7 +19,7 @@ import java.util.Map;
|
||||||
/**
|
/**
|
||||||
* Created by Ziver on 2016-06-23.
|
* Created by Ziver on 2016-06-23.
|
||||||
*/
|
*/
|
||||||
public class MapHttpPage extends HalHttpPage implements HalHttpPage.HalJsonPage {
|
public class MapHttpPage extends HalHttpPage {
|
||||||
private static final String TEMPLATE = "resource/web/map.tmpl";
|
private static final String TEMPLATE = "resource/web/map.tmpl";
|
||||||
|
|
||||||
private String bgType;
|
private String bgType;
|
||||||
|
|
@ -84,58 +79,6 @@ public class MapHttpPage extends HalHttpPage implements HalHttpPage.HalJsonPage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataNode jsonResponse(Map<String, Object> session,
|
|
||||||
Map<String, String> cookie,
|
|
||||||
Map<String, String> request) throws Exception {
|
|
||||||
DBConnection db = HalContext.getDB();
|
|
||||||
DataNode root = new DataNode(DataNode.DataType.Map);
|
|
||||||
if ("getdata".equals(request.get("action"))) {
|
|
||||||
getDeviceNode(db, root);
|
|
||||||
} else if ("save".equals(request.get("action"))) {
|
|
||||||
int id = Integer.parseInt(request.get("id"));
|
|
||||||
AbstractDevice device = null;
|
|
||||||
if ("sensor".equals(request.get("type")))
|
|
||||||
device = Sensor.getSensor(db, id);
|
|
||||||
else if ("event".equals(request.get("type")))
|
|
||||||
device = Event.getEvent(db, id);
|
|
||||||
|
|
||||||
device.setX(Float.parseFloat(request.get("x")));
|
|
||||||
device.setY(Float.parseFloat(request.get("y")));
|
|
||||||
device.save(db);
|
|
||||||
}
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void getDeviceNode(DBConnection db, DataNode root) throws SQLException {
|
|
||||||
DataNode sensorsNode = new DataNode(DataNode.DataType.List);
|
|
||||||
for (Sensor sensor : Sensor.getLocalSensors(db)) {
|
|
||||||
DataNode sensorNode = getDeviceNode(sensor);
|
|
||||||
sensorNode.set("data", ""+sensor.getDeviceData());
|
|
||||||
sensorsNode.add(sensorNode);
|
|
||||||
}
|
|
||||||
root.set("sensors", sensorsNode);
|
|
||||||
|
|
||||||
DataNode eventsNode = new DataNode(DataNode.DataType.List);
|
|
||||||
for (Event event : Event.getLocalEvents(db)) {
|
|
||||||
DataNode eventNode = getDeviceNode(event);
|
|
||||||
eventNode.set("data", ""+event.getDeviceData());
|
|
||||||
eventsNode.add(eventNode);
|
|
||||||
}
|
|
||||||
root.set("events", eventsNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataNode getDeviceNode(AbstractDevice device) {
|
|
||||||
DataNode deviceNode = new DataNode(DataNode.DataType.Map);
|
|
||||||
deviceNode.set("id", device.getId());
|
|
||||||
deviceNode.set("name", device.getName());
|
|
||||||
deviceNode.set("x", device.getX());
|
|
||||||
deviceNode.set("y", device.getY());
|
|
||||||
return deviceNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void loadBgImage() {
|
private void loadBgImage() {
|
||||||
String property = HalContext.getStringProperty("map_bgimage");
|
String property = HalContext.getStringProperty("map_bgimage");
|
||||||
if (property != null) {
|
if (property != null) {
|
||||||
|
|
|
||||||
78
src/se/hal/page/MapJsonPage.java
Executable file
78
src/se/hal/page/MapJsonPage.java
Executable file
|
|
@ -0,0 +1,78 @@
|
||||||
|
package se.hal.page;
|
||||||
|
|
||||||
|
import se.hal.HalContext;
|
||||||
|
import se.hal.intf.HalJsonPage;
|
||||||
|
import se.hal.struct.AbstractDevice;
|
||||||
|
import se.hal.struct.Event;
|
||||||
|
import se.hal.struct.Sensor;
|
||||||
|
import zutil.db.DBConnection;
|
||||||
|
import zutil.parser.DataNode;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: This json endpoint might not be needed as we have SensorJsonPage?
|
||||||
|
*
|
||||||
|
* Created by Ziver on 2016-06-23.
|
||||||
|
*/
|
||||||
|
public class MapJsonPage extends HalJsonPage {
|
||||||
|
|
||||||
|
|
||||||
|
public MapJsonPage() {
|
||||||
|
super("data/map");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataNode jsonRespond(Map<String, Object> session,
|
||||||
|
Map<String, String> cookie,
|
||||||
|
Map<String, String> request) throws Exception {
|
||||||
|
DBConnection db = HalContext.getDB();
|
||||||
|
DataNode root = new DataNode(DataNode.DataType.Map);
|
||||||
|
if ("getdata".equals(request.get("action"))) {
|
||||||
|
getDeviceNode(db, root);
|
||||||
|
} else if ("save".equals(request.get("action"))) {
|
||||||
|
int id = Integer.parseInt(request.get("id"));
|
||||||
|
AbstractDevice device = null;
|
||||||
|
if ("sensor".equals(request.get("type")))
|
||||||
|
device = Sensor.getSensor(db, id);
|
||||||
|
else if ("event".equals(request.get("type")))
|
||||||
|
device = Event.getEvent(db, id);
|
||||||
|
|
||||||
|
device.setX(Float.parseFloat(request.get("x")));
|
||||||
|
device.setY(Float.parseFloat(request.get("y")));
|
||||||
|
device.save(db);
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void getDeviceNode(DBConnection db, DataNode root) throws SQLException {
|
||||||
|
DataNode sensorsNode = new DataNode(DataNode.DataType.List);
|
||||||
|
for (Sensor sensor : Sensor.getLocalSensors(db)) {
|
||||||
|
DataNode sensorNode = getDeviceNode(sensor);
|
||||||
|
sensorNode.set("data", ""+sensor.getDeviceData());
|
||||||
|
sensorsNode.add(sensorNode);
|
||||||
|
}
|
||||||
|
root.set("sensors", sensorsNode);
|
||||||
|
|
||||||
|
DataNode eventsNode = new DataNode(DataNode.DataType.List);
|
||||||
|
for (Event event : Event.getLocalEvents(db)) {
|
||||||
|
DataNode eventNode = getDeviceNode(event);
|
||||||
|
eventNode.set("data", ""+event.getDeviceData());
|
||||||
|
eventsNode.add(eventNode);
|
||||||
|
}
|
||||||
|
root.set("events", eventsNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataNode getDeviceNode(AbstractDevice device) {
|
||||||
|
DataNode deviceNode = new DataNode(DataNode.DataType.Map);
|
||||||
|
deviceNode.set("id", device.getId());
|
||||||
|
deviceNode.set("name", device.getName());
|
||||||
|
deviceNode.set("x", device.getX());
|
||||||
|
deviceNode.set("y", device.getY());
|
||||||
|
return deviceNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class PCOverviewHttpPage extends HalHttpPage implements HalHttpPage.HalJsonPage {
|
public class PCOverviewHttpPage extends HalHttpPage {
|
||||||
private static final String TEMPLATE = "resource/web/pc_overview.tmpl";
|
private static final String TEMPLATE = "resource/web/pc_overview.tmpl";
|
||||||
|
|
||||||
public PCOverviewHttpPage() {
|
public PCOverviewHttpPage() {
|
||||||
|
|
@ -37,7 +37,7 @@ public class PCOverviewHttpPage extends HalHttpPage implements HalHttpPage.HalJs
|
||||||
DBConnection db = HalContext.getDB();
|
DBConnection db = HalContext.getDB();
|
||||||
|
|
||||||
List<User> users = User.getUsers(db);
|
List<User> users = User.getUsers(db);
|
||||||
List<Sensor> sensors = getSensorList(db);
|
List<Sensor> sensors = Sensor.getSensors(db);
|
||||||
|
|
||||||
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
|
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
|
||||||
tmpl.set("users", User.getUsers(db));
|
tmpl.set("users", User.getUsers(db));
|
||||||
|
|
@ -46,87 +46,5 @@ public class PCOverviewHttpPage extends HalHttpPage implements HalHttpPage.HalJs
|
||||||
return tmpl;
|
return tmpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public DataNode jsonResponse(
|
|
||||||
Map<String, Object> session,
|
|
||||||
Map<String, String> cookie,
|
|
||||||
Map<String, String> request) throws Exception {
|
|
||||||
DataNode root = new DataNode(DataNode.DataType.List);
|
|
||||||
|
|
||||||
DBConnection db = HalContext.getDB();
|
|
||||||
List<Sensor> sensors = getSensorList(db);
|
|
||||||
|
|
||||||
if (request.containsKey("data")) {
|
|
||||||
AggregationPeriodLength aggrType;
|
|
||||||
long aggrLength = UTCTimeUtility.INFINITY;
|
|
||||||
|
|
||||||
switch(request.get("data")){
|
|
||||||
case "minute":
|
|
||||||
default:
|
|
||||||
aggrType = AggregationPeriodLength.FIVE_MINUTES;
|
|
||||||
aggrLength = UTCTimeUtility.DAY_IN_MS;
|
|
||||||
break;
|
|
||||||
case "hour":
|
|
||||||
aggrType = AggregationPeriodLength.HOUR;
|
|
||||||
aggrLength = UTCTimeUtility.WEEK_IN_MS;
|
|
||||||
break;
|
|
||||||
case "day":
|
|
||||||
aggrType = AggregationPeriodLength.DAY;
|
|
||||||
break;
|
|
||||||
case "week":
|
|
||||||
aggrType = AggregationPeriodLength.WEEK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Sensor sensor : sensors) {
|
|
||||||
addAggregateDataToDataNode(root, sensor, aggrLength,
|
|
||||||
AggregateDataListSqlResult.getAggregateDataForPeriod(db, sensor, aggrType, aggrLength));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addAggregateDataToDataNode(DataNode root, Sensor sensor, long endTime, List<AggregateData> dataList) {
|
|
||||||
DataNode timestampNode = new DataNode(DataNode.DataType.List);
|
|
||||||
DataNode dataNode = new DataNode(DataNode.DataType.List);
|
|
||||||
// end timestamp
|
|
||||||
if (endTime != UTCTimeUtility.INFINITY){
|
|
||||||
timestampNode.add(System.currentTimeMillis() - endTime);
|
|
||||||
dataNode.add((String)null);
|
|
||||||
}
|
|
||||||
// actual data
|
|
||||||
for (AggregateDataListSqlResult.AggregateData data : dataList) {
|
|
||||||
timestampNode.add(data.timestamp);
|
|
||||||
if (data.data == null || Float.isNaN(data.data))
|
|
||||||
dataNode.add((String)null);
|
|
||||||
else
|
|
||||||
dataNode.add(data.data);
|
|
||||||
}
|
|
||||||
// start timestamp
|
|
||||||
timestampNode.add(System.currentTimeMillis());
|
|
||||||
dataNode.add((String)null);
|
|
||||||
|
|
||||||
DataNode deviceNode = new DataNode(DataNode.DataType.Map);
|
|
||||||
deviceNode.set("name", sensor.getName());
|
|
||||||
deviceNode.set("user", sensor.getUser().getUsername());
|
|
||||||
deviceNode.set("type", sensor.getDeviceConfig().getSensorDataClass().getSimpleName());
|
|
||||||
deviceNode.set("timestamps", timestampNode);
|
|
||||||
deviceNode.set("data", dataNode);
|
|
||||||
root.add(deviceNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return a List of all PowerConsumption sensors
|
|
||||||
*/
|
|
||||||
private List<Sensor> getSensorList(DBConnection db) throws SQLException {
|
|
||||||
List<Sensor> sensors = new ArrayList<>();
|
|
||||||
for (Sensor sensor : Sensor.getSensors(db)) {
|
|
||||||
if (sensor.getDeviceConfig() != null) // Show all sensors for now
|
|
||||||
// if (sensor.getDeviceConfig() != null &&
|
|
||||||
// sensor.getDeviceConfig().getSensorDataClass() == PowerConsumptionSensorData.class)
|
|
||||||
sensors.add(sensor);
|
|
||||||
}
|
|
||||||
return sensors;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
107
src/se/hal/page/SensorJsonPage.java
Executable file
107
src/se/hal/page/SensorJsonPage.java
Executable file
|
|
@ -0,0 +1,107 @@
|
||||||
|
package se.hal.page;
|
||||||
|
|
||||||
|
import se.hal.HalContext;
|
||||||
|
import se.hal.deamon.SensorDataAggregatorDaemon;
|
||||||
|
import se.hal.intf.HalJsonPage;
|
||||||
|
import se.hal.struct.Sensor;
|
||||||
|
import se.hal.util.AggregateDataListSqlResult;
|
||||||
|
import se.hal.util.UTCTimeUtility;
|
||||||
|
import zutil.db.DBConnection;
|
||||||
|
import zutil.log.LogUtil;
|
||||||
|
import zutil.parser.DataNode;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request parameters:
|
||||||
|
* aggr: Aggrigation periods. Possible values: minute,hour,day,week
|
||||||
|
*/
|
||||||
|
public class SensorJsonPage extends HalJsonPage {
|
||||||
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
|
public SensorJsonPage() {
|
||||||
|
super("data/sensor");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataNode jsonRespond(
|
||||||
|
Map<String, Object> session,
|
||||||
|
Map<String, String> cookie,
|
||||||
|
Map<String, String> request) throws Exception{
|
||||||
|
|
||||||
|
DBConnection db = HalContext.getDB();
|
||||||
|
DataNode root = new DataNode(DataNode.DataType.List);
|
||||||
|
|
||||||
|
//// Get sensors
|
||||||
|
List<Sensor> sensors = new ArrayList<>();
|
||||||
|
for (Sensor sensor : Sensor.getSensors(db)) {
|
||||||
|
if (sensor.getDeviceConfig() != null) // Show all sensors for now
|
||||||
|
// if (sensor.getDeviceConfig() != null &&
|
||||||
|
// sensor.getDeviceConfig().getSensorDataClass() == PowerConsumptionSensorData.class)
|
||||||
|
sensors.add(sensor);
|
||||||
|
}
|
||||||
|
|
||||||
|
//// Figure out aggregation period
|
||||||
|
SensorDataAggregatorDaemon.AggregationPeriodLength aggrType;
|
||||||
|
long aggrLength = UTCTimeUtility.INFINITY;
|
||||||
|
switch (request.get("aggr")) {
|
||||||
|
case "minute":
|
||||||
|
default:
|
||||||
|
aggrType = SensorDataAggregatorDaemon.AggregationPeriodLength.FIVE_MINUTES;
|
||||||
|
aggrLength = UTCTimeUtility.DAY_IN_MS;
|
||||||
|
break;
|
||||||
|
case "hour":
|
||||||
|
aggrType = SensorDataAggregatorDaemon.AggregationPeriodLength.HOUR;
|
||||||
|
aggrLength = UTCTimeUtility.WEEK_IN_MS;
|
||||||
|
break;
|
||||||
|
case "day":
|
||||||
|
aggrType = SensorDataAggregatorDaemon.AggregationPeriodLength.DAY;
|
||||||
|
break;
|
||||||
|
case "week":
|
||||||
|
aggrType = SensorDataAggregatorDaemon.AggregationPeriodLength.WEEK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate DataNode
|
||||||
|
for (Sensor sensor : sensors) {
|
||||||
|
addAggregateDataToDataNode(root, sensor, aggrLength,
|
||||||
|
AggregateDataListSqlResult.getAggregateDataForPeriod(db, sensor, aggrType, aggrLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAggregateDataToDataNode(DataNode root, Sensor sensor, long endTime, List<AggregateDataListSqlResult.AggregateData> dataList) {
|
||||||
|
DataNode timestampNode = new DataNode(DataNode.DataType.List);
|
||||||
|
DataNode dataNode = new DataNode(DataNode.DataType.List);
|
||||||
|
// end timestamp
|
||||||
|
if (endTime != UTCTimeUtility.INFINITY){
|
||||||
|
timestampNode.add(System.currentTimeMillis() - endTime);
|
||||||
|
dataNode.add((String)null);
|
||||||
|
}
|
||||||
|
// actual data
|
||||||
|
for (AggregateDataListSqlResult.AggregateData data : dataList) {
|
||||||
|
timestampNode.add(data.timestamp);
|
||||||
|
if (data.data == null || Float.isNaN(data.data))
|
||||||
|
dataNode.add((String)null);
|
||||||
|
else
|
||||||
|
dataNode.add(data.data);
|
||||||
|
}
|
||||||
|
// start timestamp
|
||||||
|
timestampNode.add(System.currentTimeMillis());
|
||||||
|
dataNode.add((String)null);
|
||||||
|
|
||||||
|
DataNode deviceNode = new DataNode(DataNode.DataType.Map);
|
||||||
|
deviceNode.set("name", sensor.getName());
|
||||||
|
deviceNode.set("user", sensor.getUser().getUsername());
|
||||||
|
deviceNode.set("type", sensor.getDeviceConfig().getSensorDataClass().getSimpleName());
|
||||||
|
deviceNode.set("timestamps", timestampNode);
|
||||||
|
deviceNode.set("data", dataNode);
|
||||||
|
root.add(deviceNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -52,8 +52,6 @@ public class SensorOverviewHttpPage extends HalHttpPage {
|
||||||
Templator tmpl = new Templator(FileUtil.find(DETAIL_TEMPLATE));
|
Templator tmpl = new Templator(FileUtil.find(DETAIL_TEMPLATE));
|
||||||
tmpl.set("sensor", sensor);
|
tmpl.set("sensor", sensor);
|
||||||
tmpl.set("history", history);
|
tmpl.set("history", history);
|
||||||
tmpl.set("aggregation",
|
|
||||||
AggregateDataListSqlResult.getAggregateDataForPeriod(db, sensor, AggregationPeriodLength.FIVE_MINUTES, UTCTimeUtility.DAY_IN_MS));
|
|
||||||
return tmpl;
|
return tmpl;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue