merge-requests/1/head
ayyoob 9 years ago
commit 03be540d99

@ -59,7 +59,6 @@
<exclude>**/axis2services/sample01.aar</exclude>
<exclude>**/axis2services/echo/**</exclude>
<exclude>**/axis2services/version/**</exclude>
<!--exclude>**/pom.xml</exclude-->
<exclude>**/version.txt</exclude>
<exclude>**/master-datasources.xml</exclude>
<exclude>**/carbon.xml</exclude>
@ -184,13 +183,6 @@
<fileMode>755</fileMode>
</fileSet>
<!-- Copy the landing page webapp -->
<!-- <fileSet>
<directory>src/repository/resources/stratos_root</directory>
<outputDirectory>wso2cdm-${pom.version}/repository/deployment/server/webapps/STRATOS_ROOT</outputDirectory>
<fileMode>755</fileMode>
</fileSet>-->
<!--Removed -->
<fileSet>
<directory>../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/modules
</directory>
@ -241,16 +233,6 @@
<exclude>authenticators.xml</exclude>
</excludes>
</fileSet>
<!-- <fileSet>
<directory>
src/repository/conf/identity/
</directory>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/identity/</outputDirectory>
<includes>
<include>**/**</include>
</includes>
</fileSet>-->
<fileSet>
<directory>src/repository/conf/datasources</directory>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/datasources
@ -606,7 +588,6 @@
<includes>
<include>**/analytics-config.xml</include>
<include>**/rdbms-config.xml</include>
<!--<include>**/hbase-analytics-config.xml</include>-->
<include>**/analytics-data-config.xml</include>
<include>**/analytics-eventsink-config.xml</include>
</includes>
@ -673,25 +654,21 @@
</includes>
</fileSet>
<!-- Copying temporary patches from DAS that fixes JIRA DAS-339 and a Concurrent DB Access Issue -->
<!-- Can be safely removed upon a DAS release with these fixes -->
<!--fileSet>
<!-- Copying the "portal" app specific modifications to the distribution pack-->
<fileSet>
<directory>
src/repository/patches
src/repository/jaggeryapps/portal/store/carbon.super/gadget
</directory>
<outputDirectory>
${pom.artifactId}-${pom.version}/repository/components/patches
${pom.artifactId}-${pom.version}/repository/deployment/server/jaggeryapps/portal/store/carbon.super/gadget
</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet-->
</fileSet>
<!-- End of "portal" app specific modifications -->
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>${pom.artifactId}-${pom.version}/lib/endorsed</outputDirectory>
@ -710,7 +687,6 @@
</dependencySets>
<files>
<file>
<source>src/repository/bin/wso2server.sh</source>
<outputDirectory>${pom.artifactId}-${pom.version}/bin</outputDirectory>
@ -721,7 +697,6 @@
<outputDirectory>${pom.artifactId}-${pom.version}/bin</outputDirectory>
<fileMode>755</fileMode>
</file>
<!-- Copying the "api-store" app specific files that uses the edited "apimstore" jaggery module -->
<file>
<source>src/repository/jaggeryapps/api-store/jagg.jag</source>
@ -735,7 +710,26 @@
</outputDirectory>
<fileMode>755</fileMode>
</file>
<!-- Copying the "portal" app specific modifications to the distribution pack-->
<file>
<source>src/repository/jaggeryapps/portal/controllers/apis/analytics.jag</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/deployment/server/jaggeryapps/portal/controllers/apis
</outputDirectory>
<fileMode>755</fileMode>
</file>
<file>
<source>src/repository/jaggeryapps/portal/js/outputAdapterUiLibrary.js</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/deployment/server/jaggeryapps/portal/js
</outputDirectory>
<fileMode>755</fileMode>
</file>
<file>
<source>src/repository/jaggeryapps/portal/templates/gadgets/igviz/js/outputAdapterUiLibrary.js</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/deployment/server/jaggeryapps/portal/templates/gadgets/igviz/js
</outputDirectory>
<fileMode>755</fileMode>
</file>
<!-- End of "portal" app specific modifications -->
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/deployment/server/webapps/mdm-android-agent.war
@ -796,22 +790,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- <file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/tomcat/webapp-classloading.xml
</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/tomcat</outputDirectory>
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/tomcat/webapp-classloading-environments.xml
</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/tomcat</outputDirectory>
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>-->
<file>
<source>src/repository/conf/tomcat/context.xml</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/tomcat</outputDirectory>
@ -861,7 +839,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Copying logging-config.xml -->
<file>
<source>
@ -871,7 +848,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Copying event-broker.xml -->
<file>
<source>src/repository/conf/event-broker.xml</source>
@ -885,7 +861,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Copying application-authentication.xml -->
<file>
<source>
@ -905,8 +880,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Copying thrift-authentication.xml -->
<file>
<source>
@ -936,7 +909,6 @@
</outputDirectory>
<fileMode>644</fileMode>
</file>
<!-- Copying governance.xml -->
<file>
<source>
@ -945,7 +917,6 @@
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf</outputDirectory>
<fileMode>644</fileMode>
</file>
<!-- Copying api-manager.xml -->
<file>
<source>src/repository/conf/api-manager.xml</source>
@ -961,7 +932,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!--cdm config file-->
<file>
<source>
@ -971,8 +941,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Copying remote-appmanager-config.xml -->
<file>
<source>
@ -982,8 +950,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!--certificate config file-->
<file>
<source>
@ -993,7 +959,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!--Metrics-->
<file>
<source>../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/metrics.properties</source>
@ -1030,7 +995,6 @@
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/etc/</outputDirectory>
<fileMode>644</fileMode>
</file>
<!--app management config file-->
<file>
<source>
@ -1040,7 +1004,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!--License Config file-->
<file>
<source>
@ -1050,7 +1013,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!--Webapp Authenticator Config file-->
<file>
<source>
@ -1060,7 +1022,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!--Notification Config File-->
<file>
<source>
@ -1070,7 +1031,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Copying the modified registry.xml file-->
<file>
<source>
@ -1080,7 +1040,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!--cdm plugin config file-->
<file>
<source>
@ -1101,7 +1060,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/claim-config.xml
@ -1111,8 +1069,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Copying H2 database related files corresponding to default API management repository schema -->
<file>
<source>
@ -1122,7 +1078,6 @@
<destName>WSO2AM_DB.h2.db</destName>
<fileMode>644</fileMode>
</file>
<!-- Copying H2 database related files corresponding to default Device management repository schema -->
<file>
<source>
@ -1132,8 +1087,6 @@
<destName>WSO2DM_DB.h2.db</destName>
<fileMode>644</fileMode>
</file>
<!-- Copying ANDROID SENSE H2 database -->
<file>
<source>
@ -1143,8 +1096,6 @@
<destName>AndroidSenseDM_DB.h2.db</destName>
<fileMode>644</fileMode>
</file>
<!-- Copying ARDUINO H2 database -->
<file>
<source>
@ -1154,8 +1105,6 @@
<destName>ArduinoDM_DB.h2.db</destName>
<fileMode>644</fileMode>
</file>
<!-- Copying DIGITAL DISPLAY H2 database -->
<file>
<source>
@ -1165,8 +1114,6 @@
<destName>DigitalDisplayDM_DB.h2.db</destName>
<fileMode>644</fileMode>
</file>
<!-- Copying DRONE ANALYZER H2 database -->
<file>
<source>
@ -1176,8 +1123,6 @@
<destName>DroneAnalyzerDM_DB.h2.db</destName>
<fileMode>644</fileMode>
</file>
<!-- Copying RASPBERRY-PI H2 database -->
<file>
<source>
@ -1187,7 +1132,6 @@
<destName>RaspberryPiDM_DB.h2.db</destName>
<fileMode>644</fileMode>
</file>
<!-- Copying VIRTUAL-FIREALARM H2 database -->
<file>
<source>
@ -1197,8 +1141,6 @@
<destName>VirtualFireAlarmDM_DB.h2.db</destName>
<fileMode>644</fileMode>
</file>
<!-- Copying MOBILE-ANDROID H2 database -->
<file>
<source>
@ -1208,7 +1150,6 @@
<destName>WSO2MobileAndroid_DB.h2.db</destName>
<fileMode>644</fileMode>
</file>
<!-- Copying MOBILE-WINDOWS H2 database -->
<file>
<source>
@ -1218,28 +1159,12 @@
<destName>WSO2MobileWindows_DB.h2.db</destName>
<fileMode>644</fileMode>
</file>
<file>
<source>src/repository/conf/carbon.xml
</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/</outputDirectory>
<filtered>true</filtered>
</file>
<!-- Copying identity-mgt.properties -->
<!--file>
<source>../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/identity/identity-mgt.properties</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/identity</outputDirectory>
<filtered>true</filtered>
</file-->
<!-- Copying email-admin-config.xml -->
<!--file>
<source>../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/email/email-admin-config.xml</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/email</outputDirectory>
<filtered>true</filtered>
</file-->
<!-- Copying axis2-client.xml -->
<file>
<source>
@ -1250,7 +1175,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Copying axis2.xml -->
<file>
<source>src/repository/conf/axis2/axis2.xml</source>
@ -1259,8 +1183,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<file>
<source>src/repository/conf/etc/launch.ini</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf/etc/
@ -1268,16 +1190,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Copying MDM jaggery app -->
<!--<file>-->
<!--<source>../apps/jaggery/mdm/target/mdm.zip</source>-->
<!--<outputDirectory>${pom.artifactId}-${pom.version}/repository/deployment/server/jaggeryapps/-->
<!--</outputDirectory>-->
<!--<filtered>false</filtered>-->
<!--<fileMode>644</fileMode>-->
<!--</file>-->
<!-- Copying authenticators.xml -->
<file>
<source>
@ -1288,7 +1200,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- Cipher Tool Files -->
<file>
<source>
@ -1311,7 +1222,6 @@
<outputDirectory>${pom.artifactId}-${pom.version}/lib</outputDirectory>
<fileMode>644</fileMode>
</file>
<!-- Analytics datasources -->
<file>
<source>
@ -1321,7 +1231,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/cep/storm/storm.yaml
@ -1330,8 +1239,6 @@
</outputDirectory>
<filtered>true</filtered>
</file>
<!--DAS Files-->
<file>
<source>
@ -1341,7 +1248,6 @@
</outputDirectory>
<filtered>true</filtered>
</file>
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/output-event-adapters.xml
@ -1351,7 +1257,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/input-event-adapters.xml
@ -1361,7 +1266,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!-- ************* Data bridge related files ********** -->
<file>
<source>../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/data-bridge/data-bridge-config.xml</source>
@ -1392,7 +1296,6 @@
</outputDirectory>
<fileMode>755</fileMode>
</file>
<!--spark classpath config file-->
<file>
<source>
@ -1402,7 +1305,6 @@
</outputDirectory>
<fileMode>755</fileMode>
</file>
<!--spark fair scheduler xml file-->
<file>
<source>
@ -1412,7 +1314,6 @@
</outputDirectory>
<fileMode>755</fileMode>
</file>
<!--spark udf conf file-->
<file>
<source>
@ -1422,7 +1323,6 @@
</outputDirectory>
<fileMode>755</fileMode>
</file>
<!--Analytics REST APIs WebApp -->
<file>
<source>
@ -1431,43 +1331,6 @@
<outputDirectory>${pom.artifactId}-${pom.version}/repository/deployment/server/webapps</outputDirectory>
<fileMode>644</fileMode>
</file>
<!--<file>-->
<!--<source>-->
<!--../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/devicemgt-config.xml-->
<!--</source>-->
<!--<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf</outputDirectory>-->
<!--<filtered>true</filtered>-->
<!--<fileMode>644</fileMode>-->
<!--</file>-->
<!--<file>-->
<!--<source>-->
<!--../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/devicemgt-config.xsd-->
<!--</source>-->
<!--<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf</outputDirectory>-->
<!--<filtered>true</filtered>-->
<!--<fileMode>644</fileMode>-->
<!--</file>-->
<!--<file>-->
<!--<source>-->
<!--../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/devicetype-config.xml-->
<!--</source>-->
<!--<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf</outputDirectory>-->
<!--<filtered>true</filtered>-->
<!--<fileMode>644</fileMode>-->
<!--</file>-->
<!--<file>-->
<!--<source>-->
<!--../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/devicetype-config.xsd-->
<!--</source>-->
<!--<outputDirectory>${pom.artifactId}-${pom.version}/repository/conf</outputDirectory>-->
<!--<filtered>true</filtered>-->
<!--<fileMode>644</fileMode>-->
<!--</file>-->
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/iot/devicemgt-config.xml
@ -1476,7 +1339,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/iot/devicemgt-config.xsd
@ -1485,7 +1347,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/iot/devicetype-config.xml
@ -1494,7 +1355,6 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<file>
<source>
../p2-profile-gen/target/wso2carbon-core-${carbon.kernel.version}/repository/conf/iot/devicetype-config.xsd
@ -1503,15 +1363,5 @@
<filtered>true</filtered>
<fileMode>644</fileMode>
</file>
<!--<file>-->
<!--<source>-->
<!--src/repository/patches/oltu-1.0.0.wso2v2.jar-->
<!--</source>-->
<!--<outputDirectory>-->
<!--${pom.artifactId}-${pom.version}/repository/components/patches/patch1000-->
<!--</outputDirectory>-->
<!--</file>-->
</files>
</assembly>

@ -0,0 +1,380 @@
<%
(function () {
var TYPE = "type";
var TABLE_NAME = "tableName";
var TIME_FROM = "timeFrom";
var TIME_TO = "timeTo";
var START = "start";
var COUNT = "count";
var FILTER = "filter";
var QUERY = "query";
var SORT_SCORE_VALUE = "scoreFunc";
var RECORDSTORE_NAME = "recordStore";
var HTTPS_TRANSPORT = "https";
var CONTENT_TYPE_JSON = "application/json";
var AUTHORIZATION_HEADER = "Authorization";
var USER_TOKEN = "user";
var USERNAME = "username";
var WAIT_TIME = "waitTime";
var LOCALHOST = "localhost";
var HTTP_USER_NOT_AUTHENTICATED = 403;
var HTTP_INTERNAL_ERROR = 500;
var MILLISECONDS_PER_SECOND = 1000;
var JS_MAX_VALUE = "9007199254740992";
var JS_MIN_VALUE = "-9007199254740992";
var ZERO_INDEX = "0";
var LAST_INDEX = "5000"; //Set the max value to 5000. This is to prevent accidental loading of millions of records.
var DEFAULT_COUNT = 20;
var TYPE_CLEAR_INDEX_DATA = 1;
// var TYPE_CREATE_TABLE = 2;
// var TYPE_DELETE_BY_ID = 3;
// var TYPE_DELETE_BY_RANGE = 4;
// var TYPE_DELETE_TABLE = 5;
var TYPE_GET_RECORD_COUNT = 6;
var TYPE_GET_BY_ID = 7;
var TYPE_GET_BY_RANGE = 8;
var TYPE_LIST_TABLES = 9;
var TYPE_GET_SCHEMA = 10;
// var TYPE_PUT_RECORDS = 11;
// var TYPE_PUT_RECORDS_TO_TABLE = 12;
var TYPE_SEARCH = 13;
var TYPE_SEARCH_COUNT = 14;
var TYPE_SET_SCHEMA = 15;
var TYPE_TABLE_EXISTS = 16;
var TYPE_WAIT_FOR_INDEXING = 17;
var TYPE_PAGINATION_SUPPORTED = 18;
var TYPE_DRILLDOWN_CATEGORIES = 19;
var TYPE_DRILLDOWN_SEARCH = 20;
var TYPE_DRILLDOWN_SEARCH_COUNT = 21;
var TYPE_ADD_STREAM_DEFINITION = 22;
var TYPE_GET_STREAM_DEFINITION = 23;
var TYPE_PUBLISH_EVENTS = 24;
var TYPE_GET_WITH_KEY_VALUES = 25;
var TYPE_GET_RECORDSTORES = 26;
var TYPE_GET_RECORDSTORE_BY_TABLE = 27;
var TYPE_WAIT_FOR_INDEXING_FOR_TABLE = 28;
var TYPE_SEARCH_WITH_AGGREGATES = 29;
var TYPE_REINDEX = 30;
var log = new Log();
var carbon = require('carbon');
var configs = require('/configs/designer.json');
var utils = require('/modules/utils.js');
var JSUtils = Packages.org.wso2.carbon.analytics.jsservice.Utils;
var AnalyticsCachedJSServiceConnector = Packages.org.wso2.carbon.analytics.jsservice.AnalyticsCachedJSServiceConnector;
var AnalyticsCache = Packages.org.wso2.carbon.analytics.jsservice.AnalyticsCachedJSServiceConnector.AnalyticsCache;
var cacheTimeoutSeconds = 5;
var loggedInUser = null;
if(configs.cacheTimeoutSeconds) {
cacheTimeoutSeconds = parseInt(configs.cacheTimeoutSeconds);
}
var cacheSizeBytes = 1024 * 1024 * 1024; // 1GB
if(configs.cacheSizeBytes) {
cacheSizeBytes = parseInt(configs.cacheSizeBytes);
}
response.contentType = CONTENT_TYPE_JSON;
var authParam = request.getHeader(AUTHORIZATION_HEADER);
if (authParam != null) {
credentials = JSUtils.authenticate(authParam);
loggedInUser = credentials[0];
} else {
var token = session.get(USER_TOKEN);
if (token != null) {
loggedInUser = token[USERNAME];
} else {
log.error("user is not authenticated!");
response.status = HTTP_USER_NOT_AUTHENTICATED;
print('{ "status": "Failed", "message": "User is not authenticated." }');
return;
}
}
var cache = application.get("AnalyticsWebServiceCache");
if (cache == null) {
cache = new AnalyticsCache(cacheTimeoutSeconds, cacheSizeBytes);
application.put("AnalyticsWebServiceCache", cache);
}
var connector = new AnalyticsCachedJSServiceConnector(cache);
var type = 0;
var typeParam = request.getParameter(TYPE);
if (typeParam != null) {
type = parseInt(typeParam);
}
if (type == 0) {
log.error("operation type is not specified!");
response.status = HTTP_INTERNAL_ERROR;
print('{ "status": "Failed", "message": "Operation type is not specified" }');
return;
}
var tableName = request.getParameter(TABLE_NAME);
if (type != TYPE_LIST_TABLES &&
// type != TYPE_PUT_RECORDS &&
type != TYPE_PAGINATION_SUPPORTED &&
type != TYPE_ADD_STREAM_DEFINITION &&
type != TYPE_GET_STREAM_DEFINITION &&
type != TYPE_PUBLISH_EVENTS &&
type != TYPE_WAIT_FOR_INDEXING &&
type != TYPE_GET_RECORDSTORES) {
if (tableName == null) {
log.error("tableName is not provided!");
response.status = HTTP_INTERNAL_ERROR;
print('{ "status": "Failed", "message": "Table name param is empty" }');
return;
}
}
var content = request.getContent();
var contentAsString = null;
if (content != '' && content != null) {
contentAsString = stringify(content);
if (log.isDebugEnabled()) {
log.debug("value of content: " + contentAsString);
}
}
if (connector != null && loggedInUser != null) {
var result = null;
switch (type) {
case TYPE_LIST_TABLES:
{
result = connector.getTableList(loggedInUser);
break;
}
/*case TYPE_CREATE_TABLE:
{
print(connector.createTable(tableName));
break;
}
case TYPE_DELETE_TABLE:
{
print(connector.deleteTable(tableName));
break;
} */
case TYPE_TABLE_EXISTS:
{
result = connector.tableExists(loggedInUser, tableName);
break;
}
case TYPE_GET_BY_RANGE:
{
var from = request.getParameter(TIME_FROM);
if (from == 'undefined') from = JS_MIN_VALUE;
var to = request.getParameter(TIME_TO);
if (to == 'undefined') to = JS_MAX_VALUE;
var start = request.getParameter(START);
var intStart = ZERO_INDEX;
if (start != 'undefined' && start != null) {
intStart = parseInt(start, 10);
}
var count = request.getParameter(COUNT);
var intCount = LAST_INDEX;
if (count != 'undefined' && count != null) {
intCount = parseInt(count, 10);
}
result = connector.getRecordsByRange(loggedInUser, tableName, from, to, intStart, intCount, contentAsString);
break;
}
case TYPE_GET_WITH_KEY_VALUES:
{
result = connector.getWithKeyValues(loggedInUser, tableName, contentAsString);
break;
}
case TYPE_GET_BY_ID:
{
result = connector.getRecordsByIds(loggedInUser, tableName, contentAsString);
break;
}
case TYPE_GET_RECORD_COUNT:
{
result = connector.getRecordCount(loggedInUser, tableName);
break;
}
/*case TYPE_DELETE_BY_RANGE:
{
var timeFrom = Long.parseLong(request.getParameter(TIME_FROM));
var timeTo = Long.parseLong(request.getParameter(TIME_TO));
print(connector.deleteRecordsByRange(tableName, timeFrom, timeTo));
break;
}
case TYPE_DELETE_BY_ID:
{
print(connector.deleteRecordsByIds(tableName, contentAsString));
break;
}*/
case TYPE_CLEAR_INDEX_DATA:
{
result = connector.clearIndexData(loggedInUser, tableName);
break;
}
/*case TYPE_PUT_RECORDS:
{
print(connector.insertRecords(contentAsString));
break;
}*/
case TYPE_SEARCH_COUNT:
{
var queryString = request.getParameter(QUERY);
if (queryString == 'undefined' || queryString == null || queryString == '') {
result = '{ "status": "Failed", "statusCode": "400", "message": "Invalid Request" }';
break;
};
contentAsString = "{query: " + queryString + "}";
result = connector.searchCount(loggedInUser, tableName, contentAsString);
break;
}
case TYPE_SEARCH:
{
var queryString = request.getParameter(QUERY);
if (queryString == 'undefined' || queryString == null || queryString == '') {
result = '{ "status": "Failed", "statusCode": "400", "message": "Invalid Request" }';
break;
};
var count = request.getParameter(COUNT);
if (count == 'undefined' || count == null || count == '') {
count = DEFAULT_COUNT;
}
contentAsString = "{query: " + queryString + ", count:" + count + "}";
result = connector.search(loggedInUser, tableName, contentAsString);
break;
}
case TYPE_SET_SCHEMA:
{
print(connector.setTableSchema(loggedInUser, tableName, contentAsString));
break;
}
case TYPE_GET_SCHEMA:
{
result = connector.getTableSchema(loggedInUser, tableName);
break;
}
case TYPE_PAGINATION_SUPPORTED:
{
var recordStore = request.getParameter(RECORDSTORE_NAME)
result = connector.isPaginationSupported(recordStore);
break;
}
case TYPE_WAIT_FOR_INDEXING:
{
var waitTimeAsString = request.getParameter(WAIT_TIME);
var waitTime = -1;
if (waitTimeAsString != null) {
waitTime = parseInt(waitTimeAsString);
}
result = connector.waitForIndexing(waitTime * MILLISECONDS_PER_SECOND);
break;
}
case TYPE_WAIT_FOR_INDEXING_FOR_TABLE:
{
var waitTimeAsString = request.getParameter(WAIT_TIME);
var waitTime = -1;
if (waitTimeAsString != null) {
waitTime = parseInt(waitTimeAsString);
}
result = connector.waitForIndexing(tableName, waitTime * MILLISECONDS_PER_SECOND);
break;
}
case TYPE_DRILLDOWN_CATEGORIES:
{
result = connector.drillDownCategories(loggedInUser, tableName, contentAsString);
break;
}
case TYPE_DRILLDOWN_SEARCH:
{
var queryString = request.getParameter(QUERY);
if (queryString == 'undefined' || queryString == null || queryString == '') {
result = '{ "status": "Failed", "statusCode": "400", "message": "Invalid Request. Query string not found." }';
break;
};
var scoreFunction = request.getParameter(SORT_SCORE_VALUE);
if (scoreFunction == 'undefined' || scoreFunction == null || scoreFunction == '') {
result = '{ "status": "Failed", "statusCode": "400", "message": "Invalid Request. Score function not found." }';
break;
};
var count = request.getParameter(COUNT);
if (count == 'undefined' || count == null || count == '') {
count = DEFAULT_COUNT;
}
contentAsString = "{query: " + queryString + ", recordCount:"+ count +", scoreFunction:'"+ scoreFunction +"', categories: []}";
result = connector.drillDownSearch(loggedInUser, tableName, contentAsString);
break;
}
case TYPE_DRILLDOWN_SEARCH_COUNT:
{
result = connector.drillDownSearchCount(loggedInUser, tableName, contentAsString);
break;
}
case TYPE_ADD_STREAM_DEFINITION:
{
result = connector.addStreamDefinition(contentAsString);
break;
}
case TYPE_GET_STREAM_DEFINITION:
{
result = connector.getStreamDefinition(contentAsString);
break;
}
case TYPE_PUBLISH_EVENTS:
{
result = connector.publishEvent(contentAsString);
break;
}
case TYPE_GET_RECORDSTORES:
{
result = connector.getRecordStoreList();
break;
}
case TYPE_GET_RECORDSTORE_BY_TABLE:
{
result = connector.getRecordStoreByTable(loggedInUser, tableName);
break;
}
case TYPE_SEARCH_WITH_AGGREGATES:
{
result = connector.searchWithAggregates(loggedInUser, contentAsString);
break;
}
case TYPE_REINDEX:
{
var from = request.getParameter(TIME_FROM);
if (from == 'undefined') from = JS_MIN_VALUE;
var to = request.getParameter(TIME_TO);
if (to == 'undefined') to = JS_MAX_VALUE;
result = connector.reIndex(loggedInUser, tableName, from, to);
break;
}
default:
result = '{ "status": "Failed", "statusCode": "500", "message": "Unidentified operation" }';
}
if (result != null) {
if (log.isDebugEnabled()) {
log.debug("value of result: " + result);
log.debug("status code: " + result.getstatusCode())
}
var statusCode = result.getStatusCode();
var status = result.getStatus();
var message = result.getMessage();
response.status = statusCode;
var finalResult = {
status: status,
message: message
};
print(finalResult);
}
} else {
print('{ "status": "Failed", "statusCode": "500", "message": "AnalyticsCachedWebServiceConnector is unavailable" }');
}
}());
%>

@ -0,0 +1,286 @@
/*
*
*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
*/
var CONSTANTS = {
webAppName: 'outputui',
urlSeperator: '/',
urlGetParameter : '?lastUpdatedTime=',
urlQueryStringBegin : '?',
tenantUrlAttribute: 't',
urlUnsecureTransportHttp : 'http://',
urlUnsecureTransportWebsocket : 'ws://',
urlSecureTransportWebsocket : 'wss://',
urlSecureTransportHttp : 'https://',
colon : ':',
defaultIntervalTime : 10 * 1000,
defaultUserDomain : 'carbon.super',
defaultHostName : 'localhost',
defaultNonsecurePortNumber : '9763',
defaultSecurePortNumber : '9443',
defaultMode : 'AUTO',
processModeHTTP : 'HTTP',
processModeWebSocket : 'WEBSOCKET',
processModeAuto : 'AUTO',
domain : 'carbon.super',
numThousand : 1000,
websocketTimeAppender : 400,
secureMode : 'SECURED'
};
var websocket = null;
var webSocketUrl;
var httpUrl;
var cepHostName;
var cepPortNumber;
var isErrorOccured = false;
var lastUpdatedtime = -1;
var polingInterval;
var stream;
var streamVersion;
var firstPollingAttempt;
var processMode;
var onSuccessFunction;
var onErrorFunction;
var userDomainUrl = "";
var terminateWebsocketInstance = false;
var pollingContinue = true;
var transportToBeUsedHttp;
var transportToBeUsedWebsocket;
function subscribe(streamName,version,intervalTime,domain,
listeningFuncSuccessData,listeningFuncErrorData,
cepHost,cepPort,mode,secureMode, queryParams){
stopPollingProcesses();
stream = streamName;
streamVersion = version;
onSuccessFunction = listeningFuncSuccessData;
onErrorFunction = listeningFuncErrorData;
if(secureMode == CONSTANTS.secureMode){
transportToBeUsedHttp = CONSTANTS.urlSecureTransportHttp;
transportToBeUsedWebsocket = CONSTANTS.urlSecureTransportWebsocket;
} else {
transportToBeUsedHttp = CONSTANTS.urlUnsecureTransportHttp;
transportToBeUsedWebsocket = CONSTANTS.urlUnsecureTransportWebsocket;
}
if(intervalTime == null || intervalTime == ""){
polingInterval = CONSTANTS.defaultIntervalTime;
} else{
polingInterval = intervalTime * CONSTANTS.numThousand;
}
if(domain == null || domain == ""){
domain = CONSTANTS.defaultUserDomain;
}
if(cepHost == null || cepHost == ""){
cepHostName = CONSTANTS.defaultHostName;
} else{
cepHostName = cepHost;
}
if(cepPort == null || cepPort == ""){
if(secureMode == CONSTANTS.secureMode){
cepPortNumber = CONSTANTS.defaultSecurePortNumber;
} else{
cepPortNumber = CONSTANTS.defaultNonsecurePortNumber;
}
} else{
cepPortNumber = cepPort;
}
if(mode == null || mode == ""){
processMode = CONSTANTS.defaultMode;
} else{
processMode = mode;
}
if(domain != CONSTANTS.domain){
userDomainUrl = CONSTANTS.tenantUrlAttribute + CONSTANTS.urlSeperator + domain + CONSTANTS.urlSeperator;
}
if (queryParams == null) {
queryParams = "";
} else if (queryParams != "") {
queryParams = CONSTANTS.urlQueryStringBegin + queryParams;
}
webSocketUrl = transportToBeUsedWebsocket + cepHostName + CONSTANTS.colon + cepPortNumber +
CONSTANTS.urlSeperator + CONSTANTS.webAppName+ CONSTANTS.urlSeperator + userDomainUrl + stream +
CONSTANTS.urlSeperator + streamVersion + queryParams;
if(processMode == CONSTANTS.processModeHTTP){
firstPollingAttempt = true;
pollingContinue = true;
startPoll();
} else{
initializeWebSocket(webSocketUrl);
}
}
/**
* Initializing Web Socket
*/
function initializeWebSocket(webSocketUrl){
websocket = new WebSocket(webSocketUrl);
websocket.onopen = webSocketOnOpen;
websocket.onmessage = webSocketOnMessage;
websocket.onclose = webSocketOnClose;
websocket.onerror = webSocketOnError;
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
// alert("Successfully connected to "+webSocketUrl);
//onErrorFunction("Successfully connected to URL:" + webSocketUrl + "\n");
};
/**
* On server sends a message
*/
var webSocketOnMessage = function (evt) {
var event = evt.data;
var array = JSON.parse(event);
constructPayload(array);
};
/**
* On server close
*/
var webSocketOnClose =function (e) {
if(isErrorOccured){
if(processMode != CONSTANTS.processModeWebSocket){
firstPollingAttempt = true;
pollingContinue = true;
startPoll();
}
} else{
if(!terminateWebsocketInstance){
waitForSocketConnection(websocket);
} else{
terminateWebsocketInstance = false;
}
}
};
/**
* On server Error
*/
var webSocketOnError = function (err) {
var error = "Error: Cannot connect to Websocket URL:" + webSocketUrl + " .Hence closing the connection!";
onErrorFunction(error);
isErrorOccured = true;
};
/**
* Gracefully increments the connection retry
*/
var waitTime = CONSTANTS.numThousand;
function waitForSocketConnection(socket, callback){
setTimeout(
function () {
if (socket.readyState === 1) {
initializeWebSocket(webSocketUrl);
console.log("Connection is made");
if(callback != null){
callback();
}
return;
} else {
websocket = new WebSocket(webSocketUrl);
waitTime += CONSTANTS.websocketTimeAppender;
waitForSocketConnection(websocket, callback);
}
}, waitTime);
}
/**
* Polling to retrieve events from http request periodically
*/
function startPoll(){
(function poll(){
setTimeout(function(){
httpUrl = transportToBeUsedHttp + cepHostName + CONSTANTS.colon + cepPortNumber + CONSTANTS.urlSeperator
+ CONSTANTS.webAppName + CONSTANTS.urlSeperator + userDomainUrl + stream + CONSTANTS.urlSeperator +
streamVersion + CONSTANTS.urlGetParameter + lastUpdatedtime;
$.getJSON(httpUrl, function(responseText) {
if(firstPollingAttempt){
/*var data = $("textarea#idConsole").val();
$("textarea#idConsole").val(data + "Successfully connected to HTTP.");*/
firstPollingAttempt = false;
}
var eventList = $.parseJSON(responseText.events);
if(eventList.length != 0){
lastUpdatedtime = responseText.lastEventTime;
for(var i=0;i<eventList.length;i++){
var arr = eventList[i];
constructPayload(arr);
}
}
if(pollingContinue){
startPoll();
}
})
.fail(function(errorData) {
var errorData = JSON.parse(errorData.responseText);
onErrorFunction(errorData.error);
});
}, polingInterval);
})()
}
function stopPollingProcesses(){
//stopping the Websocket
if(websocket != null){
terminateWebsocketInstance = true;
websocket.onclose;
}
//stopping the HTTPS Request
pollingContinue = false;
}
function constructPayload(eventsArray){
var streamId = stream + CONSTANTS.colon + streamVersion;
var twoDimentionalArray = [eventsArray];
onSuccessFunction(streamId,twoDimentionalArray);
}

@ -0,0 +1,29 @@
/*!
* d3.geomap
* https://github.com/yaph/d3-geomap/blob/master/LICENSE
* MIT licensed
* Copyright (C) 2015 by Ramiro Gómez (http://ramiro.org/)
*/
text {
fill: #333;
font-size: 12px; }
.background {
fill: none;
pointer-events: all; }
.unit {
cursor: pointer;
fill: #ccc;
stroke: #000;
stroke-width: 0.4px; }
.legend-bg {
fill: #fff;
fill-opacity: 0.8; }
.legend-bar {
stroke: #333;
stroke-width: 1px; }
/*# sourceMappingURL=geomap.css.map */

@ -0,0 +1,80 @@
#rect {
fill: none;
stroke: rgb(0, 0, 0);
stroke-width: 2;
}
#rectCurve {
fill: none;
stroke: rgb(0, 0, 0);
stroke-width: 0.5;
}
.axis path,
.axis line {
fill: none;
shape-rendering: crispEdges;
stroke: grey;
stroke-width: 2;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.label{
font-size: 16.844px !important;
}
/* arc tween shit*/
.background {
fill: #FFFFFF;
fill-opacity: 0.01;
}
.component {
fill: #e1e1e1;
}
.component .label {
font-family: Myriad, "Helvetic Neue", Helvetica, Arial;
text-anchor: middle;
fill: #0000FF;
}
.arc {
stroke-weight:0.1;
fill: #4e8fff;
}
.arc2 {
stroke-weight:0.1;
fill: #3660b0;
}
.label {
font-family: Myriad, "Helvetic Neue", Helvetica, Arial;
text-anchor: middle;
}
.labelArc {
font-family: Myriad, "Helvetic Neue", Helvetica, Arial;
text-anchor: middle;
fill: #0000FF;
}
.tooltipClass {
background-color: #e5f2ff;
padding: 4px 8px;
}
.tooltipClass p{
margin: 0;
padding: 0;
}

@ -0,0 +1 @@
{"id":"IoTServerTemperatureStats","title":"IoTServerTemperatureStats","type":"gadget","thumbnail":"local://images/gadgetIcon.png","data":{"url":"local://store/carbon.super/gadget/IoTServerTemperatureStats/index.xml"}}

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Bar Chart"
author="WSO2 Gadget Server"
height="230"
scrolling="true"
tags="charts,bar,visualization,data"
description="A generic Bar Chart gadget, that takes a json datasource as an input. It can be configured to fetch data in defined intervals. This gadget can be used to create dashboards with statistical data. This gadget can be reused as an iframe in any web page as it is self contained.">
</ModulePrefs>
<UserPref name="dataSource"
display_name="Data Source"
default_value="/portal/gadgets/bar-chart/datasource/dataFile4.jag">
</UserPref>
<!--UserPref name="options"
display_name="Chart Options"
default_value="/portal/gadgets/bar-chart/js/options-bar.js">
</UserPref-->
<UserPref name="updateGraph"
display_name="Update Interval (s)"
default_value="No">
</UserPref>
<Content type="html">
<![CDATA[
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Bar Chart</title>
<link href="css/flot-graph.css" rel="stylesheet" type="text/css">
<link href="css/igviz.css" rel="stylesheet" type="text/css">
<link href="css/bootstrap.min.css" rel="stylesheet" type="text/css">
<link href="css/d3.geomap.css" rel="stylesheet" type="text/css">
<script language="javascript" type="text/javascript" src="js/excanvas.min.js"></script>
<script language="javascript" type="text/javascript" src="js/jquery.js"></script>
<script language="javascript" type="text/javascript" src="js/topojson.js"></script>
<script language="javascript" type="text/javascript" src="js/d3.min.js"></script>
<script language="javascript" type="text/javascript" src="js/vega.js"></script>
<script language="javascript" type="text/javascript" src="js/VizGrammar.min.js"></script>
<script language="javascript" type="text/javascript" src="js/gadgetconf.js"></script>
<script language="javascript" type="text/javascript" src="js/outputAdapterUiLibrary.js"></script>
<script language="javascript" type="text/javascript" src="js/main.js"></script>
</head>
<body>
<div id="placeholder" class="demo-placeholder" style="height:90%"></div>
<script language="javascript" type="text/javascript">
if(jQuery("#placeholder").html() == ""){
jQuery("#placeholder").append('<div id="noChart"><table><tr><td style="padding:30px 20px 0px 20px"><img src="../../portal/images/noEvents.png" align="left" style="width:24;height:24"/></td><td><br/><b><p><br/> Data is not available for plotting</p></b></td></tr><tr><td></td><td><p>The chart will be loaded once the dashboard receives events</p><td/></tr></table></div>');
}
</script>
</body>
</html>
]]>
</Content>
</Module>

@ -0,0 +1,48 @@
if(navigator.appVersion.indexOf("MSIE")!=-1&&parseFloat(navigator.appVersion.split("MSIE")[1])<=8&&!document.createElement("canvas").getContext)(function(){var m=Math;var mr=m.round;var ms=m.sin;var mc=m.cos;var abs=m.abs;var sqrt=m.sqrt;var Z=10;var Z2=Z/2;var IE_VERSION=+navigator.userAgent.match(/MSIE ([\d.]+)?/)[1];function getContext(){return this.context_||(this.context_=new CanvasRenderingContext2D_(this))}var slice=Array.prototype.slice;function bind(f,obj,var_args){var a=slice.call(arguments,
2);return function(){return f.apply(obj,a.concat(slice.call(arguments)))}}function encodeHtmlAttribute(s){return String(s).replace(/&/g,"&amp;").replace(/"/g,"&quot;")}function addNamespace(doc,prefix,urn){if(!doc.namespaces[prefix])doc.namespaces.add(prefix,urn,"#default#VML")}function addNamespacesAndStylesheet(doc){addNamespace(doc,"g_vml_","urn:schemas-microsoft-com:vml");addNamespace(doc,"g_o_","urn:schemas-microsoft-com:office:office");if(!doc.styleSheets["ex_canvas_"]){var ss=doc.createStyleSheet();
ss.owningElement.id="ex_canvas_";ss.cssText="canvas{display:inline-block;overflow:hidden;"+"text-align:left;width:300px;height:150px}"}}addNamespacesAndStylesheet(document);var G_vmlCanvasManager_={init:function(opt_doc){var doc=opt_doc||document;doc.createElement("canvas");doc.attachEvent("onreadystatechange",bind(this.init_,this,doc))},init_:function(doc){var els=doc.getElementsByTagName("canvas");for(var i=0;i<els.length;i++)this.initElement(els[i])},initElement:function(el){if(!el.getContext){el.getContext=
getContext;addNamespacesAndStylesheet(el.ownerDocument);el.innerHTML="";el.attachEvent("onpropertychange",onPropertyChange);el.attachEvent("onresize",onResize);var attrs=el.attributes;if(attrs.width&&attrs.width.specified)el.style.width=attrs.width.nodeValue+"px";else el.width=el.clientWidth;if(attrs.height&&attrs.height.specified)el.style.height=attrs.height.nodeValue+"px";else el.height=el.clientHeight}return el}};function onPropertyChange(e){var el=e.srcElement;switch(e.propertyName){case "width":el.getContext().clearRect();
el.style.width=el.attributes.width.nodeValue+"px";el.firstChild.style.width=el.clientWidth+"px";break;case "height":el.getContext().clearRect();el.style.height=el.attributes.height.nodeValue+"px";el.firstChild.style.height=el.clientHeight+"px";break}}function onResize(e){var el=e.srcElement;if(el.firstChild){el.firstChild.style.width=el.clientWidth+"px";el.firstChild.style.height=el.clientHeight+"px"}}G_vmlCanvasManager_.init();var decToHex=[];for(var i=0;i<16;i++)for(var j=0;j<16;j++)decToHex[i*
16+j]=i.toString(16)+j.toString(16);function createMatrixIdentity(){return[[1,0,0],[0,1,0],[0,0,1]]}function matrixMultiply(m1,m2){var result=createMatrixIdentity();for(var x=0;x<3;x++)for(var y=0;y<3;y++){var sum=0;for(var z=0;z<3;z++)sum+=m1[x][z]*m2[z][y];result[x][y]=sum}return result}function copyState(o1,o2){o2.fillStyle=o1.fillStyle;o2.lineCap=o1.lineCap;o2.lineJoin=o1.lineJoin;o2.lineWidth=o1.lineWidth;o2.miterLimit=o1.miterLimit;o2.shadowBlur=o1.shadowBlur;o2.shadowColor=o1.shadowColor;o2.shadowOffsetX=
o1.shadowOffsetX;o2.shadowOffsetY=o1.shadowOffsetY;o2.strokeStyle=o1.strokeStyle;o2.globalAlpha=o1.globalAlpha;o2.font=o1.font;o2.textAlign=o1.textAlign;o2.textBaseline=o1.textBaseline;o2.arcScaleX_=o1.arcScaleX_;o2.arcScaleY_=o1.arcScaleY_;o2.lineScale_=o1.lineScale_}var colorData={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",
chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",
darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",
lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",
mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",
salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"};function getRgbHslContent(styleString){var start=styleString.indexOf("(",3);var end=styleString.indexOf(")",start+1);var parts=
styleString.substring(start+1,end).split(",");if(parts.length!=4||styleString.charAt(3)!="a")parts[3]=1;return parts}function percent(s){return parseFloat(s)/100}function clamp(v,min,max){return Math.min(max,Math.max(min,v))}function hslToRgb(parts){var r,g,b,h,s,l;h=parseFloat(parts[0])/360%360;if(h<0)h++;s=clamp(percent(parts[1]),0,1);l=clamp(percent(parts[2]),0,1);if(s==0)r=g=b=l;else{var q=l<0.5?l*(1+s):l+s-l*s;var p=2*l-q;r=hueToRgb(p,q,h+1/3);g=hueToRgb(p,q,h);b=hueToRgb(p,q,h-1/3)}return"#"+
decToHex[Math.floor(r*255)]+decToHex[Math.floor(g*255)]+decToHex[Math.floor(b*255)]}function hueToRgb(m1,m2,h){if(h<0)h++;if(h>1)h--;if(6*h<1)return m1+(m2-m1)*6*h;else if(2*h<1)return m2;else if(3*h<2)return m1+(m2-m1)*(2/3-h)*6;else return m1}var processStyleCache={};function processStyle(styleString){if(styleString in processStyleCache)return processStyleCache[styleString];var str,alpha=1;styleString=String(styleString);if(styleString.charAt(0)=="#")str=styleString;else if(/^rgb/.test(styleString)){var parts=
getRgbHslContent(styleString);var str="#",n;for(var i=0;i<3;i++){if(parts[i].indexOf("%")!=-1)n=Math.floor(percent(parts[i])*255);else n=+parts[i];str+=decToHex[clamp(n,0,255)]}alpha=+parts[3]}else if(/^hsl/.test(styleString)){var parts=getRgbHslContent(styleString);str=hslToRgb(parts);alpha=parts[3]}else str=colorData[styleString]||styleString;return processStyleCache[styleString]={color:str,alpha:alpha}}var DEFAULT_STYLE={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};
var fontStyleCache={};function processFontStyle(styleString){if(fontStyleCache[styleString])return fontStyleCache[styleString];var el=document.createElement("div");var style=el.style;try{style.font=styleString}catch(ex){}return fontStyleCache[styleString]={style:style.fontStyle||DEFAULT_STYLE.style,variant:style.fontVariant||DEFAULT_STYLE.variant,weight:style.fontWeight||DEFAULT_STYLE.weight,size:style.fontSize||DEFAULT_STYLE.size,family:style.fontFamily||DEFAULT_STYLE.family}}function getComputedStyle(style,
element){var computedStyle={};for(var p in style)computedStyle[p]=style[p];var canvasFontSize=parseFloat(element.currentStyle.fontSize),fontSize=parseFloat(style.size);if(typeof style.size=="number")computedStyle.size=style.size;else if(style.size.indexOf("px")!=-1)computedStyle.size=fontSize;else if(style.size.indexOf("em")!=-1)computedStyle.size=canvasFontSize*fontSize;else if(style.size.indexOf("%")!=-1)computedStyle.size=canvasFontSize/100*fontSize;else if(style.size.indexOf("pt")!=-1)computedStyle.size=
fontSize/0.75;else computedStyle.size=canvasFontSize;computedStyle.size*=0.981;return computedStyle}function buildStyle(style){return style.style+" "+style.variant+" "+style.weight+" "+style.size+"px "+style.family}var lineCapMap={"butt":"flat","round":"round"};function processLineCap(lineCap){return lineCapMap[lineCap]||"square"}function CanvasRenderingContext2D_(canvasElement){this.m_=createMatrixIdentity();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle=
"#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=Z*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=canvasElement;var cssText="width:"+canvasElement.clientWidth+"px;height:"+canvasElement.clientHeight+"px;overflow:hidden;position:absolute";var el=canvasElement.ownerDocument.createElement("div");el.style.cssText=cssText;canvasElement.appendChild(el);var overlayEl=el.cloneNode(false);overlayEl.style.backgroundColor=
"red";overlayEl.style.filter="alpha(opacity=0)";canvasElement.appendChild(overlayEl);this.element_=el;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var contextPrototype=CanvasRenderingContext2D_.prototype;contextPrototype.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};contextPrototype.beginPath=function(){this.currentPath_=[]};contextPrototype.moveTo=function(aX,aY){var p=getCoords(this,aX,aY);this.currentPath_.push({type:"moveTo",
x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};contextPrototype.lineTo=function(aX,aY){var p=getCoords(this,aX,aY);this.currentPath_.push({type:"lineTo",x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};contextPrototype.bezierCurveTo=function(aCP1x,aCP1y,aCP2x,aCP2y,aX,aY){var p=getCoords(this,aX,aY);var cp1=getCoords(this,aCP1x,aCP1y);var cp2=getCoords(this,aCP2x,aCP2y);bezierCurveTo(this,cp1,cp2,p)};function bezierCurveTo(self,cp1,cp2,p){self.currentPath_.push({type:"bezierCurveTo",cp1x:cp1.x,
cp1y:cp1.y,cp2x:cp2.x,cp2y:cp2.y,x:p.x,y:p.y});self.currentX_=p.x;self.currentY_=p.y}contextPrototype.quadraticCurveTo=function(aCPx,aCPy,aX,aY){var cp=getCoords(this,aCPx,aCPy);var p=getCoords(this,aX,aY);var cp1={x:this.currentX_+2/3*(cp.x-this.currentX_),y:this.currentY_+2/3*(cp.y-this.currentY_)};var cp2={x:cp1.x+(p.x-this.currentX_)/3,y:cp1.y+(p.y-this.currentY_)/3};bezierCurveTo(this,cp1,cp2,p)};contextPrototype.arc=function(aX,aY,aRadius,aStartAngle,aEndAngle,aClockwise){aRadius*=Z;var arcType=
aClockwise?"at":"wa";var xStart=aX+mc(aStartAngle)*aRadius-Z2;var yStart=aY+ms(aStartAngle)*aRadius-Z2;var xEnd=aX+mc(aEndAngle)*aRadius-Z2;var yEnd=aY+ms(aEndAngle)*aRadius-Z2;if(xStart==xEnd&&!aClockwise)xStart+=0.125;var p=getCoords(this,aX,aY);var pStart=getCoords(this,xStart,yStart);var pEnd=getCoords(this,xEnd,yEnd);this.currentPath_.push({type:arcType,x:p.x,y:p.y,radius:aRadius,xStart:pStart.x,yStart:pStart.y,xEnd:pEnd.x,yEnd:pEnd.y})};contextPrototype.rect=function(aX,aY,aWidth,aHeight){this.moveTo(aX,
aY);this.lineTo(aX+aWidth,aY);this.lineTo(aX+aWidth,aY+aHeight);this.lineTo(aX,aY+aHeight);this.closePath()};contextPrototype.strokeRect=function(aX,aY,aWidth,aHeight){var oldPath=this.currentPath_;this.beginPath();this.moveTo(aX,aY);this.lineTo(aX+aWidth,aY);this.lineTo(aX+aWidth,aY+aHeight);this.lineTo(aX,aY+aHeight);this.closePath();this.stroke();this.currentPath_=oldPath};contextPrototype.fillRect=function(aX,aY,aWidth,aHeight){var oldPath=this.currentPath_;this.beginPath();this.moveTo(aX,aY);
this.lineTo(aX+aWidth,aY);this.lineTo(aX+aWidth,aY+aHeight);this.lineTo(aX,aY+aHeight);this.closePath();this.fill();this.currentPath_=oldPath};contextPrototype.createLinearGradient=function(aX0,aY0,aX1,aY1){var gradient=new CanvasGradient_("gradient");gradient.x0_=aX0;gradient.y0_=aY0;gradient.x1_=aX1;gradient.y1_=aY1;return gradient};contextPrototype.createRadialGradient=function(aX0,aY0,aR0,aX1,aY1,aR1){var gradient=new CanvasGradient_("gradientradial");gradient.x0_=aX0;gradient.y0_=aY0;gradient.r0_=
aR0;gradient.x1_=aX1;gradient.y1_=aY1;gradient.r1_=aR1;return gradient};contextPrototype.drawImage=function(image,var_args){var dx,dy,dw,dh,sx,sy,sw,sh;var oldRuntimeWidth=image.runtimeStyle.width;var oldRuntimeHeight=image.runtimeStyle.height;image.runtimeStyle.width="auto";image.runtimeStyle.height="auto";var w=image.width;var h=image.height;image.runtimeStyle.width=oldRuntimeWidth;image.runtimeStyle.height=oldRuntimeHeight;if(arguments.length==3){dx=arguments[1];dy=arguments[2];sx=sy=0;sw=dw=w;
sh=dh=h}else if(arguments.length==5){dx=arguments[1];dy=arguments[2];dw=arguments[3];dh=arguments[4];sx=sy=0;sw=w;sh=h}else if(arguments.length==9){sx=arguments[1];sy=arguments[2];sw=arguments[3];sh=arguments[4];dx=arguments[5];dy=arguments[6];dw=arguments[7];dh=arguments[8]}else throw Error("Invalid number of arguments");var d=getCoords(this,dx,dy);var w2=sw/2;var h2=sh/2;var vmlStr=[];var W=10;var H=10;vmlStr.push(" <g_vml_:group",' coordsize="',Z*W,",",Z*H,'"',' coordorigin="0,0"',' style="width:',
W,"px;height:",H,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]||this.m_[1][1]!=1||this.m_[1][0]){var filter=[];filter.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",mr(d.x/Z),",","Dy=",mr(d.y/Z),"");var max=d;var c2=getCoords(this,dx+dw,dy);var c3=getCoords(this,dx,dy+dh);var c4=getCoords(this,dx+dw,dy+dh);max.x=m.max(max.x,c2.x,c3.x,c4.x);max.y=m.max(max.y,c2.y,c3.y,c4.y);vmlStr.push("padding:0 ",mr(max.x/Z),"px ",mr(max.y/
Z),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",filter.join(""),", sizingmethod='clip');")}else vmlStr.push("top:",mr(d.y/Z),"px;left:",mr(d.x/Z),"px;");vmlStr.push(' ">','<g_vml_:image src="',image.src,'"',' style="width:',Z*dw,"px;"," height:",Z*dh,'px"',' cropleft="',sx/w,'"',' croptop="',sy/h,'"',' cropright="',(w-sx-sw)/w,'"',' cropbottom="',(h-sy-sh)/h,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",vmlStr.join(""))};contextPrototype.stroke=function(aFill){var W=
10;var H=10;var chunkSize=5E3;var min={x:null,y:null};var max={x:null,y:null};for(var j=0;j<this.currentPath_.length;j+=chunkSize){var lineStr=[];var lineOpen=false;lineStr.push("<g_vml_:shape",' filled="',!!aFill,'"',' style="position:absolute;width:',W,"px;height:",H,'px;"',' coordorigin="0,0"',' coordsize="',Z*W,",",Z*H,'"',' stroked="',!aFill,'"',' path="');var newSeq=false;for(var i=j;i<Math.min(j+chunkSize,this.currentPath_.length);i++){if(i%chunkSize==0&&i>0)lineStr.push(" m ",mr(this.currentPath_[i-
1].x),",",mr(this.currentPath_[i-1].y));var p=this.currentPath_[i];var c;switch(p.type){case "moveTo":c=p;lineStr.push(" m ",mr(p.x),",",mr(p.y));break;case "lineTo":lineStr.push(" l ",mr(p.x),",",mr(p.y));break;case "close":lineStr.push(" x ");p=null;break;case "bezierCurveTo":lineStr.push(" c ",mr(p.cp1x),",",mr(p.cp1y),",",mr(p.cp2x),",",mr(p.cp2y),",",mr(p.x),",",mr(p.y));break;case "at":case "wa":lineStr.push(" ",p.type," ",mr(p.x-this.arcScaleX_*p.radius),",",mr(p.y-this.arcScaleY_*p.radius),
" ",mr(p.x+this.arcScaleX_*p.radius),",",mr(p.y+this.arcScaleY_*p.radius)," ",mr(p.xStart),",",mr(p.yStart)," ",mr(p.xEnd),",",mr(p.yEnd));break}if(p){if(min.x==null||p.x<min.x)min.x=p.x;if(max.x==null||p.x>max.x)max.x=p.x;if(min.y==null||p.y<min.y)min.y=p.y;if(max.y==null||p.y>max.y)max.y=p.y}}lineStr.push(' ">');if(!aFill)appendStroke(this,lineStr);else appendFill(this,lineStr,min,max);lineStr.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",lineStr.join(""))}};function appendStroke(ctx,
lineStr){var a=processStyle(ctx.strokeStyle);var color=a.color;var opacity=a.alpha*ctx.globalAlpha;var lineWidth=ctx.lineScale_*ctx.lineWidth;if(lineWidth<1)opacity*=lineWidth;lineStr.push("<g_vml_:stroke",' opacity="',opacity,'"',' joinstyle="',ctx.lineJoin,'"',' miterlimit="',ctx.miterLimit,'"',' endcap="',processLineCap(ctx.lineCap),'"',' weight="',lineWidth,'px"',' color="',color,'" />')}function appendFill(ctx,lineStr,min,max){var fillStyle=ctx.fillStyle;var arcScaleX=ctx.arcScaleX_;var arcScaleY=
ctx.arcScaleY_;var width=max.x-min.x;var height=max.y-min.y;if(fillStyle instanceof CanvasGradient_){var angle=0;var focus={x:0,y:0};var shift=0;var expansion=1;if(fillStyle.type_=="gradient"){var x0=fillStyle.x0_/arcScaleX;var y0=fillStyle.y0_/arcScaleY;var x1=fillStyle.x1_/arcScaleX;var y1=fillStyle.y1_/arcScaleY;var p0=getCoords(ctx,x0,y0);var p1=getCoords(ctx,x1,y1);var dx=p1.x-p0.x;var dy=p1.y-p0.y;angle=Math.atan2(dx,dy)*180/Math.PI;if(angle<0)angle+=360;if(angle<1E-6)angle=0}else{var p0=getCoords(ctx,
fillStyle.x0_,fillStyle.y0_);focus={x:(p0.x-min.x)/width,y:(p0.y-min.y)/height};width/=arcScaleX*Z;height/=arcScaleY*Z;var dimension=m.max(width,height);shift=2*fillStyle.r0_/dimension;expansion=2*fillStyle.r1_/dimension-shift}var stops=fillStyle.colors_;stops.sort(function(cs1,cs2){return cs1.offset-cs2.offset});var length=stops.length;var color1=stops[0].color;var color2=stops[length-1].color;var opacity1=stops[0].alpha*ctx.globalAlpha;var opacity2=stops[length-1].alpha*ctx.globalAlpha;var colors=
[];for(var i=0;i<length;i++){var stop=stops[i];colors.push(stop.offset*expansion+shift+" "+stop.color)}lineStr.push('<g_vml_:fill type="',fillStyle.type_,'"',' method="none" focus="100%"',' color="',color1,'"',' color2="',color2,'"',' colors="',colors.join(","),'"',' opacity="',opacity2,'"',' g_o_:opacity2="',opacity1,'"',' angle="',angle,'"',' focusposition="',focus.x,",",focus.y,'" />')}else if(fillStyle instanceof CanvasPattern_){if(width&&height){var deltaLeft=-min.x;var deltaTop=-min.y;lineStr.push("<g_vml_:fill",
' position="',deltaLeft/width*arcScaleX*arcScaleX,",",deltaTop/height*arcScaleY*arcScaleY,'"',' type="tile"',' src="',fillStyle.src_,'" />')}}else{var a=processStyle(ctx.fillStyle);var color=a.color;var opacity=a.alpha*ctx.globalAlpha;lineStr.push('<g_vml_:fill color="',color,'" opacity="',opacity,'" />')}}contextPrototype.fill=function(){this.stroke(true)};contextPrototype.closePath=function(){this.currentPath_.push({type:"close"})};function getCoords(ctx,aX,aY){var m=ctx.m_;return{x:Z*(aX*m[0][0]+
aY*m[1][0]+m[2][0])-Z2,y:Z*(aX*m[0][1]+aY*m[1][1]+m[2][1])-Z2}}contextPrototype.save=function(){var o={};copyState(this,o);this.aStack_.push(o);this.mStack_.push(this.m_);this.m_=matrixMultiply(createMatrixIdentity(),this.m_)};contextPrototype.restore=function(){if(this.aStack_.length){copyState(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function matrixIsFinite(m){return isFinite(m[0][0])&&isFinite(m[0][1])&&isFinite(m[1][0])&&isFinite(m[1][1])&&isFinite(m[2][0])&&isFinite(m[2][1])}function setM(ctx,
m,updateLineScale){if(!matrixIsFinite(m))return;ctx.m_=m;if(updateLineScale){var det=m[0][0]*m[1][1]-m[0][1]*m[1][0];ctx.lineScale_=sqrt(abs(det))}}contextPrototype.translate=function(aX,aY){var m1=[[1,0,0],[0,1,0],[aX,aY,1]];setM(this,matrixMultiply(m1,this.m_),false)};contextPrototype.rotate=function(aRot){var c=mc(aRot);var s=ms(aRot);var m1=[[c,s,0],[-s,c,0],[0,0,1]];setM(this,matrixMultiply(m1,this.m_),false)};contextPrototype.scale=function(aX,aY){this.arcScaleX_*=aX;this.arcScaleY_*=aY;var m1=
[[aX,0,0],[0,aY,0],[0,0,1]];setM(this,matrixMultiply(m1,this.m_),true)};contextPrototype.transform=function(m11,m12,m21,m22,dx,dy){var m1=[[m11,m12,0],[m21,m22,0],[dx,dy,1]];setM(this,matrixMultiply(m1,this.m_),true)};contextPrototype.setTransform=function(m11,m12,m21,m22,dx,dy){var m=[[m11,m12,0],[m21,m22,0],[dx,dy,1]];setM(this,m,true)};contextPrototype.drawText_=function(text,x,y,maxWidth,stroke){var m=this.m_,delta=1E3,left=0,right=delta,offset={x:0,y:0},lineStr=[];var fontStyle=getComputedStyle(processFontStyle(this.font),
this.element_);var fontStyleString=buildStyle(fontStyle);var elementStyle=this.element_.currentStyle;var textAlign=this.textAlign.toLowerCase();switch(textAlign){case "left":case "center":case "right":break;case "end":textAlign=elementStyle.direction=="ltr"?"right":"left";break;case "start":textAlign=elementStyle.direction=="rtl"?"right":"left";break;default:textAlign="left"}switch(this.textBaseline){case "hanging":case "top":offset.y=fontStyle.size/1.75;break;case "middle":break;default:case null:case "alphabetic":case "ideographic":case "bottom":offset.y=
-fontStyle.size/2.25;break}switch(textAlign){case "right":left=delta;right=0.05;break;case "center":left=right=delta/2;break}var d=getCoords(this,x+offset.x,y+offset.y);lineStr.push('<g_vml_:line from="',-left,' 0" to="',right,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!stroke,'" stroked="',!!stroke,'" style="position:absolute;width:1px;height:1px;">');if(stroke)appendStroke(this,lineStr);else appendFill(this,lineStr,{x:-left,y:0},{x:right,y:fontStyle.size});var skewM=m[0][0].toFixed(3)+
","+m[1][0].toFixed(3)+","+m[0][1].toFixed(3)+","+m[1][1].toFixed(3)+",0,0";var skewOffset=mr(d.x/Z)+","+mr(d.y/Z);lineStr.push('<g_vml_:skew on="t" matrix="',skewM,'" ',' offset="',skewOffset,'" origin="',left,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',encodeHtmlAttribute(text),'" style="v-text-align:',textAlign,";font:",encodeHtmlAttribute(fontStyleString),'" /></g_vml_:line>');this.element_.insertAdjacentHTML("beforeEnd",lineStr.join(""))};contextPrototype.fillText=
function(text,x,y,maxWidth){this.drawText_(text,x,y,maxWidth,false)};contextPrototype.strokeText=function(text,x,y,maxWidth){this.drawText_(text,x,y,maxWidth,true)};contextPrototype.measureText=function(text){if(!this.textMeasureEl_){var s='<span style="position:absolute;'+"top:-20000px;left:0;padding:0;margin:0;border:none;"+'white-space:pre;"></span>';this.element_.insertAdjacentHTML("beforeEnd",s);this.textMeasureEl_=this.element_.lastChild}var doc=this.element_.ownerDocument;this.textMeasureEl_.innerHTML=
"";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(doc.createTextNode(text));return{width:this.textMeasureEl_.offsetWidth}};contextPrototype.clip=function(){};contextPrototype.arcTo=function(){};contextPrototype.createPattern=function(image,repetition){return new CanvasPattern_(image,repetition)};function CanvasGradient_(aType){this.type_=aType;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}CanvasGradient_.prototype.addColorStop=function(aOffset,
aColor){aColor=processStyle(aColor);this.colors_.push({offset:aOffset,color:aColor.color,alpha:aColor.alpha})};function CanvasPattern_(image,repetition){assertImageIsValid(image);switch(repetition){case "repeat":case null:case "":this.repetition_="repeat";break;case "repeat-x":case "repeat-y":case "no-repeat":this.repetition_=repetition;break;default:throwException("SYNTAX_ERR")}this.src_=image.src;this.width_=image.width;this.height_=image.height}function throwException(s){throw new DOMException_(s);
}function assertImageIsValid(img){if(!img||img.nodeType!=1||img.tagName!="IMG")throwException("TYPE_MISMATCH_ERR");if(img.readyState!="complete")throwException("INVALID_STATE_ERR")}function DOMException_(s){this.code=this[s];this.message=s+": DOM Exception "+this.code}var p=DOMException_.prototype=new Error;p.INDEX_SIZE_ERR=1;p.DOMSTRING_SIZE_ERR=2;p.HIERARCHY_REQUEST_ERR=3;p.WRONG_DOCUMENT_ERR=4;p.INVALID_CHARACTER_ERR=5;p.NO_DATA_ALLOWED_ERR=6;p.NO_MODIFICATION_ALLOWED_ERR=7;p.NOT_FOUND_ERR=8;p.NOT_SUPPORTED_ERR=
9;p.INUSE_ATTRIBUTE_ERR=10;p.INVALID_STATE_ERR=11;p.SYNTAX_ERR=12;p.INVALID_MODIFICATION_ERR=13;p.NAMESPACE_ERR=14;p.INVALID_ACCESS_ERR=15;p.VALIDATION_ERR=16;p.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=G_vmlCanvasManager_;CanvasRenderingContext2D=CanvasRenderingContext2D_;CanvasGradient=CanvasGradient_;CanvasPattern=CanvasPattern_;DOMException=DOMException_})();

@ -0,0 +1,24 @@
var gadgetConfig = {
"id": "IoTServerTemperatureStats",
"title": "IoTServerTemperatureStats",
"datasource": "ORG_WSO2_IOT_DEVICES_TEMPERATURE",
"type": "batch",
"columns": [
{"name": "TIMESTAMP", "type": "time"},
{"name": "owner", "type": "string"},
{"name": "deviceType", "type": "string"},
{"name": "deviceId", "type": "string"},
{"name": "time", "type": "long"},
{"name": "temperature", "type": "float"}
],
"chartConfig": {
"x": "time",
"maxLength": "10",
"padding": {"top": 30, "left": 45, "bottom": 38, "right": 55},
"charts": [{"type": "line", "y": "temperature"}]
},
"domain": "carbon.super",
/* timeFrom and timeTo need not be mentioned here since they will be automatically fetched
if found in the QueryString of the URL */
"params": ["owner", "deviceId"]
};

@ -0,0 +1,568 @@
var datasource, type, columns, filter, maxUpdateValue, paramsToFilterBy;
var REFRESH_INTERVAL = 5000;
//this needs to be loaded from an autogenerated
datasource = gadgetConfig.datasource;
filter = gadgetConfig.filter;
type = gadgetConfig.type;
maxUpdateValue = gadgetConfig.maxUpdateValue;
columns = gadgetConfig.columns;
paramsToFilterBy = gadgetConfig.params;
var counter = 0;
var TYPE_GET_BY_RANGE = 8;
var TYPE_SEARCH = 13;
var TYPE_SEARCH_COUNT = 14;
var TIME_FROM_STRING = "timeFrom";
var TIME_TO_STRING = "timeTo";
var UNIX_TIME_MAX_VALUE = "9007199254740992";
var UNIX_TIME_MIN_VALUE = "-9007199254740992";
var META_TAG = "meta_";
var initialConfig, urlQueryParams, queryParamValPair, queryString;
var dataTable, chart;
executeDataFetchForGadget();
/**
* The main execution logic of the gadget is implemented in this function.
*/
function executeDataFetchForGadget() {
var urlQueryString;
// fetch all queryParams from the URL.
urlQueryParams = getAllQueryParamsFromURL();
// check if params config exists in the gadgetConf.
if (typeof paramsToFilterBy != "undefined" && paramsToFilterBy.length != 0) {
if (urlQueryParams != null) {
// get the values corresponding to the query "params" given in the gadgetConf
queryParamValPair = getValuesOfQueryFilter();
// if at-least one of the given params in the conf are missing from the URL params then returns null.
if (queryParamValPair == null) {
console.log("Incomplete set of Query Params were found in the URL.");
return;
}
// construct the Lucene query string based on the params given in the gadget-conf
// and the values parsed from the URL Query String.
queryString = constructQueryString();
switch (type) {
case "realtime":
urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
//subscribe to websocket
subscribe(
datasource.split(":")[0], datasource.split(":")[1], '10', gadgetConfig.domain,
onRealTimeEventSuccessRecieval, onRealTimeEventErrorRecieval,
location.hostname, location.port, 'WEBSOCKET', "SECURED", urlQueryString);
break;
case "batch":
//load data immediately
fetchDataOnQuery(fetchDataWithCount);
// then start periodic polling
setInterval(function () {
fetchDataOnQuery(fetchDataWithCount);
}, REFRESH_INTERVAL);
break;
}
} else {
// if there are NO queryParams in the URL then exit.
console.log("No Query Params were found in the URL to match the given filter-parameters.");
}
} else {
// if no params to filter by are given in the gadget-conf, then fetch all info available
// based on date range(if given).
switch (type) {
case "realtime":
urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
//subscribe to websocket
subscribe(datasource.split(":")[0], datasource.split(":")[1], '10', gadgetConfig.domain,
onRealTimeEventSuccessRecieval, onRealTimeEventErrorRecieval, location.hostname, location.port,
'WEBSOCKET', "SECURED", urlQueryString);
break;
case "batch":
//load data immediately
fetchDataWithoutQuery(drawBatchChart);
// then start periodic polling
setInterval(function () {
fetchDataWithoutQuery(drawBatchChart);
}, REFRESH_INTERVAL);
break;
}
}
}
/**
* Reads the page's URL Query-Params and returns them as an associative array.
* @returns {*} an associative array containing the URL QueryParams and corresponding values.
* If no such Query-Params exists then returns null.
*/
function getAllQueryParamsFromURL() {
var queryParamList = [], qParam;
var urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
if (urlQueryString) {
var queryStringPairs = urlQueryString.split('&');
for (var i = 0; i < queryStringPairs.length; i++) {
qParam = queryStringPairs[i].split('=');
queryParamList[qParam[0]] = qParam[1];
}
return queryParamList;
} else {
return null;
}
}
/**
* Retrieves the values from the URL-QueryString corresponding to the given QueryParams in the gadget-conf file.
* The parameters "timeTo" & "timeFrom" (if found in the query string) are added to the returned object regardless
* of whether they are listed in the gadget-conf.
* @returns {*} an associative array of the given params in the conf and corresponding value fetched from the
* URL string.
*/
function getValuesOfQueryFilter() {
var queryValues = [];
if (TIME_FROM_STRING in urlQueryParams) {
queryValues[TIME_FROM_STRING] = urlQueryParams[TIME_FROM_STRING];
}
if (TIME_TO_STRING in urlQueryParams) {
queryValues[TIME_TO_STRING] = urlQueryParams[TIME_TO_STRING];
}
for (var i = 0; i < paramsToFilterBy.length; i++) {
var queryV = urlQueryParams[paramsToFilterBy[i]];
// if atleast one of the queryParams given in the gadgetConf is missing then return "null".
if (typeof queryV != "undefined" && queryV != null && queryV != "") {
queryValues[paramsToFilterBy[i]] = queryV;
} else {
return null;
}
}
return queryValues;
}
/**
* Constructs the Lucene Query String to be sent to DAS API.
* @returns {string} a fully constructed query string from the params given in gadget-conf and
* the query string of the URL.
*/
function constructQueryString() {
var queryString = "'";
for (var a = 0; a < paramsToFilterBy.length; a++) {
if (queryString.length == 1) {
queryString += META_TAG + paramsToFilterBy[a] + ":" + queryParamValPair[paramsToFilterBy[a]];
} else {
queryString += " AND " + META_TAG + paramsToFilterBy[a] + ":" + queryParamValPair[paramsToFilterBy[a]];
}
}
if (TIME_FROM_STRING in queryParamValPair && TIME_TO_STRING in queryParamValPair) {
// both ends of the time-range (From What Date - To What Date) is given
queryString += " AND " + META_TAG + "time:" +
"[" + queryParamValPair[TIME_FROM_STRING] + " TO " + queryParamValPair[TIME_TO_STRING] + "]";
} else if (TIME_FROM_STRING in queryParamValPair && !(TIME_TO_STRING in queryParamValPair)) {
// Only the start of the time-range (From What Date) is given
queryString += " AND " + META_TAG + "time:" +
"[" + queryParamValPair[TIME_FROM_STRING] + " TO " + UNIX_TIME_MAX_VALUE + "]";
} else if (!(TIME_FROM_STRING in queryParamValPair) && TIME_TO_STRING in queryParamValPair) {
// Only the end of the time-range (To What Date) is given
queryString += " AND " + META_TAG + "time:" +
"[" + UNIX_TIME_MIN_VALUE + " TO " + queryParamValPair[TIME_TO_STRING] + "]";
}
//queryString += " AND meta_time:[1456467843079 TO 1456468494817]'";
queryString += "'";
return queryString;
}
/**
* Utility method to fetch columns of the datasource provided for a Batch-Type Gadget.
* @param table the name of the datasource table whose columns needs to be extracted.
*/
function getColumns(table) {
console.log("Fetching table schema for table: " + table);
var url = "/portal/apis/analytics?type=10&tableName=" + table;
$.getJSON(url, function (data) {
if (data) {
columns = parseColumns(JSON.parse(data.message));
}
});
}
/** Constructs an associative array containing the columns and the corresponding data-type ("String", "Long", etc)
* from the returned object as a result of the "getColumns" method above.
* @param data the response object returned from the "getColumns(table)" call to the DAS API.
* @returns {Array|*} an array containing the column names as keys and their type as values.
*/
function parseColumns(data) {
if (data.columns) {
var keys = Object.getOwnPropertyNames(data.columns);
columns = keys.map(function (key, i) {
return column = {
name: key,
type: data.columns[key].type
};
});
return columns;
}
}
/**
* Makes the initial call to the DAS APIs to get the count of all matching indexes based on a given query.
* Upon receiving a response (count), a subsequent method is called to fetch the given "count" amount of data from
* DAS that matches the query.
* @param callback the subsequent method to be called using the "count" response value received from the API call.
*/
function fetchDataOnQuery(callback) {
var request = {
type: TYPE_SEARCH_COUNT, // DAS API type corresponding to fetching data-count for "query"
tableName: datasource,
query: queryString
};
$.ajax({
url: "/portal/apis/analytics",
method: "GET",
data: request,
contentType: "application/json",
success: function (data) {
if (callback != null) {
callback(drawBatchChart, data.message);
}
}
});
}
/**
* Makes an API call to the DAS to fetch the "count" number of data matching the queryString constructed from the
* query-string and the param-list provided in the gadget-conf. The fetched data are passed into the provided
* "callback" method which further processes and draws the chart against this data.
* @param callback the method to which the fetched data are to be passed in for further processing.
* @param totalCount the count of all matching data available against the queryString.
*/
function fetchDataWithCount(callback, totalCount) {
var timeFrom = "undefined";
var timeTo = "undefined";
var request = {
type: TYPE_SEARCH, // DAS API type corresponding to fetching data for "query"
tableName: datasource,
filter: filter,
query: queryString,
timeFrom: timeFrom,
timeTo: timeTo,
start: 0,
count: totalCount
};
$.ajax({
url: "/portal/apis/analytics",
method: "GET",
data: request,
contentType: "application/json",
success: function (data) {
if (callback != null) {
var sortedData = sortData(data.message);
callback(makeRows(sortedData));
}
}
});
}
/**
* Retrieves all data available in a datasource irrespective of any query filters. However, the API call incorporates
* a data range to be submitted whilst fetching this info. If such date range related query strings
* ("timeFrom" or "timeTo") are found in the URL, then they are used.
* @param callback the method to which the fetched data are to be passed in for further processing.
*/
function fetchDataWithoutQuery(callback) {
var timeFrom = "undefined";
var timeTo = "undefined";
if (urlQueryParams != null) {
if (TIME_FROM_STRING in urlQueryParams) {
timeFrom = urlQueryParams[TIME_FROM_STRING];
}
if (TIME_TO_STRING in urlQueryParams) {
timeTo = urlQueryParams[TIME_TO_STRING];
}
}
var request = {
type: TYPE_GET_BY_RANGE, // DAS API type corresponding to fetching data by date range.
tableName: datasource,
timeFrom: timeFrom,
timeTo: timeTo,
start: 0
};
$.ajax({
url: "/portal/apis/analytics",
method: "GET",
data: request,
contentType: "application/json",
success: function (data) {
if (callback != null) {
callback(makeRows(JSON.parse(data.message)));
}
}
});
}
/**
* This is a utility method to convert Unix-Timestamp values to Epoch Time
* @param unix_timestamp the unix time to be converted
* @returns {string} the formatted epoch-time of the given unix-timestamp
*/
function convertToEpoch(unix_timestamp) {
// Create a new JavaScript Date object based on the timestamp
// multiplied by 1000 so that the argument is in milliseconds, not seconds.
var date = new Date(unix_timestamp * 1000);
// Hours part from the timestamp
var hours = date.getHours();
// Minutes part from the timestamp
var minutes = "0" + date.getMinutes();
// Seconds part from the timestamp
var seconds = "0" + date.getSeconds();
var thisDate = date.getDate();
var thisMonth = date.getMonth();
var thisYear = date.getUTCFullYear();
var formattedTime = hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
// Will display time in 10:30:23 format
return (formattedTime);
}
/**
* Sorts the given data array according to the values of its "timestamp" key.
* @param payload a JSON string with multiple data-arrays having a "timestamp" key-value pair.
* @returns {*} JSON Object with multiple sorted by "timestamp"
*/
function sortData(payload) {
var dataFromDAS = JSON.parse(payload);
sortedData = dataFromDAS.sort(function (a, b) {
return a.timestamp - b.timestamp;
});
return sortedData;
}
/**
* Fetches the values corresponding to the keys in the "columns" (either provided in the gadget-conf or fetched via the
* "getColumns(table)" method) array from the data object passed in.
* @param data a JSON Object containing multiple data values fetched from the datasource with column-name:value pairs.
* @returns {Array} an array with objects that contain the columns from the fetched "columns" and their corresponding
* values.
*/
function makeRows(data) {
var rows = [];
for (var i = 0; i < data.length; i++) {
var record = data[i];
var keys = Object.getOwnPropertyNames(record.values);
keys.push();
var row = columns.map(function (column, i) {
var colName = column.name;
var recordVal = record.values[colName];
if (typeof recordVal == 'undefined') {
if (column.name.toUpperCase() === "TIMESTAMP" && (record.timestamp || record.TIMESTAMP)) {
recordVal = record.timestamp;
} else {
recordVal = record.values[META_TAG + colName];
}
}
return recordVal;
});
rows.push(row);
}
return rows;
}
function makeDataTable(data) {
var dataTable = new igviz.DataTable();
if (columns.length > 0) {
columns.forEach(function (column, i) {
var type = "N";
if (column.type == "STRING" || column.type == "string") {
type = "C";
} else if (column.type == "TIME" || column.type == "time") {
type = "T";
}
dataTable.addColumn(column.name, type);
});
}
data.forEach(function (row, index) {
for (var i = 0; i < row.length; i++) {
if (dataTable.metadata.types[i] == "N") {
data[index][i] = parseInt(data[index][i]);
}
}
});
dataTable.addRows(data);
return dataTable;
}
function drawChart(data) {
var dataTable = makeDataTable(data);
gadgetConfig.chartConfig.width = $("#placeholder").width();
gadgetConfig.chartConfig.height = $("#placeholder").height() - 65;
var chartType = gadgetConfig.chartConfig.chartType;
var xAxis = gadgetConfig.chartConfig.xAxis;
jQuery("#noChart").html("");
if (chartType === "bar" && dataTable.metadata.types[xAxis] === "N") {
dataTable.metadata.types[xAxis] = "C";
}
if (gadgetConfig.chartConfig.chartType === "table" || gadgetConfig.chartConfig.chartType === "singleNumber") {
gadgetConfig.chartConfig.height = $("#placeholder").height();
chart = igviz.draw("#placeholder", gadgetConfig.chartConfig, dataTable);
chart.plot(dataTable.data);
} else {
chart = igviz.setUp("#placeholder", gadgetConfig.chartConfig, dataTable);
chart.setXAxis({
"labelAngle": -35,
"labelAlign": "right",
"labelDy": 0,
"labelDx": 0,
"titleDy": 25
})
.setYAxis({
"titleDy": -30
});
chart.plot(dataTable.data);
}
}
//stuff required for realtime charting
function onRealTimeEventSuccessRecieval(streamId, data) {
drawRealtimeChart(data);
}
function onRealTimeEventErrorRecieval(dataError) {
console.log("Error occurred " + dataError);
}
/**
* Draws the real-time chart based on the values in the data object passed in.
* @param data an object containing all the column:value pair data
*/
function drawRealtimeChart(data) {
if (chart == null) {
jQuery("#noChart").html("");
gadgetConfig.chartConfig.width = $("#placeholder").width() - 110;
gadgetConfig.chartConfig.height = $("#placeholder").height() - 40;
if (gadgetConfig.chartConfig.charts[0].type == "map") {
var mapType = gadgetConfig.chartConfig.charts[0].mapType;
if (mapType == "world") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/countryInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/world/';
} else if (mapType == "usa") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/usaInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/usa/';
} else if (mapType == "europe") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/countryInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/europe/';
}
}
chart = new vizg(createDataTable(convertData(data)), gadgetConfig.chartConfig);
chart.draw("#placeholder");
} else {
chart.insert(convertData(data));
}
}
/**
* Draws the batch-chart based on the values in the data object passed in.
* @param data an object containing all the column:value pair data
*/
function drawBatchChart(data) {
if (chart == null) {
jQuery("#noChart").html("");
gadgetConfig.chartConfig.width = $("#placeholder").width() - 110;
gadgetConfig.chartConfig.height = $("#placeholder").height() - 40;
if (gadgetConfig.chartConfig.charts[0].type == "map") {
var mapType = gadgetConfig.chartConfig.charts[0].mapType;
if (mapType == "world") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/countryInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/world/';
} else if (mapType == "usa") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/usaInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/usa/';
} else if (mapType == "europe") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/countryInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/europe/';
}
}
initialConfig = JSON.parse(JSON.stringify(gadgetConfig.chartConfig));
} else {
gadgetConfig.chartConfig = initialConfig;
initialConfig = JSON.parse(JSON.stringify(gadgetConfig.chartConfig));
}
chart = new vizg(createDataTable(convertData(data)), gadgetConfig.chartConfig);
chart.draw("#placeholder");
}
function convertData(data) {
for (var i = 0; i < data.length; i++) {
for (var x = 0; x < data[i].length; x++) {
var type = gadgetConfig.columns[x]["type"].toUpperCase();
if (type != "STRING" && type != "BOOLEAN") {
data[i][x] = parseFloat(data[i][x]);
}
}
}
return data;
}
function createDataTable(data) {
var names = [];
var types = [];
for (var i = 0; i < gadgetConfig.columns.length; i++) {
var name = gadgetConfig.columns[i]["name"];
names.push(name);
var type = columns[i]["type"].toUpperCase();
if (type === "INT" || type === "INTEGER" || type === "FLOAT" || type === "DOUBLE") {
type = "linear";
} else if (gadgetConfig.columns[i]["type"].toUpperCase() == "TIME" || name.toUpperCase() == "TIME") {
type = "time";
} else {
type = "ordinal";
}
types.push(type);
}
datatable = [
{
"metadata": {
"names": names,
"types": types
},
"data": data
}
];
return datatable;
}

@ -0,0 +1,286 @@
/*
*
*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
*/
var CONSTANTS = {
webAppName: 'outputui',
urlSeperator: '/',
urlGetParameter : '?lastUpdatedTime=',
urlQueryStringBegin : '?',
tenantUrlAttribute: 't',
urlUnsecureTransportHttp : 'http://',
urlUnsecureTransportWebsocket : 'ws://',
urlSecureTransportWebsocket : 'wss://',
urlSecureTransportHttp : 'https://',
colon : ':',
defaultIntervalTime : 10 * 1000,
defaultUserDomain : 'carbon.super',
defaultHostName : 'localhost',
defaultNonsecurePortNumber : '9763',
defaultSecurePortNumber : '9443',
defaultMode : 'AUTO',
processModeHTTP : 'HTTP',
processModeWebSocket : 'WEBSOCKET',
processModeAuto : 'AUTO',
domain : 'carbon.super',
numThousand : 1000,
websocketTimeAppender : 400,
secureMode : 'SECURED'
};
var websocket = null;
var webSocketUrl;
var httpUrl;
var cepHostName;
var cepPortNumber;
var isErrorOccured = false;
var lastUpdatedtime = -1;
var polingInterval;
var stream;
var streamVersion;
var firstPollingAttempt;
var processMode;
var onSuccessFunction;
var onErrorFunction;
var userDomainUrl = "";
var terminateWebsocketInstance = false;
var pollingContinue = true;
var transportToBeUsedHttp;
var transportToBeUsedWebsocket;
function subscribe(streamName,version,intervalTime,domain,
listeningFuncSuccessData,listeningFuncErrorData,
cepHost,cepPort,mode,secureMode, queryParams){
stopPollingProcesses();
stream = streamName;
streamVersion = version;
onSuccessFunction = listeningFuncSuccessData;
onErrorFunction = listeningFuncErrorData;
if(secureMode == CONSTANTS.secureMode){
transportToBeUsedHttp = CONSTANTS.urlSecureTransportHttp;
transportToBeUsedWebsocket = CONSTANTS.urlSecureTransportWebsocket;
} else {
transportToBeUsedHttp = CONSTANTS.urlUnsecureTransportHttp;
transportToBeUsedWebsocket = CONSTANTS.urlUnsecureTransportWebsocket;
}
if(intervalTime == null || intervalTime == ""){
polingInterval = CONSTANTS.defaultIntervalTime;
} else{
polingInterval = intervalTime * CONSTANTS.numThousand;
}
if(domain == null || domain == ""){
domain = CONSTANTS.defaultUserDomain;
}
if(cepHost == null || cepHost == ""){
cepHostName = CONSTANTS.defaultHostName;
} else{
cepHostName = cepHost;
}
if(cepPort == null || cepPort == ""){
if(secureMode == CONSTANTS.secureMode){
cepPortNumber = CONSTANTS.defaultSecurePortNumber;
} else{
cepPortNumber = CONSTANTS.defaultNonsecurePortNumber;
}
} else{
cepPortNumber = cepPort;
}
if(mode == null || mode == ""){
processMode = CONSTANTS.defaultMode;
} else{
processMode = mode;
}
if(domain != CONSTANTS.domain){
userDomainUrl = CONSTANTS.tenantUrlAttribute + CONSTANTS.urlSeperator + domain + CONSTANTS.urlSeperator;
}
if (queryParams == null) {
queryParams = "";
} else if (queryParams != "") {
queryParams = CONSTANTS.urlQueryStringBegin + queryParams;
}
webSocketUrl = transportToBeUsedWebsocket + cepHostName + CONSTANTS.colon + cepPortNumber +
CONSTANTS.urlSeperator + CONSTANTS.webAppName+ CONSTANTS.urlSeperator + userDomainUrl + stream +
CONSTANTS.urlSeperator + streamVersion + queryParams;
if(processMode == CONSTANTS.processModeHTTP){
firstPollingAttempt = true;
pollingContinue = true;
startPoll();
} else{
initializeWebSocket(webSocketUrl);
}
}
/**
* Initializing Web Socket
*/
function initializeWebSocket(webSocketUrl){
websocket = new WebSocket(webSocketUrl);
websocket.onopen = webSocketOnOpen;
websocket.onmessage = webSocketOnMessage;
websocket.onclose = webSocketOnClose;
websocket.onerror = webSocketOnError;
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
// alert("Successfully connected to "+webSocketUrl);
//onErrorFunction("Successfully connected to URL:" + webSocketUrl + "\n");
};
/**
* On server sends a message
*/
var webSocketOnMessage = function (evt) {
var event = evt.data;
var array = JSON.parse(event);
constructPayload(array);
};
/**
* On server close
*/
var webSocketOnClose =function (e) {
if(isErrorOccured){
if(processMode != CONSTANTS.processModeWebSocket){
firstPollingAttempt = true;
pollingContinue = true;
startPoll();
}
} else{
if(!terminateWebsocketInstance){
waitForSocketConnection(websocket);
} else{
terminateWebsocketInstance = false;
}
}
};
/**
* On server Error
*/
var webSocketOnError = function (err) {
var error = "Error: Cannot connect to Websocket URL:" + webSocketUrl + " .Hence closing the connection!";
onErrorFunction(error);
isErrorOccured = true;
};
/**
* Gracefully increments the connection retry
*/
var waitTime = CONSTANTS.numThousand;
function waitForSocketConnection(socket, callback){
setTimeout(
function () {
if (socket.readyState === 1) {
initializeWebSocket(webSocketUrl);
console.log("Connection is made");
if(callback != null){
callback();
}
return;
} else {
websocket = new WebSocket(webSocketUrl);
waitTime += CONSTANTS.websocketTimeAppender;
waitForSocketConnection(websocket, callback);
}
}, waitTime);
}
/**
* Polling to retrieve events from http request periodically
*/
function startPoll(){
(function poll(){
setTimeout(function(){
httpUrl = transportToBeUsedHttp + cepHostName + CONSTANTS.colon + cepPortNumber + CONSTANTS.urlSeperator
+ CONSTANTS.webAppName + CONSTANTS.urlSeperator + userDomainUrl + stream + CONSTANTS.urlSeperator +
streamVersion + CONSTANTS.urlGetParameter + lastUpdatedtime;
$.getJSON(httpUrl, function(responseText) {
if(firstPollingAttempt){
/*var data = $("textarea#idConsole").val();
$("textarea#idConsole").val(data + "Successfully connected to HTTP.");*/
firstPollingAttempt = false;
}
var eventList = $.parseJSON(responseText.events);
if(eventList.length != 0){
lastUpdatedtime = responseText.lastEventTime;
for(var i=0;i<eventList.length;i++){
var arr = eventList[i];
constructPayload(arr);
}
}
if(pollingContinue){
startPoll();
}
})
.fail(function(errorData) {
var errorData = JSON.parse(errorData.responseText);
onErrorFunction(errorData.error);
});
}, polingInterval);
})()
}
function stopPollingProcesses(){
//stopping the Websocket
if(websocket != null){
terminateWebsocketInstance = true;
websocket.onclose;
}
//stopping the HTTPS Request
pollingContinue = false;
}
function constructPayload(eventsArray){
var streamId = stream + CONSTANTS.colon + streamVersion;
var twoDimentionalArray = [eventsArray];
onSuccessFunction(streamId,twoDimentionalArray);
}

@ -0,0 +1,534 @@
!function() {
var topojson = {
version: "1.6.19",
mesh: function(topology) { return object(topology, meshArcs.apply(this, arguments)); },
meshArcs: meshArcs,
merge: function(topology) { return object(topology, mergeArcs.apply(this, arguments)); },
mergeArcs: mergeArcs,
feature: featureOrCollection,
neighbors: neighbors,
presimplify: presimplify
};
function stitchArcs(topology, arcs) {
var stitchedArcs = {},
fragmentByStart = {},
fragmentByEnd = {},
fragments = [],
emptyIndex = -1;
// Stitch empty arcs first, since they may be subsumed by other arcs.
arcs.forEach(function(i, j) {
var arc = topology.arcs[i < 0 ? ~i : i], t;
if (arc.length < 3 && !arc[1][0] && !arc[1][1]) {
t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t;
}
});
arcs.forEach(function(i) {
var e = ends(i),
start = e[0],
end = e[1],
f, g;
if (f = fragmentByEnd[start]) {
delete fragmentByEnd[f.end];
f.push(i);
f.end = end;
if (g = fragmentByStart[end]) {
delete fragmentByStart[g.start];
var fg = g === f ? f : f.concat(g);
fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
} else {
fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
}
} else if (f = fragmentByStart[end]) {
delete fragmentByStart[f.start];
f.unshift(i);
f.start = start;
if (g = fragmentByEnd[start]) {
delete fragmentByEnd[g.end];
var gf = g === f ? f : g.concat(f);
fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
} else {
fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
}
} else {
f = [i];
fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
}
});
function ends(i) {
var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1;
if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
else p1 = arc[arc.length - 1];
return i < 0 ? [p1, p0] : [p0, p1];
}
function flush(fragmentByEnd, fragmentByStart) {
for (var k in fragmentByEnd) {
var f = fragmentByEnd[k];
delete fragmentByStart[f.start];
delete f.start;
delete f.end;
f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; });
fragments.push(f);
}
}
flush(fragmentByEnd, fragmentByStart);
flush(fragmentByStart, fragmentByEnd);
arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); });
return fragments;
}
function meshArcs(topology, o, filter) {
var arcs = [];
if (arguments.length > 1) {
var geomsByArc = [],
geom;
function arc(i) {
var j = i < 0 ? ~i : i;
(geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom});
}
function line(arcs) {
arcs.forEach(arc);
}
function polygon(arcs) {
arcs.forEach(line);
}
function geometry(o) {
if (o.type === "GeometryCollection") o.geometries.forEach(geometry);
else if (o.type in geometryType) geom = o, geometryType[o.type](o.arcs);
}
var geometryType = {
LineString: line,
MultiLineString: polygon,
Polygon: polygon,
MultiPolygon: function(arcs) { arcs.forEach(polygon); }
};
geometry(o);
geomsByArc.forEach(arguments.length < 3
? function(geoms) { arcs.push(geoms[0].i); }
: function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); });
} else {
for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i);
}
return {type: "MultiLineString", arcs: stitchArcs(topology, arcs)};
}
function mergeArcs(topology, objects) {
var polygonsByArc = {},
polygons = [],
components = [];
objects.forEach(function(o) {
if (o.type === "Polygon") register(o.arcs);
else if (o.type === "MultiPolygon") o.arcs.forEach(register);
});
function register(polygon) {
polygon.forEach(function(ring) {
ring.forEach(function(arc) {
(polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon);
});
});
polygons.push(polygon);
}
function exterior(ring) {
return cartesianRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]) > 0; // TODO allow spherical?
}
polygons.forEach(function(polygon) {
if (!polygon._) {
var component = [],
neighbors = [polygon];
polygon._ = 1;
components.push(component);
while (polygon = neighbors.pop()) {
component.push(polygon);
polygon.forEach(function(ring) {
ring.forEach(function(arc) {
polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) {
if (!polygon._) {
polygon._ = 1;
neighbors.push(polygon);
}
});
});
});
}
}
});
polygons.forEach(function(polygon) {
delete polygon._;
});
return {
type: "MultiPolygon",
arcs: components.map(function(polygons) {
var arcs = [];
// Extract the exterior (unique) arcs.
polygons.forEach(function(polygon) {
polygon.forEach(function(ring) {
ring.forEach(function(arc) {
if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) {
arcs.push(arc);
}
});
});
});
// Stitch the arcs into one or more rings.
arcs = stitchArcs(topology, arcs);
// If more than one ring is returned,
// at most one of these rings can be the exterior;
// this exterior ring has the same winding order
// as any exterior ring in the original polygons.
if ((n = arcs.length) > 1) {
var sgn = exterior(polygons[0][0]);
for (var i = 0, t; i < n; ++i) {
if (sgn === exterior(arcs[i])) {
t = arcs[0], arcs[0] = arcs[i], arcs[i] = t;
break;
}
}
}
return arcs;
})
};
}
function featureOrCollection(topology, o) {
return o.type === "GeometryCollection" ? {
type: "FeatureCollection",
features: o.geometries.map(function(o) { return feature(topology, o); })
} : feature(topology, o);
}
function feature(topology, o) {
var f = {
type: "Feature",
id: o.id,
properties: o.properties || {},
geometry: object(topology, o)
};
if (o.id == null) delete f.id;
return f;
}
function object(topology, o) {
var absolute = transformAbsolute(topology.transform),
arcs = topology.arcs;
function arc(i, points) {
if (points.length) points.pop();
for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) {
points.push(p = a[k].slice());
absolute(p, k);
}
if (i < 0) reverse(points, n);
}
function point(p) {
p = p.slice();
absolute(p, 0);
return p;
}
function line(arcs) {
var points = [];
for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
if (points.length < 2) points.push(points[0].slice());
return points;
}
function ring(arcs) {
var points = line(arcs);
while (points.length < 4) points.push(points[0].slice());
return points;
}
function polygon(arcs) {
return arcs.map(ring);
}
function geometry(o) {
var t = o.type;
return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)}
: t in geometryType ? {type: t, coordinates: geometryType[t](o)}
: null;
}
var geometryType = {
Point: function(o) { return point(o.coordinates); },
MultiPoint: function(o) { return o.coordinates.map(point); },
LineString: function(o) { return line(o.arcs); },
MultiLineString: function(o) { return o.arcs.map(line); },
Polygon: function(o) { return polygon(o.arcs); },
MultiPolygon: function(o) { return o.arcs.map(polygon); }
};
return geometry(o);
}
function reverse(array, n) {
var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
}
function bisect(a, x) {
var lo = 0, hi = a.length;
while (lo < hi) {
var mid = lo + hi >>> 1;
if (a[mid] < x) lo = mid + 1;
else hi = mid;
}
return lo;
}
function neighbors(objects) {
var indexesByArc = {}, // arc index -> array of object indexes
neighbors = objects.map(function() { return []; });
function line(arcs, i) {
arcs.forEach(function(a) {
if (a < 0) a = ~a;
var o = indexesByArc[a];
if (o) o.push(i);
else indexesByArc[a] = [i];
});
}
function polygon(arcs, i) {
arcs.forEach(function(arc) { line(arc, i); });
}
function geometry(o, i) {
if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); });
else if (o.type in geometryType) geometryType[o.type](o.arcs, i);
}
var geometryType = {
LineString: line,
MultiLineString: polygon,
Polygon: polygon,
MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); }
};
objects.forEach(geometry);
for (var i in indexesByArc) {
for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) {
for (var k = j + 1; k < m; ++k) {
var ij = indexes[j], ik = indexes[k], n;
if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik);
if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij);
}
}
}
return neighbors;
}
function presimplify(topology, triangleArea) {
var absolute = transformAbsolute(topology.transform),
relative = transformRelative(topology.transform),
heap = minAreaHeap();
if (!triangleArea) triangleArea = cartesianTriangleArea;
topology.arcs.forEach(function(arc) {
var triangles = [],
maxArea = 0,
triangle;
// To store each points effective area, we create a new array rather than
// extending the passed-in point to workaround a Chrome/V8 bug (getting
// stuck in smi mode). For midpoints, the initial effective area of
// Infinity will be computed in the next step.
for (var i = 0, n = arc.length, p; i < n; ++i) {
p = arc[i];
absolute(arc[i] = [p[0], p[1], Infinity], i);
}
for (var i = 1, n = arc.length - 1; i < n; ++i) {
triangle = arc.slice(i - 1, i + 2);
triangle[1][2] = triangleArea(triangle);
triangles.push(triangle);
heap.push(triangle);
}
for (var i = 0, n = triangles.length; i < n; ++i) {
triangle = triangles[i];
triangle.previous = triangles[i - 1];
triangle.next = triangles[i + 1];
}
while (triangle = heap.pop()) {
var previous = triangle.previous,
next = triangle.next;
// If the area of the current point is less than that of the previous point
// to be eliminated, use the latter's area instead. This ensures that the
// current point cannot be eliminated without eliminating previously-
// eliminated points.
if (triangle[1][2] < maxArea) triangle[1][2] = maxArea;
else maxArea = triangle[1][2];
if (previous) {
previous.next = next;
previous[2] = triangle[2];
update(previous);
}
if (next) {
next.previous = previous;
next[0] = triangle[0];
update(next);
}
}
arc.forEach(relative);
});
function update(triangle) {
heap.remove(triangle);
triangle[1][2] = triangleArea(triangle);
heap.push(triangle);
}
return topology;
};
function cartesianRingArea(ring) {
var i = -1,
n = ring.length,
a,
b = ring[n - 1],
area = 0;
while (++i < n) {
a = b;
b = ring[i];
area += a[0] * b[1] - a[1] * b[0];
}
return area * .5;
}
function cartesianTriangleArea(triangle) {
var a = triangle[0], b = triangle[1], c = triangle[2];
return Math.abs((a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]));
}
function compareArea(a, b) {
return a[1][2] - b[1][2];
}
function minAreaHeap() {
var heap = {},
array = [],
size = 0;
heap.push = function(object) {
up(array[object._ = size] = object, size++);
return size;
};
heap.pop = function() {
if (size <= 0) return;
var removed = array[0], object;
if (--size > 0) object = array[size], down(array[object._ = 0] = object, 0);
return removed;
};
heap.remove = function(removed) {
var i = removed._, object;
if (array[i] !== removed) return; // invalid request
if (i !== --size) object = array[size], (compareArea(object, removed) < 0 ? up : down)(array[object._ = i] = object, i);
return i;
};
function up(object, i) {
while (i > 0) {
var j = ((i + 1) >> 1) - 1,
parent = array[j];
if (compareArea(object, parent) >= 0) break;
array[parent._ = i] = parent;
array[object._ = i = j] = object;
}
}
function down(object, i) {
while (true) {
var r = (i + 1) << 1,
l = r - 1,
j = i,
child = array[j];
if (l < size && compareArea(array[l], child) < 0) child = array[j = l];
if (r < size && compareArea(array[r], child) < 0) child = array[j = r];
if (j === i) break;
array[child._ = i] = child;
array[object._ = i = j] = object;
}
}
return heap;
}
function transformAbsolute(transform) {
if (!transform) return noop;
var x0,
y0,
kx = transform.scale[0],
ky = transform.scale[1],
dx = transform.translate[0],
dy = transform.translate[1];
return function(point, i) {
if (!i) x0 = y0 = 0;
point[0] = (x0 += point[0]) * kx + dx;
point[1] = (y0 += point[1]) * ky + dy;
};
}
function transformRelative(transform) {
if (!transform) return noop;
var x0,
y0,
kx = transform.scale[0],
ky = transform.scale[1],
dx = transform.translate[0],
dy = transform.translate[1];
return function(point, i) {
if (!i) x0 = y0 = 0;
var x1 = (point[0] - dx) / kx | 0,
y1 = (point[1] - dy) / ky | 0;
point[0] = x1 - x0;
point[1] = y1 - y0;
x0 = x1;
y0 = y1;
};
}
function noop() {}
if (typeof define === "function" && define.amd) define(topojson);
else if (typeof module === "object" && module.exports) module.exports = topojson;
else this.topojson = topojson;
}();

@ -0,0 +1,29 @@
/*!
* d3.geomap
* https://github.com/yaph/d3-geomap/blob/master/LICENSE
* MIT licensed
* Copyright (C) 2015 by Ramiro Gómez (http://ramiro.org/)
*/
text {
fill: #333;
font-size: 12px; }
.background {
fill: none;
pointer-events: all; }
.unit {
cursor: pointer;
fill: #ccc;
stroke: #000;
stroke-width: 0.4px; }
.legend-bg {
fill: #fff;
fill-opacity: 0.8; }
.legend-bar {
stroke: #333;
stroke-width: 1px; }
/*# sourceMappingURL=geomap.css.map */

@ -0,0 +1,80 @@
#rect {
fill: none;
stroke: rgb(0, 0, 0);
stroke-width: 2;
}
#rectCurve {
fill: none;
stroke: rgb(0, 0, 0);
stroke-width: 0.5;
}
.axis path,
.axis line {
fill: none;
shape-rendering: crispEdges;
stroke: grey;
stroke-width: 2;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.label{
font-size: 16.844px !important;
}
/* arc tween shit*/
.background {
fill: #FFFFFF;
fill-opacity: 0.01;
}
.component {
fill: #e1e1e1;
}
.component .label {
font-family: Myriad, "Helvetic Neue", Helvetica, Arial;
text-anchor: middle;
fill: #0000FF;
}
.arc {
stroke-weight:0.1;
fill: #4e8fff;
}
.arc2 {
stroke-weight:0.1;
fill: #3660b0;
}
.label {
font-family: Myriad, "Helvetic Neue", Helvetica, Arial;
text-anchor: middle;
}
.labelArc {
font-family: Myriad, "Helvetic Neue", Helvetica, Arial;
text-anchor: middle;
fill: #0000FF;
}
.tooltipClass {
background-color: #e5f2ff;
padding: 4px 8px;
}
.tooltipClass p{
margin: 0;
padding: 0;
}

@ -0,0 +1,9 @@
{
"id": "TemperatureChart",
"title": "TemperatureChart",
"type": "gadget",
"thumbnail": "local://images/gadgetIcon.png",
"data": {
"url": "local://store/carbon.super/gadget/TemperatureChart/index.xml"
}
}

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Bar Chart"
author="WSO2 Gadget Server"
height="230"
scrolling="true"
tags="charts,bar,visualization,data"
description="A generic Bar Chart gadget, that takes a json datasource as an input. It can be configured to fetch data in defined intervals. This gadget can be used to create dashboards with statistical data. This gadget can be reused as an iframe in any web page as it is self contained.">
</ModulePrefs>
<UserPref name="dataSource"
display_name="Data Source"
default_value="/portal/gadgets/bar-chart/datasource/dataFile4.jag">
</UserPref>
<!--UserPref name="options"
display_name="Chart Options"
default_value="/portal/gadgets/bar-chart/js/options-bar.js">
</UserPref-->
<UserPref name="updateGraph"
display_name="Update Interval (s)"
default_value="No">
</UserPref>
<Content type="html">
<![CDATA[
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Bar Chart</title>
<link href="css/flot-graph.css" rel="stylesheet" type="text/css">
<link href="css/igviz.css" rel="stylesheet" type="text/css">
<link href="css/bootstrap.min.css" rel="stylesheet" type="text/css">
<link href="css/d3.geomap.css" rel="stylesheet" type="text/css">
<script language="javascript" type="text/javascript" src="js/excanvas.min.js"></script>
<script language="javascript" type="text/javascript" src="js/jquery.js"></script>
<script language="javascript" type="text/javascript" src="js/topojson.js"></script>
<script language="javascript" type="text/javascript" src="js/d3.min.js"></script>
<script language="javascript" type="text/javascript" src="js/vega.js"></script>
<script language="javascript" type="text/javascript" src="js/VizGrammar.min.js"></script>
<script language="javascript" type="text/javascript" src="js/gadgetconf.js"></script>
<script language="javascript" type="text/javascript" src="js/outputAdapterUiLibrary.js"></script>
<script language="javascript" type="text/javascript" src="js/main.js"></script>
</head>
<body>
<div id="placeholder" class="demo-placeholder" style="height:90%"></div>
<script language="javascript" type="text/javascript">
if(jQuery("#placeholder").html() == ""){
jQuery("#placeholder").append('<div id="noChart"><table><tr><td style="padding:30px 20px 0px 20px"><img src="../../portal/images/noEvents.png" align="left" style="width:24;height:24"/></td><td><br/><b><p><br/> Data is not available for plotting</p></b></td></tr><tr><td></td><td><p>The chart will be loaded once the dashboard receives events</p><td/></tr></table></div>');
}
</script>
</body>
</html>
]]>
</Content>
</Module>

@ -0,0 +1,48 @@
if(navigator.appVersion.indexOf("MSIE")!=-1&&parseFloat(navigator.appVersion.split("MSIE")[1])<=8&&!document.createElement("canvas").getContext)(function(){var m=Math;var mr=m.round;var ms=m.sin;var mc=m.cos;var abs=m.abs;var sqrt=m.sqrt;var Z=10;var Z2=Z/2;var IE_VERSION=+navigator.userAgent.match(/MSIE ([\d.]+)?/)[1];function getContext(){return this.context_||(this.context_=new CanvasRenderingContext2D_(this))}var slice=Array.prototype.slice;function bind(f,obj,var_args){var a=slice.call(arguments,
2);return function(){return f.apply(obj,a.concat(slice.call(arguments)))}}function encodeHtmlAttribute(s){return String(s).replace(/&/g,"&amp;").replace(/"/g,"&quot;")}function addNamespace(doc,prefix,urn){if(!doc.namespaces[prefix])doc.namespaces.add(prefix,urn,"#default#VML")}function addNamespacesAndStylesheet(doc){addNamespace(doc,"g_vml_","urn:schemas-microsoft-com:vml");addNamespace(doc,"g_o_","urn:schemas-microsoft-com:office:office");if(!doc.styleSheets["ex_canvas_"]){var ss=doc.createStyleSheet();
ss.owningElement.id="ex_canvas_";ss.cssText="canvas{display:inline-block;overflow:hidden;"+"text-align:left;width:300px;height:150px}"}}addNamespacesAndStylesheet(document);var G_vmlCanvasManager_={init:function(opt_doc){var doc=opt_doc||document;doc.createElement("canvas");doc.attachEvent("onreadystatechange",bind(this.init_,this,doc))},init_:function(doc){var els=doc.getElementsByTagName("canvas");for(var i=0;i<els.length;i++)this.initElement(els[i])},initElement:function(el){if(!el.getContext){el.getContext=
getContext;addNamespacesAndStylesheet(el.ownerDocument);el.innerHTML="";el.attachEvent("onpropertychange",onPropertyChange);el.attachEvent("onresize",onResize);var attrs=el.attributes;if(attrs.width&&attrs.width.specified)el.style.width=attrs.width.nodeValue+"px";else el.width=el.clientWidth;if(attrs.height&&attrs.height.specified)el.style.height=attrs.height.nodeValue+"px";else el.height=el.clientHeight}return el}};function onPropertyChange(e){var el=e.srcElement;switch(e.propertyName){case "width":el.getContext().clearRect();
el.style.width=el.attributes.width.nodeValue+"px";el.firstChild.style.width=el.clientWidth+"px";break;case "height":el.getContext().clearRect();el.style.height=el.attributes.height.nodeValue+"px";el.firstChild.style.height=el.clientHeight+"px";break}}function onResize(e){var el=e.srcElement;if(el.firstChild){el.firstChild.style.width=el.clientWidth+"px";el.firstChild.style.height=el.clientHeight+"px"}}G_vmlCanvasManager_.init();var decToHex=[];for(var i=0;i<16;i++)for(var j=0;j<16;j++)decToHex[i*
16+j]=i.toString(16)+j.toString(16);function createMatrixIdentity(){return[[1,0,0],[0,1,0],[0,0,1]]}function matrixMultiply(m1,m2){var result=createMatrixIdentity();for(var x=0;x<3;x++)for(var y=0;y<3;y++){var sum=0;for(var z=0;z<3;z++)sum+=m1[x][z]*m2[z][y];result[x][y]=sum}return result}function copyState(o1,o2){o2.fillStyle=o1.fillStyle;o2.lineCap=o1.lineCap;o2.lineJoin=o1.lineJoin;o2.lineWidth=o1.lineWidth;o2.miterLimit=o1.miterLimit;o2.shadowBlur=o1.shadowBlur;o2.shadowColor=o1.shadowColor;o2.shadowOffsetX=
o1.shadowOffsetX;o2.shadowOffsetY=o1.shadowOffsetY;o2.strokeStyle=o1.strokeStyle;o2.globalAlpha=o1.globalAlpha;o2.font=o1.font;o2.textAlign=o1.textAlign;o2.textBaseline=o1.textBaseline;o2.arcScaleX_=o1.arcScaleX_;o2.arcScaleY_=o1.arcScaleY_;o2.lineScale_=o1.lineScale_}var colorData={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",
chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",
darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",
lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",
mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",
salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"};function getRgbHslContent(styleString){var start=styleString.indexOf("(",3);var end=styleString.indexOf(")",start+1);var parts=
styleString.substring(start+1,end).split(",");if(parts.length!=4||styleString.charAt(3)!="a")parts[3]=1;return parts}function percent(s){return parseFloat(s)/100}function clamp(v,min,max){return Math.min(max,Math.max(min,v))}function hslToRgb(parts){var r,g,b,h,s,l;h=parseFloat(parts[0])/360%360;if(h<0)h++;s=clamp(percent(parts[1]),0,1);l=clamp(percent(parts[2]),0,1);if(s==0)r=g=b=l;else{var q=l<0.5?l*(1+s):l+s-l*s;var p=2*l-q;r=hueToRgb(p,q,h+1/3);g=hueToRgb(p,q,h);b=hueToRgb(p,q,h-1/3)}return"#"+
decToHex[Math.floor(r*255)]+decToHex[Math.floor(g*255)]+decToHex[Math.floor(b*255)]}function hueToRgb(m1,m2,h){if(h<0)h++;if(h>1)h--;if(6*h<1)return m1+(m2-m1)*6*h;else if(2*h<1)return m2;else if(3*h<2)return m1+(m2-m1)*(2/3-h)*6;else return m1}var processStyleCache={};function processStyle(styleString){if(styleString in processStyleCache)return processStyleCache[styleString];var str,alpha=1;styleString=String(styleString);if(styleString.charAt(0)=="#")str=styleString;else if(/^rgb/.test(styleString)){var parts=
getRgbHslContent(styleString);var str="#",n;for(var i=0;i<3;i++){if(parts[i].indexOf("%")!=-1)n=Math.floor(percent(parts[i])*255);else n=+parts[i];str+=decToHex[clamp(n,0,255)]}alpha=+parts[3]}else if(/^hsl/.test(styleString)){var parts=getRgbHslContent(styleString);str=hslToRgb(parts);alpha=parts[3]}else str=colorData[styleString]||styleString;return processStyleCache[styleString]={color:str,alpha:alpha}}var DEFAULT_STYLE={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};
var fontStyleCache={};function processFontStyle(styleString){if(fontStyleCache[styleString])return fontStyleCache[styleString];var el=document.createElement("div");var style=el.style;try{style.font=styleString}catch(ex){}return fontStyleCache[styleString]={style:style.fontStyle||DEFAULT_STYLE.style,variant:style.fontVariant||DEFAULT_STYLE.variant,weight:style.fontWeight||DEFAULT_STYLE.weight,size:style.fontSize||DEFAULT_STYLE.size,family:style.fontFamily||DEFAULT_STYLE.family}}function getComputedStyle(style,
element){var computedStyle={};for(var p in style)computedStyle[p]=style[p];var canvasFontSize=parseFloat(element.currentStyle.fontSize),fontSize=parseFloat(style.size);if(typeof style.size=="number")computedStyle.size=style.size;else if(style.size.indexOf("px")!=-1)computedStyle.size=fontSize;else if(style.size.indexOf("em")!=-1)computedStyle.size=canvasFontSize*fontSize;else if(style.size.indexOf("%")!=-1)computedStyle.size=canvasFontSize/100*fontSize;else if(style.size.indexOf("pt")!=-1)computedStyle.size=
fontSize/0.75;else computedStyle.size=canvasFontSize;computedStyle.size*=0.981;return computedStyle}function buildStyle(style){return style.style+" "+style.variant+" "+style.weight+" "+style.size+"px "+style.family}var lineCapMap={"butt":"flat","round":"round"};function processLineCap(lineCap){return lineCapMap[lineCap]||"square"}function CanvasRenderingContext2D_(canvasElement){this.m_=createMatrixIdentity();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle=
"#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=Z*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=canvasElement;var cssText="width:"+canvasElement.clientWidth+"px;height:"+canvasElement.clientHeight+"px;overflow:hidden;position:absolute";var el=canvasElement.ownerDocument.createElement("div");el.style.cssText=cssText;canvasElement.appendChild(el);var overlayEl=el.cloneNode(false);overlayEl.style.backgroundColor=
"red";overlayEl.style.filter="alpha(opacity=0)";canvasElement.appendChild(overlayEl);this.element_=el;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var contextPrototype=CanvasRenderingContext2D_.prototype;contextPrototype.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};contextPrototype.beginPath=function(){this.currentPath_=[]};contextPrototype.moveTo=function(aX,aY){var p=getCoords(this,aX,aY);this.currentPath_.push({type:"moveTo",
x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};contextPrototype.lineTo=function(aX,aY){var p=getCoords(this,aX,aY);this.currentPath_.push({type:"lineTo",x:p.x,y:p.y});this.currentX_=p.x;this.currentY_=p.y};contextPrototype.bezierCurveTo=function(aCP1x,aCP1y,aCP2x,aCP2y,aX,aY){var p=getCoords(this,aX,aY);var cp1=getCoords(this,aCP1x,aCP1y);var cp2=getCoords(this,aCP2x,aCP2y);bezierCurveTo(this,cp1,cp2,p)};function bezierCurveTo(self,cp1,cp2,p){self.currentPath_.push({type:"bezierCurveTo",cp1x:cp1.x,
cp1y:cp1.y,cp2x:cp2.x,cp2y:cp2.y,x:p.x,y:p.y});self.currentX_=p.x;self.currentY_=p.y}contextPrototype.quadraticCurveTo=function(aCPx,aCPy,aX,aY){var cp=getCoords(this,aCPx,aCPy);var p=getCoords(this,aX,aY);var cp1={x:this.currentX_+2/3*(cp.x-this.currentX_),y:this.currentY_+2/3*(cp.y-this.currentY_)};var cp2={x:cp1.x+(p.x-this.currentX_)/3,y:cp1.y+(p.y-this.currentY_)/3};bezierCurveTo(this,cp1,cp2,p)};contextPrototype.arc=function(aX,aY,aRadius,aStartAngle,aEndAngle,aClockwise){aRadius*=Z;var arcType=
aClockwise?"at":"wa";var xStart=aX+mc(aStartAngle)*aRadius-Z2;var yStart=aY+ms(aStartAngle)*aRadius-Z2;var xEnd=aX+mc(aEndAngle)*aRadius-Z2;var yEnd=aY+ms(aEndAngle)*aRadius-Z2;if(xStart==xEnd&&!aClockwise)xStart+=0.125;var p=getCoords(this,aX,aY);var pStart=getCoords(this,xStart,yStart);var pEnd=getCoords(this,xEnd,yEnd);this.currentPath_.push({type:arcType,x:p.x,y:p.y,radius:aRadius,xStart:pStart.x,yStart:pStart.y,xEnd:pEnd.x,yEnd:pEnd.y})};contextPrototype.rect=function(aX,aY,aWidth,aHeight){this.moveTo(aX,
aY);this.lineTo(aX+aWidth,aY);this.lineTo(aX+aWidth,aY+aHeight);this.lineTo(aX,aY+aHeight);this.closePath()};contextPrototype.strokeRect=function(aX,aY,aWidth,aHeight){var oldPath=this.currentPath_;this.beginPath();this.moveTo(aX,aY);this.lineTo(aX+aWidth,aY);this.lineTo(aX+aWidth,aY+aHeight);this.lineTo(aX,aY+aHeight);this.closePath();this.stroke();this.currentPath_=oldPath};contextPrototype.fillRect=function(aX,aY,aWidth,aHeight){var oldPath=this.currentPath_;this.beginPath();this.moveTo(aX,aY);
this.lineTo(aX+aWidth,aY);this.lineTo(aX+aWidth,aY+aHeight);this.lineTo(aX,aY+aHeight);this.closePath();this.fill();this.currentPath_=oldPath};contextPrototype.createLinearGradient=function(aX0,aY0,aX1,aY1){var gradient=new CanvasGradient_("gradient");gradient.x0_=aX0;gradient.y0_=aY0;gradient.x1_=aX1;gradient.y1_=aY1;return gradient};contextPrototype.createRadialGradient=function(aX0,aY0,aR0,aX1,aY1,aR1){var gradient=new CanvasGradient_("gradientradial");gradient.x0_=aX0;gradient.y0_=aY0;gradient.r0_=
aR0;gradient.x1_=aX1;gradient.y1_=aY1;gradient.r1_=aR1;return gradient};contextPrototype.drawImage=function(image,var_args){var dx,dy,dw,dh,sx,sy,sw,sh;var oldRuntimeWidth=image.runtimeStyle.width;var oldRuntimeHeight=image.runtimeStyle.height;image.runtimeStyle.width="auto";image.runtimeStyle.height="auto";var w=image.width;var h=image.height;image.runtimeStyle.width=oldRuntimeWidth;image.runtimeStyle.height=oldRuntimeHeight;if(arguments.length==3){dx=arguments[1];dy=arguments[2];sx=sy=0;sw=dw=w;
sh=dh=h}else if(arguments.length==5){dx=arguments[1];dy=arguments[2];dw=arguments[3];dh=arguments[4];sx=sy=0;sw=w;sh=h}else if(arguments.length==9){sx=arguments[1];sy=arguments[2];sw=arguments[3];sh=arguments[4];dx=arguments[5];dy=arguments[6];dw=arguments[7];dh=arguments[8]}else throw Error("Invalid number of arguments");var d=getCoords(this,dx,dy);var w2=sw/2;var h2=sh/2;var vmlStr=[];var W=10;var H=10;vmlStr.push(" <g_vml_:group",' coordsize="',Z*W,",",Z*H,'"',' coordorigin="0,0"',' style="width:',
W,"px;height:",H,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]||this.m_[1][1]!=1||this.m_[1][0]){var filter=[];filter.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",mr(d.x/Z),",","Dy=",mr(d.y/Z),"");var max=d;var c2=getCoords(this,dx+dw,dy);var c3=getCoords(this,dx,dy+dh);var c4=getCoords(this,dx+dw,dy+dh);max.x=m.max(max.x,c2.x,c3.x,c4.x);max.y=m.max(max.y,c2.y,c3.y,c4.y);vmlStr.push("padding:0 ",mr(max.x/Z),"px ",mr(max.y/
Z),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",filter.join(""),", sizingmethod='clip');")}else vmlStr.push("top:",mr(d.y/Z),"px;left:",mr(d.x/Z),"px;");vmlStr.push(' ">','<g_vml_:image src="',image.src,'"',' style="width:',Z*dw,"px;"," height:",Z*dh,'px"',' cropleft="',sx/w,'"',' croptop="',sy/h,'"',' cropright="',(w-sx-sw)/w,'"',' cropbottom="',(h-sy-sh)/h,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",vmlStr.join(""))};contextPrototype.stroke=function(aFill){var W=
10;var H=10;var chunkSize=5E3;var min={x:null,y:null};var max={x:null,y:null};for(var j=0;j<this.currentPath_.length;j+=chunkSize){var lineStr=[];var lineOpen=false;lineStr.push("<g_vml_:shape",' filled="',!!aFill,'"',' style="position:absolute;width:',W,"px;height:",H,'px;"',' coordorigin="0,0"',' coordsize="',Z*W,",",Z*H,'"',' stroked="',!aFill,'"',' path="');var newSeq=false;for(var i=j;i<Math.min(j+chunkSize,this.currentPath_.length);i++){if(i%chunkSize==0&&i>0)lineStr.push(" m ",mr(this.currentPath_[i-
1].x),",",mr(this.currentPath_[i-1].y));var p=this.currentPath_[i];var c;switch(p.type){case "moveTo":c=p;lineStr.push(" m ",mr(p.x),",",mr(p.y));break;case "lineTo":lineStr.push(" l ",mr(p.x),",",mr(p.y));break;case "close":lineStr.push(" x ");p=null;break;case "bezierCurveTo":lineStr.push(" c ",mr(p.cp1x),",",mr(p.cp1y),",",mr(p.cp2x),",",mr(p.cp2y),",",mr(p.x),",",mr(p.y));break;case "at":case "wa":lineStr.push(" ",p.type," ",mr(p.x-this.arcScaleX_*p.radius),",",mr(p.y-this.arcScaleY_*p.radius),
" ",mr(p.x+this.arcScaleX_*p.radius),",",mr(p.y+this.arcScaleY_*p.radius)," ",mr(p.xStart),",",mr(p.yStart)," ",mr(p.xEnd),",",mr(p.yEnd));break}if(p){if(min.x==null||p.x<min.x)min.x=p.x;if(max.x==null||p.x>max.x)max.x=p.x;if(min.y==null||p.y<min.y)min.y=p.y;if(max.y==null||p.y>max.y)max.y=p.y}}lineStr.push(' ">');if(!aFill)appendStroke(this,lineStr);else appendFill(this,lineStr,min,max);lineStr.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",lineStr.join(""))}};function appendStroke(ctx,
lineStr){var a=processStyle(ctx.strokeStyle);var color=a.color;var opacity=a.alpha*ctx.globalAlpha;var lineWidth=ctx.lineScale_*ctx.lineWidth;if(lineWidth<1)opacity*=lineWidth;lineStr.push("<g_vml_:stroke",' opacity="',opacity,'"',' joinstyle="',ctx.lineJoin,'"',' miterlimit="',ctx.miterLimit,'"',' endcap="',processLineCap(ctx.lineCap),'"',' weight="',lineWidth,'px"',' color="',color,'" />')}function appendFill(ctx,lineStr,min,max){var fillStyle=ctx.fillStyle;var arcScaleX=ctx.arcScaleX_;var arcScaleY=
ctx.arcScaleY_;var width=max.x-min.x;var height=max.y-min.y;if(fillStyle instanceof CanvasGradient_){var angle=0;var focus={x:0,y:0};var shift=0;var expansion=1;if(fillStyle.type_=="gradient"){var x0=fillStyle.x0_/arcScaleX;var y0=fillStyle.y0_/arcScaleY;var x1=fillStyle.x1_/arcScaleX;var y1=fillStyle.y1_/arcScaleY;var p0=getCoords(ctx,x0,y0);var p1=getCoords(ctx,x1,y1);var dx=p1.x-p0.x;var dy=p1.y-p0.y;angle=Math.atan2(dx,dy)*180/Math.PI;if(angle<0)angle+=360;if(angle<1E-6)angle=0}else{var p0=getCoords(ctx,
fillStyle.x0_,fillStyle.y0_);focus={x:(p0.x-min.x)/width,y:(p0.y-min.y)/height};width/=arcScaleX*Z;height/=arcScaleY*Z;var dimension=m.max(width,height);shift=2*fillStyle.r0_/dimension;expansion=2*fillStyle.r1_/dimension-shift}var stops=fillStyle.colors_;stops.sort(function(cs1,cs2){return cs1.offset-cs2.offset});var length=stops.length;var color1=stops[0].color;var color2=stops[length-1].color;var opacity1=stops[0].alpha*ctx.globalAlpha;var opacity2=stops[length-1].alpha*ctx.globalAlpha;var colors=
[];for(var i=0;i<length;i++){var stop=stops[i];colors.push(stop.offset*expansion+shift+" "+stop.color)}lineStr.push('<g_vml_:fill type="',fillStyle.type_,'"',' method="none" focus="100%"',' color="',color1,'"',' color2="',color2,'"',' colors="',colors.join(","),'"',' opacity="',opacity2,'"',' g_o_:opacity2="',opacity1,'"',' angle="',angle,'"',' focusposition="',focus.x,",",focus.y,'" />')}else if(fillStyle instanceof CanvasPattern_){if(width&&height){var deltaLeft=-min.x;var deltaTop=-min.y;lineStr.push("<g_vml_:fill",
' position="',deltaLeft/width*arcScaleX*arcScaleX,",",deltaTop/height*arcScaleY*arcScaleY,'"',' type="tile"',' src="',fillStyle.src_,'" />')}}else{var a=processStyle(ctx.fillStyle);var color=a.color;var opacity=a.alpha*ctx.globalAlpha;lineStr.push('<g_vml_:fill color="',color,'" opacity="',opacity,'" />')}}contextPrototype.fill=function(){this.stroke(true)};contextPrototype.closePath=function(){this.currentPath_.push({type:"close"})};function getCoords(ctx,aX,aY){var m=ctx.m_;return{x:Z*(aX*m[0][0]+
aY*m[1][0]+m[2][0])-Z2,y:Z*(aX*m[0][1]+aY*m[1][1]+m[2][1])-Z2}}contextPrototype.save=function(){var o={};copyState(this,o);this.aStack_.push(o);this.mStack_.push(this.m_);this.m_=matrixMultiply(createMatrixIdentity(),this.m_)};contextPrototype.restore=function(){if(this.aStack_.length){copyState(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function matrixIsFinite(m){return isFinite(m[0][0])&&isFinite(m[0][1])&&isFinite(m[1][0])&&isFinite(m[1][1])&&isFinite(m[2][0])&&isFinite(m[2][1])}function setM(ctx,
m,updateLineScale){if(!matrixIsFinite(m))return;ctx.m_=m;if(updateLineScale){var det=m[0][0]*m[1][1]-m[0][1]*m[1][0];ctx.lineScale_=sqrt(abs(det))}}contextPrototype.translate=function(aX,aY){var m1=[[1,0,0],[0,1,0],[aX,aY,1]];setM(this,matrixMultiply(m1,this.m_),false)};contextPrototype.rotate=function(aRot){var c=mc(aRot);var s=ms(aRot);var m1=[[c,s,0],[-s,c,0],[0,0,1]];setM(this,matrixMultiply(m1,this.m_),false)};contextPrototype.scale=function(aX,aY){this.arcScaleX_*=aX;this.arcScaleY_*=aY;var m1=
[[aX,0,0],[0,aY,0],[0,0,1]];setM(this,matrixMultiply(m1,this.m_),true)};contextPrototype.transform=function(m11,m12,m21,m22,dx,dy){var m1=[[m11,m12,0],[m21,m22,0],[dx,dy,1]];setM(this,matrixMultiply(m1,this.m_),true)};contextPrototype.setTransform=function(m11,m12,m21,m22,dx,dy){var m=[[m11,m12,0],[m21,m22,0],[dx,dy,1]];setM(this,m,true)};contextPrototype.drawText_=function(text,x,y,maxWidth,stroke){var m=this.m_,delta=1E3,left=0,right=delta,offset={x:0,y:0},lineStr=[];var fontStyle=getComputedStyle(processFontStyle(this.font),
this.element_);var fontStyleString=buildStyle(fontStyle);var elementStyle=this.element_.currentStyle;var textAlign=this.textAlign.toLowerCase();switch(textAlign){case "left":case "center":case "right":break;case "end":textAlign=elementStyle.direction=="ltr"?"right":"left";break;case "start":textAlign=elementStyle.direction=="rtl"?"right":"left";break;default:textAlign="left"}switch(this.textBaseline){case "hanging":case "top":offset.y=fontStyle.size/1.75;break;case "middle":break;default:case null:case "alphabetic":case "ideographic":case "bottom":offset.y=
-fontStyle.size/2.25;break}switch(textAlign){case "right":left=delta;right=0.05;break;case "center":left=right=delta/2;break}var d=getCoords(this,x+offset.x,y+offset.y);lineStr.push('<g_vml_:line from="',-left,' 0" to="',right,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!stroke,'" stroked="',!!stroke,'" style="position:absolute;width:1px;height:1px;">');if(stroke)appendStroke(this,lineStr);else appendFill(this,lineStr,{x:-left,y:0},{x:right,y:fontStyle.size});var skewM=m[0][0].toFixed(3)+
","+m[1][0].toFixed(3)+","+m[0][1].toFixed(3)+","+m[1][1].toFixed(3)+",0,0";var skewOffset=mr(d.x/Z)+","+mr(d.y/Z);lineStr.push('<g_vml_:skew on="t" matrix="',skewM,'" ',' offset="',skewOffset,'" origin="',left,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',encodeHtmlAttribute(text),'" style="v-text-align:',textAlign,";font:",encodeHtmlAttribute(fontStyleString),'" /></g_vml_:line>');this.element_.insertAdjacentHTML("beforeEnd",lineStr.join(""))};contextPrototype.fillText=
function(text,x,y,maxWidth){this.drawText_(text,x,y,maxWidth,false)};contextPrototype.strokeText=function(text,x,y,maxWidth){this.drawText_(text,x,y,maxWidth,true)};contextPrototype.measureText=function(text){if(!this.textMeasureEl_){var s='<span style="position:absolute;'+"top:-20000px;left:0;padding:0;margin:0;border:none;"+'white-space:pre;"></span>';this.element_.insertAdjacentHTML("beforeEnd",s);this.textMeasureEl_=this.element_.lastChild}var doc=this.element_.ownerDocument;this.textMeasureEl_.innerHTML=
"";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(doc.createTextNode(text));return{width:this.textMeasureEl_.offsetWidth}};contextPrototype.clip=function(){};contextPrototype.arcTo=function(){};contextPrototype.createPattern=function(image,repetition){return new CanvasPattern_(image,repetition)};function CanvasGradient_(aType){this.type_=aType;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}CanvasGradient_.prototype.addColorStop=function(aOffset,
aColor){aColor=processStyle(aColor);this.colors_.push({offset:aOffset,color:aColor.color,alpha:aColor.alpha})};function CanvasPattern_(image,repetition){assertImageIsValid(image);switch(repetition){case "repeat":case null:case "":this.repetition_="repeat";break;case "repeat-x":case "repeat-y":case "no-repeat":this.repetition_=repetition;break;default:throwException("SYNTAX_ERR")}this.src_=image.src;this.width_=image.width;this.height_=image.height}function throwException(s){throw new DOMException_(s);
}function assertImageIsValid(img){if(!img||img.nodeType!=1||img.tagName!="IMG")throwException("TYPE_MISMATCH_ERR");if(img.readyState!="complete")throwException("INVALID_STATE_ERR")}function DOMException_(s){this.code=this[s];this.message=s+": DOM Exception "+this.code}var p=DOMException_.prototype=new Error;p.INDEX_SIZE_ERR=1;p.DOMSTRING_SIZE_ERR=2;p.HIERARCHY_REQUEST_ERR=3;p.WRONG_DOCUMENT_ERR=4;p.INVALID_CHARACTER_ERR=5;p.NO_DATA_ALLOWED_ERR=6;p.NO_MODIFICATION_ALLOWED_ERR=7;p.NOT_FOUND_ERR=8;p.NOT_SUPPORTED_ERR=
9;p.INUSE_ATTRIBUTE_ERR=10;p.INVALID_STATE_ERR=11;p.SYNTAX_ERR=12;p.INVALID_MODIFICATION_ERR=13;p.NAMESPACE_ERR=14;p.INVALID_ACCESS_ERR=15;p.VALIDATION_ERR=16;p.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=G_vmlCanvasManager_;CanvasRenderingContext2D=CanvasRenderingContext2D_;CanvasGradient=CanvasGradient_;CanvasPattern=CanvasPattern_;DOMException=DOMException_})();

@ -0,0 +1,22 @@
var gadgetConfig = {
"id": "TemperatureChart",
"title": "TemperatureChart",
"datasource": "org.wso2.iot.devices.temperature:1.0.0",
"type": "realtime",
"columns": [
{"name": "TIMESTAMP", "type": "time"},
{"name": "owner", "type": "string"},
{"name": "deviceType", "type": "string"},
{"name": "deviceId", "type": "string"},
{"name": "time", "type": "long"},
{"name": "temperature", "type": "float"}
],
"chartConfig": {
"x": "TIMESTAMP",
"maxLength": "10",
"padding": {"top": 30, "left": 45, "bottom": 38, "right": 55},
"charts": [{"type": "line", "y": "temperature"}]
},
"domain": "carbon.super",
"params": ["owner", "deviceId"]
};

@ -0,0 +1,568 @@
var datasource, type, columns, filter, maxUpdateValue, paramsToFilterBy;
var REFRESH_INTERVAL = 5000;
//this needs to be loaded from an autogenerated
datasource = gadgetConfig.datasource;
filter = gadgetConfig.filter;
type = gadgetConfig.type;
maxUpdateValue = gadgetConfig.maxUpdateValue;
columns = gadgetConfig.columns;
paramsToFilterBy = gadgetConfig.params;
var counter = 0;
var TYPE_GET_BY_RANGE = 8;
var TYPE_SEARCH = 13;
var TYPE_SEARCH_COUNT = 14;
var TIME_FROM_STRING = "timeFrom";
var TIME_TO_STRING = "timeTo";
var UNIX_TIME_MAX_VALUE = "9007199254740992";
var UNIX_TIME_MIN_VALUE = "-9007199254740992";
var META_TAG = "meta_";
var initialConfig, urlQueryParams, queryParamValPair, queryString;
var dataTable, chart;
executeDataFetchForGadget();
/**
* The main execution logic of the gadget is implemented in this function.
*/
function executeDataFetchForGadget() {
var urlQueryString;
// fetch all queryParams from the URL.
urlQueryParams = getAllQueryParamsFromURL();
// check if params config exists in the gadgetConf.
if (typeof paramsToFilterBy != "undefined" && paramsToFilterBy.length != 0) {
if (urlQueryParams != null) {
// get the values corresponding to the query "params" given in the gadgetConf
queryParamValPair = getValuesOfQueryFilter();
// if at-least one of the given params in the conf are missing from the URL params then returns null.
if (queryParamValPair == null) {
console.log("Incomplete set of Query Params were found in the URL.");
return;
}
// construct the Lucene query string based on the params given in the gadget-conf
// and the values parsed from the URL Query String.
queryString = constructQueryString();
switch (type) {
case "realtime":
urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
//subscribe to websocket
subscribe(
datasource.split(":")[0], datasource.split(":")[1], '10', gadgetConfig.domain,
onRealTimeEventSuccessRecieval, onRealTimeEventErrorRecieval,
location.hostname, location.port, 'WEBSOCKET', "SECURED", urlQueryString);
break;
case "batch":
//load data immediately
fetchDataOnQuery(fetchDataWithCount);
// then start periodic polling
setInterval(function () {
fetchDataOnQuery(fetchDataWithCount);
}, REFRESH_INTERVAL);
break;
}
} else {
// if there are NO queryParams in the URL then exit.
console.log("No Query Params were found in the URL to match the given filter-parameters.");
}
} else {
// if no params to filter by are given in the gadget-conf, then fetch all info available
// based on date range(if given).
switch (type) {
case "realtime":
urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
//subscribe to websocket
subscribe(datasource.split(":")[0], datasource.split(":")[1], '10', gadgetConfig.domain,
onRealTimeEventSuccessRecieval, onRealTimeEventErrorRecieval, location.hostname, location.port,
'WEBSOCKET', "SECURED", urlQueryString);
break;
case "batch":
//load data immediately
fetchDataWithoutQuery(drawBatchChart);
// then start periodic polling
setInterval(function () {
fetchDataWithoutQuery(drawBatchChart);
}, REFRESH_INTERVAL);
break;
}
}
}
/**
* Reads the page's URL Query-Params and returns them as an associative array.
* @returns {*} an associative array containing the URL QueryParams and corresponding values.
* If no such Query-Params exists then returns null.
*/
function getAllQueryParamsFromURL() {
var queryParamList = [], qParam;
var urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
if (urlQueryString) {
var queryStringPairs = urlQueryString.split('&');
for (var i = 0; i < queryStringPairs.length; i++) {
qParam = queryStringPairs[i].split('=');
queryParamList[qParam[0]] = qParam[1];
}
return queryParamList;
} else {
return null;
}
}
/**
* Retrieves the values from the URL-QueryString corresponding to the given QueryParams in the gadget-conf file.
* The parameters "timeTo" & "timeFrom" (if found in the query string) are added to the returned object regardless
* of whether they are listed in the gadget-conf.
* @returns {*} an associative array of the given params in the conf and corresponding value fetched from the
* URL string.
*/
function getValuesOfQueryFilter() {
var queryValues = [];
if (TIME_FROM_STRING in urlQueryParams) {
queryValues[TIME_FROM_STRING] = urlQueryParams[TIME_FROM_STRING];
}
if (TIME_TO_STRING in urlQueryParams) {
queryValues[TIME_TO_STRING] = urlQueryParams[TIME_TO_STRING];
}
for (var i = 0; i < paramsToFilterBy.length; i++) {
var queryV = urlQueryParams[paramsToFilterBy[i]];
// if atleast one of the queryParams given in the gadgetConf is missing then return "null".
if (typeof queryV != "undefined" && queryV != null && queryV != "") {
queryValues[paramsToFilterBy[i]] = queryV;
} else {
return null;
}
}
return queryValues;
}
/**
* Constructs the Lucene Query String to be sent to DAS API.
* @returns {string} a fully constructed query string from the params given in gadget-conf and
* the query string of the URL.
*/
function constructQueryString() {
var queryString = "'";
for (var a = 0; a < paramsToFilterBy.length; a++) {
if (queryString.length == 1) {
queryString += META_TAG + paramsToFilterBy[a] + ":" + queryParamValPair[paramsToFilterBy[a]];
} else {
queryString += " AND " + META_TAG + paramsToFilterBy[a] + ":" + queryParamValPair[paramsToFilterBy[a]];
}
}
if (TIME_FROM_STRING in queryParamValPair && TIME_TO_STRING in queryParamValPair) {
// both ends of the time-range (From What Date - To What Date) is given
queryString += " AND " + META_TAG + "time:" +
"[" + queryParamValPair[TIME_FROM_STRING] + " TO " + queryParamValPair[TIME_TO_STRING] + "]";
} else if (TIME_FROM_STRING in queryParamValPair && !(TIME_TO_STRING in queryParamValPair)) {
// Only the start of the time-range (From What Date) is given
queryString += " AND " + META_TAG + "time:" +
"[" + queryParamValPair[TIME_FROM_STRING] + " TO " + UNIX_TIME_MAX_VALUE + "]";
} else if (!(TIME_FROM_STRING in queryParamValPair) && TIME_TO_STRING in queryParamValPair) {
// Only the end of the time-range (To What Date) is given
queryString += " AND " + META_TAG + "time:" +
"[" + UNIX_TIME_MIN_VALUE + " TO " + queryParamValPair[TIME_TO_STRING] + "]";
}
//queryString += " AND meta_time:[1456467843079 TO 1456468494817]'";
queryString += "'";
return queryString;
}
/**
* Utility method to fetch columns of the datasource provided for a Batch-Type Gadget.
* @param table the name of the datasource table whose columns needs to be extracted.
*/
function getColumns(table) {
console.log("Fetching table schema for table: " + table);
var url = "/portal/apis/analytics?type=10&tableName=" + table;
$.getJSON(url, function (data) {
if (data) {
columns = parseColumns(JSON.parse(data.message));
}
});
}
/** Constructs an associative array containing the columns and the corresponding data-type ("String", "Long", etc)
* from the returned object as a result of the "getColumns" method above.
* @param data the response object returned from the "getColumns(table)" call to the DAS API.
* @returns {Array|*} an array containing the column names as keys and their type as values.
*/
function parseColumns(data) {
if (data.columns) {
var keys = Object.getOwnPropertyNames(data.columns);
columns = keys.map(function (key, i) {
return column = {
name: key,
type: data.columns[key].type
};
});
return columns;
}
}
/**
* Makes the initial call to the DAS APIs to get the count of all matching indexes based on a given query.
* Upon receiving a response (count), a subsequent method is called to fetch the given "count" amount of data from
* DAS that matches the query.
* @param callback the subsequent method to be called using the "count" response value received from the API call.
*/
function fetchDataOnQuery(callback) {
var request = {
type: TYPE_SEARCH_COUNT, // DAS API type corresponding to fetching data-count for "query"
tableName: datasource,
query: queryString
};
$.ajax({
url: "/portal/apis/analytics",
method: "GET",
data: request,
contentType: "application/json",
success: function (data) {
if (callback != null) {
callback(drawBatchChart, data.message);
}
}
});
}
/**
* Makes an API call to the DAS to fetch the "count" number of data matching the queryString constructed from the
* query-string and the param-list provided in the gadget-conf. The fetched data are passed into the provided
* "callback" method which further processes and draws the chart against this data.
* @param callback the method to which the fetched data are to be passed in for further processing.
* @param totalCount the count of all matching data available against the queryString.
*/
function fetchDataWithCount(callback, totalCount) {
var timeFrom = "undefined";
var timeTo = "undefined";
var request = {
type: TYPE_SEARCH, // DAS API type corresponding to fetching data for "query"
tableName: datasource,
filter: filter,
query: queryString,
timeFrom: timeFrom,
timeTo: timeTo,
start: 0,
count: totalCount
};
$.ajax({
url: "/portal/apis/analytics",
method: "GET",
data: request,
contentType: "application/json",
success: function (data) {
if (callback != null) {
var sortedData = sortData(data.message);
callback(makeRows(sortedData));
}
}
});
}
/**
* Retrieves all data available in a datasource irrespective of any query filters. However, the API call incorporates
* a data range to be submitted whilst fetching this info. If such date range related query strings
* ("timeFrom" or "timeTo") are found in the URL, then they are used.
* @param callback the method to which the fetched data are to be passed in for further processing.
*/
function fetchDataWithoutQuery(callback) {
var timeFrom = "undefined";
var timeTo = "undefined";
if (urlQueryParams != null) {
if (TIME_FROM_STRING in urlQueryParams) {
timeFrom = urlQueryParams[TIME_FROM_STRING];
}
if (TIME_TO_STRING in urlQueryParams) {
timeTo = urlQueryParams[TIME_TO_STRING];
}
}
var request = {
type: TYPE_GET_BY_RANGE, // DAS API type corresponding to fetching data by date range.
tableName: datasource,
timeFrom: timeFrom,
timeTo: timeTo,
start: 0
};
$.ajax({
url: "/portal/apis/analytics",
method: "GET",
data: request,
contentType: "application/json",
success: function (data) {
if (callback != null) {
callback(makeRows(JSON.parse(data.message)));
}
}
});
}
/**
* This is a utility method to convert Unix-Timestamp values to Epoch Time
* @param unix_timestamp the unix time to be converted
* @returns {string} the formatted epoch-time of the given unix-timestamp
*/
function convertToEpoch(unix_timestamp) {
// Create a new JavaScript Date object based on the timestamp
// multiplied by 1000 so that the argument is in milliseconds, not seconds.
var date = new Date(unix_timestamp * 1000);
// Hours part from the timestamp
var hours = date.getHours();
// Minutes part from the timestamp
var minutes = "0" + date.getMinutes();
// Seconds part from the timestamp
var seconds = "0" + date.getSeconds();
var thisDate = date.getDate();
var thisMonth = date.getMonth();
var thisYear = date.getUTCFullYear();
var formattedTime = hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
// Will display time in 10:30:23 format
return (formattedTime);
}
/**
* Sorts the given data array according to the values of its "timestamp" key.
* @param payload a JSON string with multiple data-arrays having a "timestamp" key-value pair.
* @returns {*} JSON Object with multiple sorted by "timestamp"
*/
function sortData(payload) {
var dataFromDAS = JSON.parse(payload);
sortedData = dataFromDAS.sort(function (a, b) {
return a.timestamp - b.timestamp;
});
return sortedData;
}
/**
* Fetches the values corresponding to the keys in the "columns" (either provided in the gadget-conf or fetched via the
* "getColumns(table)" method) array from the data object passed in.
* @param data a JSON Object containing multiple data values fetched from the datasource with column-name:value pairs.
* @returns {Array} an array with objects that contain the columns from the fetched "columns" and their corresponding
* values.
*/
function makeRows(data) {
var rows = [];
for (var i = 0; i < data.length; i++) {
var record = data[i];
var keys = Object.getOwnPropertyNames(record.values);
keys.push();
var row = columns.map(function (column, i) {
var colName = column.name;
var recordVal = record.values[colName];
if (typeof recordVal == 'undefined') {
if (column.name.toUpperCase() === "TIMESTAMP" && (record.timestamp || record.TIMESTAMP)) {
recordVal = record.timestamp;
} else {
recordVal = record.values[META_TAG + colName];
}
}
return recordVal;
});
rows.push(row);
}
return rows;
}
function makeDataTable(data) {
var dataTable = new igviz.DataTable();
if (columns.length > 0) {
columns.forEach(function (column, i) {
var type = "N";
if (column.type == "STRING" || column.type == "string") {
type = "C";
} else if (column.type == "TIME" || column.type == "time") {
type = "T";
}
dataTable.addColumn(column.name, type);
});
}
data.forEach(function (row, index) {
for (var i = 0; i < row.length; i++) {
if (dataTable.metadata.types[i] == "N") {
data[index][i] = parseInt(data[index][i]);
}
}
});
dataTable.addRows(data);
return dataTable;
}
function drawChart(data) {
var dataTable = makeDataTable(data);
gadgetConfig.chartConfig.width = $("#placeholder").width();
gadgetConfig.chartConfig.height = $("#placeholder").height() - 65;
var chartType = gadgetConfig.chartConfig.chartType;
var xAxis = gadgetConfig.chartConfig.xAxis;
jQuery("#noChart").html("");
if (chartType === "bar" && dataTable.metadata.types[xAxis] === "N") {
dataTable.metadata.types[xAxis] = "C";
}
if (gadgetConfig.chartConfig.chartType === "table" || gadgetConfig.chartConfig.chartType === "singleNumber") {
gadgetConfig.chartConfig.height = $("#placeholder").height();
chart = igviz.draw("#placeholder", gadgetConfig.chartConfig, dataTable);
chart.plot(dataTable.data);
} else {
chart = igviz.setUp("#placeholder", gadgetConfig.chartConfig, dataTable);
chart.setXAxis({
"labelAngle": -35,
"labelAlign": "right",
"labelDy": 0,
"labelDx": 0,
"titleDy": 25
})
.setYAxis({
"titleDy": -30
});
chart.plot(dataTable.data);
}
}
//stuff required for realtime charting
function onRealTimeEventSuccessRecieval(streamId, data) {
drawRealtimeChart(data);
}
function onRealTimeEventErrorRecieval(dataError) {
console.log("Error occurred " + dataError);
}
/**
* Draws the real-time chart based on the values in the data object passed in.
* @param data an object containing all the column:value pair data
*/
function drawRealtimeChart(data) {
if (chart == null) {
jQuery("#noChart").html("");
gadgetConfig.chartConfig.width = $("#placeholder").width() - 110;
gadgetConfig.chartConfig.height = $("#placeholder").height() - 40;
if (gadgetConfig.chartConfig.charts[0].type == "map") {
var mapType = gadgetConfig.chartConfig.charts[0].mapType;
if (mapType == "world") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/countryInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/world/';
} else if (mapType == "usa") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/usaInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/usa/';
} else if (mapType == "europe") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/countryInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/europe/';
}
}
chart = new vizg(createDataTable(convertData(data)), gadgetConfig.chartConfig);
chart.draw("#placeholder");
} else {
chart.insert(convertData(data));
}
}
/**
* Draws the batch-chart based on the values in the data object passed in.
* @param data an object containing all the column:value pair data
*/
function drawBatchChart(data) {
if (chart == null) {
jQuery("#noChart").html("");
gadgetConfig.chartConfig.width = $("#placeholder").width() - 110;
gadgetConfig.chartConfig.height = $("#placeholder").height() - 40;
if (gadgetConfig.chartConfig.charts[0].type == "map") {
var mapType = gadgetConfig.chartConfig.charts[0].mapType;
if (mapType == "world") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/countryInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/world/';
} else if (mapType == "usa") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/usaInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/usa/';
} else if (mapType == "europe") {
gadgetConfig.chartConfig.helperUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/countryInfo/';
gadgetConfig.chartConfig.geoCodesUrl = document.location.protocol + "//" + document.location.host + '/portal/geojson/europe/';
}
}
initialConfig = JSON.parse(JSON.stringify(gadgetConfig.chartConfig));
} else {
gadgetConfig.chartConfig = initialConfig;
initialConfig = JSON.parse(JSON.stringify(gadgetConfig.chartConfig));
}
chart = new vizg(createDataTable(convertData(data)), gadgetConfig.chartConfig);
chart.draw("#placeholder");
}
function convertData(data) {
for (var i = 0; i < data.length; i++) {
for (var x = 0; x < data[i].length; x++) {
var type = gadgetConfig.columns[x]["type"].toUpperCase();
if (type != "STRING" && type != "BOOLEAN") {
data[i][x] = parseFloat(data[i][x]);
}
}
}
return data;
}
function createDataTable(data) {
var names = [];
var types = [];
for (var i = 0; i < gadgetConfig.columns.length; i++) {
var name = gadgetConfig.columns[i]["name"];
names.push(name);
var type = columns[i]["type"].toUpperCase();
if (type === "INT" || type === "INTEGER" || type === "FLOAT" || type === "DOUBLE") {
type = "linear";
} else if (gadgetConfig.columns[i]["type"].toUpperCase() == "TIME" || name.toUpperCase() == "TIME") {
type = "time";
} else {
type = "ordinal";
}
types.push(type);
}
datatable = [
{
"metadata": {
"names": names,
"types": types
},
"data": data
}
];
return datatable;
}

@ -0,0 +1,285 @@
/*
*
*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
*/
var CONSTANTS = {
webAppName: 'outputui',
urlSeperator: '/',
urlGetParameter : '?lastUpdatedTime=',
urlQueryStringBegin : '?',
tenantUrlAttribute: 't',
urlUnsecureTransportHttp : 'http://',
urlUnsecureTransportWebsocket : 'ws://',
urlSecureTransportWebsocket : 'wss://',
urlSecureTransportHttp : 'https://',
colon : ':',
defaultIntervalTime : 10 * 1000,
defaultUserDomain : 'carbon.super',
defaultHostName : 'localhost',
defaultNonsecurePortNumber : '9763',
defaultSecurePortNumber : '9443',
defaultMode : 'AUTO',
processModeHTTP : 'HTTP',
processModeWebSocket : 'WEBSOCKET',
processModeAuto : 'AUTO',
domain : 'carbon.super',
numThousand : 1000,
websocketTimeAppender : 400,
secureMode : 'SECURED'
};
var websocket = null;
var webSocketUrl;
var httpUrl;
var cepHostName;
var cepPortNumber;
var isErrorOccured = false;
var lastUpdatedtime = -1;
var polingInterval;
var stream;
var streamVersion;
var firstPollingAttempt;
var processMode;
var onSuccessFunction;
var onErrorFunction;
var userDomainUrl = "";
var terminateWebsocketInstance = false;
var pollingContinue = true;
var transportToBeUsedHttp;
var transportToBeUsedWebsocket;
function subscribe(streamName,version,intervalTime,domain,
listeningFuncSuccessData,listeningFuncErrorData,
cepHost,cepPort,mode,secureMode, queryParams){
stopPollingProcesses();
stream = streamName;
streamVersion = version;
onSuccessFunction = listeningFuncSuccessData;
onErrorFunction = listeningFuncErrorData;
if(secureMode == CONSTANTS.secureMode){
transportToBeUsedHttp = CONSTANTS.urlSecureTransportHttp;
transportToBeUsedWebsocket = CONSTANTS.urlSecureTransportWebsocket;
} else {
transportToBeUsedHttp = CONSTANTS.urlUnsecureTransportHttp;
transportToBeUsedWebsocket = CONSTANTS.urlUnsecureTransportWebsocket;
}
if(intervalTime == null || intervalTime == ""){
polingInterval = CONSTANTS.defaultIntervalTime;
} else{
polingInterval = intervalTime * CONSTANTS.numThousand;
}
if(domain == null || domain == ""){
domain = CONSTANTS.defaultUserDomain;
}
if(cepHost == null || cepHost == ""){
cepHostName = CONSTANTS.defaultHostName;
} else{
cepHostName = cepHost;
}
if(cepPort == null || cepPort == ""){
if(secureMode == CONSTANTS.secureMode){
cepPortNumber = CONSTANTS.defaultSecurePortNumber;
} else{
cepPortNumber = CONSTANTS.defaultNonsecurePortNumber;
}
} else{
cepPortNumber = cepPort;
}
if(mode == null || mode == ""){
processMode = CONSTANTS.defaultMode;
} else{
processMode = mode;
}
if(domain != CONSTANTS.domain){
userDomainUrl = CONSTANTS.tenantUrlAttribute + CONSTANTS.urlSeperator + domain + CONSTANTS.urlSeperator;
}
if (queryParams == null) {
queryParams = "";
} else if (queryParams != "") {
queryParams = CONSTANTS.urlQueryStringBegin + queryParams;
}
webSocketUrl = transportToBeUsedWebsocket + cepHostName + CONSTANTS.colon + cepPortNumber +
CONSTANTS.urlSeperator + CONSTANTS.webAppName+ CONSTANTS.urlSeperator + userDomainUrl + stream +
CONSTANTS.urlSeperator + streamVersion + queryParams;
if(processMode == CONSTANTS.processModeHTTP){
firstPollingAttempt = true;
pollingContinue = true;
startPoll();
} else{
initializeWebSocket(webSocketUrl);
}
}
/**
* Initializing Web Socket
*/
function initializeWebSocket(webSocketUrl){
websocket = new WebSocket(webSocketUrl);
websocket.onopen = webSocketOnOpen;
websocket.onmessage = webSocketOnMessage;
websocket.onclose = webSocketOnClose;
websocket.onerror = webSocketOnError;
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
// alert("Successfully connected to "+webSocketUrl);
//onErrorFunction("Successfully connected to URL:" + webSocketUrl + "\n");
};
/**
* On server sends a message
*/
var webSocketOnMessage = function (evt) {
var event = evt.data;
var array = JSON.parse(event);
constructPayload(array);
};
/**
* On server close
*/
var webSocketOnClose =function (e) {
if(isErrorOccured){
if(processMode != CONSTANTS.processModeWebSocket){
firstPollingAttempt = true;
pollingContinue = true;
startPoll();
}
} else{
if(!terminateWebsocketInstance){
waitForSocketConnection(websocket);
} else{
terminateWebsocketInstance = false;
}
}
};
/**
* On server Error
*/
var webSocketOnError = function (err) {
var error = "Error: Cannot connect to Websocket URL:" + webSocketUrl + " .Hence closing the connection!";
onErrorFunction(error);
isErrorOccured = true;
};
/**
* Gracefully increments the connection retry
*/
var waitTime = CONSTANTS.numThousand;
function waitForSocketConnection(socket, callback){
setTimeout(
function () {
if (socket.readyState === 1) {
initializeWebSocket(webSocketUrl);
console.log("Connection is made");
if(callback != null){
callback();
}
return;
} else {
websocket = new WebSocket(webSocketUrl);
waitTime += CONSTANTS.websocketTimeAppender;
waitForSocketConnection(websocket, callback);
}
}, waitTime);
}
/**
* Polling to retrieve events from http request periodically
*/
function startPoll(){
(function poll(){
setTimeout(function(){
httpUrl = transportToBeUsedHttp + cepHostName + CONSTANTS.colon + cepPortNumber + CONSTANTS.urlSeperator
+ CONSTANTS.webAppName + CONSTANTS.urlSeperator + userDomainUrl + stream + CONSTANTS.urlSeperator +
streamVersion + CONSTANTS.urlGetParameter + lastUpdatedtime;
$.getJSON(httpUrl, function(responseText) {
if(firstPollingAttempt){
/*var data = $("textarea#idConsole").val();
$("textarea#idConsole").val(data + "Successfully connected to HTTP.");*/
firstPollingAttempt = false;
}
var eventList = $.parseJSON(responseText.events);
if(eventList.length != 0){
lastUpdatedtime = responseText.lastEventTime;
for(var i=0;i<eventList.length;i++){
var arr = eventList[i];
constructPayload(arr);
}
}
if(pollingContinue){
startPoll();
}
})
.fail(function(errorData) {
var errorData = JSON.parse(errorData.responseText);
onErrorFunction(errorData.error);
});
}, polingInterval);
})()
}
function stopPollingProcesses(){
//stopping the Websocket
if(websocket != null){
terminateWebsocketInstance = true;
websocket.onclose;
}
//stopping the HTTPS Request
pollingContinue = false;
}
function constructPayload(eventsArray){
var streamId = stream + CONSTANTS.colon + streamVersion;
var twoDimentionalArray = [eventsArray];
onSuccessFunction(streamId,twoDimentionalArray);
}

@ -0,0 +1,534 @@
!function() {
var topojson = {
version: "1.6.19",
mesh: function(topology) { return object(topology, meshArcs.apply(this, arguments)); },
meshArcs: meshArcs,
merge: function(topology) { return object(topology, mergeArcs.apply(this, arguments)); },
mergeArcs: mergeArcs,
feature: featureOrCollection,
neighbors: neighbors,
presimplify: presimplify
};
function stitchArcs(topology, arcs) {
var stitchedArcs = {},
fragmentByStart = {},
fragmentByEnd = {},
fragments = [],
emptyIndex = -1;
// Stitch empty arcs first, since they may be subsumed by other arcs.
arcs.forEach(function(i, j) {
var arc = topology.arcs[i < 0 ? ~i : i], t;
if (arc.length < 3 && !arc[1][0] && !arc[1][1]) {
t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t;
}
});
arcs.forEach(function(i) {
var e = ends(i),
start = e[0],
end = e[1],
f, g;
if (f = fragmentByEnd[start]) {
delete fragmentByEnd[f.end];
f.push(i);
f.end = end;
if (g = fragmentByStart[end]) {
delete fragmentByStart[g.start];
var fg = g === f ? f : f.concat(g);
fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg;
} else {
fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
}
} else if (f = fragmentByStart[end]) {
delete fragmentByStart[f.start];
f.unshift(i);
f.start = start;
if (g = fragmentByEnd[start]) {
delete fragmentByEnd[g.end];
var gf = g === f ? f : g.concat(f);
fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf;
} else {
fragmentByStart[f.start] = fragmentByEnd[f.end] = f;
}
} else {
f = [i];
fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f;
}
});
function ends(i) {
var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1;
if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; });
else p1 = arc[arc.length - 1];
return i < 0 ? [p1, p0] : [p0, p1];
}
function flush(fragmentByEnd, fragmentByStart) {
for (var k in fragmentByEnd) {
var f = fragmentByEnd[k];
delete fragmentByStart[f.start];
delete f.start;
delete f.end;
f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; });
fragments.push(f);
}
}
flush(fragmentByEnd, fragmentByStart);
flush(fragmentByStart, fragmentByEnd);
arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); });
return fragments;
}
function meshArcs(topology, o, filter) {
var arcs = [];
if (arguments.length > 1) {
var geomsByArc = [],
geom;
function arc(i) {
var j = i < 0 ? ~i : i;
(geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom});
}
function line(arcs) {
arcs.forEach(arc);
}
function polygon(arcs) {
arcs.forEach(line);
}
function geometry(o) {
if (o.type === "GeometryCollection") o.geometries.forEach(geometry);
else if (o.type in geometryType) geom = o, geometryType[o.type](o.arcs);
}
var geometryType = {
LineString: line,
MultiLineString: polygon,
Polygon: polygon,
MultiPolygon: function(arcs) { arcs.forEach(polygon); }
};
geometry(o);
geomsByArc.forEach(arguments.length < 3
? function(geoms) { arcs.push(geoms[0].i); }
: function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); });
} else {
for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i);
}
return {type: "MultiLineString", arcs: stitchArcs(topology, arcs)};
}
function mergeArcs(topology, objects) {
var polygonsByArc = {},
polygons = [],
components = [];
objects.forEach(function(o) {
if (o.type === "Polygon") register(o.arcs);
else if (o.type === "MultiPolygon") o.arcs.forEach(register);
});
function register(polygon) {
polygon.forEach(function(ring) {
ring.forEach(function(arc) {
(polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon);
});
});
polygons.push(polygon);
}
function exterior(ring) {
return cartesianRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]) > 0; // TODO allow spherical?
}
polygons.forEach(function(polygon) {
if (!polygon._) {
var component = [],
neighbors = [polygon];
polygon._ = 1;
components.push(component);
while (polygon = neighbors.pop()) {
component.push(polygon);
polygon.forEach(function(ring) {
ring.forEach(function(arc) {
polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) {
if (!polygon._) {
polygon._ = 1;
neighbors.push(polygon);
}
});
});
});
}
}
});
polygons.forEach(function(polygon) {
delete polygon._;
});
return {
type: "MultiPolygon",
arcs: components.map(function(polygons) {
var arcs = [];
// Extract the exterior (unique) arcs.
polygons.forEach(function(polygon) {
polygon.forEach(function(ring) {
ring.forEach(function(arc) {
if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) {
arcs.push(arc);
}
});
});
});
// Stitch the arcs into one or more rings.
arcs = stitchArcs(topology, arcs);
// If more than one ring is returned,
// at most one of these rings can be the exterior;
// this exterior ring has the same winding order
// as any exterior ring in the original polygons.
if ((n = arcs.length) > 1) {
var sgn = exterior(polygons[0][0]);
for (var i = 0, t; i < n; ++i) {
if (sgn === exterior(arcs[i])) {
t = arcs[0], arcs[0] = arcs[i], arcs[i] = t;
break;
}
}
}
return arcs;
})
};
}
function featureOrCollection(topology, o) {
return o.type === "GeometryCollection" ? {
type: "FeatureCollection",
features: o.geometries.map(function(o) { return feature(topology, o); })
} : feature(topology, o);
}
function feature(topology, o) {
var f = {
type: "Feature",
id: o.id,
properties: o.properties || {},
geometry: object(topology, o)
};
if (o.id == null) delete f.id;
return f;
}
function object(topology, o) {
var absolute = transformAbsolute(topology.transform),
arcs = topology.arcs;
function arc(i, points) {
if (points.length) points.pop();
for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) {
points.push(p = a[k].slice());
absolute(p, k);
}
if (i < 0) reverse(points, n);
}
function point(p) {
p = p.slice();
absolute(p, 0);
return p;
}
function line(arcs) {
var points = [];
for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points);
if (points.length < 2) points.push(points[0].slice());
return points;
}
function ring(arcs) {
var points = line(arcs);
while (points.length < 4) points.push(points[0].slice());
return points;
}
function polygon(arcs) {
return arcs.map(ring);
}
function geometry(o) {
var t = o.type;
return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)}
: t in geometryType ? {type: t, coordinates: geometryType[t](o)}
: null;
}
var geometryType = {
Point: function(o) { return point(o.coordinates); },
MultiPoint: function(o) { return o.coordinates.map(point); },
LineString: function(o) { return line(o.arcs); },
MultiLineString: function(o) { return o.arcs.map(line); },
Polygon: function(o) { return polygon(o.arcs); },
MultiPolygon: function(o) { return o.arcs.map(polygon); }
};
return geometry(o);
}
function reverse(array, n) {
var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t;
}
function bisect(a, x) {
var lo = 0, hi = a.length;
while (lo < hi) {
var mid = lo + hi >>> 1;
if (a[mid] < x) lo = mid + 1;
else hi = mid;
}
return lo;
}
function neighbors(objects) {
var indexesByArc = {}, // arc index -> array of object indexes
neighbors = objects.map(function() { return []; });
function line(arcs, i) {
arcs.forEach(function(a) {
if (a < 0) a = ~a;
var o = indexesByArc[a];
if (o) o.push(i);
else indexesByArc[a] = [i];
});
}
function polygon(arcs, i) {
arcs.forEach(function(arc) { line(arc, i); });
}
function geometry(o, i) {
if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); });
else if (o.type in geometryType) geometryType[o.type](o.arcs, i);
}
var geometryType = {
LineString: line,
MultiLineString: polygon,
Polygon: polygon,
MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); }
};
objects.forEach(geometry);
for (var i in indexesByArc) {
for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) {
for (var k = j + 1; k < m; ++k) {
var ij = indexes[j], ik = indexes[k], n;
if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik);
if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij);
}
}
}
return neighbors;
}
function presimplify(topology, triangleArea) {
var absolute = transformAbsolute(topology.transform),
relative = transformRelative(topology.transform),
heap = minAreaHeap();
if (!triangleArea) triangleArea = cartesianTriangleArea;
topology.arcs.forEach(function(arc) {
var triangles = [],
maxArea = 0,
triangle;
// To store each points effective area, we create a new array rather than
// extending the passed-in point to workaround a Chrome/V8 bug (getting
// stuck in smi mode). For midpoints, the initial effective area of
// Infinity will be computed in the next step.
for (var i = 0, n = arc.length, p; i < n; ++i) {
p = arc[i];
absolute(arc[i] = [p[0], p[1], Infinity], i);
}
for (var i = 1, n = arc.length - 1; i < n; ++i) {
triangle = arc.slice(i - 1, i + 2);
triangle[1][2] = triangleArea(triangle);
triangles.push(triangle);
heap.push(triangle);
}
for (var i = 0, n = triangles.length; i < n; ++i) {
triangle = triangles[i];
triangle.previous = triangles[i - 1];
triangle.next = triangles[i + 1];
}
while (triangle = heap.pop()) {
var previous = triangle.previous,
next = triangle.next;
// If the area of the current point is less than that of the previous point
// to be eliminated, use the latter's area instead. This ensures that the
// current point cannot be eliminated without eliminating previously-
// eliminated points.
if (triangle[1][2] < maxArea) triangle[1][2] = maxArea;
else maxArea = triangle[1][2];
if (previous) {
previous.next = next;
previous[2] = triangle[2];
update(previous);
}
if (next) {
next.previous = previous;
next[0] = triangle[0];
update(next);
}
}
arc.forEach(relative);
});
function update(triangle) {
heap.remove(triangle);
triangle[1][2] = triangleArea(triangle);
heap.push(triangle);
}
return topology;
};
function cartesianRingArea(ring) {
var i = -1,
n = ring.length,
a,
b = ring[n - 1],
area = 0;
while (++i < n) {
a = b;
b = ring[i];
area += a[0] * b[1] - a[1] * b[0];
}
return area * .5;
}
function cartesianTriangleArea(triangle) {
var a = triangle[0], b = triangle[1], c = triangle[2];
return Math.abs((a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]));
}
function compareArea(a, b) {
return a[1][2] - b[1][2];
}
function minAreaHeap() {
var heap = {},
array = [],
size = 0;
heap.push = function(object) {
up(array[object._ = size] = object, size++);
return size;
};
heap.pop = function() {
if (size <= 0) return;
var removed = array[0], object;
if (--size > 0) object = array[size], down(array[object._ = 0] = object, 0);
return removed;
};
heap.remove = function(removed) {
var i = removed._, object;
if (array[i] !== removed) return; // invalid request
if (i !== --size) object = array[size], (compareArea(object, removed) < 0 ? up : down)(array[object._ = i] = object, i);
return i;
};
function up(object, i) {
while (i > 0) {
var j = ((i + 1) >> 1) - 1,
parent = array[j];
if (compareArea(object, parent) >= 0) break;
array[parent._ = i] = parent;
array[object._ = i = j] = object;
}
}
function down(object, i) {
while (true) {
var r = (i + 1) << 1,
l = r - 1,
j = i,
child = array[j];
if (l < size && compareArea(array[l], child) < 0) child = array[j = l];
if (r < size && compareArea(array[r], child) < 0) child = array[j = r];
if (j === i) break;
array[child._ = i] = child;
array[object._ = i = j] = object;
}
}
return heap;
}
function transformAbsolute(transform) {
if (!transform) return noop;
var x0,
y0,
kx = transform.scale[0],
ky = transform.scale[1],
dx = transform.translate[0],
dy = transform.translate[1];
return function(point, i) {
if (!i) x0 = y0 = 0;
point[0] = (x0 += point[0]) * kx + dx;
point[1] = (y0 += point[1]) * ky + dy;
};
}
function transformRelative(transform) {
if (!transform) return noop;
var x0,
y0,
kx = transform.scale[0],
ky = transform.scale[1],
dx = transform.translate[0],
dy = transform.translate[1];
return function(point, i) {
if (!i) x0 = y0 = 0;
var x1 = (point[0] - dx) / kx | 0,
y1 = (point[1] - dy) / ky | 0;
point[0] = x1 - x0;
point[1] = y1 - y0;
x0 = x1;
y0 = y1;
};
}
function noop() {}
if (typeof define === "function" && define.amd) define(topojson);
else if (typeof module === "object" && module.exports) module.exports = topojson;
else this.topojson = topojson;
}();

