forked from community/device-mgt-plugins
parent
60e99704d2
commit
2d6aa46ca2
@ -1,5 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
|
||||||
<IoTDeviceTypeConfigManager>
|
<IoTDeviceTypeConfigManager>
|
||||||
|
<IotDeviceTypeConfig type="virtual_firealarm">
|
||||||
|
<DatasourceName>jdbc/VirtualFireAlarmDM_DB</DatasourceName>
|
||||||
|
<!--TODO: Uncomment this to work with apim @ 192.168.67.21 -->
|
||||||
|
<!--ApiApplicationName>firealarm</ApiApplicationName-->
|
||||||
|
</IotDeviceTypeConfig>
|
||||||
</IoTDeviceTypeConfigManager>
|
</IoTDeviceTypeConfigManager>
|
||||||
|
@ -0,0 +1,266 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var graph;
|
||||||
|
var xAxis;
|
||||||
|
|
||||||
|
var deviceType = $("#details").data("devicetype");
|
||||||
|
var deviceId = $("#details").data("deviceid");
|
||||||
|
var monitor_operations = $("#details").data("monitor");
|
||||||
|
|
||||||
|
var marker_1 = '/store/extensions/app/store-device-type/themes/store/img/map-marker-1.png';
|
||||||
|
var marker_2 = '/store/extensions/app/store-device-type/themes/store/img/map-marker-2.png';
|
||||||
|
|
||||||
|
var map;
|
||||||
|
var mapPoints = [], mapPaths = [], mapMarkers = [];
|
||||||
|
function initMap() {
|
||||||
|
map = new google.maps.Map(document.getElementById('map'), {
|
||||||
|
center: {lat: 6.9344, lng: 79.8428},
|
||||||
|
zoom: 12
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDates() {
|
||||||
|
$(".formatDate").each(function () {
|
||||||
|
var timeStamp = $(this).html();
|
||||||
|
$(this).html(getDateString(timeStamp));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDateString(timeStamp) {
|
||||||
|
var monthNames = [
|
||||||
|
"Jan", "Feb", "Mar",
|
||||||
|
"Apr", "May", "Jun", "Jul",
|
||||||
|
"Aug", "Sept", "Oct",
|
||||||
|
"Nov", "Dec"
|
||||||
|
];
|
||||||
|
|
||||||
|
var date = new Date(parseInt(timeStamp));
|
||||||
|
var day = date.getDate();
|
||||||
|
var monthIndex = date.getMonth() + 1;
|
||||||
|
if (monthIndex < 10) {
|
||||||
|
monthIndex = "0" + monthIndex;
|
||||||
|
}
|
||||||
|
var year = date.getFullYear();
|
||||||
|
|
||||||
|
var hours = date.getHours();
|
||||||
|
var amPm = hours < 12 ? "AM" : "PM";
|
||||||
|
if (hours > 12) {
|
||||||
|
hours -= 12;
|
||||||
|
}
|
||||||
|
if (hours == 0) {
|
||||||
|
hours = 12;
|
||||||
|
}
|
||||||
|
return day + '-'
|
||||||
|
+ monthNames[monthIndex - 1] + '-'
|
||||||
|
+ year + ' ' + hours + ':' + date.getMinutes() + amPm;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(window).on('resize', function () {
|
||||||
|
if (graph) {
|
||||||
|
location.reload(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
formatDates();
|
||||||
|
updateGraphs();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("form").on('submit', function (e) {
|
||||||
|
var postOperationRequest = $.ajax({
|
||||||
|
url: $(this).attr("action") + '&' + $(this).serialize(),
|
||||||
|
method: "post"
|
||||||
|
});
|
||||||
|
|
||||||
|
var lblSending = $('#lblSending', this);
|
||||||
|
lblSending.removeClass('hidden');
|
||||||
|
|
||||||
|
var lblSent = $('#lblSent', this);
|
||||||
|
var sentValue = $(this).find('input[name="value"]').val();
|
||||||
|
postOperationRequest.done(function (data) {
|
||||||
|
lblSending.addClass('hidden');
|
||||||
|
lblSent.removeClass('hidden');
|
||||||
|
setTimeout(function () {
|
||||||
|
lblSent.addClass('hidden');
|
||||||
|
}, 3000);
|
||||||
|
$('#lblLastState').text('Current value: ' + (sentValue == '1' ? 'On' : 'Off'));
|
||||||
|
});
|
||||||
|
|
||||||
|
postOperationRequest.fail(function (jqXHR, textStatus) {
|
||||||
|
lblSending.addClass('hidden');
|
||||||
|
lblSent.addClass('hidden');
|
||||||
|
});
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateGraphs() {
|
||||||
|
var tv = 5000;
|
||||||
|
|
||||||
|
var fields = [];
|
||||||
|
for (var op in monitor_operations) {
|
||||||
|
if (monitor_operations[op].name == 'gps') {
|
||||||
|
$('#map').removeClass('hidden');
|
||||||
|
} else {
|
||||||
|
fields.push({name: monitor_operations[op].name});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// instantiate our graph!
|
||||||
|
graph = new Rickshaw.Graph({
|
||||||
|
element: document.getElementById("chart"),
|
||||||
|
width: $("#chartWrapper").width() - 50,
|
||||||
|
height: 300,
|
||||||
|
renderer: 'line',
|
||||||
|
series: new Rickshaw.Series.FixedDuration(fields, undefined, {
|
||||||
|
timeInterval: 10000,
|
||||||
|
maxDataPoints: 20,
|
||||||
|
timeBase: new Date().getTime() / 1000
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
var iv = setInterval(function () {
|
||||||
|
|
||||||
|
var getStatsRequest = $.ajax({
|
||||||
|
url: "/store/apis/operations/" + deviceType + "/stats?deviceId=" + deviceId,
|
||||||
|
method: "get"
|
||||||
|
});
|
||||||
|
|
||||||
|
getStatsRequest.done(function (data) {
|
||||||
|
var stats = data.data;
|
||||||
|
var lastUpdate = -1;
|
||||||
|
var graphVals = {};
|
||||||
|
for (var s in stats) {
|
||||||
|
var val = stats[s];
|
||||||
|
if (!val){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (val.time > lastUpdate) {
|
||||||
|
lastUpdate = val.time;
|
||||||
|
}
|
||||||
|
delete val['time'];
|
||||||
|
if (val.map) {
|
||||||
|
mapPoints.push(val.map);
|
||||||
|
var marker = new google.maps.Marker({
|
||||||
|
position: val.map,
|
||||||
|
map: map,
|
||||||
|
icon: marker_1,
|
||||||
|
title: 'Seen at ' + getDateString(lastUpdate)
|
||||||
|
});
|
||||||
|
marker.setMap(map);
|
||||||
|
map.panTo(val.map);
|
||||||
|
mapMarkers.push(marker);
|
||||||
|
|
||||||
|
if (mapPoints.length > 1 ){
|
||||||
|
var l = mapPoints.length;
|
||||||
|
var path = new google.maps.Polyline({
|
||||||
|
path: [mapPoints[l - 1], mapPoints[l - 2]],
|
||||||
|
geodesic: true,
|
||||||
|
strokeColor: '#FF0000',
|
||||||
|
strokeOpacity: 1.0,
|
||||||
|
strokeWeight: 2
|
||||||
|
});
|
||||||
|
|
||||||
|
path.setMap(map);
|
||||||
|
mapPaths.push(path);
|
||||||
|
|
||||||
|
mapMarkers[l - 2].setIcon(marker_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapPoints.length >= 10){
|
||||||
|
mapMarkers[0].setMap(null);
|
||||||
|
mapMarkers.splice(0, 1);
|
||||||
|
|
||||||
|
mapPaths[0].setMap(null);
|
||||||
|
mapPaths.splice(0, 1);
|
||||||
|
|
||||||
|
mapPoints.splice(0, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var key in val) {
|
||||||
|
graphVals[key] = val[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
graph.series.addData(graphVals);
|
||||||
|
|
||||||
|
if (lastUpdate == -1){
|
||||||
|
$('#last_seen').text("Not seen recently");
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeDiff = new Date().getTime() - lastUpdate;
|
||||||
|
if (timeDiff < tv * 2) {
|
||||||
|
graph.render();
|
||||||
|
$('#last_seen').text("Last seen: A while ago");
|
||||||
|
} else if (timeDiff < 60 * 1000) {
|
||||||
|
graph.render();
|
||||||
|
$('#last_seen').text("Last seen: Less than a minute ago");
|
||||||
|
} else if (timeDiff < 60 * 60 * 1000) {
|
||||||
|
$('#last_seen').text("Last seen: " + Math.round(timeDiff / (60 * 1000)) + " minutes ago");
|
||||||
|
} else {
|
||||||
|
$('#last_seen').text("Last seen: " + getDateString(lastUpdate));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//var data = {Temperature: Math.floor(Math.random() * (50 - 20) + 20)};
|
||||||
|
//
|
||||||
|
//graph.series.addData(data);
|
||||||
|
//graph.render();
|
||||||
|
|
||||||
|
}, tv);
|
||||||
|
|
||||||
|
graph.render();
|
||||||
|
|
||||||
|
xAxis = new Rickshaw.Graph.Axis.Time({
|
||||||
|
graph: graph
|
||||||
|
});
|
||||||
|
|
||||||
|
xAxis.render();
|
||||||
|
|
||||||
|
var y_ticks = new Rickshaw.Graph.Axis.Y({
|
||||||
|
graph: graph,
|
||||||
|
orientation: 'left',
|
||||||
|
height: 300,
|
||||||
|
tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
|
||||||
|
element: document.getElementById('y_axis')
|
||||||
|
});
|
||||||
|
|
||||||
|
var legend = new Rickshaw.Graph.Legend({
|
||||||
|
graph: graph,
|
||||||
|
element: document.getElementById('legend')
|
||||||
|
});
|
||||||
|
|
||||||
|
var hoverDetail = new Rickshaw.Graph.HoverDetail({
|
||||||
|
graph: graph
|
||||||
|
});
|
||||||
|
|
||||||
|
var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
|
||||||
|
graph: graph,
|
||||||
|
legend: legend
|
||||||
|
});
|
||||||
|
|
||||||
|
var order = new Rickshaw.Graph.Behavior.Series.Order({
|
||||||
|
graph: graph,
|
||||||
|
legend: legend
|
||||||
|
});
|
||||||
|
|
||||||
|
var highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({
|
||||||
|
graph: graph,
|
||||||
|
legend: legend
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
<!-- statistics -->
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading" role="tab" id="headingFour">
|
||||||
|
<h2 class="sub-title panel-title">
|
||||||
|
<a data-toggle="collapse"
|
||||||
|
href="#collapseTwo" aria-expanded="true"
|
||||||
|
aria-controls="collapseTwo">
|
||||||
|
<span class="fw-stack">
|
||||||
|
<i class="fw fw-ring fw-stack-2x"></i>
|
||||||
|
<i class="fw fw-arrow fw-down fw-stack-1x"></i>
|
||||||
|
</span>
|
||||||
|
Device Statistics
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div id="collapseTwo" class="panel-collapse collapse in"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="headingTwo">
|
||||||
|
<div class="panel-body">
|
||||||
|
<div id="chartWrapper">
|
||||||
|
<div id="y_axis" class="custom_y_axis"></div>
|
||||||
|
<div class="legend_container">
|
||||||
|
<div id="smoother" title="Smoothing"></div>
|
||||||
|
<div id="legend"></div>
|
||||||
|
</div>
|
||||||
|
<div id="chart" class="custom_rickshaw_graph"></div>
|
||||||
|
<div class="custom_x_axis"></div>
|
||||||
|
</div>
|
||||||
|
<div id="map" class="map-wrapper hidden">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<a class="padding-left" href="{{@app.context}}/pages/analytics?deviceId={{deviceId}}&deviceType={{deviceType}}">
|
||||||
|
<span class="fw-stack">
|
||||||
|
<i class="fw fw-ring fw-stack-2x"></i>
|
||||||
|
<i class="fw fw-statistics fw-stack-1x"></i>
|
||||||
|
</span> View Device Analytics</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /statistics -->
|
||||||
|
|
||||||
|
<!-- events -->
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading" role="tab" id="headingTwo">
|
||||||
|
<h2 class="sub-title panel-title">
|
||||||
|
<a data-toggle="collapse"
|
||||||
|
href="#collapseThree" aria-expanded="true"
|
||||||
|
aria-controls="collapseThree">
|
||||||
|
<span class="fw-stack">
|
||||||
|
<i class="fw fw-ring fw-stack-2x"></i>
|
||||||
|
<i class="fw fw-arrow fw-down fw-stack-1x"></i>
|
||||||
|
</span>
|
||||||
|
Device Events
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div id="collapseThree" class="panel-collapse collapse in"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="headingThree">
|
||||||
|
<div class="panel-body">
|
||||||
|
{{#if data}}
|
||||||
|
<div class="container container-bg white-bg">
|
||||||
|
<div class=" margin-top-double">
|
||||||
|
<div class="row row padding-top-double padding-bottom-double margin-bottom-double">
|
||||||
|
<div id="event-stream-place-holder" style="padding-top: 20px;">
|
||||||
|
<div style="padding: 15px;">
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="20%">Time</th>
|
||||||
|
<th>Activity</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#each data}}
|
||||||
|
<tr>
|
||||||
|
<td width="20%" class="formatDate">{{time}}</td>
|
||||||
|
<td>{{activity}}</td>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="assets-container">
|
||||||
|
<div class="top-assets-empty-assert">You don't have any
|
||||||
|
events logged at
|
||||||
|
the moment.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{#zone "bottomJs"}}
|
||||||
|
{{js "js/device-details.js"}}
|
||||||
|
{{/zone}}
|
@ -0,0 +1,3 @@
|
|||||||
|
function onRequest(context) {
|
||||||
|
return context;
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
<div id="device_overview">
|
||||||
|
<div class="media-left media-middle asset-image col-xs-2 col-sm-2 col-md-2 col-lg-2">
|
||||||
|
{{unit "cdmf.unit.device.overview.firealarm-display-image"}}
|
||||||
|
</div>
|
||||||
|
<div class="media-body asset-desc add-padding-left-5x">
|
||||||
|
<div style="background: #11375B; color: #fff; padding: 10px; margin-bottom: 5px">Device Overview - Virtual Firealarm</div>
|
||||||
|
{{#defineZone "device-detail-properties"}}
|
||||||
|
<table class="table table-responsive table-striped" id="members">
|
||||||
|
<tbody>
|
||||||
|
<tr role="row" class="even"><td class="sorting_1" style="padding:10px 15px; width: 1%;;">Device</td><td style="padding:10px 15px;">{{device.viewModel.vendor}} {{device.properties.model}}</td></tr>
|
||||||
|
<tr role="row" class="odd"><td class="sorting_1" style="padding:10px 15px;">Model</td><td style="padding:10px 15px;">{{device.viewModel.model}}</td></tr>
|
||||||
|
<tr role="row" class="even"><td class="sorting_1" style="padding:10px 15px;">IMEI</td><td style="padding:10px 15px;">{{device.viewModel.imei}}</td></tr>
|
||||||
|
{{#if device.viewModel.udid}}
|
||||||
|
<tr role="row" class="even"><td class="sorting_1" style="padding:10px 15px;">UDID</td><td style="padding:10px 15px;">{{device.viewModel.udid}}</td></tr>
|
||||||
|
{{/if}}
|
||||||
|
{{#if device.viewModel.phoneNumber}}
|
||||||
|
<tr role="row" class="even"><td class="sorting_1" style="padding:10px 15px;">Phone Number</td><td style="padding:10px 15px;">{{device.viewModel.phoneNumber}}</td></tr>
|
||||||
|
{{/if}}
|
||||||
|
<tr role="row" class="even">
|
||||||
|
<td class="sorting_1" style="padding:10px 15px;">Status</td>
|
||||||
|
<td style="padding:10px 15px;">
|
||||||
|
{{#equal device.status "ACTIVE"}}<span><i class="fw fw-ok icon-success"></i> Active</span>{{/equal}}
|
||||||
|
{{#equal device.status "INACTIVE"}}<span><i class="fw fw-warning icon-warning"></i> Inactive</span>{{/equal}}
|
||||||
|
{{#equal device.status "BLOCKED"}}<span><i class="fw fw-remove icon-danger"></i> Blocked</span>{{/equal}}
|
||||||
|
{{#equal device.status "REMOVED"}}<span><i class="fw fw-delete icon-danger"></i> Removed</span>{{/equal}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{/defineZone}}
|
||||||
|
<div style="background: #11375B; color: #fff; padding: 10px; margin-bottom: 5px">Operations</div>
|
||||||
|
<div class="add-margin-top-4x">
|
||||||
|
{{unit "cdmf.unit.device.iot-operation" deviceType=device.type}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,25 @@
|
|||||||
|
function onRequest (context) {
|
||||||
|
var log = new Log("detail.js");
|
||||||
|
var deviceType = request.getParameter("type");
|
||||||
|
var deviceId = request.getParameter("id");
|
||||||
|
|
||||||
|
if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) {
|
||||||
|
var deviceModule = require("/modules/device.js").deviceModule;
|
||||||
|
var device = deviceModule.viewDevice(deviceType, deviceId);
|
||||||
|
|
||||||
|
if (device) {
|
||||||
|
var viewModel = {};
|
||||||
|
var deviceInfo = device.properties.DEVICE_INFO;
|
||||||
|
if (deviceInfo != undefined && String(deviceInfo.toString()).length > 0) {
|
||||||
|
deviceInfo = parse(stringify(deviceInfo));
|
||||||
|
viewModel.system = device.properties.IMEI;
|
||||||
|
viewModel.machine = "Virtual Firealarm";
|
||||||
|
viewModel.vendor = device.properties.VENDOR;
|
||||||
|
}
|
||||||
|
device.viewModel = viewModel;
|
||||||
|
}
|
||||||
|
context.device = device;
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
Loading…
Reference in new issue