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" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module-library" exported="">
|
||||
<library name="lib">
|
||||
|
|
|
|||
|
|
@ -44,3 +44,80 @@ $.fn.relTimestamp = function() {
|
|||
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(){
|
||||
// Get map data
|
||||
$.getJSON("?json&action=getdata", function(json){
|
||||
$.getJSON("/data/map?action=getdata", function(json){
|
||||
// reset map
|
||||
svg.clear();
|
||||
|
||||
|
|
@ -183,7 +183,7 @@
|
|||
$.ajax({
|
||||
async: false,
|
||||
dataType: "json",
|
||||
url: "?json",
|
||||
url: "/data/map?",
|
||||
data: {
|
||||
action: "save",
|
||||
id: element.attr("device-id"),
|
||||
|
|
|
|||
|
|
@ -20,83 +20,10 @@
|
|||
<script>
|
||||
|
||||
$(function(){
|
||||
initChart("#minute-power-chart", "?json&data=minute", 5*60*1000);
|
||||
initChart("#hour-power-chart", "?json&data=hour", 60*60*1000);
|
||||
initChart("#day-power-chart", "?json&data=day", 24*60*60*1000);
|
||||
initChart("#week-power-chart", "?json&data=week", 7*24*60*60*1000);
|
||||
|
||||
createChart("#minute-power-chart", "/data/sensor?aggr=minute", 5*60*1000);
|
||||
createChart("#hour-power-chart", "/data/sensor?aggr=hour", 60*60*1000);
|
||||
createChart("#day-power-chart", "/data/sensor?aggr=day", 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>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,5 @@
|
|||
<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="panel panel-default drop-shadow">
|
||||
<div class="panel-heading">Last 24 hours</div>
|
||||
|
|
@ -29,7 +8,11 @@
|
|||
</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="panel panel-default drop-shadow">
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import zutil.io.file.FileUtil;
|
|||
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 zutil.ui.Navigation;
|
||||
|
|
@ -44,31 +43,21 @@ public abstract class HalHttpPage implements HttpPage{
|
|||
Map<String, String> request) throws IOException {
|
||||
|
||||
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));
|
||||
tmpl.set("user", User.getLocalUser(db));
|
||||
tmpl.set("showSubNav", showSubNav);
|
||||
if (showSubNav) {
|
||||
List<Navigation> breadcrumb = Navigation.getBreadcrumb(Navigation.getPagedNavigation(header));
|
||||
if (!breadcrumb.isEmpty())
|
||||
tmpl.set("subNav", breadcrumb.get(1).createPagedNavInstance(header).getSubNavs());
|
||||
}
|
||||
tmpl.set("rootNav", rootNav.createPagedNavInstance(header).getSubNavs());
|
||||
tmpl.set("userNav", userNav.createPagedNavInstance(header).getSubNavs());
|
||||
tmpl.set("alerts", HalAlertManager.getInstance().generateAlerts());
|
||||
tmpl.set("content", httpRespond(session, cookie, request));
|
||||
out.print(tmpl.compile());
|
||||
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
|
||||
tmpl.set("user", User.getLocalUser(db));
|
||||
tmpl.set("showSubNav", showSubNav);
|
||||
if (showSubNav) {
|
||||
List<Navigation> breadcrumb = Navigation.getBreadcrumb(Navigation.getPagedNavigation(header));
|
||||
if (!breadcrumb.isEmpty())
|
||||
tmpl.set("subNav", breadcrumb.get(1).createPagedNavInstance(header).getSubNavs());
|
||||
}
|
||||
tmpl.set("rootNav", rootNav.createPagedNavInstance(header).getSubNavs());
|
||||
tmpl.set("userNav", userNav.createPagedNavInstance(header).getSubNavs());
|
||||
tmpl.set("alerts", HalAlertManager.getInstance().generateAlerts());
|
||||
tmpl.set("content", httpRespond(session, cookie, request));
|
||||
out.print(tmpl.compile());
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
|
@ -95,13 +84,4 @@ public abstract class HalHttpPage implements HttpPage{
|
|||
Map<String, String> request)
|
||||
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.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.net.http.HttpHeader;
|
||||
import zutil.net.http.HttpPrintStream;
|
||||
|
|
@ -14,7 +10,6 @@ import zutil.net.http.multipart.MultipartFileField;
|
|||
import zutil.net.http.multipart.MultipartParser;
|
||||
import zutil.parser.Base64Decoder;
|
||||
import zutil.parser.Base64Encoder;
|
||||
import zutil.parser.DataNode;
|
||||
import zutil.parser.Templator;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
@ -24,7 +19,7 @@ import java.util.Map;
|
|||
/**
|
||||
* 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 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() {
|
||||
String property = HalContext.getStringProperty("map_bgimage");
|
||||
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.Map;
|
||||
|
||||
public class PCOverviewHttpPage extends HalHttpPage implements HalHttpPage.HalJsonPage {
|
||||
public class PCOverviewHttpPage extends HalHttpPage {
|
||||
private static final String TEMPLATE = "resource/web/pc_overview.tmpl";
|
||||
|
||||
public PCOverviewHttpPage() {
|
||||
|
|
@ -37,7 +37,7 @@ public class PCOverviewHttpPage extends HalHttpPage implements HalHttpPage.HalJs
|
|||
DBConnection db = HalContext.getDB();
|
||||
|
||||
List<User> users = User.getUsers(db);
|
||||
List<Sensor> sensors = getSensorList(db);
|
||||
List<Sensor> sensors = Sensor.getSensors(db);
|
||||
|
||||
Templator tmpl = new Templator(FileUtil.find(TEMPLATE));
|
||||
tmpl.set("users", User.getUsers(db));
|
||||
|
|
@ -46,87 +46,5 @@ public class PCOverviewHttpPage extends HalHttpPage implements HalHttpPage.HalJs
|
|||
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));
|
||||
tmpl.set("sensor", sensor);
|
||||
tmpl.set("history", history);
|
||||
tmpl.set("aggregation",
|
||||
AggregateDataListSqlResult.getAggregateDataForPeriod(db, sensor, AggregationPeriodLength.FIVE_MINUTES, UTCTimeUtility.DAY_IN_MS));
|
||||
return tmpl;
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue