Dashboard
Flow Event Grid Widget
<div class="row">
<div class="col-md-12">
<div class="table-responsive">
<h5>Total Records: <span class="totalCount"></span></h5>
<table id="gridTable" class="display nowrap table table-hover table-bordered" cellspacing="0" width="100%">
</table>
</div>
</div>
</div>
table{
font-size:13px;
}
/********************************************
Pre Defined variables to access in the widget
********************************************/
// API_BASE_PATH - to get boodskap api base path
// DOMAIN_KEY - to get domain key
// API_KEY - to get api key
// API_TOKEN - to get api token
// MESSAGE_ID - to get message id
// DEVICE_ID - to get device id
// ASSET_ID - to get asset id
// RECORD_ID - to get record id
// WIDGET_ID - to get current widget id
// USER_ID - to get user id (In public share this will be empty)
$(document).ready(function () {
//To start realtime time update
startLiveUpdate()
loadTable();
});
var loading=true;
// for realtime update, call the initial method inside this function too
function liveUpdate(){
if(loading){
loading=false;
loadTable();
}
}
var gridTable = null;
function loadTable(){
if (gridTable) {
gridTable.destroy();
$("#gridTable").html("");
}
var fields = [
{
mData: 'created_ts',
orderable: true,
"aTargets": [ 0 ],
sTitle: 'Last Updated Time',
mRender: function (data, type, row) {
return moment(data).format('MM/DD/YYYY hh:mm:ss a')
}
},
{
mData: 'device_id',
sTitle: 'Device',
orderable: false,
mRender: function (data, type, row) {
return '<b>'+data+'</b>';
}
},
{
mData: 'event_name',
sTitle: 'Event Name',
orderable: false,
mRender: function (data, type, row) {
var str="";
if(data =="HIGH"){
str = '<label class="label label-danger">High</label>'
}
else if(data == "LOW"){
str = '<label class="label label-warning">Low</label>'
}
return data+' FLOW<br>'+str;
}
},
];
var queryParams = {
query: {
"bool": {
"must": [],
}
},
sort: [{"created_ts": {"order": "desc"}}],
};
var tableOption = {
fixedHeader: false,
responsive: false,
paging: true,
searching: true,
//aaSorting: [[5, 'desc']],
"ordering": true,
iDisplayLength: 5,
lengthMenu: [[5,10, 50, 100], [5,10, 50, 100]],
aoColumns: fields,
"oLanguage": {
sSearchPlaceholder : 'Search',
"sSearch": "<i class='fa fa-search'></i>",
"sProcessing": '<i class="fa fa-spinner fa-spin" style="color:#333"></i> Processing',
"sEmptyTable" : "No data available!",
},
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": API_BASE_PATH + "/elastic/search/query/" + API_TOKEN,
"fnServerData": function (sSource, aoData, fnCallback, oSettings) {
queryParams.query['bool']['must'] = [];
queryParams.query['bool']['should'] = [];
delete queryParams.query['bool']["minimum_should_match"];
var keyName = fields[oSettings.aaSorting[0][0]]
var sortingJson = {};
sortingJson[keyName['mData']] = {"order": oSettings.aaSorting[0][1]};
queryParams.sort = [sortingJson];
queryParams['size'] = oSettings._iDisplayLength;
queryParams['from'] = oSettings._iDisplayStart;
var searchText = oSettings.oPreviousSearch.sSearch;
if (searchText) {
queryParams.query['bool']['should'].push({"wildcard" : { "device_addr" : "*"+searchText.toLowerCase()+"*" }})
queryParams.query['bool']["minimum_should_match"]=1;
}
var searchQuery = {
"extraPath": "",
"query": JSON.stringify(queryParams),
"params": [],
"specId" : RECORD_ID,
"type":"RECORD"
};
oSettings.jqXHR = $.ajax({
"dataType": 'json',
"contentType": 'application/json',
"type": "POST",
"url": sSource,
"data": JSON.stringify(searchQuery),
success: function (data) {
var resultData = searchQueryFormatter(data).data;
$(".totalCount").html(resultData.recordsFiltered);
resultData['draw'] = oSettings.iDraw;
loading=true;
fnCallback(resultData);
}
});
}
};
gridTable = $("#gridTable").DataTable(tableOption);
}
function searchQueryFormatter(data) {
var resultObj = {
total: 0,
data: {},
aggregations: {}
}
if (data.httpCode === 200) {
var arrayData = JSON.parse(data.result);
var totalRecords = arrayData.hits.total.value;
var records = arrayData.hits.hits;
var aggregations = arrayData.aggregations ? arrayData.aggregations : {};
for (var i = 0; i < records.length; i++) {
records[i]['_source']['_id'] = records[i]['_id'];
}
resultObj = {
"total": totalRecords,
"data": {
"recordsTotal": totalRecords,
"recordsFiltered": totalRecords,
"data": _.pluck(records, '_source')
},
aggregations: aggregations
}
console.log(resultObj)
return resultObj;
} else {
return resultObj;
}
}
// CSS
cdn.datatables.net/1.11.2/css/jquery.dataTables.min.css
//JS
cdn.datatables.net/1.11.2/js/jquery.dataTables.min.js
Flow Gauge Widget
<p>Last Reported Time: <span id="reported_ts"></span></p>
<div class = "container" id="chart_div" style="width: 400px; height: 120px;"></div>
#box{
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
}
#chart_div text {
font-size: 16;
}
/********************************************
Pre Defined variables to access in the widget
********************************************/
// API_BASE_PATH - to get boodskap api base path
// DOMAIN_KEY - to get domain key
// API_KEY - to get api key
// API_TOKEN - to get api token
// MESSAGE_ID - to get message id
// DEVICE_ID - to get device id
// ASSET_ID - to get asset id
// RECORD_ID - to get record id
// WIDGET_ID - to get current widget id
// USER_ID - to get user id (In public share this will be empty)
var DATA_FIELD = "flow_rate"
var FLOW_UNIT = 'L/mins'
var DATE_TIME_FORMAT = 'MM/DD/YYYY hh:mm:ss a';
var CHART_WIDTH = 600
var CHART_HEIGHT = 300
var CHART_LABEL = 'Flow Rate in'+' '+FLOW_UNIT
var RED_FROM = 90
var RED_TO = 100
var YELLOW_FROM = 75
var YELLOW_TO = 90
var MINOR_TICKS = 5
$(document).ready(function () {
//To start realtime time update
startLiveUpdate()
loadPage()
});
// for realtime update, call the initial method inside this function too
function liveUpdate(){
loadPage()
}
function loadPage(){
var queryParams = {
sort: [{
receivedstamp: {
order: 'desc'
}
}],
size: 1,
query: {
bool: {
must: [{
match: {
deviceid: DEVICE_ID
}
}]
}
}
};
var searchQuery = {
"extraPath": "",
"query": JSON.stringify(queryParams),
"params": [],
"specId": MESSAGE_ID,
"type": "MESSAGE"
};
searchByQuery(searchQuery, function(status, data) {
if (status) {
var result = searchQueryFormatter(data);
if (result.total > 0) {
var resultData = result.data.data;
$("#reported_ts").html(resultData[0].receivedstamp ? moment(resultData[0].receivedstamp).format(DATE_TIME_FORMAT) : "-")
renderGauge(resultData, DATA_FIELD);
}
} else {
$('.container-widget').html('<h5 class="text-danger text-center py-5"><i class="fa fa-info-circle" aria-hidden="true"></i> Please Check the widget configuration settings</h5>');
}
});
}
function searchByQuery(data, cbk) {
$.ajax({
url: API_BASE_PATH + "/elastic/search/query/" + API_TOKEN,
data: JSON.stringify(data),
contentType: "application/json",
type: 'POST',
success: function(data) {
//called when successful
cbk(true, data);
},
error: function(e) {
//called when there is an error
cbk(false, e);
}
});
}
function searchQueryFormatter(data) {
var resultObj = {
total: 0,
data: {},
aggregations: {}
};
if (data.httpCode === 200) {
var arrayData = JSON.parse(data.result);
var totalRecords = arrayData.hits.total.value;
var records = arrayData.hits.hits;
var aggregations = arrayData.aggregations ? arrayData.aggregations : {};
for (var i = 0; i < records.length; i++) {
records[i]['_source']['_id'] = records[i]['_id'];
}
resultObj = {
"total": totalRecords,
"data": {
"recordsTotal": totalRecords,
"recordsFiltered": totalRecords,
"data": _.pluck(records, '_source')
},
aggregations: aggregations
};
return resultObj;
} else {
return resultObj;
}
}
function renderGauge(data)
{
google.charts.load('current', {'packages':['gauge']});
google.charts.setOnLoadCallback(drawChart);
var value = data[0][DATA_FIELD] ? data[0][DATA_FIELD] : "-"
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Label', 'Value'],
[CHART_LABEL,value],
]);
var options = {
width: CHART_WIDTH,
height: CHART_HEIGHT,
redFrom: RED_FROM,
redTo: RED_TO,
yellowFrom:YELLOW_FROM,
yellowTo: YELLOW_TO,
minorTicks: MINOR_TICKS
};
var chart = new google.visualization.Gauge(document.getElementById('chart_div'));
chart.draw(data, options);
}}
//Java Script
https://www.gstatic.com/charts/loader.js
Flow Line Chart Widget
<div id="chart" style="width:auto; height:80%;"></div>
#box{
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
}
#chart text {
font-size: 13px;
}
/********************************************
Pre Defined variables to access in the widget
********************************************/
// API_BASE_PATH - to get boodskap api base path
// DOMAIN_KEY - to get domain key
// API_KEY - to get api key
// API_TOKEN - to get api token
// MESSAGE_ID - to get message id
// DEVICE_ID - to get device id
// ASSET_ID - to get asset id
// RECORD_ID - to get record id
// WIDGET_ID - to get current widget id
// USER_ID - to get user id (In public share this will be empty)
// majar properties
var CHART_TITLE = "Flow Rate History";
var YAXIS_LABEL = 'Flow Rate';
var YAXIS_VALUES = 'flow_rate'; //message field name
var XAXIS_LABEL = 'Time';
var XAXIS_VALUES = 'receivedstamp'; //message field name
var DATE_TIME_FORMAT = 'MM/DD/YYYY hh:mm a';
$(document).ready(function () {
//To start realtime time update
startLiveUpdate();
loadPage();
});
// for realtime update, call the initial method inside this function too
function liveUpdate() {
loadPage();
}
function loadPage() {
var queryParams = {
sort: [{
receivedstamp: {
order: 'desc'
}
}],
size: 300,
query: {
bool: {
must: [{
match: {
deviceid: DEVICE_ID
}
}]
}
}
};
var searchQuery = {
"extraPath": "",
"query": JSON.stringify(queryParams),
"params": [],
"specId": MESSAGE_ID,
"type": "MESSAGE"
};
searchByQuery(searchQuery, function (status, data) {
if (status) {
var result = searchQueryFormatter(data);
if (result.total > 0) {
var resultData = result.data.data;
renderChart(resultData);
} else {
renderChart(0);
}
} else {
$('.main').html('<h5 class="text-danger text-center py-5"><i class="fa fa-info-circle" aria-hidden="true"></i> Please Check the widget configuration settings</h5>');
}
});
}
function searchByQuery(data, cbk) {
$.ajax({
url: API_BASE_PATH + "/elastic/search/query/" + API_TOKEN,
data: JSON.stringify(data),
contentType: "application/json",
type: 'POST',
success: function (data) {
//called when successful
cbk(true, data);
},
error: function (e) {
//called when there is an error
cbk(false, e);
}
});
}
function searchQueryFormatter(data) {
var resultObj = {
total: 0,
data: {},
aggregations: {}
};
if (data.httpCode === 200) {
var arrayData = JSON.parse(data.result);
var totalRecords = arrayData.hits.total.value;
var records = arrayData.hits.hits;
var aggregations = arrayData.aggregations ? arrayData.aggregations : {};
for (var i = 0; i < records.length; i++) {
records[i]['_source']['_id'] = records[i]['_id'];
}
resultObj = {
"total": totalRecords,
"data": {
"recordsTotal": totalRecords,
"recordsFiltered": totalRecords,
"data": _.pluck(records, '_source')
},
aggregations: aggregations
};
return resultObj;
} else {
return resultObj;
}
}
function renderChart(data){
google.charts.load('visualization', { packages: ['corechart'] });
google.charts.setOnLoadCallback(drawLineChart);
function drawLineChart() {
var value_array = [[YAXIS_LABEL, XAXIS_LABEL,]];
$.each(data, function (index, value) {
value_array.push([moment(value[XAXIS_VALUES]).format(DATE_TIME_FORMAT), value[YAXIS_VALUES]]);
});
// Set chart Options.
var options = {
title: CHART_TITLE,
legend: { position: 'none' },
hAxis: {
title: XAXIS_LABEL
},
vAxis: {
title: YAXIS_LABEL
},
tooltip: {isHtml: true}
};
// Create DataTable and add the array to it.
var figures = google.visualization.arrayToDataTable(value_array)
// Define the chart type (LineChart) and the container (a DIV in our case).
var chart = new google.visualization.LineChart(document.getElementById('chart'));
chart.draw(figures, options); // Draw the chart with Options.
}
}
//Java Script File
https://www.gstatic.com/charts/loader.js
Total Consumption Widget
<div class="container-fluid" id="box">
<div class="card">
<div class="card-body">
<p>Last Reported Time: <span id="reported_ts"></span></p>
<h4 class="center">Total Consumption</h4><br><br>
<img id="icon"
src="https://cdn-icons-png.flaticon.com/512/4343/4343120.png" alt="" /><br><br>
<p class="center" id="value_text"><span id="consumption"></span> <span id="consumption_unit"></span></p>
</div>
</div>
</div>
.center{
text-align:center;
}
#icon{
display: block;
margin-left: auto;
margin-right: auto;
width: 15%;
height:15%;
}
#value_text{
font-size:20px;
}
/********************************************
Pre Defined variables to access in the widget
********************************************/
// API_BASE_PATH - to get boodskap api base path
// DOMAIN_KEY - to get domain key
// API_KEY - to get api key
// API_TOKEN - to get api token
// MESSAGE_ID - to get message id
// DEVICE_ID - to get device id
// ASSET_ID - to get asset id
// RECORD_ID - to get record id
// WIDGET_ID - to get current widget id
// USER_ID - to get user id (In public share this will be empty)
var DATA_FIELD = 'total_consumption'
var CONSUMPTION_UNIT = 'L'
var DATE_TIME_FORMAT = 'MM/DD/YYYY hh:mm:ss a';
$(document).ready(function () {
//To start realtime time update
$("#main").css('height', '100%');
startLiveUpdate()
loadPage()
});
// for realtime update, call the initial method inside this function too
function liveUpdate(){
loadPage()
}
function loadPage(){
var queryParams = {
sort: [{
receivedstamp: {
order: 'desc'
}
}],
size: 1,
query: {
bool: {
must: [{
match: {
deviceid: DEVICE_ID
}
}]
}
}
};
var searchQuery = {
"extraPath": "",
"query": JSON.stringify(queryParams),
"params": [],
"specId": MESSAGE_ID,
"type": "MESSAGE"
};
searchByQuery(searchQuery, function(status, data) {
if (status) {
var result = searchQueryFormatter(data);
if (result.total > 0) {
var resultData = result.data.data;
renderContent(resultData);
}
} else {
$('.container-widget').html('<h5 class="text-danger text-center py-5"><i class="fa fa-info-circle" aria-hidden="true"></i> Please Check the widget configuration settings</h5>');
}
});
}
function searchByQuery(data, cbk) {
$.ajax({
url: API_BASE_PATH + "/elastic/search/query/" + API_TOKEN,
data: JSON.stringify(data),
contentType: "application/json",
type: 'POST',
success: function(data) {
//called when successful
cbk(true, data);
},
error: function(e) {
//called when there is an error
cbk(false, e);
}
});
}
function searchQueryFormatter(data) {
var resultObj = {
total: 0,
data: {},
aggregations: {}
};
if (data.httpCode === 200) {
var arrayData = JSON.parse(data.result);
var totalRecords = arrayData.hits.total.value;
var records = arrayData.hits.hits;
var aggregations = arrayData.aggregations ? arrayData.aggregations : {};
for (var i = 0; i < records.length; i++) {
records[i]['_source']['_id'] = records[i]['_id'];
}
resultObj = {
"total": totalRecords,
"data": {
"recordsTotal": totalRecords,
"recordsFiltered": totalRecords,
"data": _.pluck(records, '_source')
},
aggregations: aggregations
};
return resultObj;
} else {
return resultObj;
}
}
function renderContent(data){
$("#reported_ts").html(data[0].receivedstamp ? moment(data[0].receivedstamp).format(DATE_TIME_FORMAT) : "-")
$("#consumption").html(data[0][DATA_FIELD] ? data[0][DATA_FIELD] : "-")
$("#consumption_unit").html( CONSUMPTION_UNIT ? CONSUMPTION_UNIT : "")
}
//CSS
https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css
//JS
https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js
https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js
Updated about 3 years ago