Merge branch 'master' of https://github.com/wso2/product-iots into 3.0.0

merge-requests/1/head
ayyoob 8 years ago
commit 4ca84a9f2d

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<artifact name="GadgetLocationData" version="1.0.0" type="dashboards/gadget" serverRole="GeoDashboard">
<file>geo-dashboard</file>
</artifact>

@ -0,0 +1,69 @@
<!--~ Copyright (c) 2016, 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.-->
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="viewWithinAlert" >
<form role="form" style="width: auto">
<div class="form-group">
<label class="text-info">Query name</label>
<div id="viewQueryName" class="well well-sm"></div>
<label class="text-info">Area name</label>
<div id="viewAreaName" class="well well-sm"></div>
</div>
<div>
<div class="btn-group btn-group-sm btn-group-justified">
<div class="btn-group">
<a id="exportGeoJson" download="geoJson.json" href="#" onclick="exportToGeoJSON(this,JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'))" class="btn btn-default btn-xs" data-toggle="tooltip" data-placement="left" title="Export selected area as a geoJson file">Export</a>
</div>
<div class="btn-group">
<a id="hideViewFence" class="btn btn-default btn-xs" data-toggle="tooltip" data-placement="left" title="Hide this fence" onclick="map.removeLayer(map._layers[$(this).attr('leaflet_id')])" >Hide</a>
</div>
</div>
</div>
</form>
</div>
<div id="viewStationeryAlert" >
<form role="form" style="width: auto">
<div class="form-group">
<label class="text-info">Query name</label>
<div id="viewQueryName" class="well well-sm"></div>
<label class="text-info">Stationery name</label>
<div id="viewAreaName" class="well well-sm"></div>
<label class="text-info">Stationery time(Seconds)</label>
<div id="viewAreaTime" class="well well-sm"></div>
</div>
<div>
<div class="btn-group btn-group-sm btn-group-justified">
<div class="btn-group">
<a id="exportGeoJson" download="geoJson.json" href="#" onclick="exportToGeoJSON(this,JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'))" class="btn btn-default btn-xs" data-toggle="tooltip" data-placement="left" title="Export selected area as a geoJson file">Export</a>
</div>
<div class="btn-group">
<a id="hideViewFence" class="btn btn-default btn-xs" data-toggle="tooltip" data-placement="left" title="Hide this fence" onclick="map.removeLayer(map._layers[$(this).attr('leaflet_id')])" >Hide</a>
</div>
</div>
</div>
</form>
</div>
</body>
</html>

@ -0,0 +1,140 @@
/* Enter a unique ExecutionPlan */
@Plan:name('Geo-ExecutionPlan-Proximity_alert')
/* Enter a unique description for ExecutionPlan */
-- @Plan:description('ExecutionPlan')
/* define streams/tables and write queries here ... */
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string );
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
define stream dataOut ( id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string );
@IndexBy('id')
define table ProximityTable(id string, timeStamp long);
@IndexBy('id')
define table AlertsTable(id string , proximityWith string, eventId string);
from dataIn#geodashboard:subscribe()
select id, latitude, longitude, timeStamp, type, speed, heading, eventId
insert into initialStream;
from initialStream[type == 'STOP']
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity
insert into dataOutStream;
from initialStream[type != 'STOP']
select *
insert into objectInitialStream;
from objectInitialStream#geo:proximity(id,longitude,latitude, $proximityDistance)
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith
insert into proxymityStream;
from proxymityStream[AlertsTable.id == proxymityStream.id in AlertsTable]
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable
insert into innerStreamOne;
from proxymityStream[not(AlertsTable.id == proxymityStream.id in AlertsTable)]
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable
insert into innerStreamOne;
from proxymityStream[AlertsTable.id == proxymityStream.proximityWith in AlertsTable]
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable
insert into innerStreamSeven;
from proxymityStream[not(AlertsTable.id == proxymityStream.proximityWith in AlertsTable)]
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable
insert into innerStreamSeven;
from innerStreamOne[inCloseProximity == true AND not(inAlertTable)]
select id,str:concat(",",proximityWith) as proximityWith , eventId
insert into AlertsTable;
from innerStreamSeven[inCloseProximity == true AND not(inAlertTable)]
select proximityWith as id,str:concat(",",id) as proximityWith , eventId
insert into AlertsTable;
from innerStreamOne[innerStreamOne.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable
on innerStreamOne.id == AlertsTable.id
select innerStreamOne.id as id, str:concat(",", innerStreamOne.proximityWith, AlertsTable.proximityWith) as proximityWith, innerStreamOne.eventId as eventId
insert into updateStream;
from innerStreamSeven[innerStreamSeven.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable
on innerStreamSeven.proximityWith == AlertsTable.id
select innerStreamSeven.proximityWith as id, str:concat(",", innerStreamSeven.id, AlertsTable.proximityWith) as proximityWith, innerStreamSeven.eventId as eventId
insert into updateStream;
from innerStreamOne[innerStreamOne.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable
on innerStreamOne.id == AlertsTable.id
select innerStreamOne.id as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamOne.proximityWith), "") as proximityWith, innerStreamOne.eventId as eventId
insert into updateStream;
from innerStreamSeven[innerStreamSeven.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable
on innerStreamSeven.proximityWith == AlertsTable.id
select innerStreamSeven.proximityWith as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamSeven.id), "") as proximityWith, innerStreamSeven.eventId as eventId
insert into updateStream;
from updateStream
select *
update AlertsTable
on id== AlertsTable.id;
from updateStream[proximityWith == ""]
delete AlertsTable
on id== AlertsTable.id;
from objectInitialStream[AlertsTable.id == objectInitialStream.id in AlertsTable]
select id, latitude, longitude, timeStamp, type, speed, heading, eventId, true as inAlertTable
insert into publishStream;
from objectInitialStream[not(AlertsTable.id == objectInitialStream.id in AlertsTable)]
select id, latitude, longitude, timeStamp, type, speed, heading, eventId, false as inAlertTable
insert into publishStream;
from publishStream[inAlertTable == true]#window.length(0) join AlertsTable
on publishStream.id== AlertsTable.id
select publishStream.id as id, publishStream.latitude as latitude, publishStream.longitude as longitude, publishStream.timeStamp as timeStamp, publishStream.type as type, publishStream.speed as speed, publishStream.heading as heading, publishStream.eventId as eventId, AlertsTable.proximityWith as proximityInfo
insert into innerStreamTwo;
from publishStream[inAlertTable == false]
delete ProximityTable on ProximityTable.id==id;
from publishStream[inAlertTable == false]
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity
insert into dataOutStream;
from innerStreamTwo[ProximityTable.id == innerStreamTwo.id in ProximityTable]
insert into innerStreamThree;
from innerStreamThree#window.length(0) join ProximityTable
on innerStreamThree.id == ProximityTable.id
select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId, ProximityTable.timeStamp as storedTime, innerStreamThree.proximityInfo as proximityInfo
insert into innerStreamFour;
from innerStreamFour[(timeStamp - storedTime) >= $proximityTime]
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,proximityInfo,"true" as isProximity
insert into dataOutStream;
from innerStreamFour[(timeStamp - storedTime) < $proximityTime]
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , proximityInfo ,"false" as isProximity
insert into dataOutStream;
from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)]
select innerStreamTwo.id, innerStreamTwo.timeStamp
insert into ProximityTable;
from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)]
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity
insert into dataOutStream;
from dataOutStream[isProximity == 'true']
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,"WARNING" as state,str:concat("Proximity with "," ",proximityInfo) as information
insert into dataOut;
from dataOutStream[isProximity == 'false']
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information
insert into dataOut;

@ -0,0 +1,20 @@
/* Enter a unique ExecutionPlan */
@Plan:name('Geo-ExecutionPlan-Speed---$deviceId_alert')
/* Enter a unique description for ExecutionPlan */
-- @Plan:description('ExecutionPlan')
/* define streams/tables and write queries here ... */
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string);
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string);
from dataIn[speed >= $speedAlertValue and id == "$deviceId"]#geodashboard:subscribe()
select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "ALERTED" as state, "This device movement is not normal!!" as information
insert into dataOut;
from dataIn[speed < $speedAlertValue and id == "$deviceId"]
select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "NORMAL" as state, "This device movement is normal" as information
insert into dataOut;

@ -0,0 +1,89 @@
/* Enter a unique ExecutionPlan */
@Plan:name('$executionPlanName')
/* Enter a unique description for ExecutionPlan */
-- @Plan:description('ExecutionPlan')
/* define streams/tables and write queries here ... */
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string);
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string);
@IndexBy('id')
define table StationeryTable(id string, timeStamp long);
@IndexBy('id')
define table AlertsTable(id string, stationary bool);
from dataIn#geodashboard:subscribe()
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,geo:within(longitude,latitude,"$geoFenceGeoJSON") as isWithin
insert into innerStreamOne;
from innerStreamOne[isWithin == false]
delete StationeryTable on StationeryTable.id==id;
from innerStreamOne[isWithin == false]
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary
insert into dataOutStream;
from innerStreamOne[isWithin == true]#geo:stationary(id,longitude,latitude, $fluctuationRadius)
select id, latitude, longitude, timeStamp, type, speed, heading, eventId,stationary
insert into innerStreamTwo;
from innerStreamTwo[innerStreamTwo.stationary == true]
select innerStreamTwo.id, innerStreamTwo.stationary
insert into AlertsTable;
from innerStreamTwo[innerStreamTwo.stationary == false]
delete AlertsTable on AlertsTable.id==id;
from innerStreamTwo[innerStreamTwo.stationary == false]
delete StationeryTable on StationeryTable.id==id;
from innerStreamOne[isWithin == true AND not(AlertsTable.id == innerStreamOne.id in AlertsTable)]
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary
insert into dataOutStream;
from innerStreamOne[isWithin == true AND AlertsTable.id == innerStreamOne.id in AlertsTable]
insert into innerStreamThree;
from innerStreamThree#window.length(0) join AlertsTable
on innerStreamThree.id == AlertsTable.id
select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId
insert into innerStreamFour;
from innerStreamFour[not(StationeryTable.id == innerStreamFour.id in StationeryTable)]
select innerStreamFour.id, innerStreamFour.timeStamp
insert into StationeryTable;
from innerStreamOne[isWithin == true AND not(StationeryTable.id == innerStreamOne.id in StationeryTable)]
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary
insert into dataOutStream;
from innerStreamOne[isWithin == true AND StationeryTable.id == innerStreamOne.id in StationeryTable]
insert into innerStreamFive;
from innerStreamFive#window.length(0) join StationeryTable
on innerStreamFive.id == StationeryTable.id
select innerStreamFive.id , innerStreamFive.latitude, innerStreamFive.longitude,innerStreamFive.timeStamp, innerStreamFive.type, innerStreamFive.speed, innerStreamFive.heading ,innerStreamFive.eventId, StationeryTable.timeStamp as storedTime
insert into innerStreamSix;
from innerStreamSix[(timeStamp - storedTime) >= $stationeryTime]
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"true" as isStationary
insert into dataOutStream;
from innerStreamSix[(timeStamp - storedTime) < $stationeryTime]
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"false" as isStationary
insert into dataOutStream;
from dataOutStream[isStationary == 'true']
select id ,latitude, longitude,timeStamp, type, speed, heading ,eventId ,"ALERTED" as state, "This device is in $stationeryName area!!!" as information
insert into dataOut;
from dataOutStream[isStationary == 'false']
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information
insert into dataOut;

@ -0,0 +1,17 @@
/* Enter a unique ExecutionPlan */
@Plan:name('$executionPlanName')
/* Enter a unique description for ExecutionPlan */
-- @Plan:description('ExecutionPlan')
/* define streams/tables and write queries here ... */
@Import('rawGeoStream:1.0.0')
define stream dataIn (id string, timeStamp long, geometry string, state string, information string);
@Export('AlertsNotifications:1.0.0')
define stream dataOut (id string, state string, information string, timeStamp long, latitude double, longitude double);
from dataIn[geo:intersects(geometry, "$geoFenceGeoJSON")==true and geodashboard:needToNotify(id, str:concat(information, state), "sendFirst") == true and id == $deviceId]
select id, state, str:concat("Traffic alert in $areaName. State: ", state, " ", information) as information, timeStamp, 0.0 as latitude, 0.0 as longitude
insert into dataOut

@ -0,0 +1,20 @@
/* Enter a unique ExecutionPlan */
@Plan:name('$executionPlanName')
/* Enter a unique description for ExecutionPlan */
-- @Plan:description('ExecutionPlan')
/* define streams/tables and write queries here ... */
@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string);
@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0')
define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string);
from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==true and id == "$deviceId"]#geodashboard:subscribe()
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is in $areaName restricted area!!!" as information
insert into dataOut;
from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=true and id == "$deviceId"]
select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information
insert into dataOut;