@ -0,0 +1,286 @@
/*
*
*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*
*/
var CONSTANTS = {
webAppName: 'outputui',
urlSeperator: '/',
urlGetParameter : '?lastUpdatedTime=',
urlQueryStringBegin : '?',
tenantUrlAttribute: 't',
urlUnsecureTransportHttp : 'http://',
urlUnsecureTransportWebsocket : 'ws://',
urlSecureTransportWebsocket : 'wss://',
urlSecureTransportHttp : 'https://',
colon : ':',
defaultIntervalTime : 10 * 1000,
defaultUserDomain : 'carbon.super',
defaultHostName : 'localhost',
defaultNonsecurePortNumber : '9763',
defaultSecurePortNumber : '9443',
defaultMode : 'AUTO',
processModeHTTP : 'HTTP',
processModeWebSocket : 'WEBSOCKET',
processModeAuto : 'AUTO',
domain : 'carbon.super',
numThousand : 1000,
websocketTimeAppender : 400,
secureMode : 'SECURED'
};
var websocket = null;
var webSocketUrl;
var httpUrl;
var cepHostName;
var cepPortNumber;
var isErrorOccured = false;
var lastUpdatedtime = -1;
var polingInterval;
var stream;
var streamVersion;
var firstPollingAttempt;
var processMode;
var onSuccessFunction;
var onErrorFunction;
var userDomainUrl = "";
var terminateWebsocketInstance = false;
var pollingContinue = true;
var transportToBeUsedHttp;
var transportToBeUsedWebsocket;
function subscribe(streamName,version,intervalTime,domain,
listeningFuncSuccessData,listeningFuncErrorData,
cepHost,cepPort,mode,secureMode, queryParams){
stopPollingProcesses();
stream = streamName;
streamVersion = version;
onSuccessFunction = listeningFuncSuccessData;
onErrorFunction = listeningFuncErrorData;
if(secureMode == CONSTANTS.secureMode){
transportToBeUsedHttp = CONSTANTS.urlSecureTransportHttp;
transportToBeUsedWebsocket = CONSTANTS.urlSecureTransportWebsocket;
} else {
transportToBeUsedHttp = CONSTANTS.urlUnsecureTransportHttp;
transportToBeUsedWebsocket = CONSTANTS.urlUnsecureTransportWebsocket;
}
if(intervalTime == null || intervalTime == ""){
polingInterval = CONSTANTS.defaultIntervalTime;
} else{
polingInterval = intervalTime * CONSTANTS.numThousand;
}
if(domain == null || domain == ""){
domain = CONSTANTS.defaultUserDomain;
}
if(cepHost == null || cepHost == ""){
cepHostName = CONSTANTS.defaultHostName;
} else{
cepHostName = cepHost;
}
if(cepPort == null || cepPort == ""){
if(secureMode == CONSTANTS.secureMode){
cepPortNumber = CONSTANTS.defaultSecurePortNumber;
} else{
cepPortNumber = CONSTANTS.defaultNonsecurePortNumber;
}
} else{
cepPortNumber = cepPort;
}
if(mode == null || mode == ""){
processMode = CONSTANTS.defaultMode;
} else{
processMode = mode;
}
if(domain != CONSTANTS.domain){
userDomainUrl = CONSTANTS.tenantUrlAttribute + CONSTANTS.urlSeperator + domain + CONSTANTS.urlSeperator;
}
if (queryParams == null) {
queryParams = "";
} else if (queryParams != "") {
queryParams = CONSTANTS.urlQueryStringBegin + queryParams;
}
webSocketUrl = transportToBeUsedWebsocket + cepHostName + CONSTANTS.colon + cepPortNumber +
CONSTANTS.urlSeperator + CONSTANTS.webAppName+ CONSTANTS.urlSeperator + userDomainUrl + stream +
CONSTANTS.urlSeperator + streamVersion + queryParams;
if(processMode == CONSTANTS.processModeHTTP){
firstPollingAttempt = true;
pollingContinue = true;
startPoll();
} else{
initializeWebSocket(webSocketUrl);
}
}
/**
* Initializing Web Socket
*/
function initializeWebSocket(webSocketUrl){
websocket = new WebSocket(webSocketUrl);
websocket.onopen = webSocketOnOpen;
websocket.onmessage = webSocketOnMessage;
websocket.onclose = webSocketOnClose;
websocket.onerror = webSocketOnError;
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
// alert("Successfully connected to "+webSocketUrl);
//onErrorFunction("Successfully connected to URL:" + webSocketUrl + "\n");
};
/**
* On server sends a message
*/
var webSocketOnMessage = function (evt) {
var event = evt.data;
var array = JSON.parse(event);
constructPayload(array);
};
/**
* On server close
*/
var webSocketOnClose =function (e) {
if(isErrorOccured){
if(processMode != CONSTANTS.processModeWebSocket){
firstPollingAttempt = true;
pollingContinue = true;
startPoll();
}
} else{
if(!terminateWebsocketInstance){
waitForSocketConnection(websocket);
} else{
terminateWebsocketInstance = false;
}
}
};
/**
* On server Error
*/
var webSocketOnError = function (err) {
var error = "Error: Cannot connect to Websocket URL:" + webSocketUrl + " .Hence closing the connection!";
onErrorFunction(error);
isErrorOccured = true;
};
/**
* Gracefully increments the connection retry
*/
var waitTime = CONSTANTS.numThousand;
function waitForSocketConnection(socket, callback){
setTimeout(
function () {
if (socket.readyState === 1) {
initializeWebSocket(webSocketUrl);
console.log("Connection is made");
if(callback != null){
callback();
}
return;
} else {
websocket = new WebSocket(webSocketUrl);
waitTime += CONSTANTS.websocketTimeAppender;
waitForSocketConnection(websocket, callback);
}
}, waitTime);
}
/**
* Polling to retrieve events from http request periodically
*/
function startPoll(){
(function poll(){
setTimeout(function(){
httpUrl = transportToBeUsedHttp + cepHostName + CONSTANTS.colon + cepPortNumber + CONSTANTS.urlSeperator
+ CONSTANTS.webAppName + CONSTANTS.urlSeperator + userDomainUrl + stream + CONSTANTS.urlSeperator +
streamVersion + CONSTANTS.urlGetParameter + lastUpdatedtime;
$.getJSON(httpUrl, function(responseText) {
if(firstPollingAttempt){
/*var data = $("textarea#idConsole").val();
$("textarea#idConsole").val(data + "Successfully connected to HTTP.");*/
firstPollingAttempt = false;
}
var eventList = $.parseJSON(responseText.events);
if(eventList.length != 0){
lastUpdatedtime = responseText.lastEventTime;
for(var i=0;i<eventList.length;i++){
var arr = eventList[i];
constructPayload(arr);
}
}
if(pollingContinue){
startPoll();
}
})
.fail(function(errorData) {
var errorData = JSON.parse(errorData.responseText);
onErrorFunction(errorData.error);
});
}, polingInterval);
})()
}
function stopPollingProcesses(){
//stopping the Websocket
if(websocket != null){
terminateWebsocketInstance = true;
websocket.onclose;
}
//stopping the HTTPS Request
pollingContinue = false;
}
function constructPayload(eventsArray){
var streamId = stream + CONSTANTS.colon + streamVersion;
var twoDimentionalArray = [eventsArray];
onSuccessFunction(streamId,twoDimentionalArray);
}

