Adding new Android sense analytic view

revert-dabc3590
lasantha 8 years ago
parent 71a979ef0b
commit bb975d26f6

@ -1,5 +1,5 @@
{{! {{!
Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
WSO2 Inc. licenses this file to you under the Apache License, WSO2 Inc. licenses this file to you under the Apache License,
Version 2.0 (the "License"); you may not use this file except Version 2.0 (the "License"); you may not use this file except
@ -15,118 +15,39 @@
specific language governing permissions and limitations specific language governing permissions and limitations
under the License. under the License.
}} }}
<span id="android_sense-details" data-devices="{{devices}}" data-devicename="{{device.name}}"
data-deviceid="{{device.deviceIdentifier}}"
data-appcontext="{{@app.context}}"></span>
<div id="android_sense-div-chart" data-backend-api-url= {{backendApiUrl}}>
<div class="chartWrapper" id="chartWrapper-battery">
<span id="span-title">Battery</span>
<div id="y_axis-battery" class="custom_y_axis"></div>
<div class="legend_container">
<div id="smoother-battery" title="Smoothing"></div>
<div id="legend-battery"></div>
</div>
<div id="chart-battery" class="custom_rickshaw_graph" ></div>
<div id="x_axis-battery" class="custom_x_axis"></div>
<div id="slider-battery" class="custom_slider"></div>
</div>
<div class="chartWrapper" id="chartWrapper-light">
<span id="span-title">Light</span>
<div id="y_axis-light" class="custom_y_axis"></div>
<div class="legend_container">
<div id="smoother-light" title="Smoothing"></div>
<div id="legend-light"></div>
</div>
<div id="chart-light" class="custom_rickshaw_graph" ></div>
<div id="x_axis-light" class="custom_x_axis"></div>
<div id="slider-light" class="custom_slider"></div>
</div>
<div class="chartWrapper" id="chartWrapper-pressure">
<span id="span-title">Pressure</span>
<div id="y_axis-pressure" class="custom_y_axis"></div>
<div class="legend_container">
<div id="smoother-pressure" title="Smoothing"></div>
<div id="legend-pressure"></div>
</div>
<div id="chart-pressure" class="custom_rickshaw_graph" ></div>
<div id="x_axis-pressure" class="custom_x_axis"></div>
<div id="slider-pressure" class="custom_slider"></div>
</div>
<div class="chartWrapper" id="chartWrapper-proximity">
<span id="span-title">Proximity</span>
<div id="y_axis-proximity" class="custom_y_axis"></div>
<div class="legend_container">
<div id="smoother-proximity" title="Smoothing"></div>
<div id="legend-proximity"></div>
</div>
<div id="chart-proximity" class="custom_rickshaw_graph" ></div>
<div id="x_axis-proximity" class="custom_x_axis"></div>
<div id="slider-proximity" class="custom_slider"></div>
</div>
<div class="chartWrapper" id="chartWrapper-accelerometer"> {{#zone "topCss"}}
<span id="span-title">Acceleromter</span> {{css "css/custom.css"}}
<div id="y_axis-accelerometer" class="custom_y_axis"></div> {{/zone}}
<div class="legend_container">
<div id="smoother-accelerometer" title="Smoothing"></div>
<div id="legend-accelerometer"></div>
</div>
<div id="chart-accelerometer" class="custom_rickshaw_graph" ></div>
<div id="x_axis-accelerometer" class="custom_x_axis"></div>
<div id="slider-accelerometer" class="custom_slider"></div>
</div>
<div class="chartWrapper" id="chartWrapper-magnetic">
<span id="span-title">Magnetic</span>
<div id="y_axis-magnetic" class="custom_y_axis"></div>
<div class="legend_container">
<div id="smoother-magnetic" title="Smoothing"></div>
<div id="legend-magnetic"></div>
</div>
<div id="chart-magnetic" class="custom_rickshaw_graph" ></div>
<div id="x_axis-magnetic" class="custom_x_axis"></div>
<div id="slider-magnetic" class="custom_slider"></div>
</div>
<div class="chartWrapper" id="chartWrapper-rotation"> <span id="android_sense-details" data-devicename="{{device.name}}" data-deviceid="{{device.deviceIdentifier}}"
<span id="span-title">Rotation</span> data-appcontext="{{@app.context}}"></span>
<div id="y_axis-rotation" class="custom_y_axis"></div> <div id="android_sense-div-chart" data-backend-api-url= "{{backendApiUrl}}">
<div class="legend_container"> {{#each graphData}}
<div id="smoother-rotation" title="Smoothing"></div> {{#each this}}
<div id="legend-rotation"></div> <div class="chartWrapper " id="chartWrapper-{{this}}">
</div> <div class="custom_y_axis">
<div id="chart-rotation" class="custom_rickshaw_graph" ></div> <div class="y-axis-label">{{this}}</div>
<div id="x_axis-rotation" class="custom_x_axis"></div> <div id="y-axis-{{this}}"></div>
<div id="slider-rotation" class="custom_slider"></div>
</div> </div>
<div class="chartWrapper" id="chartWrapper-gyroscope">
<span id="span-title">Gyroscope</span>
<div id="y_axis-gyroscope" class="custom_y_axis"></div>
<div class="legend_container"> <div class="legend_container">
<div id="smoother-gyroscope" title="Smoothing"></div> <div id="smoother-{{this}}" title="Smoothing"></div>
<div id="legend-gyroscope"></div> <div id="legend-{{this}}"></div>
<div class="chart-type-toggle">
<input type="radio" name="offset" value="lines" class="{{this}}" >
<label class="lines" for="lines">lines</label><br>
<input type="radio" name="offset" value="zero" class="{{this}}" checked>
<label class="stack" for="stack">stack</label>
</div> </div>
<div id="chart-gyroscope" class="custom_rickshaw_graph" ></div>
<div id="x_axis-gyroscope" class="custom_x_axis"></div>
<div id="slider-gyroscope" class="custom_slider"></div>
</div> </div>
<div id="chart-{{this}}" class="custom_rickshaw_graph"></div>
<div class="chartWrapper" id="chartWrapper-gravity"> <div class="custom_x_axis">
<span id="span-title">Gravity</span> <div class="x-axis-label">Time</div>
<div id="y_axis-gravity" class="custom_y_axis"></div> <div id="x_axis-{{this}}"></div>
<div class="legend_container">
<div id="smoother-gravity" title="Smoothing"></div>
<div id="legend-gravity"></div>
</div> </div>
<div id="chart-gravity" class="custom_rickshaw_graph" ></div>
<div id="x_axis-gravity" class="custom_x_axis"></div>
<div id="slider-gravity" class="custom_slider"></div>
</div> </div>
{{/each}}
{{/each}}
</div> </div>
{{#zone "bottomJs"}} {{#zone "bottomJs"}}

@ -17,9 +17,26 @@
*/ */
function onRequest(context) { function onRequest(context) {
var log = new Log("analytics-view.js");
var user = context.user; var user = context.user;
var graphData={};
var graphType = request.getParameter("graphType");
var graph =request.getParameter("sensor");
graphData[graphType]=[graph];
var deviceId = request.getParameter("deviceId"); var deviceId = request.getParameter("deviceId");
var deviceType = context.uriParams.deviceType;
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
var device = deviceModule.viewDevice(deviceType, deviceId);
if (device && device.status != "error") {
return {
"device": device.content,
"backendApiUrl": "/android_sense/stats/" + deviceId + "/sensors/",
"graphData":graphData
};
} else {
response.sendError(404, "Device Id " + deviceId + " of type " + deviceType + " cannot be found!");
exit();
}
//Redirects to the portal app as we do not use the old analytics view.
response.sendRedirect(context.app.conf["portalURL"] + "/portal/dashboards/android-iot/sensors?owner=" + user.username + "&deviceId=" + deviceId);
} }

@ -0,0 +1,56 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
.chartWrapper {
position: relative;
margin-bottom: 40px;
}
.chart-type-toggle {
background: #737373;
padding: 40px;
font-family: Arial;
font-size: 12px;
color: white;
display: inline-block;
padding: 5px 12px;
margin-top: 5px;
border-radius: 2px;
position: relative;
float: right;
white-space: nowrap;
}
.y-axis-label {
position: absolute;
top: -40px;
font-weight: 400;
text-transform: capitalize;
}
.x-axis-label {
position: absolute;
right: 0;
bottom: 40px;
font-weight: 400;
text-transform: capitalize;
}
#dateRangePickerContainer{
display: none;
}

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* *
* WSO2 Inc. licenses this file to you under the Apache License, * WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except * Version 2.0 (the "License"); you may not use this file except
@ -16,34 +16,40 @@
* under the License. * under the License.
*/ */
var palette = new Rickshaw.Color.Palette({scheme: "classic9"}); var palette = new Rickshaw.Color.Palette({scheme: "munin"});
var graphMap = {}; var graphMap = {};
function drawGraph_android_sense(from, to) { function drawGraph_android_sense(from, to) {
from = new Date();
from.setDate(from.getDate()-1);
from.setHours(0,0,0,0);
from = parseInt(from.getTime());
to = parseInt(new Date().getTime());
var devices = $("#android_sense-details").data("devices"); var devices = $("#android_sense-details").data("devices");
var tzOffset = new Date().getTimezoneOffset() * 60; var tzOffset = new Date().getTimezoneOffset() * 60;
var streamIndex = 0; var streamIndex = 0;
var streams = ["battery", "light", "pressure", "proximity", "accelerometer", "magnetic", "rotation", "gyroscope", "gravity"]; var streams = ["battery", "light", "pressure", "proximity", "magnetic", "rotation", "gyroscope", "gravity", "accelerometer"];
var graphType = $(".y-axis-label").text();
populateGraph(); populateGraph();
function populateGraph() { function populateGraph() {
if (streamIndex < 4) { if (streams.indexOf(graphType) < 4) {
retrieveDataAndDrawLineGraph(streams[streamIndex], from, to); retrieveDataAndDrawGraph(graphType, from, to);
} else if (streamIndex < 9) { } else if (streams.indexOf(graphType) < 9) {
retrieveDataAndDrawMultiLineGraph(streams[streamIndex], from, to); retrieveDataAndDrawMultiLineGraph(graphType, from, to);
} }
streamIndex++;
} }
function clearContent(type) { function clearContent(type) {
$("#y_axis-" + type).html(""); $("#y-axis-" + type).html("");
$("#smoother-" + type).html(""); $("#smoother-" + type).html("");
$("#legend-" + type).html(""); $("#legend-" + type).html("");
$("#chart-" + type).html(""); $("#chart-" + type).html("");
$("#x_axis-" + type).html(""); $("#x_axis-" + type).html("");
$("#slider-" + type).html("");
} }
function initGraph(type, isMultilined) { function initGraph(type, isMultilined) {
@ -52,17 +58,14 @@ function drawGraph_android_sense(from, to) {
} }
var chartWrapperElmId = "#android_sense-div-chart"; var chartWrapperElmId = "#android_sense-div-chart";
var graphWidth = $(chartWrapperElmId).width() - 50; var graphWidth = $(chartWrapperElmId).width() - 100;
var graphConfig = { var graphConfig = {
element: document.getElementById("chart-" + type), element: document.getElementById("chart-" + type),
width: graphWidth, width: graphWidth,
height: 400, height: 400,
strokeWidth: 2, strokeWidth: 2,
renderer: 'line',
interpolation: "linear", interpolation: "linear",
unstack: true,
stack: false,
xScale: d3.time.scale(), xScale: d3.time.scale(),
padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0.2}, padding: {top: 0.2, left: 0.02, right: 0.02, bottom: 0.2},
series: [] series: []
@ -89,7 +92,7 @@ function drawGraph_android_sense(from, to) {
x: parseInt(new Date().getTime() / 1000), x: parseInt(new Date().getTime() / 1000),
y: 0 y: 0
}], }],
'name': "x" 'name': "x " + type
}, },
{ {
'color': palette.color(), 'color': palette.color(),
@ -97,7 +100,7 @@ function drawGraph_android_sense(from, to) {
x: parseInt(new Date().getTime() / 1000), x: parseInt(new Date().getTime() / 1000),
y: 0 y: 0
}], }],
'name': "y" 'name': "y " + type
}, },
{ {
'color': palette.color(), 'color': palette.color(),
@ -105,7 +108,7 @@ function drawGraph_android_sense(from, to) {
x: parseInt(new Date().getTime() / 1000), x: parseInt(new Date().getTime() / 1000),
y: 0 y: 0
}], }],
'name': "z" 'name': "z " + type
} }
); );
} else { } else {
@ -116,13 +119,12 @@ function drawGraph_android_sense(from, to) {
x: parseInt(new Date().getTime() / 1000), x: parseInt(new Date().getTime() / 1000),
y: 0 y: 0
}], }],
'name': $("#android_sense-details").data("devicename") 'name': type
}); });
} }
} }
var graph = new Rickshaw.Graph(graphConfig); var graph = new Rickshaw.Graph(graphConfig);
graph.render();
var xAxis = new Rickshaw.Graph.Axis.Time({ var xAxis = new Rickshaw.Graph.Axis.Time({
graph: graph graph: graph
@ -132,17 +134,15 @@ function drawGraph_android_sense(from, to) {
var yAxis = new Rickshaw.Graph.Axis.Y({ var yAxis = new Rickshaw.Graph.Axis.Y({
graph: graph, graph: graph,
orientation: 'left', orientation: 'left',
element: document.getElementById("y_axis-" + type),
width: 40, width: 40,
height: 410 height: 410,
}); tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
yAxis.render(); element: document.getElementById("y-axis-" + type)
var slider = new Rickshaw.Graph.RangeSlider.Preview({
graph: graph,
element: document.getElementById("slider-" + type)
}); });
yAxis.render();
var legend = new Rickshaw.Graph.Legend({ var legend = new Rickshaw.Graph.Legend({
graph: graph, graph: graph,
element: document.getElementById("legend-" + type) element: document.getElementById("legend-" + type)
@ -159,34 +159,35 @@ function drawGraph_android_sense(from, to) {
} }
}); });
var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({ new Rickshaw.Graph.Behavior.Series.Toggle({
graph: graph, graph: graph,
legend: legend legend: legend
}); });
var order = new Rickshaw.Graph.Behavior.Series.Order({ new Rickshaw.Graph.Behavior.Series.Order({
graph: graph, graph: graph,
legend: legend legend: legend
}); });
var highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({ new Rickshaw.Graph.Behavior.Series.Highlight({
graph: graph, graph: graph,
legend: legend legend: legend
}); });
graph.render();
graphMap[type] = {}; graphMap[type] = {};
graphMap[type].graph = graph; graphMap[type].graph = graph;
graphMap[type].config = graphConfig; graphMap[type].config = graphConfig;
return graphMap[type]; return graphMap[type];
} }
function retrieveDataAndDrawLineGraph(type, from, to) { function retrieveDataAndDrawGraph(type, from, to) {
clearContent(type); clearContent(type);
var graphObj = initGraph(type, false); var graphObj = initGraph(type, false);
var graph = graphObj.graph; var graph = graphObj.graph;
var graphConfig = graphObj.config; var graphConfig = graphObj.config;
var deviceIndex = 0; var deviceIndex = 0;
if (devices) { if (devices) {
@ -195,12 +196,10 @@ function drawGraph_android_sense(from, to) {
var backendApiUrl = $("#android_sense-div-chart").data("backend-api-url") + type + "?from=" + from + "&to=" + to; var backendApiUrl = $("#android_sense-div-chart").data("backend-api-url") + type + "?from=" + from + "&to=" + to;
var successCallback = function (data) { var successCallback = function (data) {
if (data) { if (data) {
drawLineGraph(JSON.parse(data)); drawGraph(JSON.parse(data));
} }
populateGraph();
}; };
invokerUtil.get(backendApiUrl, successCallback, function (message) { invokerUtil.get(backendApiUrl, successCallback, function (message) {
populateGraph();
}); });
} }
@ -212,7 +211,7 @@ function drawGraph_android_sense(from, to) {
+ "/sensors/" + type + "?from=" + from + "&to=" + to; + "/sensors/" + type + "?from=" + from + "&to=" + to;
var successCallback = function (data) { var successCallback = function (data) {
if (data) { if (data) {
drawLineGraph(JSON.parse(data)); drawGraph(JSON.parse(data));
} }
deviceIndex++; deviceIndex++;
getData(); getData();
@ -223,21 +222,21 @@ function drawGraph_android_sense(from, to) {
}); });
} }
function drawLineGraph(data) { function drawGraph(data) {
if (data.length === 0 || data.length === undefined) { if (data.length === 0 || data.length === undefined) {
return; return;
} }
var chartData = []; var chartData = [];
console.log(data.length);
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
chartData.push( chartData.push(
{ {
x: parseInt(data[i].values.time) - tzOffset, x: parseInt((data[i].values.meta_timestamp - tzOffset)/1000),
y: parseInt(getFieldData(data[i], type)) y: parseInt(getFieldData(data[i], type))
} }
); );
} }
graphConfig.series[deviceIndex].data = chartData; graphConfig.series[deviceIndex].data = chartData;
graph.update(); graph.update();
} }
@ -258,12 +257,10 @@ function drawGraph_android_sense(from, to) {
var backendApiUrl = $("#android_sense-div-chart").data("backend-api-url") + type + "?from=" + from + "&to=" + to; var backendApiUrl = $("#android_sense-div-chart").data("backend-api-url") + type + "?from=" + from + "&to=" + to;
var successCallback = function (data) { var successCallback = function (data) {
if (data) { if (data) {
drawLineGraph(JSON.parse(data)); drawGraph(JSON.parse(data));
} }
populateGraph();
}; };
invokerUtil.get(backendApiUrl, successCallback, function (message) { invokerUtil.get(backendApiUrl, successCallback, function (message) {
populateGraph();
}); });
} }
@ -276,7 +273,7 @@ function drawGraph_android_sense(from, to) {
+ "/sensors/" + type + "?from=" + from + "&to=" + to; + "/sensors/" + type + "?from=" + from + "&to=" + to;
var successCallback = function (data) { var successCallback = function (data) {
if (data) { if (data) {
drawLineGraph(JSON.parse(data)); drawGraph(JSON.parse(data));
} }
deviceIndex++; deviceIndex++;
getData(); getData();
@ -287,7 +284,7 @@ function drawGraph_android_sense(from, to) {
}); });
} }
function drawLineGraph(data) { function drawGraph(data) {
if (data.length === 0 || data.length === undefined) { if (data.length === 0 || data.length === undefined) {
return; return;
} }
@ -297,32 +294,53 @@ function drawGraph_android_sense(from, to) {
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
chartData.push( chartData.push(
{ {
x: parseInt(data[i].values.time) - tzOffset, x: parseInt(data[i].values.meta_timestamp) - tzOffset,
y: sqrt(pow(parseInt(data[i].values.y), 2) + pow(parseInt(data[i].values.x), 2) + pow(parseInt(data[i].values.z), 2)) y: sqrt(pow(parseInt(data[i].values.Y), 2) + pow(parseInt(data[i].values.X), 2) + pow(parseInt(data[i].values.z), 2))
}); });
} }
graphConfig.series[deviceIndex].data = chartData; graphConfig.series[deviceIndex].data = chartData;
} else { } else {
var chartDataX = [], chartDataY = [], chartDataZ = []; var chartDataX = [], chartDataY = [], chartDataZ = [];
console.log(data.length);
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
if (data[i].values.axis==="X"){
console.log(new Date(parseInt(data[i].values.meta_timestamp)- tzOffset));
chartDataX.push( chartDataX.push(
{ {
x: parseInt(data[i].values.time) - tzOffset, x: parseInt(((data[i].values.meta_timestamp) - tzOffset)/1000),
y: parseInt(data[i].values.y) y: parseInt(data[i].values.value)
}); });
}else if(data[i].values.axis==="Y"){
chartDataY.push( chartDataY.push(
{ {
x: parseInt(data[i].values.time) - tzOffset, x: parseInt(((data[i].values.meta_timestamp) - tzOffset)/1000),
y: parseInt(data[i].values.value)
});
}else if(data[i].values.axis==="Z"){
chartDataZ.push(
{
x: parseInt(((data[i].values.meta_timestamp) - tzOffset)/1000),
y: parseInt(data[i].values.value)
});
}else if(data[i].values.hasOwnProperty("x") && data[i].values.hasOwnProperty("y") && data[i].values.hasOwnProperty("z")){
chartDataX.push(
{
x: parseInt(((data[i].values.meta_timestamp) - tzOffset)/1000),
y: parseInt(data[i].values.x) y: parseInt(data[i].values.x)
}); });
chartDataY.push(
{
x: parseInt(((data[i].values.meta_timestamp) - tzOffset)/1000),
y: parseInt(data[i].values.y)
});
chartDataZ.push( chartDataZ.push(
{ {
x: parseInt(data[i].values.time) - tzOffset, x: parseInt(((data[i].values.meta_timestamp) - tzOffset)/1000),
y: parseInt(data[i].values.z) y: parseInt(data[i].values.z)
}); });
} }
}
graphConfig.series[0].data = chartDataX; graphConfig.series[0].data = chartDataX;
graphConfig.series[1].data = chartDataY; graphConfig.series[1].data = chartDataY;
graphConfig.series[2].data = chartDataZ; graphConfig.series[2].data = chartDataZ;
@ -352,5 +370,21 @@ function drawGraph_android_sense(from, to) {
return columnData; return columnData;
} }
}
$(document).ready(function() {
$("input:radio").click(function(e) {
var offsetMode = e.target.value;
var graphType = e.target.className;
if (offsetMode == 'lines') {
graphMap[graphType].graph.setRenderer('line');
graphMap[graphType].graph.offset = 'zero';
} else {
graphMap[graphType].graph.setRenderer('stack');
graphMap[graphType].graph.offset = offsetMode;
} }
graphMap[graphType].graph.update();
});
});
Loading…
Cancel
Save