@ -0,0 +1,97 @@
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.point {
stroke: #000;
}
form {
margin-top: 25px;
text-align: center;
}
.slider {
width: 80%;
display: block;
margin: 0 auto;
}
output {
display: block;
margin: 25px auto;
font-size:2em;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: orange;
}
.bar:hover {
fill: orangered ;
}
.x.axis path {
display: none;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
z-index: 1000;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
.btn-space {
margin-right: 30px;
margin-bottom: 10px;
margin-top: 10px;
}
.element-space{
margin-right: 30px;
margin-bottom: 10px;
margin-top: 10px;
}

@ -0,0 +1,26 @@
{
"id": "geo-dashboard",
"title": "Geo Dashboard",
"type": "widget",
"thumbnail": "gadget/geo-dashboard/img/thumbnail.png",
"settings": {
"personalize": true
},
"data": {
"url": "gadget/geo-dashboard/index.xml"
},
"styles": {
"borders": false,
"title": false
},
"notify": {
"select": {
"type": "address",
"description": "This notifies selected state"
},
"cancel": {
"type": "boolean",
"description": "This notifies cancellation of state selection"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

@ -0,0 +1,31 @@
<%
/*
~ Copyright (c) 2016, 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 escapeSiddhiql = function (s) {
XML_CHAR_MAP = {
'<': '&lt;',
'>': '&gt;',
'&': '&amp;',
'"': '&quot;',
"'": '&apos;'
};
return s.replace(/[<>&"']/g, function (ch) {
return XML_CHAR_MAP[ch];
});
};
%>

@ -0,0 +1,165 @@
<%
/*
~ Copyright (c) 2016, 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.
*/
// TODO: change the name of this jaggery file even thoe it says 'store_alerts' it is actually removing the alerts from the data store as well o.O wired
var log = new Log();
var constants = require("../controllers/constants.jag");
var getRegistry = function() {
var carbon = require("carbon");
var server = new carbon.server.Server();
return new carbon.registry.Registry(server, {
system: true
});
};
/**
* Get the registry path to save the alert
* @param {String} alert_type Type of the alert
* @param {String} id Id of the device
* @param {String} optional /optional identity
* @return {String} Registry Path to save teh alert
* */
var registryPath = function (alert_type, id, optional) {
if (alert_type && id ) {
if (alert_type === constants.EXECUTION_PLAN_TYPE_SPEED || alert_type === constants
.EXECUTION_PLAN_TYPE_PROXIMITY) {
return constants.REGISTRY_PATH_FOR_ALERTS + alert_type + "/" + id;
} else {
return constants.REGISTRY_PATH_FOR_ALERTS + alert_type + "/" + id + "/" + optional;
}
} else {
throw "Alert type and ID are mandatory field to generate the relevant registry path";
}
};
/**
* To store the alerts for visualizing purposes
* @param resourceContents Value that need to saved
* @param executionPlan Type of the execution plan
* @param optional Optional parameters that are only specific to particular device types
* @param deviceId Id of the device
*/
function store(resourceContents, executionPlan, optional, deviceId) {
var registry = getRegistry();
var pathToAddAlert = "";
if (log.isDebugEnabled()) {
log.debug("DEBUG:*** resourceContents:" + resourceContents);
}
if (executionPlan === constants.EXECUTION_PLAN_TYPE_SPEED) {
pathToAddAlert = registryPath(constants.EXECUTION_PLAN_TYPE_SPEED, deviceId);
registry.put(pathToAddAlert, {
content: '{"speedLimit": ' + resourceContents + '}',
mediaType: 'application/json'
});
if (log.isDebugEnabled()) {
log.debug("DEBUG:*** Current speed limit set to:" + currentLimit.content);
}
}
else if (executionPlan === constants.EXECUTION_PLAN_TYPE_WITHIN) {
pathToAddAlert = registryPath(constants.EXECUTION_PLAN_TYPE_WITHIN, deviceId, optional.queryName);
if (log.isDebugEnabled()) {
log.debug("DEBUG:****** resourceContents = " + String('{"geoJson": ' + resourceContents + '}'));
}
registry.put(pathToAddAlert, {
content: JSON.stringify(resourceContents),
mediaType: 'application/json',
properties : {
"queryName" : optional.queryName,
"areaName" : optional.customName
}
});
} else if (executionPlan === constants.EXECUTION_PLAN_TYPE_PROXIMITY) {
pathToAddAlert = registryPath(constants.EXECUTION_PLAN_TYPE_PROXIMITY, deviceId);
if (log.isDebugEnabled()) {
log.debug("DEBUG:****** resourceContents = " + resourceContents);
}
registry.put(pathToAddAlert, {
content: "",
mediaType: 'application/json'
});
registry.addProperty(pathToAddAlert, "proximityDistance", resourceContents.proximityDistance);
registry.addProperty(pathToAddAlert, "proximityTime", resourceContents.proximityTime);
} else if (executionPlan === constants.EXECUTION_PLAN_TYPE_STATIONARY) {
pathToAddAlert = registryPath(constants.EXECUTION_PLAN_TYPE_STATIONARY, deviceId, optional.queryName);
if (log.isDebugEnabled()) {
log.debug("DEBUG:****** resourceContents = " + resourceContents);
}
var registryResource = {
content: JSON.stringify(resourceContents.geoFenceGeoJSON),
mediaType: 'application/json',
properties: {
"queryName" : optional.queryName,
"stationeryName" : optional.customName,
"stationeryTime" : resourceContents.stationeryTime,
"fluctuationRadius" : resourceContents.fluctuationRadius
}
};
registry.put(pathToAddAlert, registryResource);
} else if (executionPlan === constants.EXECUTION_PLAN_TYPE_TRAFFIC) {
pathToAddAlert = registryPath(constants.EXECUTION_PLAN_TYPE_TRAFFIC, deviceId, optional.queryName);
if (log.isDebugEnabled()) {
log.debug("DEBUG:****** resourceContents = " + resourceContents.geoFenceGeoJSON);
}
var registryResource = {
content: JSON.stringify(resourceContents),
mediaType: 'application/json',
properties: {
"queryName" : optional.queryName,
"stationeryName" : optional.customName,
"stationeryTime" : resourceContents.stationeryTime,
"fluctuationRadius" : resourceContents.fluctuationRadius
}
};
registry.put(pathToAddAlert, {
content: JSON.stringify(resourceContents),
mediaType: 'application/json',
properties: {
"queryName" : optional.queryName,
"areaName" : optional.customName
}
});
}
}
/**
* To remove the registry resource
* @param queryName Name of the query that need to be removed
* @param executionPlanType type of the execution plan that need to be removed
* @param deviceId Id of the device
*/
function remove(queryName, executionPlanType, deviceId) {
var path = "";
try {
if (executionPlanType === constants.EXECUTION_PLAN_TYPE_SPEED || executionPlanType === constants.EXECUTION_PLAN_TYPE_PROXIMITY) {
path = registryPath(executionPlanType, deviceId);
} else {
path = registryPath(executionPlanType, deviceId, queryName);
}
getRegistry().remove(path);
if (log.isDebugEnabled()) {
log.debug("Resource is removed from the path" + path);
}
}
catch (e) {
log.error("The requested resource " + path + " was not found on this server.");
}
}
%>

@ -0,0 +1,196 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
~ Copyright (c) 2016, 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.
-->
<Module>
<ModulePrefs title="Location Data" description="Location Data">
<Require feature="dynamic-height" />
<Require feature="dynamic-width" />
<Require feature="wso2-gadgets-identity" />
<Require feature="wso2-gadgets-state" />
</ModulePrefs>
<Content type="html">
<![CDATA[
<html>
<meta charset="utf-8">
<head>
<link rel="stylesheet" href="css/style.css">
</head>
<link rel="stylesheet" type="text/css" href="css/style.css">
<script src="lib/js/jquery.js"></script>
<body>
<link rel="stylesheet" href="lib/css/bootstrap.css">
<script src="lib/js/bootstrap.js"></script>
<script src="lib/js/d3.js"></script>
<script src="js/RestCaller.js"></script>
<script src="js/graph.js"></script>
<script src="js/traffic.js"></script>
<script src="lib/js/d3tip.js"></script>
<script>
var imageX=-30;
var imageY=-5
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 1400 - margin.left - margin.right,
height = 744 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([0,height]);
loadImage(imageX,imageY);
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
loadImage(imageX,imageY);
getDimension();
GetInitStartTime();
GetEndTime();
</script>
<div class="well">
<div class="container">
<div class="col-sm-4">
<h3 class="text-primary">Select Time</h3>
<input class="slider form-control input-sm" type="range" id="valueSlider" value="" step="1000" min="01170000853070" max="01172715042247" oninput="outputUpdate(value)">
<output for=value id="output" hidden="true"></output>
<output id="calenderDate"></output>
<div hidden="true">
<label for="stt">Starting Time</label>
<input id="stt" name="stt" onchange="show()">
</div>
</div>
<div class="col-sm-5">
<h3 class="text-primary">Select Duration</h3>
<select class="form-control input-sm-4" id="gap" name="gap" onclick="changeStep()">
<option value=1000>1s</option>
<option value=5000>5s</option>
<option value=15000>15s</option>
<option value=30000>30s</option>
<option value=60000>1min</option>
<option value=300000>5min</option>
<option value=600000>10min</option>
<option value=3600000>1hour</option>
<option value=7200000>2hour</option>
<option value=86400000>1day</option>
</select>
</br>
<button class="btn btn-default btn-space" onclick="show() "style="align-content: center;width: 110px;height: 40px" >Show</button>
<button class="btn btn-default btn-space" onclick="showPrevious()"style="align-content: center;width: 110px;height: 40px">Previous</button>
<button class="btn btn-default btn-space" onclick="showNext()"style="align-content: center;width: 110px;height: 40px">Next</button>
<button class="btn btn-primary btn-space" onclick="play()"style="align-content: center;width: 110px;height: 40px">Play</button>
<button class="btn btn-default btn-space" onclick="showDensity()"style="align-content: center;width: 110px;height: 40px">Show Density</button>
<button class="btn btn-default btn-space" onclick="display()"style="align-content: center;width: 110px;height: 40px">Reset</button>
</div>
</div>
</div>
<div class="well">
<div class="container">
<div class="col-sm-4">
<div class="container">
<h3 class="text-primary">Typical Scenario</h3>
<select class="form-control input-sm-4 element-space" id="time" name="time" style="width: 200px" >
<option value=00>0AM</option>
<option value=01>1AM</option>
<option value=02>2AM</option>
<option value=03>3AM</option>
<option value=04>4AM</option>
<option value=05>5AM</option>
<option value=06>6AM</option>
<option value=07>7AM</option>
<option value=08>8AM</option>
<option value=09>9AM</option>
<option value=10>10AM</option>
<option value=11>11AM</option>
<option value=12>12AM</option>
<option value=13>1PM</option>
<option value=14>2PM</option>
<option value=15>3PM</option>
<option value=16>4PM</option>
<option value=17>5PM</option>
<option value=18>6PM</option>
<option value=19>7PM</option>
<option value=20>8PM</option>
<option value=21>9PM</option>
<option value=22>10PM</option>
<option value=23>11PM</option>
</select>
<select class="form-control input-sm-4 element-space" id="day" name="day" style="width: 200px" >
<option value=mon>Monday</option>
<option value=tue>Tuesday</option>
<option value=wed>Wednesday</option>
<option value=thu>Thursday</option>
<option value=fri>Friday</option>
<option value=sat>Saturday</option>
<option value=sun>Sunday</option>
</select>
<button class="btn btn-primary element-space" onclick="showScene()"style="align-content: center;width: 110px;height: 40px" >View Scenario</button>
</div>
</div>
<div class="col-sm-4 " >
<h3 class="text-primary">Upload Data file</h3>
<input class="form-control input-sm-4 element-space" id="fileupload" type="file" />
<Button class="btn btn-primary element-space" onclick="sendFile()" id="submit" style="align-content: center;width: 110px;height: 40px">Submit</Button>
</div>
<div class="col-sm-4 " >
<h3 class="text-primary">Change Image</h3>
<button class="btn btn-default btn-space" onclick="changeImage(0,1)"style="align-content: center;width: 110px;height: 40px" >Up</button>
<button class="btn btn-default btn-space" onclick="changeImage(0,-1)"style="align-content: center;width: 110px;height: 40px">Down</button>
<button class="btn btn-default btn-space" onclick="changeImage(1,0)"style="align-content: center;width: 110px;height: 40px">Left</button>
<button class="btn btn-default btn-space" onclick="changeImage(-1,0)"style="align-content: center;width: 110px;height: 40px">Right</button>
<button class="btn btn-default btn-space" onclick="showDensity()"style="align-content: center;width: 110px;height: 40px">Show Density</button>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade row-fluid" id="frequency_view" role="dialog" >
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content" style="width: 1000px">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Sensor Triggered Frequencies</h4>
</div>
<div id="modal_body" name="modal_body" class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</body>
</html>
]]>
</Content>
</Module>

@ -0,0 +1,478 @@
require("lib/js/d3.js");
require("js/graph.js");
require("js/traffic.js");
require("lib/js/d3tip.js");
var GetInitStartTime = function () {
$.ajax({
url: 'http://localhost:8080/service/time/start',
type: 'GET',
dataType:'json',
success: function(data) {
var start =JSON.parse(JSON.stringify(data.stt));
document.getElementById("stt").value=start;
var valueSlider =document.getElementById("valueSlider");
valueSlider.innerHTML=start;
valueSlider.value=start;
valueSlider.min=parseInt(start);
setCalendarDate(start);
//alert(JSON.stringify(data));
},
error:function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
};
var GetEndTime = function () {
$.ajax({
url: 'http://localhost:8080/service/time/end',
type: 'GET',
dataType:'json',
success: function(data) {
var end =JSON.parse(JSON.stringify(data.stt));
document.getElementById("valueSlider").max =end;
show();
//alert(JSON.stringify(data));
},
error:function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
};
var show = function () {
var start = parseInt(document.getElementById('stt').value);
document.getElementById('valueSlider').value = start;
var end = start + parseInt(document.getElementById('gap').value);
var data2 = [];
$.ajax({
url: 'http://localhost:8080/service/data',
type: 'GET',
data: 'start=' + start + '&end=' + end, // or $('#myform').serializeArray()
dataType: 'json',
success: function (data) {
var X = JSON.parse(JSON.stringify(data.map.X.myArrayList));
var Y = JSON.parse(JSON.stringify(data.map.Y.myArrayList));
for (i = 0; i < X.length; i++) {
data2.push({x: X[i], y: Y[i]});
}
draw(data2);
//alert(JSON.stringify(data));
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
};
function sendFile() {
var file = document.getElementById('fileupload').files[0];
var fd = new FormData();
fd.append( 'file', file);
$.ajax({
url: 'http://localhost:8080/service/file/upload',
data: fd,
processData: false,
contentType: false,
type: 'POST',
success: function(data) {
alert("file upload sucessfull");
GetInitStartTime();
GetEndTime();
show();
//alert(JSON.stringify(data));
},
error:function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
}
function getDimension() {
var url;
var value;
$.ajax({
url: 'http://localhost:8080/service/get/dimension',
type: 'GET',
dataType: 'json',
success: function (data) {
Xmax = JSON.parse(JSON.stringify(data.maxX));
Ymax = JSON.parse(JSON.stringify(data.maxY));
Xmin = JSON.parse(JSON.stringify(data.minX));
Ymin = JSON.parse(JSON.stringify(data.minY));
x.domain(d3.extent([Xmin,Xmax])).nice();
y.domain(d3.extent([Ymin,Ymax])).nice();
return value;
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
})
x.domain(d3.extent([-50,50])).nice();
y.domain(d3.extent([-100,100])).nice();
}
function play(start,chunk) {
var start=parseInt(document.getElementById('stt').value);
var chunk =parseInt(document.getElementById('gap').value)
var end = parseInt(start) + (500*parseInt(chunk));
// var data2 =[];
var xList,yList,tList,cList;
$.ajax({
url: 'http://localhost:8080/service/data/chunk',
type: 'GET',
data: 'start='+start+'&end='+end, // or $('#myform').serializeArray()
dataType:'json',
success: function(data) {
alert("data loaded");
xList=JSON.parse(JSON.stringify(data.X));
yList=JSON.parse(JSON.stringify(data.Y));
tList=JSON.parse(JSON.stringify(data.T));
cList=JSON.parse(JSON.stringify(data.C));
var i=0;
while(i<500){
var s=parseInt(start)+(i*1000);
doScaledTimeout(i,s,tList,chunk,xList,yList,cList);
i+=1;
}
},
error:function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
}
var draw=function (data) {
svg.selectAll(".series").remove();
svg.selectAll(".g").remove();
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x"; })
.sort();
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +parseFloat(d.x), y: +parseFloat(d.y),c:+parseFloat(d.c)};
});
});
// Compute the scales domains.
// Add the x-axis.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"))
// Add the y-axis.
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Add the points!
svg.selectAll(".series")
.data(series)
.enter().append("g")
.attr("class", "series")
.selectAll(".point")
.data(function(d) {
return d; })
.enter().append("circle")
.attr("class", "point")
.style("fill", function (d) {
if(isNaN(d.c)){
return colorRed(50);
}
return d3.rgb(255,d.c*255/100,d.c*255/100);
})
.attr("r", 4.5)
.attr("cx", function(d) {
return x(parseFloat(d.x));})
.attr("cy", function(d) {
return y(parseFloat(d.y));})
};
function require(script) {
$.ajax({
url: script,
dataType: "script",
async: false,
success: function () {
},
error: function () {
throw new Error("Could not load script " + script);
}
});
}
function showDensity() {
var start = parseInt(document.getElementById('stt').value);
document.getElementById('valueSlider').value = start;
var end = start + parseInt(document.getElementById('gap').value);
var data2 = [];
$.ajax({
url: 'http://localhost:8080/service/data/density',
type: 'GET',
data: 'start=' + parseInt(document.getElementById('stt').value) + '&end=' +(parseInt(document.getElementById('stt').value)+ parseInt(document.getElementById('gap').value)), // or $('#myform').serializeArray()
dataType: 'json',
success: function (data) {
var X = JSON.parse(JSON.stringify(data.map.X.myArrayList));
var Y = JSON.parse(JSON.stringify(data.map.Y.myArrayList));
var D = JSON.parse(JSON.stringify(data.map.D.myArrayList));
var ID = JSON.parse(JSON.stringify(data.map.ID.myArrayList));
for (i = 0; i < X.length; i++) {
data2.push({x: X[i], y: Y[i], c:parseInt(D[i]), id:ID[i]});
}
var max=D[0];
var min=D[0];
for (j=1;j<X.length;j++){
if(D[j]>max){
max=D[j];
}
if(D[j]<min){
min=D[j];
}
}
drawDensity(data2,max,min);
//alert(JSON.stringify(data));
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
};
var drawDensity=function (data,max,min) {
svg.selectAll(".series").remove();
svg.selectAll(".g").remove();
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x" && d!=="c" && d!="id"; })
.sort();
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +parseFloat(d.x), y: +parseFloat(d.y),c:+(parseFloat(d.c)-min)*100/(max-min), id:parseInt(d.id)};
});
});
// Compute the scales domains.
x.domain(d3.extent([-71,40])).nice();
y.domain(d3.extent([4,65])).nice();
// Add the x-axis.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
// Add the y-axis.
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
// Add the points!
svg.selectAll(".series")
.data(series)
.enter().append("g")
.attr("class", "series")
.selectAll(".point")
.data(function(d) {
return d; })
.enter().append("circle")
.attr("class", "point")
.style("fill", function (d) {
if(d.c==0){
return d3.rgb(255,255,255);
}
else if(d.c>20){
return colorRed(d.c);
}
else if(d.c>10){
return colorBlue(d.c);
}
else if(d.c>=0){
return colorGreen(d.c);
}
else{
return d3.rgb(255,255,255);
}
})
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html((d.c).toFixed(2) )
.style("left", (x(parseInt(d.x)) + "px"))
.style("top", (y(parseInt(d.y)) + "px"));
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
.attr("r", 4.5)
.attr("cx", function(d) {
return x(parseFloat(d.x));})
.attr("cy", function(d) {
return y(parseFloat(d.y));})
.on("click",function (d){
var id=d.id;
getFrequency(id);
});
};
function getFrequency(id) {
var start = parseInt(document.getElementById('stt').value);
document.getElementById('valueSlider').value = start;
var gap = parseInt(document.getElementById('gap').value);
var data1 = [];
$.ajax({
url:'http://localhost:8080/service/data/count',
type: 'GET',
data: 'start=' + start + '&gap=' + gap + '&sensor=' + id, // or $('#myform').serializeArray()
dataType: 'json',
success: function (data) {
var count = JSON.parse(JSON.stringify(data.map.Count.myArrayList));
for (i = 0; i < count.length; i++) {
var gap = parseInt(document.getElementById('gap').value);
data1.push({x: tsToCal(gap,(gap*i)+start+(gap/2.0)), y: count[i]});
}
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x" && d!=="c" && d!="id"; })
.sort();
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +i, y: d.y};
});
});
var stt = parseInt(document.getElementById("stt").value);
var gap = parseInt(document.getElementById("gap").value);
d3.select("#barChart").remove();
var margin = {top: 40, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg2 = d3.select("#modal_body").append("svg")
.attr("id","barChart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
return d.y;
});
svg2.call(tip);
x.domain(data1.map(function(d) {
return d.x; }));
y.domain([0, d3.max(data1, function(d) {
return d.y; })]);
svg2.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg2.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Frequency");
svg2.selectAll(".bar")
.data(data1)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {return x(d.x); })
.attr("width", x.rangeBand())
.attr("y", function(d) {return y(d.y); })
.attr("height", function(d) { return height - y(d.y); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
function type(d) {
d.y = +d.y;
return d;
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
$("#frequency_view").modal("show");
}

@ -0,0 +1,111 @@
/**
* Created by dimuth on 10/25/16.
*/
function setCalendarDate(start){
var calendarTime=timeStampToCalendarDate(start);
document.getElementById("calenderDate").innerHTML=calendarTime;
}
var showNext =function () {
var currentStart = parseInt(document.getElementById('stt').value);
var duration = parseInt(document.getElementById('gap').value);
document.getElementById("stt").value =currentStart+duration;
show();
};
var showPrevious =function () {
var currentStart = parseInt(document.getElementById('stt').value);
var duration = parseInt(document.getElementById('gap').value);
document.getElementById("stt").value =currentStart-duration;
show();
};
function outputUpdate(num) {
document.querySelector('#output').value = num;
document.getElementById('stt').value =num;
setCalendarDate(num);
show();
}
function changeStep() {
document.getElementById("valueSlider").step =document.getElementById("gap").value;
}
function timeStampToCalendarDate(time) {
var date = new Date(parseInt(time));
var Months =["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
return date.getFullYear()+" "+Months[date.getMonth()]+" "+date.getDate()+" "+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
}
function showChunk(start,chunk,tList,xList,yList) {
var data2=[];
var gap=document.getElementById("gap").value;
var e=parseInt(start)+parseInt(chunk);
for(i=0;i<tList.length;i++ ){
if(parseInt(tList[i])<e && parseInt(tList[i])>parseInt(start)){
data2.push({x:xList[i] ,y:yList[i], c:((e-parseInt(tList[i]))*100/parseInt(gap))});
}
}
return data2;
}
function doScaledTimeout(j,start,tList,chunk,xList,yList,cList) {
setTimeout(function() {
document.getElementById('stt').value=start;
document.getElementById('output').value=start;
setCalendarDate(start);
var data2=showChunk(start,chunk,tList,xList,yList,cList);
draw(data2);
}, j * 300);
}
colorRed = d3.scale.linear().domain([20,100])
.interpolate(d3.interpolateHcl)
.range([d3.rgb('#F99FA2'),d3.rgb("#F72128"),]);
colorBlue = d3.scale.linear().domain([10,20])
.interpolate(d3.interpolateHcl)
.range([d3.rgb("#00C1FF"),d3.rgb('#6670AC')]);
colorGreen = d3.scale.linear().domain([10,0])
.interpolate(d3.interpolateHcl)
.range([d3.rgb("#0A7E03"),d3.rgb('#0FF300')]);
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
function tsToCal(gap,time) {
var date = new Date(parseInt(time));
var Months =["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
if(gap < 60000){
return date.getMinutes()+":"+date.getSeconds();
}
else if(gap <=7200000) {
return Months[date.getMonth()]+" "+date.getDate() + " " + date.getHours() + ":" + date.getMinutes();
}
else{
return date.getFullYear()+" "+Months[date.getMonth()]+" "+date.getDate();
}
}
function display() {
window.location.reload();
};
function loadImage(x,y) {
var image = d3.select("g").append("svg:image")
.attr("xlink:href", "img/floor.jpg")
.attr("width", 1500)
.attr("height", 699)
.attr("x",x)
.attr("y",y);
}
function changeImage(x,y) {
imageX=imageX+x;
imageY=imageY+y;
loadImage(imageX,imageY);
}
colorData = d3.scale.linear().domain([10,0])
.interpolate(d3.interpolateHcl)
.range([d3.rgb(125,0,0),d3.rgb(255,0,0)]);

@ -0,0 +1,130 @@
/**
* Created by dimuth on 11/2/16.
*/
var drawScene=function (data) {
svg.selectAll(".series").remove();
svg.selectAll(".g").remove();
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x" && d!=="c" && d!="id"; })
.sort();
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +parseFloat(d.x), y: +parseFloat(d.y),c:+(parseFloat(d.c)), id:parseInt(d.id)};
});
});
// Compute the scales domains.
x.domain(d3.extent([-71,40])).nice();
y.domain(d3.extent([4,65])).nice();
// Add the x-axis.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
// Add the y-axis.
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
// Add the points!
svg.selectAll(".series")
.data(series)
.enter().append("g")
.attr("class", "series")
.selectAll(".point")
.data(function(d) {
return d; })
.enter().append("circle")
.attr("class", "point")
.style("fill", function (d) {
if(d.c==0){
return d3.rgb(255,255,255);
}
else if(d.c>10){
return colorRed(d.c);
}
else if(d.c>3){
return colorBlue(d.c);
}
else if(d.c>=0){
return colorGreen(d.c);
}
else{
return d3.rgb(255,255,255);
}
})
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html((d.c).toFixed(2) )
.style("left", (x(parseInt(d.x)) + "px"))
.style("top", (y(parseInt(d.y)) + "px"));
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
.attr("r", 4.5)
.attr("cx", function(d) {
return x(parseFloat(d.x));})
.attr("cy", function(d) {
return y(parseFloat(d.y));});
};
function showScene() {
var data2 = [];
$.ajax({
url: 'http://localhost:8080/service/typical/scene',
type: 'GET',
data: 'hour=' + document.getElementById('time').value + '&day=' +document.getElementById('day').value, // or $('#myform').serializeArray()
dataType: 'json',
success: function (data) {
var X = JSON.parse(JSON.stringify(data.X));
var Y = JSON.parse(JSON.stringify(data.Y));
var C = JSON.parse(JSON.stringify(data.C));
var ID = JSON.parse(JSON.stringify(data.ID));
for (i = 0; i < X.length; i++) {
data2.push({x: X[i], y: Y[i], c:C[i], id:ID[i]});
}
drawScene(data2);
//alert(JSON.stringify(data));
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
};
colorRed2 = d3.scale.linear().domain([10,100])
.interpolate(d3.interpolateHcl)
.range([d3.rgb('#F99FA2'),d3.rgb("#F72128"),]);
colorBlue2 = d3.scale.linear().domain([3,10])
.interpolate(d3.interpolateHcl)
.range([d3.rgb("#00C1FF"),d3.rgb('#6670AC')]);
colorGreen2 = d3.scale.linear().domain([3,0])
.interpolate(d3.interpolateHcl)
.range([d3.rgb("#0A7E03"),d3.rgb('#0FF300')]);

File diff suppressed because it is too large Load Diff

@ -0,0 +1,352 @@
/**
* d3.tip
* Copyright (c) 2013 Justin Palmer
*
* Tooltips for d3.js SVG visualizations
*/
// eslint-disable-next-line no-extra-semi
;(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module with d3 as a dependency.
define([
'd3-collection',
'd3-selection'
], factory)
} else if (typeof module === 'object' && module.exports) {
/* eslint-disable global-require */
// CommonJS
var d3Collection = require('d3-collection'),
d3Selection = require('d3-selection')
module.exports = factory(d3Collection, d3Selection)
/* eslint-enable global-require */
} else {
// Browser global.
var d3 = root.d3
// eslint-disable-next-line no-param-reassign
root.d3.tip = factory(d3, d3)
}
}(this, function(d3Collection, d3Selection) {
// Public - contructs a new tooltip
//
// Returns a tip
return function() {
var direction = d3TipDirection,
offset = d3TipOffset,
html = d3TipHTML,
rootElement = document.body,
node = initNode(),
svg = null,
point = null,
target = null
function tip(vis) {
svg = getSVGNode(vis)
if (!svg) return
point = svg.createSVGPoint()
rootElement.appendChild(node)
}
// Public - show the tooltip on the screen
//
// Returns a tip
tip.show = function() {
var args = Array.prototype.slice.call(arguments)
if (args[args.length - 1] instanceof SVGElement) target = args.pop()
var content = html.apply(this, args),
poffset = offset.apply(this, args),
dir = direction.apply(this, args),
nodel = getNodeEl(),
i = directions.length,
coords,
scrollTop = document.documentElement.scrollTop ||
rootElement.scrollTop,
scrollLeft = document.documentElement.scrollLeft ||
rootElement.scrollLeft
nodel.html(content)
.style('opacity', 1).style('pointer-events', 'all')
while (i--) nodel.classed(directions[i], false)
coords = directionCallbacks.get(dir).apply(this)
nodel.classed(dir, true)
.style('top', (coords.top + poffset[0]) + scrollTop + 'px')
.style('left', (coords.left + poffset[1]) + scrollLeft + 'px')
return tip
}
// Public - hide the tooltip
//
// Returns a tip
tip.hide = function() {
var nodel = getNodeEl()
nodel.style('opacity', 0).style('pointer-events', 'none')
return tip
}
// Public: Proxy attr calls to the d3 tip container.
// Sets or gets attribute value.
//
// n - name of the attribute
// v - value of the attribute
//
// Returns tip or attribute value
// eslint-disable-next-line no-unused-vars
tip.attr = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return getNodeEl().attr(n)
}
var args = Array.prototype.slice.call(arguments)
d3Selection.selection.prototype.attr.apply(getNodeEl(), args)
return tip
}
// Public: Proxy style calls to the d3 tip container.
// Sets or gets a style value.
//
// n - name of the property
// v - value of the property
//
// Returns tip or style property value
// eslint-disable-next-line no-unused-vars
tip.style = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return getNodeEl().style(n)
}
var args = Array.prototype.slice.call(arguments)
d3Selection.selection.prototype.style.apply(getNodeEl(), args)
return tip
}
// Public: Set or get the direction of the tooltip
//
// v - One of n(north), s(south), e(east), or w(west), nw(northwest),
// sw(southwest), ne(northeast) or se(southeast)
//
// Returns tip or direction
tip.direction = function(v) {
if (!arguments.length) return direction
direction = v == null ? v : functor(v)
return tip
}
// Public: Sets or gets the offset of the tip
//
// v - Array of [x, y] offset
//
// Returns offset or
tip.offset = function(v) {
if (!arguments.length) return offset
offset = v == null ? v : functor(v)
return tip
}
// Public: sets or gets the html value of the tooltip
//
// v - String value of the tip
//
// Returns html value or tip
tip.html = function(v) {
if (!arguments.length) return html
html = v == null ? v : functor(v)
return tip
}
// Public: sets or gets the root element anchor of the tooltip
//
// v - root element of the tooltip
//
// Returns root node of tip
tip.rootElement = function(v) {
if (!arguments.length) return rootElement
rootElement = v == null ? v : functor(v)
return tip
}
// Public: destroys the tooltip and removes it from the DOM
//
// Returns a tip
tip.destroy = function() {
if (node) {
getNodeEl().remove()
node = null
}
return tip
}
function d3TipDirection() { return 'n' }
function d3TipOffset() { return [0, 0] }
function d3TipHTML() { return ' ' }
var directionCallbacks = d3Collection.map({
n: directionNorth,
s: directionSouth,
e: directionEast,
w: directionWest,
nw: directionNorthWest,
ne: directionNorthEast,
sw: directionSouthWest,
se: directionSouthEast
}),
directions = directionCallbacks.keys()
function directionNorth() {
var bbox = getScreenBBox()
return {
top: bbox.n.y - node.offsetHeight,
left: bbox.n.x - node.offsetWidth / 2
}
}
function directionSouth() {
var bbox = getScreenBBox()
return {
top: bbox.s.y,
left: bbox.s.x - node.offsetWidth / 2
}
}
function directionEast() {
var bbox = getScreenBBox()
return {
top: bbox.e.y - node.offsetHeight / 2,
left: bbox.e.x
}
}
function directionWest() {
var bbox = getScreenBBox()
return {
top: bbox.w.y - node.offsetHeight / 2,
left: bbox.w.x - node.offsetWidth
}
}
function directionNorthWest() {
var bbox = getScreenBBox()
return {
top: bbox.nw.y - node.offsetHeight,
left: bbox.nw.x - node.offsetWidth
}
}
function directionNorthEast() {
var bbox = getScreenBBox()
return {
top: bbox.ne.y - node.offsetHeight,
left: bbox.ne.x
}
}
function directionSouthWest() {
var bbox = getScreenBBox()
return {
top: bbox.sw.y,
left: bbox.sw.x - node.offsetWidth
}
}
function directionSouthEast() {
var bbox = getScreenBBox()
return {
top: bbox.se.y,
left: bbox.se.x
}
}
function initNode() {
var div = d3Selection.select(document.createElement('div'))
div
.style('position', 'absolute')
.style('top', 0)
.style('opacity', 0)
.style('pointer-events', 'none')
.style('box-sizing', 'border-box')
return div.node()
}
function getSVGNode(element) {
var svgNode = element.node()
if (!svgNode) return null
if (svgNode.tagName.toLowerCase() === 'svg') return svgNode
return svgNode.ownerSVGElement
}
function getNodeEl() {
if (node == null) {
node = initNode()
// re-add node to DOM
rootElement.appendChild(node)
}
return d3Selection.select(node)
}
// Private - gets the screen coordinates of a shape
//
// Given a shape on the screen, will return an SVGPoint for the directions
// n(north), s(south), e(east), w(west), ne(northeast), se(southeast),
// nw(northwest), sw(southwest).
//
// +-+-+
// | |
// + +
// | |
// +-+-+
//
// Returns an Object {n, s, e, w, nw, sw, ne, se}
function getScreenBBox() {
var targetel = target || d3Selection.event.target
while (targetel.getScreenCTM == null && targetel.parentNode == null) {
targetel = targetel.parentNode
}
var bbox = {},
matrix = targetel.getScreenCTM(),
tbbox = targetel.getBBox(),
width = tbbox.width,
height = tbbox.height,
x = tbbox.x,
y = tbbox.y
point.x = x
point.y = y
bbox.nw = point.matrixTransform(matrix)
point.x += width
bbox.ne = point.matrixTransform(matrix)
point.y += height
bbox.se = point.matrixTransform(matrix)
point.x -= width
bbox.sw = point.matrixTransform(matrix)
point.y -= height / 2
bbox.w = point.matrixTransform(matrix)
point.x += width
bbox.e = point.matrixTransform(matrix)
point.x -= width / 2
point.y -= height / 2
bbox.n = point.matrixTransform(matrix)
point.y += height
bbox.s = point.matrixTransform(matrix)
return bbox
}
// Private - replace D3JS 3.X d3.functor() function
function functor(v) {
return typeof v === 'function' ? v : function() {
return v
}
}
return tip
}
// eslint-disable-next-line semi
}));

File diff suppressed because it is too large Load Diff

@ -1,8 +1,47 @@
<iframe src="{{dashboardserverURL}}/portal/gadgets/connected-cup-analytics/landing" width="100%" height="1700" frameBorder="0"></iframe>
{{!
Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
<style>
#rangeSliderWrapper{ display: none;}
</style>
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.
}}
<span id="connectedcup-details" data-devices="{{devices}}" data-devicename="{{device.name}}"
data-deviceid="{{device.deviceIdentifier}}"
data-appcontext="{{@app.context}}"></span>
<div id="connectedcup-div-chart" data-backend-api-url= {{backendApiUri}}>
<div class="chartWrapper" id="chartWrapper">
<h3 id="span-title">Temperature</h3>
<div id="y_axis-temperature" class="custom_y_axis"></div>
<div class="legend_container">
<div id="smoother-temperature" title="Smoothing"></div>
<div id="legend-temperature"></div>
</div>
<div id="chart-temperature" class="custom_rickshaw_graph"></div>
<div id="x_axis-temperature" class="custom_x_axis"></div>
<div id="slider-temperature" class="custom_slider"></div>
</div>
<div class="chartWrapper" id="chartWrapper">
<h3 id="span-title">Coffee Level</h3>
<div id="y_axis-coffeelevel" class="custom_y_axis"></div>
<div class="legend_container">
<div id="smoother-coffeelevel" title="Smoothing"></div>
<div id="legend-coffeelevel"></div>
</div>
<div id="chart-coffeelevel" class="custom_rickshaw_graph"></div>
<div id="x_axis-coffeelevel" class="custom_x_axis"></div>
<div id="slider-coffeelevel" class="custom_slider"></div>
</div>
</div>
{{#zone "bottomJs"}}
{{js "js/connectedcup.js"}}

@ -17,29 +17,25 @@
*/
function onRequest(context) {
var devicemgtProps = require('/app/conf/devicemgt-props.js').config();
var devices = context.unit.params.devices;
var deviceType = context.uriParams.deviceType;
var deviceId = request.getParameter('deviceId');
var deviceId = request.getParameter("deviceId");
if (devices) {
return {
'devices': stringify(devices),
'backendApiUri': devicemgtProps['httpsURL'] + '/connectedcup/stats/',
'dashboardserverURL': devicemgtProps['dashboardserverURL']
"devices": stringify(devices),
"backendApiUri": "/connectedcup/stats/"
};
} else if (deviceType && deviceId) {
var deviceModule = require('/app/modules/device.js').deviceModule;
} else if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) {
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
var device = deviceModule.viewDevice(deviceType, deviceId);
if (device && device.status != 'error') {
if (device && device.status != "error") {
return {
'device': device.content,
'backendApiUri': devicemgtProps['httpsURL'] + '/connectedcup/stats/' + deviceId,
'dashboardserverURL': devicemgtProps['dashboardserverURL']
"device": device.content,
"backendApiUri": "/connectedcup/stats/" + deviceId
};
} else {
response.sendError(404, 'Device Id ' + deviceId + ' of type ' + deviceType + ' cannot be found!');
response.sendError(404, "Device Id " + deviceId + " of type " + deviceType + " cannot be found!");
exit();
}
}

@ -224,7 +224,8 @@ function drawGraph_connectedcup(from, to) {
if (devices) {
getData();
} else {
var backendApiUrl = $('#connectedcup-div-chart').data('backend-api-url') + '/sensors/temperature' + '?from=' + from + '&to=' + to;
var backendApiUrl = $('#connectedcup-div-chart').data('backend-api-url') + '/sensors/temperature'
+ '?from=' + from + '&to=' + to;
var successCallback = function (data) {
if (data) {
drawTemperatureLineGraph(JSON.parse(data));
@ -249,8 +250,7 @@ function drawGraph_connectedcup(from, to) {
return;
}
var backendApiUrl = $('#connectedcup-div-chart').data('backend-api-url') + devices[deviceIndex].deviceIdentifier
+ '/sensors/temperature'
+ '?from=' + from + '&to=' + to;
+ '/sensors/temperature?from=' + from + '&to=' + to;
var successCallback = function (data) {
if (data) {
drawTemperatureLineGraph(JSON.parse(data));
@ -264,7 +264,7 @@ function drawGraph_connectedcup(from, to) {
getData();
});
var coffeeLevelApiUrl = $('#connectedcup-div-chart').data('backend-api-url') + devices[deviceIndex].deviceIdentifier
+ '/sensors/coffeelevel' + '?from=' + from + '&to=' + to;
+ '/sensors/coffeelevel?from=' + from + '&to=' + to;
var successCallbackCoffeeLevel = function (data) {
if (data) {

@ -24,26 +24,23 @@
</div>
{{/zone}}
{{#zone "device-detail-properties"}}
<div class="media">
<div class="media-left col-xs-12 col-sm-2 col-md-2 col-lg-2">
<ul class="list-group" role="tablist">
<li class="active">
<a class="list-group-item" href="#device_statistics" role="tab" data-toggle="tab"
aria-controls="device_statistics">Device Statistics</a>
{{#zone "device-view-tabs"}}
<li class="active"><a class="list-group-item" href="#device_statistics" role="tab"
data-toggle="tab" aria-controls="device_statistics">Device
Statistics</a>
</li>
<li><a class="list-group-item" href="#event_log" role="tab" data-toggle="tab"
aria-controls="event_log">Operations Log</a></li>
</ul>
</div>
<div class="media-body add-padding-left-5x remove-padding-xs tab-content">
<div class="panel-group tab-content">
{{/zone}}
{{#zone "device-view-tab-contents"}}
<div class="panel panel-default tab-pane active"
id="device_statistics" role="tabpanel" aria-labelledby="device_statistics">
<div class="panel-heading">Device Statistics</div>
{{unit "cdmf.unit.device.type.connectedcup.realtime.analytics-view" device=device}}
</div>
<div class="panel panel-default tab-pane" id="event_log" role="tabpanel"
aria-labelledby="event_log">
<div class="panel-heading">Operations Log <span><a href="#"
@ -52,9 +49,9 @@
<div class="panel-body">
<div id="operations-spinner" class="wr-advance-operations-init hidden">
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<i class="fw fw-settings fw-spin fw-2x"></i>
&nbsp;&nbsp;&nbsp;
Loading Operations Log . . .
<br>
<br>
@ -67,7 +64,4 @@
</div>
</div>
</div>
</div>
</div>
</div>
{{/zone}}

@ -18,26 +18,23 @@
function onRequest(context) {
var log = new Log('detail.js');
var deviceType = context.uriParams.deviceType;
var deviceId = request.getParameter('id');
var devicemgtProps = require('/app/conf/devicemgt-props.js').config();
if (deviceType && deviceId) {
var deviceModule = require('/app/modules/device.js').deviceModule;
var device = deviceModule.viewDevice(deviceType, deviceId);
var deviceModule = require("/app/modules/business-controllers/device.js").deviceModule;
var deviceData = deviceModule.viewDevice(deviceType, deviceId);
if (device && device.status != 'error') {
if (deviceData && deviceData.status != 'error') {
var device = deviceData.content;
var constants = require('/app/modules/constants.js');
var tokenPair = session.get(constants.ACCESS_TOKEN_PAIR_IDENTIFIER);
var token = '';
var tokenPair = JSON.parse(session.get(constants.TOKEN_PAIR));
if (tokenPair) {
token = tokenPair.accessToken;
device.accessToken = tokenPair.accessToken;
}
device.accessToken = token;
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
device.ip = devicemgtProps['httpsWebURL'];
return {'device': device.content};
return {'device': deviceData.content};
}
}
}

@ -1,8 +1,25 @@
{{!
Copyright (c) 2016, 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.
}}
{{unit "cdmf.unit.lib.rickshaw-graph"}}
<div id="div-chart" data-websocketurl="{{websocketEndpoint}}">
<div class="chartWrapper" id="chartWrapper">
<div id="y_axis" class="custom_y_axis">Temperature</div>
<div id="y_axis" class="custom_y_axis" style="margin-top: -20px;">Temperature</div>
<div class="legend_container">
<div id="smoother" title="Smoothing"></div>
<div id="legend"></div>

@ -17,16 +17,28 @@
*/
function onRequest(context) {
var log = new Log("stats.js");
var carbonServer = require("carbon").server;
var device = context.unit.params.device;
var devicemgtProps = require('/app/conf/devicemgt-props.js').config();
var constants = require('/app/modules/constants.js');
var websocketEndpoint = devicemgtProps['wssURL'].replace('https', 'wss');
var tokenPair = session.get(constants.ACCESS_TOKEN_PAIR_IDENTIFIER);
var token = '';
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var constants = require("/app/modules/constants.js");
var websocketEndpoint = devicemgtProps["wssURL"].replace("https", "wss");
var jwtService = carbonServer.osgiService(
'org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService');
var jwtClient = jwtService.getJWTClient();
var encodedClientKeys = session.get(constants["ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS"]);
var token = "";
if (encodedClientKeys) {
var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"];
var resp = tokenUtil.decode(encodedClientKeys).split(":");
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {});
if (tokenPair) {
token = tokenPair.accessToken;
}
websocketEndpoint = websocketEndpoint + '/secured-outputui/org.wso2.iot.connectedcup/1.0.0?' +
'token=' + token + '&deviceId=' + device.deviceIdentifier;
return {'device': device, 'websocketEndpoint': websocketEndpoint};
websocketEndpoint = websocketEndpoint + "/secured-websocket/org.wso2.iot.devices.temperature/1.0.0?"
+ "deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type;
var websocketToken= {'name':'websocket-token','value': token, 'path':'/', "maxAge":18000};
response.addCookie(websocketToken);
}
return {"device": device, "websocketEndpoint": websocketEndpoint};
}

@ -18,41 +18,30 @@
var ws;
var graph;
var temperatureData = [];
var coffeeData = [];
var temperature = 0;
var coffeelevel = 0;
var lastTime = 0;
var palette = new Rickshaw.Color.Palette({scheme: 'classic9'});
var chartData = [];
var palette = new Rickshaw.Color.Palette({scheme: "classic9"});
$(window).load(function () {
var tNow = new Date().getTime() / 1000;
for (var i = 0; i < 30; i++) {
temperatureData.push({
x: tNow - (30 - i) * 15,
y: parseFloat(0)
});
coffeeData.push({
chartData.push({
x: tNow - (30 - i) * 15,
y: parseFloat(0)
});
}
graph = new Rickshaw.Graph({
element: document.getElementById('chart'),
width: $('#div-chart').width() - 50,
element: document.getElementById("chart"),
width: $("#div-chart").width() - 50,
height: 300,
renderer: 'line',
renderer: "line",
interpolation: "linear",
padding: {top: 0.2, left: 0.0, right: 0.0, bottom: 0.2},
xScale: d3.time.scale(),
series: [{
'color': palette.color(),
'data': coffeeData,
'name': 'Coffee Level'
}, {
'color': palette.color(),
'data': temperatureData,
'name': 'Temperature'
'data': chartData,
'name': "Temperature"
}]
});
@ -77,11 +66,11 @@ $(window).load(function () {
formatter: function (series, x, y) {
var date = '<span class="date">' + moment(x * 1000).format('Do MMM YYYY h:mm:ss a') + '</span>';
var swatch = '<span class="detail_swatch" style="background-color: ' + series.color + '"></span>';
return swatch + series.name + ': ' + parseInt(y) + '<br>' + date;
return swatch + series.name + ": " + parseInt(y) + '<br>' + date;
}
});
var websocketUrl = $('#div-chart').data('websocketurl');
var websocketUrl = $("#div-chart").data("websocketurl");
connect(websocketUrl)
});
@ -101,25 +90,12 @@ function connect(target) {
if (ws) {
ws.onmessage = function (event) {
var dataPoint = JSON.parse(event.data);
if (lastTime < parseInt(dataPoint[4]) / 1000) {
lastTime = parseInt(dataPoint[4]) / 1000;
if (dataPoint[3] == 'temperature') {
temperature = parseFloat(dataPoint[5]);
} else if (dataPoint[3] == 'coffeelevel') {
coffeelevel = parseFloat(dataPoint[6]);
}
temperatureData.push({
x: lastTime,
y: temperature
});
temperatureData.shift();
coffeeData.push({
x: lastTime,
y: coffeelevel
chartData.push({
x: parseInt(dataPoint[4]) / 1000,
y: parseFloat(dataPoint[5])
});
coffeeData.shift();
chartData.shift();
graph.update();
}
};
}
}

@ -0,0 +1,66 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.
*/
.circle {
background: none repeat scroll 0 0 #191919;
border-radius: 50px;
height: 50px;
padding: 10px;
width: 50px;
color: #fff;
}
.padding-top-double {
padding-top: 20px;
}
.padding-double {
padding: 20px;
}
.grey {
color: #333;
}
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #7f7f7f;
margin: 1em 0;
padding: 0;
opacity: 0.2;
}
.light-grey {
color: #7c7c7c;
}
.uppercase {
text-transform: uppercase;
}
.grey-bg {
background-color: #f6f4f4;
}
.doc-link{
background: none;
color: #000;
padding: 10px 0px;
}
.doc-link a {
color: #006eff;
}

@ -16,13 +16,13 @@
* under the License.
*/
var modalPopup = '.wr-modalpopup';
var modalPopupContainer = modalPopup + ' .modalpopup-container';
var modalPopupContent = modalPopup + ' .modalpopup-content';
var body = 'body';
var modalPopup = ".modal";
var modalPopupContainer = modalPopup + " .modal-content";
var modalPopupContent = modalPopup + " .modal-content";
var body = "body";
/*
* set popup maximum height function.
* Set popup maximum height function.
*/
function setPopupMaxHeight() {
$(modalPopupContent).css('max-height', ($(body).height() - ($(body).height() / 100 * 30)));
@ -33,36 +33,14 @@ function setPopupMaxHeight() {
* show popup function.
*/
function showPopup() {
$(modalPopup).show();
$(modalPopup).modal('show');
setPopupMaxHeight();
$('#downloadForm').validate({
rules: {
deviceName: {
minlength: 4,
required: true
}
},
highlight: function (element) {
$(element).closest('.control-group').removeClass('success').addClass('error');
},
success: function (element) {
$(element).closest('.control-group').removeClass('error').addClass('success');
$('label[for=deviceName]').remove();
}
});
var deviceType = '';
var deviceType = "";
$('.deviceType').each(function () {
if (this.value != '') {
deviceType = this.value;
}
});
if (deviceType == 'digitaldisplay') {
$('.sketchType').remove();
$('input[name="sketchType"][value="digitaldisplay"]').prop('checked', true);
$('label[for="digitaldisplay"]').text('Simple Agent');
} else {
$('.sketchTypes').remove();
}
}
/*
@ -72,7 +50,7 @@ function hidePopup() {
$('label[for=deviceName]').remove();
$('.control-group').removeClass('success').removeClass('error');
$(modalPopupContent).html('');
$(modalPopup).hide();
$(modalPopup).modal('hide');
}
/*
@ -88,46 +66,9 @@ function attachEvents() {
* when a user clicks on "Download" link
* on Device Management page in WSO2 DC Console.
*/
$('a.download-link').click(function () {
var sketchType = $(this).data('sketchtype');
var deviceType = $(this).data('devicetype');
var downloadDeviceAPI = '/devicemgt/api/devices/sketch/generate_link';
var payload = {'sketchType': sketchType, 'deviceType': deviceType};
$("a.download-link").click(function () {
$(modalPopupContent).html($('#download-device-modal-content').html());
showPopup();
var deviceName;
$('a#download-device-download-link').click(function () {
$('.new-device-name').each(function () {
if (this.value != '') {
deviceName = this.value;
}
});
$('label[for=deviceName]').remove();
if (deviceName && deviceName.length >= 4) {
payload.deviceName = deviceName;
invokerUtil.post(
downloadDeviceAPI,
payload,
function (data, textStatus, jqxhr) {
doAction(data);
},
function (data) {
doAction(data);
}
);
} else if (deviceName) {
$('.controls').append('<label for="deviceName" generated="true" class="error" style="display: inline-block;">Please enter at least 4 characters.</label>');
$('.control-group').removeClass('success').addClass('error');
} else {
$('.controls').append('<label for="deviceName" generated="true" class="error" style="display: inline-block;">This field is required.</label>');
$('.control-group').removeClass('success').addClass('error');
}
});
$('a#download-device-cancel-link').click(function () {
hidePopup();
});
});
}
@ -141,33 +82,40 @@ function downloadAgent() {
values[this.name] = $(this).val();
});
var deviceName = $inputs[0].value;
$('.new-device-name').each(function () {
if (this.value != '') {
deviceName = this.value;
}
});
var deviceNameFormat = /^[^~?!#$:;%^*`+={}\[\]\\()|<>,'"]{1,30}$/;
if (deviceName && deviceName.length < 4) {
$("#invalid-username-error-msg span").text("Device name should be more than 3 letters!");
$("#invalid-username-error-msg").removeClass("hidden");
} else if (deviceName && deviceNameFormat.test(deviceName)) {
var payload = {};
payload.name = $inputs[0].value;
payload.owner = $inputs[1].value;
var connectedCupRegisterURL = '/connectedcup/device/register?name=' + encodeURI(payload.name);
invokerUtil.post(
connectedCupRegisterURL,
payload,
function (data, textStatus, jqxhr) {
$(modalPopupContent).html($('#device-created-content').html());
$('#device-created-link').click(function () {
hidePopup();
},
function (data) {
hidePopup();
}
);
var deviceName;
$('.new-device-name').each(function () {
if (this.value != '') {
deviceName = this.value;
}
});
if (deviceName && deviceName.length >= 4) {
setTimeout(function () {
hidePopup();
}, 1000);
},
function (data) {
doAction(data)
}
);
} else {
$("#invalid-username-error-msg span").text("Invalid device name");
$("#invalid-username-error-msg").removeClass("hidden");
}
}

@ -1,16 +1,28 @@
<div class="col-lg-12 margin-top-double" xmlns="http://www.w3.org/1999/html">
{{!
Copyright (c) 2016, 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.
}}
<div class="col-lg-12 margin-top-double">
<h1 class="grey ">Connected Cup</h1>
<hr>
</div>
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4 padding-top">
<div class="col-xs-12 col-sm-4 col-md-3 col-lg-3 padding-top">
<img src="{{@unit.publicUri}}/images/coffeecup.png" class="img-responsive">
</div>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-8 padding-top">
<h4 class="doc-link">Click
<a href="https://docs.wso2.com/display/IoTS100/Sample+-+Getting+the+Connected+Cup+into+the+WSO2+IoT+Server"
target="_blank">[ here ]</a> for latest instructions and troubleshooting.</h4>
</div>
<div class="col-xs-12 col-sm-6 col-md-8 col-lg-8 padding-top">
<div class="col-xs-12 col-sm-8 col-md-9 col-lg-9 padding-top">
<h3 class="uppercase">What it Does</h3>
<hr>
<p class="grey margin-top">Connected cup is a virtual simulation of a smart coffee cup from the IOT Hardware
@ -18,35 +30,36 @@
around with the temperature and Coffee level. And the information will be relayed back to
the IoTServer and summarized.
</p>
<p>The device supports communication via HTTPS only.</p>
<br>
<h3 class="uppercase">What You Need</h3>
<hr>
<ul class="list-unstyled">
<li class="padding-top-double"><span class="circle">STEP 01</span>&nbsp;&nbsp;&nbsp;Go ahead and
[Crete an Instance] of the Device.
<li class="padding-top-double">
<span class="badge">STEP 01</span>
Go ahead and [Download] the Device.
</li>
<li class="padding-top-double"><span class="circle">STEP 02</span>&nbsp;&nbsp;&nbsp;Give a name to your
Connected Cup instance.
<li>
<span class="badge">STEP 02</span>
Proceed to [Prepare] section.
</li>
<li class="padding-top-double"><span class="circle">STEP 03</span>&nbsp;&nbsp;&nbsp;Read
[Try Out] section
to further experiment with the device.
<li>
<span class="badge">STEP 03</span>
Read [Try Out] section to further experiment with the device.
</li>
</ul>
<br>
<a href="/api-store/apis/info?name={{@uriParams.deviceType}}&version=1.0.0&provider=admin"
class="btn-operations" target="_blank"><i class="fw fw-api"></i> View API</i> &nbsp;</a>
<a href="#" class="download-link btn-operations"><i class="fw fw-download"></i>Create an Instance</a>
class="btn-operations"
target="_blank"><i class="fw fw-api"></i> View API</i>
</a>
<a href="#" class="download-link btn-operations">
<i class="fw fw-download"></i>Create an instance</a>
<div id="download-device-modal-content" class="hide">
<div class="modal-content">
<div class="row">
<div class="col-md-7 col-centered">
<h3>Name your device and download the agent from following link.</h3>
<h3>Name your Connected cup instance.</h3>
<br/>
<form id="downloadForm">
<div class="control-group">
@ -69,16 +82,16 @@
</div>
</div>
<div id="download-device-modal-content-links" class="hide">
<div id="device-created-content" class="hide">
<div class="modal-content">
<div class="row">
<div class="col-md-7 col-centered center-container">
<h3>Please download the file from following link(Press CTRL+C).</h3>
<br/>
<div>
<input id="download-device-url" style="color:#3f3f3f;padding:5px"
type="text" value="" placeholder="Type here" size="60">
<h3>Connected cup device created. </h3>
<p> Select instance of the Connected Cup you created from the "Devices" section. </p>
<div class="buttons">
<a href="#" id="device-created-link" class="btn-operations">
&nbsp;&nbsp;&nbsp;&nbsp;OK&nbsp;&nbsp;&nbsp;&nbsp;
</a>
</div>
</div>
</div>
@ -176,75 +189,28 @@
<p class="grey margin-top">Access your Device</p>
<br/>
<ul>
<p class="padding-top-double"><span class="circle">01</span> Select instance of the Connected Cup you created from the "Devices" section and click "View".</p>
<p class="padding-top-double"><span class="circle">01</span> Select instance of the Connected Cup you created from the "Devices" section.</p>
<p class="padding-top-double"><span class="circle">02</span> Click the [Go to Device] button from the "Operations" section and you will be able to view and experiment with the device.</p>
</ul>
<br>
</div>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-12 padding-double">
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 padding-double">
<h3 class="uppercase">Connected Cup Agent</h3><hr>
<p class="grey margin-top">Click on the image to zoom</p>
<center>
<a href="{{@unit.publicUri}}/images/coffee_stats.png" target="_blank">
<img src="{{@unit.publicUri}}/images/coffee_stats.png" class="img-responsive" style="max-width: 500px; max-height: 500px">
<img src="{{@unit.publicUri}}/images/coffee_stats.png" class="img-responsive">
</a>
</center>
<br/>
</div>
</div>
<style type="text/css">
.circle {
background: none repeat scroll 0 0 #191919;
border-radius: 50px;
height: 50px;
padding: 10px;
width: 50px;
color: #fff;
}
.padding-top-double {
padding-top: 20px;
}
.padding-double {
padding: 20px;
}
.grey {
color: #333;
}
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #7f7f7f;
margin: 1em 0;
padding: 0;
opacity: 0.2;
}
.light-grey {
color: #7c7c7c;
}
.uppercase {
text-transform: uppercase;
}
.grey-bg {
background-color: #f6f4f4;
}
.doc-link {
background: #11375B;
padding: 20px;
color: white;
margin-top: 0;
}
.doc-link a {
color: white;
}
</style>
{{#zone "topCss"}}
{{css "css/styles.css"}}
{{/zone}}
{{#zone "bottomJs"}}
{{js "/js/download.js"}}
{{js "/js/jquery.validate.js"}}
{{/zone}}

@ -24,6 +24,10 @@
<version>1</version>
</parent>
<modules>
<module>connectedcup</module>
</modules>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.iot.devicemgt-plugins</groupId>
<artifactId>iot-devicetype-samples</artifactId>
@ -46,13 +50,13 @@
<goal>p2-repo-gen</goal>
</goals>
<configuration>
<metadataRepository>file:\${basedir}/p2-repo</metadataRepository>
<artifactRepository>file:\${basedir}/p2-repo</artifactRepository>
<metadataRepository>file:${basedir}/p2-repo</metadataRepository>
<artifactRepository>file:${basedir}/p2-repo</artifactRepository>
<publishArtifacts>true</publishArtifacts>
<publishArtifactRepository>true</publishArtifactRepository>
<featureArtifacts>
<featureArtifactDef>
org.coffeeking:org.coffeeking.connectedcup.feature:\${carbon.device.mgt.plugin.version}
org.coffeeking:org.coffeeking.connectedcup.feature:${carbon.device.mgt.plugin.version}
</featureArtifactDef>
</featureArtifacts>
</configuration>
@ -65,14 +69,14 @@
</goals>
<configuration>
<profile>default</profile>
<metadataRepository>file:\${basedir}/p2-repo</metadataRepository>
<artifactRepository>file:\${basedir}/p2-repo</artifactRepository>
<destination>\${basedir}/../core/repository/components</destination>
<metadataRepository>file:${basedir}/p2-repo</metadataRepository>
<artifactRepository>file:${basedir}/p2-repo</artifactRepository>
<destination>${basedir}/../core/repository/components</destination>
<deleteOldProfileFiles>false</deleteOldProfileFiles>
<features>
<feature>
<id>org.coffeeking.connectedcup.feature.group</id>
<version>\${carbon.device.mgt.plugin.version}</version>
<version>${carbon.device.mgt.plugin.version}</version>
</feature>
</features>
</configuration>

@ -0,0 +1 @@
Subproject commit ec24a6d552876d517c2070fdce5ccbff1b4c15bb

@ -0,0 +1,19 @@
<project name="create-data-analytics-capps" default="zip" basedir=".">
<property name="project-name" value="${ant.project.name}"/>
<property name="target-dir" value="target/carbonapps"/>
<property name="src-dir" value="src/main/resources/carbonapps"/>
<property name="location_dir" value="locationTraker"/>
<target name="clean">
<delete dir="${target-dir}" />
</target>
<target name="zip" depends="clean">
<mkdir dir="${target-dir}"/>
<zip destfile="${target-dir}/${location_dir}.car">
<zipfileset dir="${src-dir}/${location_dir}"/>
</zip>
</target>
</project>

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2016, 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<groupId>org.wso2.sample</groupId>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.sample.x</artifactId>
<name>WSO2 Carbon - IoT Server Location Data Analytics Application</name>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<target>
<ant antfile="build.xml" target="zip" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<finalName>${project.artifactId}-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/assembly/src.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>create-archive</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<project.version>1.0.0-SNAPSHOT</project.version>
</properties>
</project>

@ -0,0 +1,37 @@
<!--
~ Copyright (c) 2016, 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.
-->
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>src</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<baseDirectory>${basedir}/src</baseDirectory>
<fileSets>
<fileSet>
<directory>${basedir}/target/carbonapps</directory>
<outputDirectory>/</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
</fileSets>
</assembly>

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016, 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.
-->
<artifacts>
<artifact name="turn" version="1.0.0" type="carbon/application">
<dependency artifact="location_data_visualizer_dashboard" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="location_data_visualizer_gadget" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
</artifact>
</artifacts>

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016, 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.
-->
<artifact name="location_data_visualizer_dashboard" version="1.0.0" type="dashboards/dashboard" serverRole="DataAnalyticsServer">
<file>location-data-dashboard.json</file>
</artifact>

@ -0,0 +1 @@
{"id" : "location-data-dashboard", "title" : "Location Data Dashboard", "description" : "Location data viewer", "permissions" : {"viewers" : ["Internal/location-data-dashboard-viewer"], "editors" : ["Internal/location-data-dashboard-editor"], "owners" : ["Internal/location-data-dashboard-owner"]}, "pages" : [{"id" : "page1", "title" : "Page 1", "layout" : {"content" : {"loggedIn" : {"blocks" : [{"id" : "e5070bafe141065d065bcd63786ad9c9", "x" : 0, "y" : 0, "width" : 12, "height" : 11, "banner" : false}]}}, "fluidLayout" : false}, "isanon" : false, "content" : {"default" : {"a" : [], "b" : [], "e5070bafe141065d065bcd63786ad9c9" : [{"id" : "location-data-visualizer-0", "content" : {"id" : "location-data-visualizer", "title" : "Location Data Visuializer", "type" : "gadget", "thumbnail" : "fs://gadget/location-data-visualizer/index.jpg", "settings" : {"personalize" : true}, "data" : {"url" : "fs://gadget/location-data-visualizer/index.xml"}, "description" : "Allows to view and select US states", "notify" : {"state" : {"type" : "address", "description" : "This notifies selected state"}, "cancel" : {"type" : "boolean", "description" : "This notifies cancellation of state selection"}}, "styles" : {"title" : "Location Data Visuializer", "borders" : true}, "options" : {}, "locale_titles" : {}}}]}, "anon" : {}}}], "menu" : [{"id" : "page1", "isanon" : false, "ishidden" : false, "title" : "Page 1", "subordinates" : []}], "hideAllMenuItems" : false, "identityServerUrl" : "", "accessTokenUrl" : "", "apiKey" : "", "apiSecret" : "", "theme" : "Default Theme", "shareDashboard" : false, "isUserCustom" : false, "isEditorEnable" : false, "banner" : {"globalBannerExists" : false, "customBannerExists" : false}, "landing" : "page1", "isanon" : false, "defaultPriority" : "5"}

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016, 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.
-->
<artifact name= "location_data_visualizer_gadget" version="1.0.0" type="dashboards/gadget" serverRole="DataAnalyticsServer">
<file>location-data-visualizer</file>
</artifact>

@ -0,0 +1,97 @@
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.point {
stroke: #000;
}
form {
margin-top: 25px;
text-align: center;
}
.slider {
width: 80%;
display: block;
margin: 0 auto;
}
output {
display: block;
margin: 25px auto;
font-size:2em;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: orange;
}
.bar:hover {
fill: orangered ;
}
.x.axis path {
display: none;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
z-index: 1000;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
.btn-space {
margin-right: 30px;
margin-bottom: 10px;
margin-top: 10px;
}
.element-space{
margin-right: 30px;
margin-bottom: 10px;
margin-top: 10px;
}

@ -0,0 +1,23 @@
{
"id": "location-data-visualizer",
"title": "Location Data Visuializer",
"type": "gadget",
"thumbnail": "gadget/location-data-visualizer/index.jpg",
"settings": {
"personalize": true
},
"data": {
"url": "gadget/location-data-visualizer/index.xml"
},
"description": "Allows to view and select US states",
"notify": {
"state": {
"type": "address",
"description": "This notifies selected state"
},
"cancel": {
"type": "boolean",
"description": "This notifies cancellation of state selection"
}
}
}

@ -0,0 +1,209 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Location Data Visualizer" description="g1">
<Require feature="pubsub-2"/>
<Require feature="dynamic-height"/>
<Require feature="wso2-gadgets-remoteClient" />
</ModulePrefs>
<Content type="html">
<![CDATA[
<head>
<!--
-->
<!--
loading stylesheets
-->
<link rel="stylesheet" type="text/css" href="css/style.css">
<link rel="stylesheet" type="text/css" href="lib/css/bootstrap.css">
<!--
loading javascript libraries
-->
<script src="lib/js/jquery.js"></script>
<script src="lib/js/bootstrap.js"></script>
<script src="lib/js/d3.js"></script>
<script src="lib/js/d3tip.js"></script>
<!--
Loading created javascript functions
-->
<script src="js/RestCaller.js"></script>
<script src="js/graph.js"></script>
<script src="js/traffic.js"></script>
</head>
<body>
<script src="lib/js/d3.js"></script>
<script src="lib/js/d3tip.js"></script>
<script>
//initializing variables
var imageX=-30;
var imageY=-5;
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 1400 - margin.left - margin.right,
height = 744 - margin.top - margin.bottom;
//setting axises
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([0,height]);
loadImage(imageX,imageY);
//adding a SVG element to hold the map image
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
loadImage(imageX,imageY);
//initializing axises with database and slider with file values
getDimension();
GetInitStartTime();
GetEndTime();
</script>
<div class="well">
<div class="container">
<div class="col-sm-4">
<h3 class="text-primary">Select Time</h3>
<input class="slider form-control input-sm" type="range" id="valueSlider" value="" step="1000" min="01170000853070" max="01172715042247" oninput="outputUpdate(value)">
<output for=value id="output" hidden="true"></output>
<output id="calenderDate"></output>
<div hidden="true">
<label for="stt">Starting Time</label>
<input id="stt" name="stt" onchange="show()">
</div>
</div>
<div class="col-sm-5">
<h3 class="text-primary">Select Duration</h3>
<select class="form-control input-sm-4" id="gap" name="gap" onclick="changeStep()">
<option value=1000>1s</option>
<option value=5000>5s</option>
<option value=15000>15s</option>
<option value=30000>30s</option>
<option value=60000>1min</option>
<option value=300000>5min</option>
<option value=600000>10min</option>
<option value=3600000>1hour</option>
<option value=7200000>2hour</option>
<option value=86400000>1day</option>
</select>
</br>
<button class="btn btn-default btn-space" onclick="show() "style="align-content: center;width: 110px;height: 40px" >Show</button>
<button class="btn btn-default btn-space" onclick="showPrevious()"style="align-content: center;width: 110px;height: 40px">Previous</button>
<button class="btn btn-default btn-space" onclick="showNext()"style="align-content: center;width: 110px;height: 40px">Next</button>
<button class="btn btn-primary btn-space" onclick="play()"style="align-content: center;width: 110px;height: 40px">Play</button>
<button class="btn btn-default btn-space" onclick="showDensity()"style="align-content: center;width: 110px;height: 40px">Show Density</button>
<button class="btn btn-default btn-space" onclick="display()"style="align-content: center;width: 110px;height: 40px">Reset</button>
</div>
</div>
</div>
<div class="well">
<div class="container">
<div class="col-sm-4">
<div class="container">
<h3 class="text-primary">Typical Scenario</h3>
<select class="form-control input-sm-4 element-space" id="time" name="time" style="width: 200px" >
<option value=00>0AM</option>
<option value=01>1AM</option>
<option value=02>2AM</option>
<option value=03>3AM</option>
<option value=04>4AM</option>
<option value=05>5AM</option>
<option value=06>6AM</option>
<option value=07>7AM</option>
<option value=08>8AM</option>
<option value=09>9AM</option>
<option value=10>10AM</option>
<option value=11>11AM</option>
<option value=12>12AM</option>
<option value=13>1PM</option>
<option value=14>2PM</option>
<option value=15>3PM</option>
<option value=16>4PM</option>
<option value=17>5PM</option>
<option value=18>6PM</option>
<option value=19>7PM</option>
<option value=20>8PM</option>
<option value=21>9PM</option>
<option value=22>10PM</option>
<option value=23>11PM</option>
</select>
<select class="form-control input-sm-4 element-space" id="day" name="day" style="width: 200px" >
<option value=mon>Monday</option>
<option value=tue>Tuesday</option>
<option value=wed>Wednesday</option>
<option value=thu>Thursday</option>
<option value=fri>Friday</option>
<option value=sat>Saturday</option>
<option value=sun>Sunday</option>
</select>
<button class="btn btn-primary element-space" onclick="showScene()"style="align-content: center;width: 110px;height: 40px" >View Scenario</button>
</div>
</div>
<div class="col-sm-4 " >
<h3 class="text-primary">Upload Data file</h3>
<input class="form-control input-sm-4 element-space" id="fileupload" type="file" />
<Button class="btn btn-primary element-space" onclick="sendFile()" id="submit" style="align-content: center;width: 110px;height: 40px">Submit</Button>
</div>
<div class="col-sm-4 " >
<h3 class="text-primary">Change Image</h3>
<button class="btn btn-default btn-space" onclick="changeImage(0,1)"style="align-content: center;width: 110px;height: 40px" >Up</button>
<button class="btn btn-default btn-space" onclick="changeImage(0,-1)"style="align-content: center;width: 110px;height: 40px">Down</button>
<button class="btn btn-default btn-space" onclick="changeImage(1,0)"style="align-content: center;width: 110px;height: 40px">Left</button>
<button class="btn btn-default btn-space" onclick="changeImage(-1,0)"style="align-content: center;width: 110px;height: 40px">Right</button>
<button class="btn btn-default btn-space" onclick="showDensity()"style="align-content: center;width: 110px;height: 40px">Show Density</button>
</div>
</div>
</div>
<!-- Modal for showing frequencies-->
<div class="modal fade row-fluid" id="frequency_view" role="dialog" >
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content" style="width: 1000px">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Sensor Triggered Frequencies</h4>
</div>
<div id="modal_body" name="modal_body" class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</body>
]]>
</Content>
</Module>

@ -0,0 +1,511 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.
*/
//this method request starting timestamp and set it in relevant UI components
var GetInitStartTime = function(){
var endpointUrl = 'http://localhost:9763/location-data-visualizer/service/time/start' ;
wso2.gadgets.XMLHttpRequest.get(endpointUrl,
function(data){
var start =JSON.parse(JSON.stringify(data.stt));
document.getElementById("stt").value=start;
var valueSlider =document.getElementById("valueSlider");
valueSlider.innerHTML=start;
valueSlider.value=start;
valueSlider.min=parseInt(start);
setCalendarDate(start);
},
function(error){
alert(error);
}
);
}
//this method request ending timestamp and set it in relevant UI components
var GetEndTime = function(){
var url = 'http://localhost:9763/location-data-visualizer/service/time/end'
wso2.gadgets.XMLHttpRequest.get(url,
function(data){
var end =JSON.parse(JSON.stringify(data.stt));
document.getElementById("valueSlider").max =end;
show();
},
function(error){
alert(error);
}
);
}
//when this method is called, it fletch starting time and range from UI components and request triggered sensor data in that range and draw them in the map
var show = function(){
var start = parseInt(document.getElementById('stt').value);
document.getElementById('valueSlider').value = start;
var end = start + parseInt(document.getElementById('gap').value);
var url ='http://localhost:9763/location-data-visualizer/service/data'+'?start=' + start + '&end=' + end;
var data2=[];
wso2.gadgets.XMLHttpRequest.get(url,
function(data){
var X = data.X;
var Y = data.Y;
for (i = 0; i < X.length; i++) {
data2.push({x: X[i], y: Y[i]});
}
draw(data2);
},
function(error){
alert(error);
}
);
}
//this method send a file to evaluate for typical scenario and save as output.txt
var sendFile = function(){
var file = document.getElementById('fileupload').files[0];
var fd = new FormData();
fd.append( 'file', file);
var url ='https://localhost:9763/location-data-visualizer/service/file/upload';
wso2.gadgets.XMLHttpRequest.post(url,fd,
function(data){
GetInitStartTime();
GetEndTime();
show();
},
function(error){
alert(error);
},
'application/x-www-form-urlencoded; charset=UTF-8'
);
}
//request dimension of map area. Then set those values in axises
var getDimension = function(){
var url='http://localhost:9763/location-data-visualizer/service/get/dimension';
var value;
wso2.gadgets.XMLHttpRequest.get(url,
function(data){
Xmax = JSON.parse(JSON.stringify(data.maxX));
Ymax = JSON.parse(JSON.stringify(data.maxY));
Xmin = JSON.parse(JSON.stringify(data.minX));
Ymin = JSON.parse(JSON.stringify(data.minY));
x.domain(d3.extent([Xmin,Xmax])).nice();
y.domain(d3.extent([Ymin,Ymax])).nice();
return value;
},
function(error){
alert(error);
}
);
}
//request data chunk and call play it using doScaledTimeout Method
var play = function(){
var start=parseInt(document.getElementById('stt').value);
var chunk =parseInt(document.getElementById('gap').value)
var end = parseInt(start) + (500*parseInt(chunk));
var url= 'http://localhost:9763/location-data-visualizer/service/data/chunk'+'?start='+start+'&end='+end;
wso2.gadgets.XMLHttpRequest.get(url,
function(data){
xList=data.X;
yList=data.Y;
tList=data.T;
cList=data.C;
var i=0;
while(i<500){
var s=parseInt(start)+(i*1000);
doScaledTimeout(i,s,tList,chunk,xList,yList,cList);
i+=1;
}
},
function(error){
alert(error);
}
);
}
//when a dataset in appropriate format is given to this function, this method will visualize that dataset on the map
var draw=function (data) {
svg.selectAll(".series").remove();
svg.selectAll(".g").remove();
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x"; })
.sort();
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +parseFloat(d.x), y: +parseFloat(d.y),c:+parseFloat(d.c)};
});
});
// Compute the scales domains.
// Add the x-axis.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"))
// Add the y-axis.
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Add the points!
svg.selectAll(".series")
.data(series)
.enter().append("g")
.attr("class", "series")
.selectAll(".point")
.data(function(d) {
return d; })
.enter().append("circle")
.attr("class", "point")
.style("fill", function (d) {
if(isNaN(d.c)){
return colorRed(50);
}
return d3.rgb(255,d.c*255/100,d.c*255/100);
})
.attr("r", 4.5)
.attr("cx", function(d) {
return x(parseFloat(d.x));})
.attr("cy", function(d) {
return y(parseFloat(d.y));})
};
//request triggering densities and show them with colour variations when respond comes
var showDensity = function(){
var start = parseInt(document.getElementById('stt').value);
var data2 = [];
document.getElementById('valueSlider').value = start;
var end = start + parseInt(document.getElementById('gap').value);
var url= 'http://localhost:9763/location-data-visualizer/service/data/density'+'?start=' + parseInt(document.getElementById('stt').value) + '&end=' +(parseInt(document.getElementById('stt').value)+ parseInt(document.getElementById('gap').value));
wso2.gadgets.XMLHttpRequest.get(url,
function(data){
var X = data.X;
var Y = data.Y;
var D = data.D;
var ID = data.ID;
for (i = 0; i < X.length; i++) {
data2.push({x: X[i], y: Y[i], c:parseInt(D[i]), id:ID[i]});
}
var max=D[0];
var min=D[0];
for (j=1;j<X.length;j++){
if(D[j]>max){
max=D[j];
}
if(D[j]<min){
min=D[j];
}
}
drawDensity(data2,max,min);
//alert(JSON.stringify(data));
},
function(error){
alert(error);
}
);
}
//drawing function with color variations
var drawDensity=function (data,max,min) {
svg.selectAll(".series").remove();
svg.selectAll(".g").remove();
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x" && d!=="c" && d!="id"; })
.sort();
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +parseFloat(d.x), y: +parseFloat(d.y),c:+(parseFloat(d.c)-min)*100/(max-min), id:parseInt(d.id)};
});
});
// Compute the scales domains.
x.domain(d3.extent([-71,40])).nice();
y.domain(d3.extent([4,65])).nice();
// Add the x-axis.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
// Add the y-axis.
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
// Add the points!
svg.selectAll(".series")
.data(series)
.enter().append("g")
.attr("class", "series")
.selectAll(".point")
.data(function(d) {
return d; })
.enter().append("circle")
.attr("class", "point")
.style("fill", function (d) {
if(d.c==0){
return d3.rgb(255,255,255);
}
else if(d.c>20){
return colorRed(d.c);
}
else if(d.c>10){
return colorBlue(d.c);
}
else if(d.c>=0){
return colorGreen(d.c);
}
else{
return d3.rgb(255,255,255);
}
})
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html((d.c).toFixed(2) )
.style("left", (x(parseInt(d.x)) + "px"))
.style("top", (y(parseInt(d.y)) + "px"));
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
.attr("r", 4.5)
.attr("cx", function(d) {
return x(parseFloat(d.x));})
.attr("cy", function(d) {
return y(parseFloat(d.y));})
.on("click",function (d){
var id=d.id;
getFrequency(id);
});
};
//request upcoming frequencies of a particular sensor. Show them in a modal when respond comes. Range in UI will used as range in here too
var getFrequency = function(id){
var start = parseInt(document.getElementById('stt').value);
document.getElementById('valueSlider').value = start;
var gap = parseInt(document.getElementById('gap').value);
var data1 = [];
var url='http://localhost:9763/location-data-visualizer/service/data/count'+'?start=' + start + '&gap=' + gap + '&sensor=' + id;
wso2.gadgets.XMLHttpRequest.get(url,
function(data){
var count =data.Count;
for (i = 0; i < count.length; i++) {
var gap = parseInt(document.getElementById('gap').value);
data1.push({x: tsToCal(gap,(gap*i)+start+(gap/2.0)), y: count[i]});
}
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x" && d!=="c" && d!="id"; })
.sort();
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +i, y: d.y};
});
});
var stt = parseInt(document.getElementById("stt").value);
var gap = parseInt(document.getElementById("gap").value);
d3.select("#barChart").remove();
var margin = {top: 40, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg2 = d3.select("#modal_body").append("svg")
.attr("id","barChart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
return d.y;
});
svg2.call(tip);
x.domain(data1.map(function(d) {
return d.x; }));
y.domain([0, d3.max(data1, function(d) {
return d.y; })]);
svg2.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg2.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Frequency");
svg2.selectAll(".bar")
.data(data1)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {return x(d.x); })
.attr("width", x.rangeBand())
.attr("y", function(d) {return y(d.y); })
.attr("height", function(d) { return height - y(d.y); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
function type(d) {
d.y = +d.y;
return d;
}
},
function(error){
alert(error);
}
);
$("#frequency_view").modal("show");
}
var showScene = function(){
var data2=[];
var endpointUrl = 'http://localhost:9763/location-data-visualizer/service/typical/scene'+'?hour=' + document.getElementById('time').value + '&day=' +document.getElementById('day').value;
wso2.gadgets.XMLHttpRequest.get(endpointUrl,
function(data){
var X = JSON.parse(JSON.stringify(data.X));
var Y = JSON.parse(JSON.stringify(data.Y));
var C = JSON.parse(JSON.stringify(data.C));
var ID = JSON.parse(JSON.stringify(data.ID));
for (i = 0; i < X.length; i++) {
data2.push({x: X[i], y: Y[i], c:C[i], id:ID[i]});
}
drawScene(data2);
},
function(error){
alert(error);
}
);
}

@ -0,0 +1,136 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.
*/
//method to set starting time to UI component calender date
function setCalendarDate(start){
var calendarTime=timeStampToCalendarDate(start);
document.getElementById("calenderDate").innerHTML=calendarTime;
}
//method that show triggered data in the upcoming range
var showNext =function () {
var currentStart = parseInt(document.getElementById('stt').value);
var duration = parseInt(document.getElementById('gap').value);
document.getElementById("stt").value =currentStart+duration;
show();
};
//method that show triggered data in the previous range
var showPrevious =function () {
var currentStart = parseInt(document.getElementById('stt').value);
var duration = parseInt(document.getElementById('gap').value);
document.getElementById("stt").value =currentStart-duration;
show();
};
//method will update output UI component
function outputUpdate(num) {
document.querySelector('#output').value = num;
document.getElementById('stt').value =num;
setCalendarDate(num);
show();
}
//this will change value slider value according to current gap value
function changeStep() {
document.getElementById("valueSlider").step =document.getElementById("gap").value;
}
function timeStampToCalendarDate(time) {
var date = new Date(parseInt(time));
var Months =["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
return date.getFullYear()+" "+Months[date.getMonth()]+" "+date.getDate()+" "+date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
}
//show data chunk
function showChunk(start,chunk,tList,xList,yList) {
var data2=[];
var gap=document.getElementById("gap").value;
var e=parseInt(start)+parseInt(chunk);
for(i=0;i<tList.length;i=i+1){
if(parseInt(tList[i])<e && parseInt(tList[i])>parseInt(start)){
data2.push({x:xList[i] ,y:yList[i], c:((e-parseInt(tList[i]))*100/parseInt(gap))});
}
}
return data2;
}
//show play data
function doScaledTimeout(j,start,tList,chunk,xList,yList,cList) {
setTimeout(function() {
document.getElementById('stt').value=start;
document.getElementById('output').value=start;
setCalendarDate(start);
var data2=showChunk(start,chunk,tList,xList,yList,cList);
draw(data2);
}, j * 300);
}
//colour schema for
colorRed = d3.scale.linear().domain([20,100])
.interpolate(d3.interpolateHcl)
.range([d3.rgb('#F99FA2'),d3.rgb("#F72128"),]);
colorBlue = d3.scale.linear().domain([10,20])
.interpolate(d3.interpolateHcl)
.range([d3.rgb("#00C1FF"),d3.rgb('#6670AC')]);
colorGreen = d3.scale.linear().domain([10,0])
.interpolate(d3.interpolateHcl)
.range([d3.rgb("#0A7E03"),d3.rgb('#0FF300')]);
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
//timestamp to calendar date
function tsToCal(gap,time) {
var date = new Date(parseInt(time));
var Months =["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
if(gap < 60000){
return date.getMinutes()+":"+date.getSeconds();
}
else if(gap <=7200000) {
return Months[date.getMonth()]+" "+date.getDate() + " " + date.getHours() + ":" + date.getMinutes();
}
else{
return date.getFullYear()+" "+Months[date.getMonth()]+" "+date.getDate();
}
}
//reload UI
function display() {
window.location.reload();
};
//loading image to svg element
function loadImage(x,y) {
var image = d3.select("g").append("svg:image")
.attr("xlink:href", "/portal/store/carbon.super/fs/gadget/location-data-visualizer/img/floor.jpg")
.attr("width", 1500)
.attr("height", 699)
.attr("x",x)
.attr("y",y);
}
function changeImage(x,y) {
imageX=imageX+x;
imageY=imageY+y;
loadImage(imageX,imageY);
}
//colour schema
colorData = d3.scale.linear().domain([10,0])
.interpolate(d3.interpolateHcl)
.range([d3.rgb(125,0,0),d3.rgb(255,0,0)]);

@ -0,0 +1,153 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.
*/
//when a data related to typical Scenario is passed,this method will draw it with color variations
var drawScene=function (data) {
svg.selectAll(".series").remove();
svg.selectAll(".g").remove();
var seriesNames = d3.keys(data[0])
.filter(function(d) { return d !== "x" && d!=="c" && d!="id"; })
.sort();
var series = seriesNames.map(function(series) {
return data.map(function(d) {
return {x: +parseFloat(d.x), y: +parseFloat(d.y),c:+(parseFloat(d.c)), id:parseInt(d.id)};
});
});
// Compute the scales domains.
x.domain(d3.extent([-71,40])).nice();
y.domain(d3.extent([4,65])).nice();
// Add the x-axis.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
// Add the y-axis.
svg.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
// Add the points!
svg.selectAll(".series")
.data(series)
.enter().append("g")
.attr("class", "series")
.selectAll(".point")
.data(function(d) {
return d; })
.enter().append("circle")
.attr("class", "point")
.style("fill", function (d) {
if(d.c==0){
return d3.rgb(255,255,255);
}
else if(d.c>10){
return colorRed(d.c);
}
else if(d.c>3){
return colorBlue(d.c);
}
else if(d.c>=0){
return colorGreen(d.c);
}
else{
return d3.rgb(255,255,255);
}
})
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", 0.9);
tooltip.html((d.c).toFixed(2) )
.style("left", (x(parseInt(d.x)) + "px"))
.style("top", (y(parseInt(d.y)) + "px"));
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
})
.attr("r", 4.5)
.attr("cx", function(d) {
return x(parseFloat(d.x));})
.attr("cy", function(d) {
return y(parseFloat(d.y));});
};
//this method request data on typical scenario and ask to draw them in the map
function showScene() {
var data2 = [];
$.ajax({
url: "http://localhost:8080/service/typical/scene",
type: "GET",
data: "hour=" + document.getElementById("time").value + "&day=" +document.getElementById("day").value, // or $('#myform').serializeArray()
dataType: "json",
success: function (data) {
var X = JSON.parse(JSON.stringify(data.X));
var Y = JSON.parse(JSON.stringify(data.Y));
var C = JSON.parse(JSON.stringify(data.C));
var ID = JSON.parse(JSON.stringify(data.ID));
for(i = 0; i < X.length; i+=1) {
data2.push({x: X[i], y: Y[i], c:C[i], id:ID[i]});
}
drawScene(data2);
//alert(JSON.stringify(data));
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
}
//color schemas to show traffic. Red for high traffic, blue for medium traffic, green for low traffic
colorRed2 = d3.scale.linear().domain([10,100])
.interpolate(d3.interpolateHcl)
.range([d3.rgb("#F99FA2"),d3.rgb("#F72128"),]);
colorBlue2 = d3.scale.linear().domain([3,10])
.interpolate(d3.interpolateHcl)
.range([d3.rgb("#00C1FF"),d3.rgb("#6670AC")]);
colorGreen2 = d3.scale.linear().domain([3,0])
.interpolate(d3.interpolateHcl)
.range([d3.rgb("#0A7E03"),d3.rgb("#0FF300")]);

@ -0,0 +1,352 @@
/**
* d3.tip
* Copyright (c) 2013 Justin Palmer
*
* Tooltips for d3.js SVG visualizations
*/
// eslint-disable-next-line no-extra-semi
;(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module with d3 as a dependency.
define([
'd3-collection',
'd3-selection'
], factory)
} else if (typeof module === 'object' && module.exports) {
/* eslint-disable global-require */
// CommonJS
var d3Collection = require('d3-collection'),
d3Selection = require('d3-selection')
module.exports = factory(d3Collection, d3Selection)
/* eslint-enable global-require */
} else {
// Browser global.
var d3 = root.d3
// eslint-disable-next-line no-param-reassign
root.d3.tip = factory(d3, d3)
}
}(this, function(d3Collection, d3Selection) {
// Public - contructs a new tooltip
//
// Returns a tip
return function() {
var direction = d3TipDirection,
offset = d3TipOffset,
html = d3TipHTML,
rootElement = document.body,
node = initNode(),
svg = null,
point = null,
target = null
function tip(vis) {
svg = getSVGNode(vis)
if (!svg) return
point = svg.createSVGPoint()
rootElement.appendChild(node)
}
// Public - show the tooltip on the screen
//
// Returns a tip
tip.show = function() {
var args = Array.prototype.slice.call(arguments)
if (args[args.length - 1] instanceof SVGElement) target = args.pop()
var content = html.apply(this, args),
poffset = offset.apply(this, args),
dir = direction.apply(this, args),
nodel = getNodeEl(),
i = directions.length,
coords,
scrollTop = document.documentElement.scrollTop ||
rootElement.scrollTop,
scrollLeft = document.documentElement.scrollLeft ||
rootElement.scrollLeft
nodel.html(content)
.style('opacity', 1).style('pointer-events', 'all')
while (i--) nodel.classed(directions[i], false)
coords = directionCallbacks.get(dir).apply(this)
nodel.classed(dir, true)
.style('top', (coords.top + poffset[0]) + scrollTop + 'px')
.style('left', (coords.left + poffset[1]) + scrollLeft + 'px')
return tip
}
// Public - hide the tooltip
//
// Returns a tip
tip.hide = function() {
var nodel = getNodeEl()
nodel.style('opacity', 0).style('pointer-events', 'none')
return tip
}
// Public: Proxy attr calls to the d3 tip container.
// Sets or gets attribute value.
//
// n - name of the attribute
// v - value of the attribute
//
// Returns tip or attribute value
// eslint-disable-next-line no-unused-vars
tip.attr = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return getNodeEl().attr(n)
}
var args = Array.prototype.slice.call(arguments)
d3Selection.selection.prototype.attr.apply(getNodeEl(), args)
return tip
}
// Public: Proxy style calls to the d3 tip container.
// Sets or gets a style value.
//
// n - name of the property
// v - value of the property
//
// Returns tip or style property value
// eslint-disable-next-line no-unused-vars
tip.style = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return getNodeEl().style(n)
}
var args = Array.prototype.slice.call(arguments)
d3Selection.selection.prototype.style.apply(getNodeEl(), args)
return tip
}
// Public: Set or get the direction of the tooltip
//
// v - One of n(north), s(south), e(east), or w(west), nw(northwest),
// sw(southwest), ne(northeast) or se(southeast)
//
// Returns tip or direction
tip.direction = function(v) {
if (!arguments.length) return direction
direction = v == null ? v : functor(v)
return tip
}
// Public: Sets or gets the offset of the tip
//
// v - Array of [x, y] offset
//
// Returns offset or
tip.offset = function(v) {
if (!arguments.length) return offset
offset = v == null ? v : functor(v)
return tip
}
// Public: sets or gets the html value of the tooltip
//
// v - String value of the tip
//
// Returns html value or tip
tip.html = function(v) {
if (!arguments.length) return html
html = v == null ? v : functor(v)
return tip
}
// Public: sets or gets the root element anchor of the tooltip
//
// v - root element of the tooltip
//
// Returns root node of tip
tip.rootElement = function(v) {
if (!arguments.length) return rootElement
rootElement = v == null ? v : functor(v)
return tip
}
// Public: destroys the tooltip and removes it from the DOM
//
// Returns a tip
tip.destroy = function() {
if (node) {
getNodeEl().remove()
node = null
}
return tip
}
function d3TipDirection() { return 'n' }
function d3TipOffset() { return [0, 0] }
function d3TipHTML() { return ' ' }
var directionCallbacks = d3Collection.map({
n: directionNorth,
s: directionSouth,
e: directionEast,
w: directionWest,
nw: directionNorthWest,
ne: directionNorthEast,
sw: directionSouthWest,
se: directionSouthEast
}),
directions = directionCallbacks.keys()
function directionNorth() {
var bbox = getScreenBBox()
return {
top: bbox.n.y - node.offsetHeight,
left: bbox.n.x - node.offsetWidth / 2
}
}
function directionSouth() {
var bbox = getScreenBBox()
return {
top: bbox.s.y,
left: bbox.s.x - node.offsetWidth / 2
}
}
function directionEast() {
var bbox = getScreenBBox()
return {
top: bbox.e.y - node.offsetHeight / 2,
left: bbox.e.x
}
}
function directionWest() {
var bbox = getScreenBBox()
return {
top: bbox.w.y - node.offsetHeight / 2,
left: bbox.w.x - node.offsetWidth
}
}
function directionNorthWest() {
var bbox = getScreenBBox()
return {
top: bbox.nw.y - node.offsetHeight,
left: bbox.nw.x - node.offsetWidth
}
}
function directionNorthEast() {
var bbox = getScreenBBox()
return {
top: bbox.ne.y - node.offsetHeight,
left: bbox.ne.x
}
}
function directionSouthWest() {
var bbox = getScreenBBox()
return {
top: bbox.sw.y,
left: bbox.sw.x - node.offsetWidth
}
}
function directionSouthEast() {
var bbox = getScreenBBox()
return {
top: bbox.se.y,
left: bbox.se.x
}
}
function initNode() {
var div = d3Selection.select(document.createElement('div'))
div
.style('position', 'absolute')
.style('top', 0)
.style('opacity', 0)
.style('pointer-events', 'none')
.style('box-sizing', 'border-box')
return div.node()
}
function getSVGNode(element) {
var svgNode = element.node()
if (!svgNode) return null
if (svgNode.tagName.toLowerCase() === 'svg') return svgNode
return svgNode.ownerSVGElement
}
function getNodeEl() {
if (node == null) {
node = initNode()
// re-add node to DOM
rootElement.appendChild(node)
}
return d3Selection.select(node)
}
// Private - gets the screen coordinates of a shape
//
// Given a shape on the screen, will return an SVGPoint for the directions
// n(north), s(south), e(east), w(west), ne(northeast), se(southeast),
// nw(northwest), sw(southwest).
//
// +-+-+
// | |
// + +
// | |
// +-+-+
//
// Returns an Object {n, s, e, w, nw, sw, ne, se}
function getScreenBBox() {
var targetel = target || d3Selection.event.target
while (targetel.getScreenCTM == null && targetel.parentNode == null) {
targetel = targetel.parentNode
}
var bbox = {},
matrix = targetel.getScreenCTM(),
tbbox = targetel.getBBox(),
width = tbbox.width,
height = tbbox.height,
x = tbbox.x,
y = tbbox.y
point.x = x
point.y = y
bbox.nw = point.matrixTransform(matrix)
point.x += width
bbox.ne = point.matrixTransform(matrix)
point.y += height
bbox.se = point.matrixTransform(matrix)
point.x -= width
bbox.sw = point.matrixTransform(matrix)
point.y -= height / 2
bbox.w = point.matrixTransform(matrix)
point.x += width
bbox.e = point.matrixTransform(matrix)
point.x -= width / 2
point.y -= height / 2
bbox.n = point.matrixTransform(matrix)
point.y += height
bbox.s = point.matrixTransform(matrix)
return bbox
}
// Private - replace D3JS 3.X d3.functor() function
function functor(v) {
return typeof v === 'function' ? v : function() {
return v
}
}
return tip
}
// eslint-disable-next-line semi
}));
Loading…
Cancel
Save