@ -738,7 +738,7 @@
org.wso2.carbon.analytics-common:org.wso2.carbon.event.publisher.feature:${carbon.analytics.common.version}
</featureArtifactDef>
<featureArtifactDef>
org.wso2.carbon.event-processing:org.wso2.carbon.event.processor.feature:${carbon.event-processing.version}
org.wso2.carbon.event-processing:org.wso2.carbon.event.processor.server.feature:${carbon.event-processing.version}
</featureArtifactDef>
<featureArtifactDef>
org.wso2.carbon.analytics-common:org.wso2.carbon.event.tracer.feature:${carbon.analytics.common.version}
@ -1617,7 +1617,7 @@
<version>${carbon.analytics.common.version}</version>
</feature>
<feature>
<id>org.wso2.carbon.event.processor.feature.group</id>
<id>org.wso2.carbon.event.processor.server.feature.group</id>
<version>${carbon.event-processing.version}</version>
</feature>
<feature>

@ -147,11 +147,13 @@ public class DoorManagerControllerService {
@FormParam("policy") String policy,
@FormParam("cardNumber") String cardNumber,
@FormParam("userName") String userName,
@FormParam("emailAddress") String emailAddress,
@Context HttpServletResponse response) {
try {
if (userName != null && cardNumber != null && deviceId != null) {
try {
UserStoreManager userStoreManager = this.getUserStoreManager();
DoorLockSafe doorLockSafe = new DoorLockSafe();
if (userStoreManager.isExistingUser(userName)) {
TokenClient accessTokenClient = new TokenClient(DoorManagerConstants.DEVICE_TYPE);
AccessTokenInfo accessTokenInfo = accessTokenClient.getAccessToken(deviceId, userName);
@ -165,7 +167,35 @@ public class DoorManagerControllerService {
claims.put("http://wso2.org/claims/lock/refreshtoken", accessTokenInfo.getRefresh_token());
claims.put("http://wso2.org/claims/lock/cardnumber", cardNumber);
userStoreManager.setUserClaimValues(userName, claims, null);
//TODO: Add content to dto
doorLockSafe.setAccessToken(accessTokenInfo.getAccess_token());
doorLockSafe.setRefreshToken(accessTokenInfo.getRefresh_token());
doorLockSafe.setDeviceId(deviceId);
doorLockSafe.setOwner(owner);
doorLockSafe.setEmailAddress(emailAddress);
doorLockSafe.setUIDofUser(cardNumber);
doorLockSafe.setPolicy(policy);
doorLockSafe.setSerialNumber(deviceId);
boolean status;
try {
DoorManagerDAO.beginTransaction();
status = DOOR_MANAGER_DAO.getAutomaticDoorLockerDeviceDAO().registerDoorLockSafe(doorLockSafe);
DoorManagerDAO.commitTransaction();
if (status) {
response.setStatus(Response.Status.OK.getStatusCode());
} else {
response.setStatus(Response.Status.FORBIDDEN.getStatusCode());
}
} catch (DoorManagerDeviceMgtPluginException e) {
try {
DoorManagerDAO.rollbackTransaction();
} catch (DoorManagerDeviceMgtPluginException e1) {
String msg = "Error while updating the enrollment of the Door Manager Locker device : "
+ doorLockSafe.getOwner();
response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
log.error(msg, e);
}
}
response.setStatus(Response.Status.OK.getStatusCode());
} else {
response.setStatus(Response.Status.NOT_FOUND.getStatusCode());
@ -184,7 +214,7 @@ public class DoorManagerControllerService {
}
}
@Path("controller/registerNewUser")
/* @Path("controller/registerNewUser")
@POST
@Feature(code = "registerNewUser", name = "Assign to new user", type = "operation",
description = "Assign to new user")
@ -241,7 +271,7 @@ public class DoorManagerControllerService {
response.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
log.error(e);
}
}
}*/
/*@Path("controller/registerNewUser")
@POST

@ -12,6 +12,7 @@ import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.transport.mqtt.MQTTTransportHandler;
import javax.ws.rs.core.Response;
import java.io.File;
import java.util.Calendar;
import java.util.UUID;
@ -80,12 +81,16 @@ public class DoorManagerMQTTConnector extends MQTTTransportHandler {
}
if (messageData.length == 2) {
log.warn("-------------------------------------------");
log.warn(messageData[2]);
log.warn(messageData[0]);
log.warn(messageData[1]);
String lockerCurrentState = messageData[1];
try {
SensorDataManager.getInstance().setSensorRecord(deviceId, "door_locker_state",
String.valueOf(1), Calendar.getInstance().getTimeInMillis());
if (!DoorManagerServiceUtils.publishToDASCurrent(owner, deviceId, 1)) {
log.warn("An error occured whilst trying to publish with ID [" + deviceId +
"] of owner [" + owner + "]");
}
} catch(Exception e){
log.error(e);
}
@ -110,6 +115,21 @@ public class DoorManagerMQTTConnector extends MQTTTransportHandler {
String payload = operation + param;
try {
publishToAutomaticDoorLocker(topic, payload, 2, false);
if(param.equals("LOCK")){
if (!DoorManagerServiceUtils.publishToDASCurrent(deviceOwner, deviceId, 0)) {
log.warn("An error occured whilst trying to publish with ID [" + deviceId +
"] of owner [" + deviceOwner + "]");
}
}else{
if (!DoorManagerServiceUtils.publishToDASCurrent(deviceOwner, deviceId, 1)) {
log.warn("An error occured whilst trying to publish with ID [" + deviceId +
"] of owner [" + deviceOwner + "]");
}
}
if (!DoorManagerServiceUtils.publishToDASCurrent(deviceOwner, deviceId, 1)) {
log.warn("An error occured whilst trying to publish with ID [" + deviceId +
"] of owner [" + deviceOwner + "]");
}
} catch (TransportHandlerException e) {
String errorMessage = "Error publishing data to device with ID " + deviceId;
throw new DoorManagerException(errorMessage, e);

@ -0,0 +1,54 @@
/*
* 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.
*/
package org.homeautomation.doormanager.controller.api.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.homeautomation.doormanager.plugin.constants.DoorManagerConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.analytics.exception.DataPublisherConfigurationException;
import org.wso2.carbon.device.mgt.analytics.service.DeviceAnalyticsService;
public class DoorManagerServiceUtils {
private static final Log log = LogFactory.getLog(DoorManagerServiceUtils.class);
//TODO; replace this tenant domain
private static final String SUPER_TENANT = "carbon.super";
private static final String CURRENT_STREAM_DEFINITION = "org.wso2.iot.devices.sensor";
public static boolean publishToDASCurrent(String owner, String deviceId, float current) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
ctx.setTenantDomain(SUPER_TENANT, true);
DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx.getOSGiService(
DeviceAnalyticsService.class, null);
Object metdaData[] = {owner, DoorManagerConstants.DEVICE_TYPE, deviceId, System.currentTimeMillis()};
Object payloadCurrent[] = {current};
try {
deviceAnalyticsService.publishEvent(CURRENT_STREAM_DEFINITION, "1.0.0", metdaData, new Object[0], payloadCurrent);
} catch (DataPublisherConfigurationException e) {
return false;
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
return true;
}
}

@ -228,5 +228,10 @@
<artifactId>json-simple</artifactId>
<version>1.1.wso2v1</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
</dependencies>
</project>

@ -18,9 +18,16 @@
package org.homeautomation.doormanager.manager.api;
import com.google.gson.JsonObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geronimo.mail.util.Base64;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.homeautomation.doormanager.manager.api.dto.UserInfo;
import org.homeautomation.doormanager.plugin.constants.DoorManagerConstants;
import org.homeautomation.doormanager.plugin.exception.DoorManagerDeviceMgtPluginException;
@ -54,6 +61,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.*;
@ -265,18 +273,22 @@ public class DoorManagerManagerService {
log.warn(userInfo.userName);
log.warn(userInfo.cardNumber);
log.warn(userInfo.deviceId);
response.addHeader("REMOTE_USER", "ppppppppppppppppppppp");
//response.addDateHeader("Authentication","55555555555555555555");
if (userInfo.userName != null && userInfo.cardNumber != null && userInfo.deviceId != null) {
try {
UserStoreManager userStoreManager = this.getUserStoreManager();
if (userStoreManager.isExistingUser(userInfo.userName)) {
String accessToken = userStoreManager.getUserClaimValue(userInfo.userName, "http://wso2.org/claims/lock/accesstoken", null);
String cardNumber = userStoreManager.getUserClaimValue(userInfo.userName, "http://wso2.org/claims/lock/cardnumber", null);
log.warn(accessToken);
log.warn(cardNumber);
if(cardNumber.equals(userInfo.cardNumber)){
if(accessToken != null){
if(accessToken != null && doorManagerDAO.getAutomaticDoorLockerDeviceDAO().
checkCardDoorAssociation(cardNumber, userInfo.deviceId)){
JSONObject credentials = new JSONObject();
credentials.put(DoorManagerConstants.DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN, accessToken);
credentials.put(DoorManagerConstants.DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN, accessToken);
sendCEPEvent(userInfo.deviceId, cardNumber, true);
log.warn(doorManagerDAO.getAutomaticDoorLockerDeviceDAO().getUserEmailAddress(cardNumber));
return Response.ok(credentials, MediaType.APPLICATION_JSON_TYPE).build();
}
}
@ -299,6 +311,39 @@ public class DoorManagerManagerService {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
private void sendCEPEvent(String deviceId, String cardId, boolean accessStatus){
String cepEventReciever = "http://localhost:9768/endpoints/LockEventReciever";
HttpClient httpClient = new SystemDefaultHttpClient();
HttpPost method = new HttpPost(cepEventReciever);
JsonObject event = new JsonObject();
JsonObject metaData = new JsonObject();
metaData.addProperty("deviceID", deviceId);
metaData.addProperty("cardID", cardId);
event.add("metaData", metaData);
String eventString = "{\"event\": " + event + "}";
try {
StringEntity entity = new StringEntity(eventString);
method.setEntity(entity);
if (cepEventReciever.startsWith("https")) {
method.setHeader("Authorization", "Basic " + Base64.encode(("admin" + ":" + "admin").getBytes()));
}
httpClient.execute(method).getEntity().getContent().close();
} catch (UnsupportedEncodingException e) {
log.error("Error while constituting CEP event"+ e.getMessage());
} catch (ClientProtocolException e) {
log.error("Error while sending message to CEP "+ e.getMessage());
} catch (IOException e) {
log.error("Error while sending message to CEP "+ e.getMessage());
}
}
@POST
@Path("manager/get_user_info")
@Produces(MediaType.APPLICATION_JSON)

@ -261,6 +261,56 @@ public class DoorManagerDAOImpl {
return status;
}
public boolean checkCardDoorAssociation(String cardNum, String deviceID) throws DoorManagerDeviceMgtPluginException {
Connection conn;
PreparedStatement stmt = null;
ResultSet resultSet = null;
try {
conn = DoorManagerDAO.getConnection();
String selectDBQuery = "SELECT * FROM REGISTERED_DOORLOCK_SAFE WHERE UID_of_USER = ? AND doormanager_DEVICE_ID = ?";
stmt = conn.prepareStatement(selectDBQuery);
stmt.setString(1, cardNum);
stmt.setString(2, deviceID);
resultSet = stmt.executeQuery();
String result;
if(resultSet.next()){
return true;
}else{
return false;
}
} catch (SQLException e) {
String msg = "No associations were found between lock : "+ deviceID +" and card : "+ cardNum;
throw new DoorManagerDeviceMgtPluginException(msg, e);
} finally {
DoorManagerUtils.cleanupResources(stmt, null);
}
}
public String getUserEmailAddress(String cardNum) throws DoorManagerDeviceMgtPluginException {
Connection conn;
PreparedStatement stmt = null;
ResultSet resultSet = null;
String email;
try {
conn = DoorManagerDAO.getConnection();
String selectDBQuery = "SELECT EMAIL_ADDRESS FROM REGISTERED_DOORLOCK_SAFE WHERE UID_of_USER = ?";
stmt = conn.prepareStatement(selectDBQuery);
stmt.setString(1, cardNum);
resultSet = stmt.executeQuery();
if(resultSet.next()){
email = resultSet.getString("EMAIL_ADDRESS");
log.warn(email);
return email;
}
return null;
} catch (SQLException e) {
String msg = "No email found for the and card : "+ cardNum;
throw new DoorManagerDeviceMgtPluginException(msg, e);
} finally {
DoorManagerUtils.cleanupResources(stmt, null);
}
}
public List<String> getUserCredentials(String deviceId, String UIDofUser) throws DoorManagerDeviceMgtPluginException {
Connection conn = null;

@ -25,7 +25,7 @@
{{/zone}}
{{#zone "device-thumbnail"}}
<img src="{{@unit.publicUri}}/images/current-sensor.png"/>
<img src="{{@unit.publicUri}}/images/doormanager-icon.png"/>
{{/zone}}
{{#zone "operation-status"}}

@ -4,7 +4,7 @@
</div>
<div class="col-xs-12 col-sm-4 col-md-4 col-lg-4 padding-top">
<img src="{{@unit.publicUri}}/images/doorManager-icon.png" class="img-responsive">
<img src="{{@unit.publicUri}}/images/doormanager-icon.png" class="img-responsive">
</div>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-8 padding-top">

@ -140,6 +140,11 @@
<version>4.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
</dependencies>
</dependencyManagement>
<pluginRepositories>
@ -254,4 +259,4 @@
<maven-antrun-plugin.version>1.8</maven-antrun-plugin.version>
<maven-scr-plugin.version>1.7.2</maven-scr-plugin.version>
</properties>
</project>
</project>

@ -0,0 +1,40 @@
<?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 name="create-sample-sensor-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="temperature_dir" value="Temperature_Sensor"/>
<property name="humidity_dir" value="Humidity_Sensor"/>
<target name="clean">
<delete dir="${target-dir}"/>
</target>
<target name="zip" depends="clean">
<mkdir dir="${target-dir}"/>
<zip destfile="${target-dir}/${temperature_dir}.car">
<zipfileset dir="${src-dir}/${temperature_dir}"/>
</zip>
<zip destfile="${target-dir}/${humidity_dir}.car">
<zipfileset dir="${src-dir}/${humidity_dir}"/>
</zip>
</target>
</project>

@ -0,0 +1,90 @@
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.homeautomation</groupId>
<artifactId>firealarm-component</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>${groupId}.firealarm.analytics</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>${groupId}.firealarm.analytics</name>
<url>http://wso2.org</url>
<build>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>${maven-clean-plugin.version}</version>
<executions>
<execution>
<id>auto-clean</id>
<phase>initialize</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>${wso2.maven.compiler.source}</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>${maven-assembly-plugin.version}</version>
<configuration>
<finalName>${project.artifactId}-1.0.0-SNAPSHOT</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>
</project>

@ -0,0 +1,36 @@
<!--
~ 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:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
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,27 @@
<?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.
-->
<eventReceiver name="EventReceiver_humidity" statistics="disable" trace="disable"
xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="wso2event">
<property name="events.duplicated.in.cluster">false</property>
</from>
<mapping customMapping="disable" type="wso2event"/>
<to streamName="org.wso2.iot.devices.humidity" version="1.0.0"/>
</eventReceiver>

@ -0,0 +1,23 @@
<?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="Eventreceiver_humidity" version="1.0.0" type="event/receiver"
serverRole="DataAnalyticsServer">
<file>EventReceiver_humidity.xml</file>
</artifact>

@ -0,0 +1,23 @@
<?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="Eventstore_humidity" version="1.0.0" type="analytics/eventstore"
serverRole="DataAnalyticsServer">
<file>org_wso2_iot_devices_humidity.xml</file>
</artifact>

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ 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.
-->
<EventStoreConfiguration>
<Source>
<StreamId>org.wso2.iot.devices.humidity:1.0.0</StreamId>
</Source>
<RecordStoreName>EVENT_STORE</RecordStoreName>
<TableSchema>
<ColumnDefinition>
<Name>meta_owner</Name>
<EnableIndexing>true</EnableIndexing>
<IsPrimaryKey>true</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>STRING</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>meta_deviceType</Name>
<EnableIndexing>true</EnableIndexing>
<IsPrimaryKey>true</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>STRING</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>meta_deviceId</Name>
<EnableIndexing>true</EnableIndexing>
<IsPrimaryKey>true</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>STRING</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>meta_time</Name>
<EnableIndexing>true</EnableIndexing>
<IsPrimaryKey>true</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>LONG</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>humidity</Name>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>FLOAT</Type>
</ColumnDefinition>
</TableSchema>
</EventStoreConfiguration>

@ -0,0 +1,24 @@
<?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="Eventstream_humidity" version="1.0.0" type="event/stream"
serverRole="DataAnalyticsServer">
<file>org.wso2.iot.devices.humidity_1.0.0.json</file>
</artifact>

@ -0,0 +1,33 @@
{
"name": "org.wso2.iot.devices.humidity",
"version": "1.0.0",
"nickName": "Humidity Data",
"description": "Humidity data received from the Device",
"metaData": [
{
"name": "owner",
"type": "STRING"
},
{
"name": "deviceType",
"type": "STRING"
},
{
"name": "deviceId",
"type": "STRING"
},
{
"name": "time",
"type": "LONG"
}
],
"payloadData": [
{
"name": "humidity",
"type": "FLOAT"
}
]
}

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ 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.
-->
<Analytics>
<Name>IoTServer_Sensor_Script</Name>
<Script>
CREATE TEMPORARY TABLE DeviceHumidityData USING CarbonAnalytics OPTIONS(tableName
"ORG_WSO2_IOT_DEVICES_HUMIDITY");
CREATE TEMPORARY TABLE DeviceHumiditySummaryData USING CarbonAnalytics OPTIONS (tableName
"DEVICE_HUMIDITY_SUMMARY", schema "humidity FLOAT, deviceType STRING -i, deviceId STRING -i,
owner STRING -i, time LONG -i",primaryKeys "deviceType, deviceId, owner, time");
insert overwrite table DeviceHumiditySummaryData select humidity, meta_deviceType as
deviceType, meta_deviceId as deviceId, meta_owner as owner, cast(meta_time/1000 as BIGINT)as
time from DeviceHumidityData group by humidity, meta_deviceType, meta_deviceId, meta_owner,
cast(meta_time/1000 as BIGINT);
</Script>
<CronExpression>0 * * * * ?</CronExpression>
</Analytics>

@ -0,0 +1,23 @@
<?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="Sparkscripts" version="1.0.0" type="analytics/spark"
serverRole="DataAnalyticsServer">
<file>Humidity_Sensor_Script.xml</file>
</artifact>

@ -0,0 +1,33 @@
<?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="Humidity_Sensor_CAPP" version="1.0.0" type="carbon/application">
<dependency artifact="Eventstream_humidity" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="Eventstore_humidity" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="Eventreceiver_humidity" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="Sparkscripts" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
</artifact>
</artifacts>

@ -0,0 +1,27 @@
<?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.
-->
<eventReceiver name="EventReceiver_temperature" statistics="disable" trace="disable"
xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="wso2event">
<property name="events.duplicated.in.cluster">false</property>
</from>
<mapping customMapping="disable" type="wso2event"/>
<to streamName="org.wso2.iot.devices.temperature" version="1.0.0"/>
</eventReceiver>

@ -0,0 +1,23 @@
<?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="Eventreceiver_temperature" version="1.0.0" type="event/receiver"
serverRole="DataAnalyticsServer">
<file>EventReceiver_temperature.xml</file>
</artifact>

@ -0,0 +1,23 @@
<?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="Eventstore_temperature" version="1.0.0" type="analytics/eventstore"
serverRole="DataAnalyticsServer">
<file>org_wso2_iot_devices_temperature.xml</file>
</artifact>

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ 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.
-->
<EventStoreConfiguration>
<Source>
<StreamId>org.wso2.iot.devices.temperature:1.0.0</StreamId>
</Source>
<RecordStoreName>EVENT_STORE</RecordStoreName>
<TableSchema>
<ColumnDefinition>
<Name>meta_owner</Name>
<EnableIndexing>true</EnableIndexing>
<IsPrimaryKey>true</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>STRING</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>meta_deviceType</Name>
<EnableIndexing>true</EnableIndexing>
<IsPrimaryKey>true</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>STRING</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>meta_deviceId</Name>
<EnableIndexing>true</EnableIndexing>
<IsPrimaryKey>true</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>STRING</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>meta_time</Name>
<EnableIndexing>true</EnableIndexing>
<IsPrimaryKey>true</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>LONG</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>temperature</Name>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>FLOAT</Type>
</ColumnDefinition>
</TableSchema>
</EventStoreConfiguration>

@ -0,0 +1,24 @@
<?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="Eventstream_temperature" version="1.0.0" type="event/stream"
serverRole="DataAnalyticsServer">
<file>org.wso2.iot.devices.temperature_1.0.0.json</file>
</artifact>

@ -0,0 +1,33 @@
{
"name": "org.wso2.iot.devices.temperature",
"version": "1.0.0",
"nickName": "Temperature Data",
"description": "Temperature data received from the Device",
"metaData": [
{
"name": "owner",
"type": "STRING"
},
{
"name": "deviceType",
"type": "STRING"
},
{
"name": "deviceId",
"type": "STRING"
},
{
"name": "time",
"type": "LONG"
}
],
"payloadData": [
{
"name": "temperature",
"type": "FLOAT"
}
]
}

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ 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.
-->
<Analytics>
<Name>IoTServer_Sensor_Script</Name>
<Script>
CREATE TEMPORARY TABLE DeviceTemperatureData USING CarbonAnalytics OPTIONS(tableName
"ORG_WSO2_IOT_DEVICES_TEMPERATURE");
CREATE TEMPORARY TABLE DeviceTemperatureSummaryData USING CarbonAnalytics OPTIONS (tableName
"DEVICE_TEMPERATURE_SUMMARY", schema "temperature FLOAT, deviceType STRING -i, deviceId
STRING -i, owner STRING -i, time LONG -i",primaryKeys "deviceType, deviceId, owner, time");
insert overwrite table DeviceTemperatureSummaryData select temperature, meta_deviceType as
deviceType, meta_deviceId as deviceId, meta_owner as owner, cast(meta_time/1000 as BIGINT)as
time from DeviceTemperatureData group by temperature, meta_deviceType, meta_deviceId,
meta_owner, cast(meta_time/1000 as BIGINT);
</Script>
<CronExpression>0 * * * * ?</CronExpression>
</Analytics>

@ -0,0 +1,23 @@
<?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="Sparkscripts" version="1.0.0" type="analytics/spark"
serverRole="DataAnalyticsServer">
<file>Temperature_Sensor_Script.xml</file>
</artifact>

@ -0,0 +1,34 @@
<?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="Temperature_Sensor_CAPP" version="1.0.0" type="carbon/application">
<dependency artifact="Eventstream_temperature" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="Eventstore_temperature" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="Eventreceiver_temperature" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="Sparkscripts" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
</artifact>
</artifacts>

@ -0,0 +1,226 @@
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.homeautomation</groupId>
<artifactId>firealarm-component</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>${groupId}.firealarm.controller</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>${groupId}.firealarm.controller</name>
<url>http://wso2.com</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<source>${wso2.maven.compiler.source}</source>
<target>${wso2.maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration>
<warName>${groupId}.firealarm.controller</warName>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.homeautomation</groupId>
<artifactId>${project-base-package}.plugin</artifactId>
</dependency>
<!-- CDM -->
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.analytics</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.certificate.mgt.core</artifactId>
</dependency>
<!--CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
</dependency>
<!--IOT -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
<version>4.1</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot</artifactId>
</dependency>
<!--MQTT -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
</dependency>
<!--JAX-RS -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</dependency>
<dependency>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
<exclusions>
<exclusion>
<groupId>org.bouncycastle.wso2</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.queuing</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.base</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2</artifactId>
</exclusion>
<exclusion>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
</exclusion>
<exclusion>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
</exclusion>
<exclusion>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
</exclusion>
<exclusion>
<groupId>commons-fileupload.wso2</groupId>
<artifactId>commons-fileupload</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ant.wso2</groupId>
<artifactId>ant</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ant.wso2</groupId>
<artifactId>ant</artifactId>
</exclusion>
<exclusion>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.equinox</groupId>
<artifactId>javax.servlet</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.registry.api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,220 @@
/*
* 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.
*/
package org.homeautomation.firealarm.controller.api;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.homeautomation.firealarm.controller.api.dto.DeviceJSON;
import org.homeautomation.firealarm.controller.api.exception.DeviceTypeException;
import org.homeautomation.firealarm.controller.api.transport.MQTTConnector;
import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants;
import org.wso2.carbon.apimgt.annotations.api.API;
import org.wso2.carbon.apimgt.annotations.device.DeviceType;
import org.wso2.carbon.apimgt.annotations.device.feature.Feature;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.iot.DeviceManagement;
import org.wso2.carbon.device.mgt.iot.DeviceValidator;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException;
import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager;
import org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* This is the controller API which is used to control agent side functionality
*/
@SuppressWarnings("NonJaxWsWebServices")
@API(name = "firealarm", version = "1.0.0", context = "/firealarm")
@DeviceType(value = "firealarm")
public class ControllerService {
private static Log log = LogFactory.getLog(ControllerService.class);
private MQTTConnector mqttConnector;
private boolean waitForServerStartup() {
while (!DeviceManagement.isServerReady()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return true;
}
}
return false;
}
@SuppressWarnings("unused")
public MQTTConnector getMQTTConnector() {
return mqttConnector;
}
@SuppressWarnings("unused")
public void setMQTTConnector(final MQTTConnector MQTTConnector) {
Runnable connector = new Runnable() {
public void run() {
if (waitForServerStartup()) {
return;
}
ControllerService.this.mqttConnector = MQTTConnector;
if (MqttConfig.getInstance().isEnabled()) {
mqttConnector.connect();
} else {
log.warn("MQTT disabled in 'devicemgt-config.xml'. Hence, MQTTConnector" +
" not started.");
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.setDaemon(true);
connectorThread.start();
}
/**
* @param agentInfo device owner,id and sensor value
* @return device registration status
*/
@Path("controller/register")
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response registerDevice(final DeviceJSON agentInfo) {
if ((agentInfo.deviceId != null) && (agentInfo.owner != null)) {
return Response.status(Response.Status.OK).entity("Device has been registered successfully").build();
}
return Response.status(Response.Status.NOT_ACCEPTABLE).entity("Message body not " +
"well-formed and still invalid").build();
}
/**
* @param owner device owner
* @param deviceId unique identifier for given device type
* @param protocol name of supported protocol. here MQTT is used
* @param response to request
* @return sensor record
*/
@Path("controller/read-temperature")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Feature(code = "read-temperature", name = "Temperature", type = "monitor",
description = "Request temperature reading from device")
public SensorRecord readTemperature(@HeaderParam("owner") String owner,
@HeaderParam("deviceId") String deviceId,
@HeaderParam("protocol") String protocol,
@Context HttpServletResponse response) {
SensorRecord sensorRecord = null;
if (isPermitted(owner, deviceId, response)) {
try {
sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
DeviceTypeConstants.SENSOR_TEMPERATURE);
} catch (DeviceControllerException e) {
response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
response.setStatus(Response.Status.OK.getStatusCode());
}
return sensorRecord;
}
/**
* @param owner device owner
* @param deviceId unique identifier for given device type
* @param protocol name of supported protocol. here MQTT is used
* @param response to request
* @return sensor record
*/
@Path("controller/read-humidity")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Feature(code = "read-humidity", name = "Humidity", type = "monitor",
description = "Request humidity reading from device")
public SensorRecord readHumidity(@HeaderParam("owner") String owner,
@HeaderParam("deviceId") String deviceId,
@HeaderParam("protocol") String protocol,
@Context HttpServletResponse response) {
SensorRecord sensorRecord = null;
if (isPermitted(owner, deviceId, response)) {
try {
sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
DeviceTypeConstants.SENSOR_HUMIDITY);
} catch (DeviceControllerException e) {
response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
response.setStatus(Response.Status.OK.getStatusCode());
}
return sensorRecord;
}
/**
* @param owner device owner
* @param deviceId unique identifier for given device type
* @param protocol name of supported protocol. Here MQTT is used
* @param state change status of buzzer: on/off
* @param response to request
*/
@Path("controller/change-status")
@POST
@Feature(code = "change-status", name = "Buzzer: on/off", type = "operation",
description = "Switch on/off Fire Alarm Buzzer. (On / Off)")
public void changeBuzzerState(@HeaderParam("owner") String owner,
@HeaderParam("deviceId") String deviceId,
@HeaderParam("protocol") String protocol,
@FormParam("state") String state,
@Context HttpServletResponse response) {
if (isPermitted(owner, deviceId, response)) {
try {
mqttConnector.sendCommandViaMQTT(owner, deviceId, "buzzer:", state.toUpperCase());
response.setStatus(Response.Status.OK.getStatusCode());
} catch (DeviceManagementException e) {
log.error(e);
response.setStatus(Response.Status.UNAUTHORIZED.getStatusCode());
} catch (DeviceTypeException e) {
log.error(e);
response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
}
}
private boolean isPermitted(String owner, String deviceId, HttpServletResponse response) {
DeviceValidator deviceValidator = new DeviceValidator();
try {
String tenantDomain = CarbonContext.getThreadLocalCarbonContext().getTenantDomain();
if (!deviceValidator.isExist(owner, tenantDomain, new DeviceIdentifier(
deviceId, DeviceTypeConstants.DEVICE_TYPE))) {
response.setStatus(Response.Status.UNAUTHORIZED.getStatusCode());
} else {
return true;
}
} catch (DeviceManagementException e) {
response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
return false;
}
}

@ -0,0 +1,38 @@
/*
* 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.
*/
package org.homeautomation.firealarm.controller.api.dto;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* These information are sent by agent in each request to server
*/
@XmlRootElement
@JsonIgnoreProperties(ignoreUnknown = true)
public class DeviceJSON {
@XmlElement(required = true)
public String owner;
@XmlElement(required = true)
public String deviceId;
@XmlElement(required = true)
public Float sensorValue;
}

@ -0,0 +1,57 @@
/*
* 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.
*/
package org.homeautomation.firealarm.controller.api.exception;
public class DeviceTypeException extends Exception {
private static final long serialVersionUID = 2736466230451105441L;
private String errorMessage;
public DeviceTypeException(String msg, DeviceTypeException nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public DeviceTypeException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public DeviceTypeException(String msg) {
super(msg);
setErrorMessage(msg);
}
public DeviceTypeException() {
super();
}
public DeviceTypeException(Throwable cause) {
super(cause);
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}

@ -0,0 +1,229 @@
/*
* 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.
*/
package org.homeautomation.firealarm.controller.api.transport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.homeautomation.firealarm.controller.api.exception.DeviceTypeException;
import org.homeautomation.firealarm.controller.api.util.ServiceUtils;
import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.transport.mqtt.MQTTTransportHandler;
import java.io.File;
import java.util.Calendar;
import java.util.UUID;
/**
* MQTT is used as transport protocol. So this will provide basic functional requirement in order to communicate over
* MQTT
*/
@SuppressWarnings("no JAX-WS annotation")
public class MQTTConnector extends MQTTTransportHandler {
private static final String publisherContext = "publisher";
private static final String subscriberContext = "subscriber";
private static final String subscribeTopic =
"wso2" + File.separator + "iot" + File.separator + "+" + File.separator +
DeviceTypeConstants.DEVICE_TYPE + File.separator + "+" + File.separator +
publisherContext;
private static Log log = LogFactory.getLog(MQTTConnector.class);
private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5);
String publisher = "wso2/iot/%s/firealarm/%s/" + subscriberContext;
private MQTTConnector() {
super(iotServerSubscriber, DeviceTypeConstants.DEVICE_TYPE,
MqttConfig.getInstance().getMqttQueueEndpoint(), subscribeTopic);
}
/**
* This method will initialize connection with message broker
*/
@Override
public void connect() {
Runnable connector = new Runnable() {
public void run() {
while (!isConnected()) {
try {
String brokerUsername = MqttConfig.getInstance().getMqttQueueUsername();
String brokerPassword = MqttConfig.getInstance().getMqttQueuePassword();
setUsernameAndPassword(brokerUsername, brokerPassword);
connectToQueue();
} catch (TransportHandlerException e) {
log.error("Connection to MQTT Broker at: " + mqttBrokerEndPoint + " failed", e);
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException ex) {
log.error("MQTT-Connector: Thread Sleep Interrupt Exception.", ex);
}
}
try {
subscribeToQueue();
} catch (TransportHandlerException e) {
log.warn("Subscription to MQTT Broker at: " + mqttBrokerEndPoint + " failed", e);
}
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.setDaemon(true);
connectorThread.start();
}
/**
* This callback function will be called by message broker when some messages available to subscribed topic
*
* @param message mqtt message which is coming form agent side
* @param messageParams metadata of mqtt message
*/
@Override
public void processIncomingMessage(MqttMessage message, String... messageParams) {
String topic = messageParams[0];
String ownerAndId = topic.replace("wso2" + File.separator + "iot" + File.separator, "");
ownerAndId = ownerAndId.replace(File.separator + DeviceTypeConstants.DEVICE_TYPE
+ File.separator, ":");
ownerAndId = ownerAndId.replace(File.separator + publisherContext, "");
String owner = ownerAndId.split(":")[0];
String deviceId = ownerAndId.split(":")[1];
String[] messageData = message.toString().split(":");
if (log.isDebugEnabled()) {
log.debug("Received MQTT message for: [OWNER-" + owner + "] & [DEVICE.ID-" + deviceId + "]");
}
if (messageData.length == 4) {
SensorDataManager.getInstance().setSensorRecord(deviceId, DeviceTypeConstants.SENSOR_TEMPERATURE,
messageData[1], Calendar.getInstance().getTimeInMillis());
SensorDataManager.getInstance().setSensorRecord(deviceId, DeviceTypeConstants.SENSOR_HUMIDITY,
messageData[3], Calendar.getInstance().getTimeInMillis());
if (!ServiceUtils.publishTemperatureToDAS(owner, deviceId, messageData[1])) {
log.error("MQTT Subscriber: Publishing data to DAS failed.");
}
if (!ServiceUtils.publishHumidityToDAS(owner, deviceId, messageData[3])) {
log.error("MQTT Subscriber: Publishing data to DAS failed.");
}
if (log.isDebugEnabled()) {
log.debug("Temperature: " + messageData[1]);
log.debug("Humidity: " + messageData[3]);
}
}
}
/**
* Publish a MQTT message to device through message broker
*
* @param topic mqtt topic which will be used to uniquely identify who are the subscribers to this topic
* @param payLoad message is to be published
* @param qos level of qos(quality of service):1,2,3
* @param retained life status
* @throws TransportHandlerException
*/
private void publishToAgent(String topic, String payLoad, int qos, boolean retained)
throws TransportHandlerException {
if (log.isDebugEnabled()) {
log.debug("Publishing message [" + payLoad + "to topic [" + topic + "].");
}
publishToQueue(topic, payLoad, qos, retained);
}
/**
* Publish a MQTT message to device through message broker
*
* @param deviceOwner person who own the device
* @param deviceId unique identifier for each device
* @param operation command is to executed at agent side e.g: off, on
* @param param additional payload
* @throws DeviceManagementException
* @throws DeviceTypeException
*/
public void sendCommandViaMQTT(String deviceOwner, String deviceId, String operation,
String param)
throws DeviceManagementException, DeviceTypeException {
String topic = String.format(publisher, deviceOwner, deviceId);
String payload = operation + param;
try {
publishToAgent(topic, payload, 2, false);
} catch (TransportHandlerException e) {
String errorMessage = "Error publishing data to device with ID " + deviceId;
throw new DeviceTypeException(errorMessage, e);
}
}
/**
* connection with message broker can be terminated
*/
@Override
public void disconnect() {
Runnable stopConnection = new Runnable() {
public void run() {
while (isConnected()) {
try {
closeConnection();
} catch (MqttException e) {
if (log.isDebugEnabled()) {
log.warn("Unable to 'STOP' MQTT connection at broker at: " + mqttBrokerEndPoint);
}
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException e1) {
log.error("MQTT-Terminator: Thread Sleep Interrupt Exception");
}
}
}
}
};
Thread terminatorThread = new Thread(stopConnection);
terminatorThread.setDaemon(true);
terminatorThread.start();
}
@Override
public void publishDeviceData() throws TransportHandlerException {
}
@Override
public void publishDeviceData(MqttMessage publishData) throws TransportHandlerException {
}
@Override
public void publishDeviceData(String... publishData) throws TransportHandlerException {
}
@Override
public void processIncomingMessage() {
}
@Override
public void processIncomingMessage(MqttMessage message) throws TransportHandlerException {
}
}

@ -0,0 +1,83 @@
/*
* 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.
*/
package org.homeautomation.firealarm.controller.api.util;
import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.analytics.exception.DataPublisherConfigurationException;
import org.wso2.carbon.device.mgt.analytics.service.DeviceAnalyticsService;
public class ServiceUtils {
private static final String ORG_WSO2_IOT_DEVICES_TEMPERATURE = "org.wso2.iot.devices.temperature";
private static final String ORG_WSO2_IOT_DEVICES_HUMIDITY = "org.wso2.iot.devices.humidity";
private static final String SENSOR_STREAM_VERSION = "1.0.0";
/**
* sensor data are published to DAS
*
* @param owner name of device owner
* @param deviceId unique identifier of the device
* @param sensorValue current value of sensor which is set at agent side
* @return status
*/
public static boolean publishTemperatureToDAS(String owner, String deviceId,
String sensorValue) {
float temperature = Float.parseFloat(sensorValue);
Object payloadCurrent[] = {temperature};
return publishToDAS(owner, deviceId, payloadCurrent, ORG_WSO2_IOT_DEVICES_TEMPERATURE);
}
/**
* sensor data are published to DAS
*
* @param owner name of device owner
* @param deviceId unique identifier of the device
* @param sensorValue current value of sensor which is set at agent side
* @return status
*/
public static boolean publishHumidityToDAS(String owner, String deviceId,
String sensorValue) {
float humidity = Float.parseFloat(sensorValue);
Object payloadCurrent[] = {humidity};
return publishToDAS(owner, deviceId, payloadCurrent, ORG_WSO2_IOT_DEVICES_HUMIDITY);
}
private static boolean publishToDAS(String owner, String deviceId, Object[] payloadCurrent,
String definition) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
ctx.setUsername(owner);
if (ctx.getTenantDomain(true) == null) {
ctx.setTenantDomain("carbon.super", true);
}
DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx.getOSGiService(
DeviceAnalyticsService.class, null);
Object metaData[] = {owner, DeviceTypeConstants.DEVICE_TYPE, deviceId, System.currentTimeMillis()};
try {
deviceAnalyticsService.publishEvent(definition, SENSOR_STREAM_VERSION, metaData,
new Object[0], payloadCurrent);
} catch (DataPublisherConfigurationException e) {
return false;
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
return true;
}
}

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ 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.
-->
<!--
This file defines class loading policy of the whole container. But this behaviour can be overridden by individual webapps by putting this file into the META-INF/ directory.
-->
<Classloading xmlns="http://wso2.org/projects/as/classloading">
<!-- Parent-first or child-first. Default behaviour is child-first.-->
<ParentFirst>false</ParentFirst>
<!--
Default environments that contains provides to all the webapps. This can be overridden by individual webapps by specifing required environments
Tomcat environment is the default and every webapps gets it even if they didn't specify it.
e.g. If a webapps requires CXF, they will get both Tomcat and CXF.
-->
<Environments>CXF,Carbon</Environments>
</Classloading>

@ -0,0 +1,42 @@
<?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.
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<jaxrs:server id="Controller" address="/">
<jaxrs:serviceBeans>
<bean id="ControllerService"
class="org.homeautomation.firealarm.controller.api.ControllerService">
<property name="MQTTConnector" ref="communicationHandler"/>
</bean>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
<bean id="communicationHandler"
class="org.homeautomation.firealarm.controller.api.transport.MQTTConnector">
</bean>
</beans>

@ -0,0 +1,68 @@
<?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.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Sample-Webapp-Controller</display-name>
<servlet>
<description>JAX-WS/JAX-RS Endpoint</description>
<display-name>JAX-WS/JAX-RS Servlet</display-name>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>isAdminService</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>false</param-value>
</context-param>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>managed-api-context-template</param-name>
<param-value>/firealarm/{version}</param-value>
</context-param>
<context-param>
<param-name>managed-api-application</param-name>
<param-value>firealarm</param-value>
</context-param>
<context-param>
<param-name>managed-api-isSecured</param-name>
<param-value>true</param-value>
</context-param>
</web-app>

@ -0,0 +1,231 @@
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.homeautomation</groupId>
<artifactId>firealarm-component</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>${groupId}.firealarm.manager</artifactId>
<packaging>war</packaging>
<version>1.0.0-SNAPSHOT</version>
<name>${groupId}.firealarm.manager</name>
<url>http://wso2.org</url>
<build>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<source>${wso2.maven.compiler.source}</source>
<target>${wso2.maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration>
<warName>${groupId}.firealarm.manager_mgt</warName>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.homeautomation</groupId>
<artifactId>${project-base-package}.plugin</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.analytics</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.certificate.mgt.core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-codec.wso2</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
</dependency>
<!--IOT -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot</artifactId>
</dependency>
<!--JAX-RS -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</dependency>
<dependency>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
<exclusions>
<exclusion>
<groupId>org.bouncycastle.wso2</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.queuing</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.base</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2</artifactId>
</exclusion>
<exclusion>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
</exclusion>
<exclusion>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
</exclusion>
<exclusion>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
</exclusion>
<exclusion>
<groupId>commons-fileupload.wso2</groupId>
<artifactId>commons-fileupload</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ant.wso2</groupId>
<artifactId>ant</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ant.wso2</groupId>
<artifactId>ant</artifactId>
</exclusion>
<exclusion>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.equinox</groupId>
<artifactId>javax.servlet</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.registry.api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.webapp.publisher</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,337 @@
/*
* 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.
*/
package org.homeautomation.firealarm.manager.api;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.homeautomation.firealarm.manager.api.util.APIUtil;
import org.homeautomation.firealarm.manager.api.util.ResponsePayload;
import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants;
import org.wso2.carbon.apimgt.annotations.device.DeviceType;
import org.wso2.carbon.apimgt.webapp.publisher.KeyGenerationUtil;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.iot.apimgt.AccessTokenInfo;
import org.wso2.carbon.device.mgt.iot.apimgt.TokenClient;
import org.wso2.carbon.device.mgt.iot.exception.AccessTokenException;
import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException;
import org.wso2.carbon.device.mgt.iot.util.ZipArchive;
import org.wso2.carbon.device.mgt.iot.util.ZipUtil;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@SuppressWarnings("NonJaxWsWebServices")
@DeviceType(value = "firealarm")
public class ManagerService {
private static Log log = LogFactory.getLog(ManagerService.class);
@Context //injected response proxy supporting multiple thread
private HttpServletResponse response;
/**
* Generate UUID
*
* @return generated UUID
*/
private static String shortUUID() {
UUID uuid = UUID.randomUUID();
long l = ByteBuffer.wrap(uuid.toString().getBytes(StandardCharsets.UTF_8)).getLong();
return Long.toString(l, Character.MAX_RADIX);
}
/**
* Register new device into IoT Server
*
* @param deviceId unique identifier for device
* @param name name of new device
* @return registration status
*/
@Path("manager/device/register")
@PUT
public boolean register(@QueryParam("deviceId") String deviceId,
@QueryParam("name") String name) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(DeviceTypeConstants.DEVICE_TYPE);
try {
if (APIUtil.getDeviceManagementService().isEnrolled(deviceIdentifier)) {
response.setStatus(Response.Status.CONFLICT.getStatusCode());
return false;
}
String owner = APIUtil.getAuthenticatedUser();
Device device = new Device();
device.setDeviceIdentifier(deviceId);
EnrolmentInfo enrolmentInfo = new EnrolmentInfo();
enrolmentInfo.setDateOfEnrolment(new Date().getTime());
enrolmentInfo.setDateOfLastUpdate(new Date().getTime());
enrolmentInfo.setStatus(EnrolmentInfo.Status.ACTIVE);
enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.BYOD);
device.setName(name);
device.setType(DeviceTypeConstants.DEVICE_TYPE);
enrolmentInfo.setOwner(owner);
device.setEnrolmentInfo(enrolmentInfo);
KeyGenerationUtil.createApplicationKeys(DeviceTypeConstants.DEVICE_TYPE);
TokenClient accessTokenClient = new TokenClient(DeviceTypeConstants.DEVICE_TYPE);
AccessTokenInfo accessTokenInfo = accessTokenClient.getAccessToken(owner, deviceId);
//create token
String accessToken = accessTokenInfo.getAccess_token();
String refreshToken = accessTokenInfo.getRefresh_token();
List<Device.Property> properties = new ArrayList<>();
Device.Property accessTokenProperty = new Device.Property();
accessTokenProperty.setName("accessToken");
accessTokenProperty.setValue(accessToken);
Device.Property refreshTokenProperty = new Device.Property();
refreshTokenProperty.setName("refreshToken");
refreshTokenProperty.setValue(refreshToken);
properties.add(accessTokenProperty);
properties.add(refreshTokenProperty);
device.setProperties(properties);
boolean added = APIUtil.getDeviceManagementService().enrollDevice(device);
if (added) {
response.setStatus(Response.Status.OK.getStatusCode());
} else {
response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode());
}
return added;
} catch (DeviceManagementException e) {
response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
log.error(e.getErrorMessage(), e);
return false;
} catch (AccessTokenException e) {
response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
log.error("Unable to obtain access token", e);
return false;
}
}
/**
* Remove installed device
*
* @param deviceId unique identifier for device
* @param response to request
*/
@Path("manager/device/remove/{device_id}")
@DELETE
public void removeDevice(@PathParam("device_id") String deviceId,
@Context HttpServletResponse response) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(DeviceTypeConstants.DEVICE_TYPE);
try {
boolean removed = APIUtil.getDeviceManagementService().disenrollDevice(
deviceIdentifier);
if (removed) {
response.setStatus(Response.Status.OK.getStatusCode());
} else {
response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode());
}
} catch (DeviceManagementException e) {
response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
}
/**
* Update device name
*
* @param deviceId unique identifier for device
* @param name new name of the device
* @param response to request
* @return update status
*/
@Path("manager/device/update/{device_id}")
@POST
public boolean updateDevice(@PathParam("device_id") String deviceId,
@QueryParam("name") String name,
@Context HttpServletResponse response) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(DeviceTypeConstants.DEVICE_TYPE);
try {
Device device = APIUtil.getDeviceManagementService().getDevice(deviceIdentifier);
device.setDeviceIdentifier(deviceId);
device.getEnrolmentInfo().setDateOfLastUpdate(new Date().getTime());
device.setName(name);
device.setType(DeviceTypeConstants.DEVICE_TYPE);
boolean updated = APIUtil.getDeviceManagementService().modifyEnrollment(device);
if (updated) {
response.setStatus(Response.Status.OK.getStatusCode());
} else {
response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode());
}
return updated;
} catch (DeviceManagementException e) {
log.error(e.getErrorMessage());
return false;
}
}
/**
* Get device information
*
* @param deviceId unique identifier for device
* @return device
*/
@Path("manager/device/{device_id}")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Device getDevice(@PathParam("device_id") String deviceId) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(DeviceTypeConstants.DEVICE_TYPE);
try {
return APIUtil.getDeviceManagementService().getDevice(deviceIdentifier);
} catch (DeviceManagementException ex) {
log.error("Error occurred while retrieving device with Id " + deviceId + "\n" + ex);
return null;
}
}
/**
* This will download the agent for given device type
*
* @param deviceName name of the device which is to be created
* @param sketchType name of sketch type
* @return agent archive
*/
@Path("manager/device/{sketch_type}/download")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response downloadSketch(@QueryParam("deviceName") String deviceName,
@PathParam("sketch_type") String sketchType) {
try {
ZipArchive zipFile = createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName, sketchType);
Response.ResponseBuilder response = Response.ok(FileUtils.readFileToByteArray(zipFile.getZipFile()));
response.type("application/zip");
response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\"");
return response.build();
} catch (IllegalArgumentException ex) {
return Response.status(400).entity(ex.getMessage()).build();//bad request
} catch (DeviceManagementException ex) {
return Response.status(500).entity(ex.getMessage()).build();
} catch (AccessTokenException ex) {
return Response.status(500).entity(ex.getMessage()).build();
} catch (DeviceControllerException ex) {
return Response.status(500).entity(ex.getMessage()).build();
} catch (IOException ex) {
return Response.status(500).entity(ex.getMessage()).build();
}
}
/**
* This will give link to generated agent
*
* @param deviceName name of the device which is to be created
* @param sketchType name of sketch type
* @return link to generated agent
*/
@Path("manager/device/{sketch_type}/generate_link")
@GET
public Response generateSketchLink(@QueryParam("deviceName") String deviceName,
@PathParam("sketch_type") String sketchType) {
try {
ZipArchive zipFile = createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName, sketchType);
ResponsePayload responsePayload = new ResponsePayload();
responsePayload.setStatusCode(HttpStatus.SC_OK);
responsePayload.setMessageFromServer("Sending Requested sketch by type: " + sketchType +
" and id: " + zipFile.getDeviceId() + ".");
responsePayload.setResponseContent(zipFile.getDeviceId());
return Response.status(HttpStatus.SC_OK).entity(responsePayload).build();
} catch (IllegalArgumentException ex) {
return Response.status(HttpStatus.SC_BAD_REQUEST).entity(ex.getMessage()).build();
} catch (DeviceManagementException ex) {
log.error("Error occurred while creating device with name " + deviceName + "\n", ex);
return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
} catch (AccessTokenException ex) {
log.error(ex.getMessage(), ex);
return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
} catch (DeviceControllerException ex) {
log.error(ex.getMessage(), ex);
return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).entity(ex.getMessage()).build();
}
}
/**
* Make zip file which include all the agent source codes and configuration file
*
* @param owner owner of the device
* @param deviceName name of device
* @param sketchType name of sketch type
* @return zip archive file
* @throws DeviceManagementException
* @throws AccessTokenException
* @throws DeviceControllerException
*/
private ZipArchive createDownloadFile(String owner, String deviceName, String sketchType)
throws DeviceManagementException, AccessTokenException, DeviceControllerException {
if (owner == null) {
throw new IllegalArgumentException("Error on createDownloadFile() Owner is null!");
}
//create new device id
String deviceId = shortUUID();
KeyGenerationUtil.createApplicationKeys(DeviceTypeConstants.DEVICE_TYPE);
TokenClient accessTokenClient = new TokenClient(DeviceTypeConstants.DEVICE_TYPE);
AccessTokenInfo accessTokenInfo = accessTokenClient.getAccessToken(owner, deviceId);
//create token
String accessToken = accessTokenInfo.getAccess_token();
String refreshToken = accessTokenInfo.getRefresh_token();
//adding registering data
boolean status;
//Register the device with CDMF
status = register(deviceId, deviceName);
if (!status) {
String msg = "Error occurred while registering the device with " + "id: " + deviceId + " owner:" + owner;
throw new DeviceManagementException(msg);
}
ZipUtil ziputil = new ZipUtil();
ZipArchive zipFile = ziputil.createZipFile(owner, APIUtil.getTenantDomainOfUser(), sketchType, deviceId, deviceName, accessToken,
refreshToken);
zipFile.setDeviceId(deviceId);
return zipFile;
}
}

@ -0,0 +1,54 @@
/*
* 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.
*/
package org.homeautomation.firealarm.manager.api.util;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
/**
* This class provides utility functions used by REST-API.
*/
public class APIUtil {
public static String getAuthenticatedUser() {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
String username = threadLocalCarbonContext.getUsername();
String tenantDomain = threadLocalCarbonContext.getTenantDomain();
if (username.endsWith(tenantDomain)) {
return username.substring(0, username.lastIndexOf("@"));
}
return username;
}
public static String getTenantDomainOfUser() {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
return threadLocalCarbonContext.getTenantDomain();
}
public static DeviceManagementProviderService getDeviceManagementService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceManagementProviderService deviceManagementProviderService =
(DeviceManagementProviderService) ctx.getOSGiService(DeviceManagementProviderService.class, null);
if (deviceManagementProviderService == null) {
String msg = "Device Management service has not initialized.";
throw new IllegalStateException(msg);
}
return deviceManagementProviderService;
}
}

@ -0,0 +1,108 @@
/*
* 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.
*/
package org.homeautomation.firealarm.manager.api.util;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ResponsePayload {
private int statusCode;
private String messageFromServer;
private Object responseContent;
public static ResponsePayload.ResponsePayloadBuilder statusCode(int statusCode) {
ResponsePayload message = new ResponsePayload();
return message.getBuilder().statusCode(statusCode);
}
public static ResponsePayload.ResponsePayloadBuilder messageFromServer(
String messageFromServer) {
ResponsePayload message = new ResponsePayload();
return message.getBuilder().messageFromServer(messageFromServer);
}
public static ResponsePayload.ResponsePayloadBuilder responseContent(String responseContent) {
ResponsePayload message = new ResponsePayload();
return message.getBuilder().responseContent(responseContent);
}
@XmlElement
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
@XmlElement
public String getMessageFromServer() {
return messageFromServer;
}
public void setMessageFromServer(String messageFromServer) {
this.messageFromServer = messageFromServer;
}
@XmlElement
public Object getResponseContent() {
return responseContent;
}
public void setResponseContent(Object responseContent) {
this.responseContent = responseContent;
}
private ResponsePayload.ResponsePayloadBuilder getBuilder() {
return new ResponsePayload.ResponsePayloadBuilder();
}
public class ResponsePayloadBuilder {
private int statusCode;
private String messageFromServer;
private Object responseContent;
public ResponsePayloadBuilder statusCode(int statusCode) {
this.statusCode = statusCode;
return this;
}
public ResponsePayloadBuilder messageFromServer(String messageFromServer) {
this.messageFromServer = messageFromServer;
return this;
}
public ResponsePayloadBuilder responseContent(String responseContent) {
this.responseContent = responseContent;
return this;
}
public ResponsePayload build() {
ResponsePayload payload = new ResponsePayload();
payload.setStatusCode(statusCode);
payload.setMessageFromServer(messageFromServer);
payload.setResponseContent(responseContent);
return payload;
}
}
}

@ -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.
-->
<!-- This file contains the list of permissions that are associated with URL end points
of the web app. Each permission should contain the name, permission path ,API path
(URL) , HTTP method and OAUTH2 authorization scope (not-required).
When defining dynamic paths for APIs, path variables are denoted by '*' notation.
NOTE: All the endpoints of the web app should be available in this file. Otherwise
it will result 403 error at the runtime.
-->
<PermissionConfiguration>
<APIVersion></APIVersion>
<!-- Device related APIs -->
<Permission>
<name>Get device</name>
<path>/device-mgt/user/devices/list</path>
<url>/manager/device/*</url>
<method>GET</method>
<scope>emm_admin,emm_user</scope>
</Permission>
<Permission>
<name>Add device</name>
<path>/device-mgt/user/devices/add</path>
<url>/manager/device/register</url>
<method>PUT</method>
<scope>emm_admin,emm_user</scope>
</Permission>
<Permission>
<name>Download device</name>
<path>/device-mgt/user/devices/add</path>
<url>/manager/device/firealarm/download</url>
<method>GET</method>
<scope>emm_admin,emm_user</scope>
</Permission>
<Permission>
<name>Generate link to download</name>
<path>/device-mgt/user/devices/add</path>
<url>/manager/device/firealarm/generate_link</url>
<method>GET</method>
<scope>emm_admin,emm_user</scope>
</Permission>
<Permission>
<name>Update device</name>
<path>/device-mgt/user/devices/update</path>
<url>/manager/device/update/*</url>
<method>POST</method>
<scope>emm_admin,emm_user</scope>
</Permission>
<Permission>
<name>Remove device</name>
<path>/device-mgt/user/devices/remove</path>
<url>/manager/device/remove/*</url>
<method>DELETE</method>
<scope>emm_admin,emm_user</scope>
</Permission>
</PermissionConfiguration>

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ 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.
-->
<!--
This file defines class loading policy of the whole container. But this behaviour can be overridden by individual webapps by putting this file into the META-INF/ directory.
-->
<Classloading xmlns="http://wso2.org/projects/as/classloading">
<!-- Parent-first or child-first. Default behaviour is child-first.-->
<ParentFirst>false</ParentFirst>
<!--
Default environments that contains provides to all the webapps. This can be overridden by individual webapps by specifing required environments
Tomcat environment is the default and every webapps gets it even if they didn't specify it.
e.g. If a webapps requires CXF, they will get both Tomcat and CXF.
-->
<Environments>CXF,Carbon</Environments>
</Classloading>

@ -0,0 +1,38 @@
<?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.
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<jaxrs:server id="Manager" address="/">
<jaxrs:serviceBeans>
<bean id="ManagerService"
class="org.homeautomation.firealarm.manager.api.ManagerService">
</bean>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
</beans>

@ -0,0 +1,68 @@
<?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.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Firealarm-Webapp-Manager</display-name>
<servlet>
<description>JAX-WS/JAX-RS Endpoint</description>
<display-name>JAX-WS/JAX-RS Servlet</display-name>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>isAdminService</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>true</param-value>
</context-param>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>managed-api-context-template</param-name>
<param-value>/firealarm/{version}</param-value>
</context-param>
<context-param>
<param-name>managed-api-application</param-name>
<param-value>firealarm</param-value>
</context-param>
<context-param>
<param-name>managed-api-isSecured</param-name>
<param-value>true</param-value>
</context-param>
</web-app>

@ -0,0 +1,114 @@
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.homeautomation</groupId>
<artifactId>firealarm-component</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>1.0.0-SNAPSHOT</version>
<artifactId>${groupId}.firealarm.plugin</artifactId>
<packaging>bundle</packaging>
<name>${groupId}.firealarm.plugin</name>
<url>http://wso2.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<source>${wso2.maven.compiler.source}</source>
<target>${wso2.maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${org.apache.felix.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${groupId}.firealarm.plugin</Bundle-SymbolicName>
<Bundle-Name>${groupId}.firealarm.plugin</Bundle-Name>
<Bundle-Version>1.0.0-SNAPSHOT</Bundle-Version>
<Bundle-Description>IoT Server Impl Bundle</Bundle-Description>
<Private-Package>${project-base-package}.plugin.internal</Private-Package>
<Import-Package>
org.osgi.framework,
org.osgi.service.component,
org.apache.commons.logging,
javax.naming,
javax.sql,
javax.xml.parsers,
javax.net,
javax.net.ssl,
org.w3c.dom,
org.wso2.carbon.device.mgt.common.*,
org.wso2.carbon.context.*,
org.wso2.carbon.ndatasource.core,
org.wso2.carbon.device.mgt.iot.*,
</Import-Package>
<Export-Package>
!${project-base-package}.plugin.internal,
${project-base-package}.plugin.*
</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.ndatasource.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,33 @@
/*
* 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.
*/
package org.homeautomation.firealarm.plugin.constants;
public class DeviceTypeConstants {
public final static String DEVICE_TYPE = "firealarm";
public final static String DEVICE_PLUGIN_DEVICE_NAME = "DEVICE_NAME";
public final static String DEVICE_PLUGIN_DEVICE_ID = "firealarm_DEVICE_ID";
public final static String SENSOR_TEMPERATURE = "temperature";
public final static String SENSOR_HUMIDITY = "humidity";
public static final String DATA_SOURCE_NAME = "jdbc/firealarmDM_DB";
public final static String DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN = "accessToken";
public final static String DEVICE_PLUGIN_PROPERTY_REFRESH_TOKEN = "refreshToken";
}

@ -0,0 +1,56 @@
/*
* 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.
*/
package org.homeautomation.firealarm.plugin.exception;
public class FirealarmPluginException extends Exception {
private String errorMessage;
public FirealarmPluginException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public FirealarmPluginException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public FirealarmPluginException(String msg) {
super(msg);
setErrorMessage(msg);
}
public FirealarmPluginException() {
super();
}
public FirealarmPluginException(Throwable cause) {
super(cause);
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}

@ -0,0 +1,259 @@
/*
* 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.
*/
package org.homeautomation.firealarm.plugin.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.homeautomation.firealarm.plugin.exception.FirealarmPluginException;
import org.homeautomation.firealarm.plugin.impl.dao.DeviceTypeDAO;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.DeviceManager;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.FeatureManager;
import org.wso2.carbon.device.mgt.common.configuration.mgt.TenantConfiguration;
import org.wso2.carbon.device.mgt.common.license.mgt.License;
import org.wso2.carbon.device.mgt.common.license.mgt.LicenseManagementException;
import java.util.List;
/**
*
*/
public class DeviceTypeManager implements DeviceManager {
private static final Log log = LogFactory.getLog(DeviceTypeManager.class);
private static final DeviceTypeDAO connectedCupDAO = new DeviceTypeDAO();
@Override
public FeatureManager getFeatureManager() {
return null;
}
@Override
public boolean saveConfiguration(TenantConfiguration tenantConfiguration)
throws DeviceManagementException {
//TODO implement this
return false;
}
@Override
public TenantConfiguration getConfiguration() throws DeviceManagementException {
//TODO implement this
return null;
}
@Override
public boolean enrollDevice(Device device) throws DeviceManagementException {
boolean status;
try {
if (log.isDebugEnabled()) {
log.debug("Enrolling a new Connected Cup device : " + device.getDeviceIdentifier());
}
DeviceTypeDAO.beginTransaction();
status = connectedCupDAO.getConnectedCupDeviceDAO().addDevice(device);
DeviceTypeDAO.commitTransaction();
} catch (FirealarmPluginException e) {
try {
DeviceTypeDAO.rollbackTransaction();
} catch (FirealarmPluginException iotDAOEx) {
String msg = "Error occurred while roll back the device enrol transaction :" + device.toString();
log.warn(msg, iotDAOEx);
}
String msg = "Error while enrolling the Connected Cup device : " + device.getDeviceIdentifier();
log.error(msg, e);
throw new DeviceManagementException(msg, e);
}
return status;
}
@Override
public boolean modifyEnrollment(Device device) throws DeviceManagementException {
boolean status;
try {
if (log.isDebugEnabled()) {
log.debug("Modifying the Connected Cup device enrollment data");
}
DeviceTypeDAO.beginTransaction();
status = connectedCupDAO.getConnectedCupDeviceDAO().updateDevice(device);
DeviceTypeDAO.commitTransaction();
} catch (FirealarmPluginException e) {
try {
DeviceTypeDAO.rollbackTransaction();
} catch (FirealarmPluginException iotDAOEx) {
String msg = "Error occurred while roll back the update device transaction :" + device.toString();
log.warn(msg, iotDAOEx);
}
String msg = "Error while updating the enrollment of the Connected Cup device : " +
device.getDeviceIdentifier();
log.error(msg, e);
throw new DeviceManagementException(msg, e);
}
return status;
}
@Override
public boolean disenrollDevice(DeviceIdentifier deviceId) throws DeviceManagementException {
boolean status;
try {
if (log.isDebugEnabled()) {
log.debug("Dis-enrolling Connected Cup device : " + deviceId);
}
DeviceTypeDAO.beginTransaction();
status = connectedCupDAO.getConnectedCupDeviceDAO().deleteDevice(deviceId.getId());
DeviceTypeDAO.commitTransaction();
} catch (FirealarmPluginException e) {
try {
DeviceTypeDAO.rollbackTransaction();
} catch (FirealarmPluginException iotDAOEx) {
String msg = "Error occurred while roll back the device dis enrol transaction :" + deviceId.toString();
log.warn(msg, iotDAOEx);
}
String msg = "Error while removing the Connected Cup device : " + deviceId.getId();
log.error(msg, e);
throw new DeviceManagementException(msg, e);
}
return status;
}
@Override
public boolean isEnrolled(DeviceIdentifier deviceId) throws DeviceManagementException {
boolean isEnrolled = false;
try {
if (log.isDebugEnabled()) {
log.debug("Checking the enrollment of Connected Cup device : " + deviceId.getId());
}
Device iotDevice = connectedCupDAO.getConnectedCupDeviceDAO().getDevice(deviceId.getId());
if (iotDevice != null) {
isEnrolled = true;
}
} catch (FirealarmPluginException e) {
String msg = "Error while checking the enrollment status of Connected Cup device : " +
deviceId.getId();
log.error(msg, e);
throw new DeviceManagementException(msg, e);
}
return isEnrolled;
}
@Override
public boolean isActive(DeviceIdentifier deviceId) throws DeviceManagementException {
return true;
}
@Override
public boolean setActive(DeviceIdentifier deviceId, boolean status)
throws DeviceManagementException {
return true;
}
@Override
public Device getDevice(DeviceIdentifier deviceId) throws DeviceManagementException {
Device device;
try {
if (log.isDebugEnabled()) {
log.debug("Getting the details of Connected Cup device : " + deviceId.getId());
}
device = connectedCupDAO.getConnectedCupDeviceDAO().getDevice(deviceId.getId());
} catch (FirealarmPluginException e) {
String msg = "Error while fetching the Connected Cup device : " + deviceId.getId();
log.error(msg, e);
throw new DeviceManagementException(msg, e);
}
return device;
}
@Override
public boolean setOwnership(DeviceIdentifier deviceId, String ownershipType)
throws DeviceManagementException {
return true;
}
public boolean isClaimable(DeviceIdentifier deviceIdentifier) throws DeviceManagementException {
return false;
}
@Override
public boolean setStatus(DeviceIdentifier deviceId, String currentOwner,
EnrolmentInfo.Status status) throws DeviceManagementException {
return false;
}
@Override
public License getLicense(String s) throws LicenseManagementException {
return null;
}
@Override
public void addLicense(License license) throws LicenseManagementException {
}
@Override
public boolean requireDeviceAuthorization() {
return false;
}
@Override
public boolean updateDeviceInfo(DeviceIdentifier deviceIdentifier, Device device)
throws DeviceManagementException {
boolean status;
try {
if (log.isDebugEnabled()) {
log.debug(
"updating the details of Connected Cup device : " + deviceIdentifier);
}
DeviceTypeDAO.beginTransaction();
status = connectedCupDAO.getConnectedCupDeviceDAO().updateDevice(device);
DeviceTypeDAO.commitTransaction();
} catch (FirealarmPluginException e) {
try {
DeviceTypeDAO.rollbackTransaction();
} catch (FirealarmPluginException iotDAOEx) {
String msg = "Error occurred while roll back the update device info transaction :" + device.toString();
log.warn(msg, iotDAOEx);
}
String msg =
"Error while updating the Connected Cup device : " + deviceIdentifier;
log.error(msg, e);
throw new DeviceManagementException(msg, e);
}
return status;
}
@Override
public List<Device> getAllDevices() throws DeviceManagementException {
List<Device> devices;
try {
if (log.isDebugEnabled()) {
log.debug("Fetching the details of all Connected Cup devices");
}
devices = connectedCupDAO.getConnectedCupDeviceDAO().getAllDevices();
} catch (FirealarmPluginException e) {
String msg = "Error while fetching all Connected Cup devices.";
log.error(msg, e);
throw new DeviceManagementException(msg, e);
}
return devices;
}
}

@ -0,0 +1,114 @@
/*
* 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.
*/
package org.homeautomation.firealarm.plugin.impl;
import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.DeviceManager;
import org.wso2.carbon.device.mgt.common.app.mgt.Application;
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException;
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService;
import java.util.List;
public class DeviceTypeManagerService implements DeviceManagementService {
private DeviceManager deviceManager;
@Override
public String getType() {
return DeviceTypeConstants.DEVICE_TYPE;
}
@Override
public String getProviderTenantDomain() {
return "carbon.super";
}
@Override
public boolean isSharedWithAllTenants() {
return true;
}
@Override
public String[] getSharedTenantsDomain() {
return new String[0];
}
@Override
public void init() throws DeviceManagementException {
this.deviceManager = new DeviceTypeManager();
}
@Override
public DeviceManager getDeviceManager() {
return deviceManager;
}
@Override
public ApplicationManager getApplicationManager() {
return null;
}
@Override
public void notifyOperationToDevices(Operation operation, List<DeviceIdentifier> deviceIds)
throws DeviceManagementException {
}
@Override
public Application[] getApplications(String domain, int pageNumber, int size)
throws ApplicationManagementException {
return new Application[0];
}
@Override
public void updateApplicationStatus(DeviceIdentifier deviceId, Application application,
String status) throws ApplicationManagementException {
}
@Override
public String getApplicationStatus(DeviceIdentifier deviceId, Application application)
throws ApplicationManagementException {
return null;
}
@Override
public void installApplicationForDevices(Operation operation,
List<DeviceIdentifier> deviceIdentifiers)
throws ApplicationManagementException {
}
@Override
public void installApplicationForUsers(Operation operation, List<String> userNameList)
throws ApplicationManagementException {
}
@Override
public void installApplicationForUserRoles(Operation operation, List<String> userRoleList)
throws ApplicationManagementException {
}
}

@ -0,0 +1,132 @@
/*
* 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.
*/
package org.homeautomation.firealarm.plugin.impl.dao;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants;
import org.homeautomation.firealarm.plugin.exception.FirealarmPluginException;
import org.homeautomation.firealarm.plugin.impl.dao.impl.DeviceTypeDAOImpl;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class DeviceTypeDAO {
private static final Log log = LogFactory.getLog(DeviceTypeDAO.class);
private static DataSource dataSource;
private static ThreadLocal<Connection> currentConnection = new ThreadLocal<>();
public DeviceTypeDAO() {
initConnectedCupDAO();
}
public static void initConnectedCupDAO() {
try {
Context ctx = new InitialContext();
dataSource = (DataSource) ctx.lookup(DeviceTypeConstants.DATA_SOURCE_NAME);
} catch (NamingException e) {
log.error("Error while looking up the data source: " +
DeviceTypeConstants.DATA_SOURCE_NAME);
}
}
public static void beginTransaction() throws FirealarmPluginException {
try {
Connection conn = dataSource.getConnection();
conn.setAutoCommit(false);
currentConnection.set(conn);
} catch (SQLException e) {
throw new FirealarmPluginException(
"Error occurred while retrieving datasource connection", e);
}
}
public static Connection getConnection() throws FirealarmPluginException {
if (currentConnection.get() == null) {
try {
currentConnection.set(dataSource.getConnection());
} catch (SQLException e) {
throw new FirealarmPluginException(
"Error occurred while retrieving data source connection", e);
}
}
return currentConnection.get();
}
public static void commitTransaction() throws FirealarmPluginException {
try {
Connection conn = currentConnection.get();
if (conn != null) {
conn.commit();
} else {
if (log.isDebugEnabled()) {
log.debug("Datasource connection associated with the current thread is null, " +
"hence commit has not been attempted");
}
}
} catch (SQLException e) {
throw new FirealarmPluginException(
"Error occurred while committing the transaction", e);
} finally {
closeConnection();
}
}
public static void closeConnection() throws FirealarmPluginException {
Connection con = currentConnection.get();
if (con != null) {
try {
con.close();
} catch (SQLException e) {
log.error("Error occurred while close the connection");
}
}
currentConnection.remove();
}
public static void rollbackTransaction() throws FirealarmPluginException {
try {
Connection conn = currentConnection.get();
if (conn != null) {
conn.rollback();
} else {
if (log.isDebugEnabled()) {
log.debug(
"Datasource connection associated with the current thread is null, " +
"hence rollback has not been attempted");
}
}
} catch (SQLException e) {
throw new FirealarmPluginException("Error occurred while rollback the transaction", e);
} finally {
closeConnection();
}
}
public DeviceTypeDAOImpl getConnectedCupDeviceDAO() {
return new DeviceTypeDAOImpl();
}
}

@ -0,0 +1,239 @@
/*
* 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.
*/
package org.homeautomation.firealarm.plugin.impl.dao.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.homeautomation.firealarm.plugin.constants.DeviceTypeConstants;
import org.homeautomation.firealarm.plugin.exception.FirealarmPluginException;
import org.homeautomation.firealarm.plugin.impl.dao.DeviceTypeDAO;
import org.homeautomation.firealarm.plugin.impl.dao.util.DeviceTypeUtils;
import org.wso2.carbon.device.mgt.common.Device;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Device Dao for Firealarm Devices.
*/
public class DeviceTypeDAOImpl {
private static final Log log = LogFactory.getLog(DeviceTypeDAOImpl.class);
public Device getDevice(String deviceId) throws FirealarmPluginException {
Connection conn;
PreparedStatement stmt = null;
Device connectedCupDevice = null;
ResultSet resultSet = null;
try {
conn = DeviceTypeDAO.getConnection();
String selectDBQuery =
"SELECT firealarm_DEVICE_ID, DEVICE_NAME, ACCESS_TOKEN, REFRESH_TOKEN" +
" FROM firealarm_DEVICE WHERE firealarm_DEVICE_ID = ?";
stmt = conn.prepareStatement(selectDBQuery);
stmt.setString(1, deviceId);
resultSet = stmt.executeQuery();
if (resultSet.next()) {
connectedCupDevice = new Device();
connectedCupDevice.setName(resultSet.getString(
DeviceTypeConstants.DEVICE_PLUGIN_DEVICE_NAME));
List<Device.Property> propertyList = new ArrayList<>();
propertyList.add(DeviceTypeUtils.getProperty(
DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN,
resultSet.getString("ACCESS_TOKEN")));
propertyList.add(DeviceTypeUtils.getProperty(
DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_REFRESH_TOKEN,
resultSet.getString("REFRESH_TOKEN")));
connectedCupDevice.setProperties(propertyList);
if (log.isDebugEnabled()) {
log.debug("Firealarm service " + deviceId + " data has been fetched from" +
"Firealarm database.");
}
}
} catch (SQLException e) {
String msg = "Error occurred while fetching Firealarm device : '" + deviceId + "'";
log.error(msg, e);
throw new FirealarmPluginException(msg, e);
} finally {
DeviceTypeUtils.cleanupResources(stmt, resultSet);
DeviceTypeDAO.closeConnection();
}
return connectedCupDevice;
}
public boolean addDevice(Device connectedCupDevice) throws FirealarmPluginException {
boolean status = false;
Connection conn;
PreparedStatement stmt = null;
try {
conn = DeviceTypeDAO.getConnection();
String createDBQuery =
"INSERT INTO firealarm_DEVICE(firealarm_DEVICE_ID, DEVICE_NAME, " +
"ACCESS_TOKEN, REFRESH_TOKEN) VALUES (?, ?, ?, ?)";
stmt = conn.prepareStatement(createDBQuery);
stmt.setString(1, connectedCupDevice.getDeviceIdentifier());
stmt.setString(2, connectedCupDevice.getName());
stmt.setString(3, DeviceTypeUtils.getDeviceProperty(
connectedCupDevice.getProperties(),
DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN));
stmt.setString(4, DeviceTypeUtils.getDeviceProperty(
connectedCupDevice.getProperties(),
DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_REFRESH_TOKEN));
int rows = stmt.executeUpdate();
if (rows > 0) {
status = true;
if (log.isDebugEnabled()) {
log.debug("Connected Cup device " + connectedCupDevice.getDeviceIdentifier() +
" data has been added to the Connected Cup database.");
}
}
} catch (SQLException e) {
String msg = "Error occurred while adding the Connected Cup device '" +
connectedCupDevice.getDeviceIdentifier() + "' to the Connected Cup db.";
throw new FirealarmPluginException(msg, e);
} finally {
DeviceTypeUtils.cleanupResources(stmt, null);
}
return status;
}
public boolean updateDevice(Device connectedCupDevice) throws FirealarmPluginException {
boolean status = false;
Connection conn;
PreparedStatement stmt = null;
try {
conn = DeviceTypeDAO.getConnection();
String updateDBQuery =
"UPDATE firealarm_DEVICE SET DEVICE_NAME = ?, ACCESS_TOKEN=?, " +
"REFRESH_TOKEN=? WHERE firealarm_DEVICE_ID = ?";
stmt = conn.prepareStatement(updateDBQuery);
if (connectedCupDevice.getProperties() == null) {
connectedCupDevice.setProperties(new ArrayList<Device.Property>());
}
stmt.setString(1, connectedCupDevice.getName());
stmt.setString(2, DeviceTypeUtils.getDeviceProperty(
connectedCupDevice.getProperties(),
DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN));
stmt.setString(3, DeviceTypeUtils.getDeviceProperty(
connectedCupDevice.getProperties(),
DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_REFRESH_TOKEN));
stmt.setString(4, connectedCupDevice.getDeviceIdentifier());
int rows = stmt.executeUpdate();
if (rows > 0) {
status = true;
if (log.isDebugEnabled()) {
log.debug("Connected Cup device " + connectedCupDevice.getDeviceIdentifier() +
" data has been modified.");
}
}
} catch (SQLException e) {
String msg = "Error occurred while modifying the Connected Cup device '" +
connectedCupDevice.getDeviceIdentifier() + "' data.";
log.error(msg, e);
throw new FirealarmPluginException(msg, e);
} finally {
DeviceTypeUtils.cleanupResources(stmt, null);
}
return status;
}
public boolean deleteDevice(String deviceId) throws FirealarmPluginException {
boolean status = false;
Connection conn;
PreparedStatement stmt = null;
try {
conn = DeviceTypeDAO.getConnection();
String deleteDBQuery =
"DELETE FROM firealarm_DEVICE WHERE firealarm_DEVICE_ID = ?";
stmt = conn.prepareStatement(deleteDBQuery);
stmt.setString(1, deviceId);
int rows = stmt.executeUpdate();
if (rows > 0) {
status = true;
if (log.isDebugEnabled()) {
log.debug("Connected Cup device " + deviceId + " data has deleted" +
" from the Connected Cup database.");
}
}
} catch (SQLException e) {
String msg = "Error occurred while deleting Connected Cup device " + deviceId;
log.error(msg, e);
throw new FirealarmPluginException(msg, e);
} finally {
DeviceTypeUtils.cleanupResources(stmt, null);
}
return status;
}
public List<Device> getAllDevices() throws FirealarmPluginException {
Connection conn;
PreparedStatement stmt = null;
ResultSet resultSet = null;
Device connectedCupDevice;
List<Device> iotDevices = new ArrayList<>();
try {
conn = DeviceTypeDAO.getConnection();
String selectDBQuery =
"SELECT firealarm_DEVICE_ID, DEVICE_NAME, ACCESS_TOKEN, REFRESH_TOKEN" +
"FROM firealarm_DEVICE";
stmt = conn.prepareStatement(selectDBQuery);
resultSet = stmt.executeQuery();
while (resultSet.next()) {
connectedCupDevice = new Device();
connectedCupDevice.setDeviceIdentifier(resultSet.getString(
DeviceTypeConstants.DEVICE_PLUGIN_DEVICE_ID));
connectedCupDevice.setName(resultSet.getString(
DeviceTypeConstants.DEVICE_PLUGIN_DEVICE_NAME));
List<Device.Property> propertyList = new ArrayList<>();
propertyList.add(DeviceTypeUtils.getProperty(
DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_ACCESS_TOKEN,
resultSet.getString("ACCESS_TOKEN")));
propertyList.add(DeviceTypeUtils.getProperty(
DeviceTypeConstants.DEVICE_PLUGIN_PROPERTY_REFRESH_TOKEN,
resultSet.getString("REFRESH_TOKEN")));
connectedCupDevice.setProperties(propertyList);
}
if (log.isDebugEnabled()) {
log.debug("All Connected Cup device details have fetched from Connected Cup database" +
".");
}
return iotDevices;
} catch (SQLException e) {
String msg = "Error occurred while fetching all Connected Cup device data'";
log.error(msg, e);
throw new FirealarmPluginException(msg, e);
} finally {
DeviceTypeUtils.cleanupResources(stmt, resultSet);
DeviceTypeDAO.closeConnection();
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save