added default UI for realtime,batch, device view and type view

revert-70aa11f8
ayyoob 8 years ago
parent 2a89a2fb23
commit 3df2912a6a

@ -22,7 +22,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.policy.mgt.Profile;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig;
@ -101,7 +100,7 @@ public class MQTTNotificationStrategy implements NotificationStrategy {
for (ProfileOperation profileOperation : profileOperations) {
Map<String, String> dynamicProperties = new HashMap<>();
String topic = tenantDomain + "/"
+ deviceType + "/" + deviceId + "/" + profileOperation.getType()
+ deviceType + "/" + deviceId + "/operation/" + profileOperation.getType()
.toString().toLowerCase() + "/" + profileOperation.getCode().toLowerCase();
dynamicProperties.put("topic", topic);
MQTTDataHolder.getInstance().getOutputEventAdapterService().publish(mqttAdapterName, dynamicProperties,
@ -111,11 +110,11 @@ public class MQTTNotificationStrategy implements NotificationStrategy {
} else {
Map<String, String> dynamicProperties = new HashMap<>();
String topic = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(true) + "/"
+ ctx.getDeviceId().getType() + "/" + ctx.getDeviceId().getId() + "/" + operation.getType()
.toString().toLowerCase() + "/" + operation.getCode();
+ ctx.getDeviceId().getType() + "/" + ctx.getDeviceId().getId() + "/operation/"
+ operation.getType().toString().toLowerCase() + "/" + operation.getCode();
dynamicProperties.put("topic", topic);
if (operation.getPayLoad() == null) {
operation.setPayLoad("");
operation.setPayLoad(operation.getCode());
}
MQTTDataHolder.getInstance().getOutputEventAdapterService().publish(mqttAdapterName, dynamicProperties,
operation.getPayLoad());

@ -42,7 +42,6 @@ public class EventRecords extends BasePaginatedResult {
public void setList(List<Record> records) {
this.records = records;
setCount(records.size());
}
@Override

@ -41,7 +41,7 @@ import javax.ws.rs.core.Response;
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "DeviceEventManagement"),
@ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/device-types/events"),
@ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/events"),
})
}
),
@ -65,7 +65,7 @@ import javax.ws.rs.core.Response;
)
}
)
@Path("/device-types/events")
@Path("/events")
@Api(value = "Device Event Management", description = "This API corresponds to all tasks related to device " +
"event management")
@Produces(MediaType.APPLICATION_JSON)

@ -2,6 +2,7 @@ package org.wso2.carbon.device.mgt.jaxrs.service.impl;
import org.apache.axis2.AxisFault;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.Stub;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.Header;
@ -82,7 +83,7 @@ import java.util.UUID;
* This is used for simple analytics purpose, to create streams and receiver dynamically and a common endpoint
* to retrieve data.
*/
@Path("/device-types/events")
@Path("/events")
public class DeviceEventManagementServiceImpl implements DeviceEventManagementService {
private static final Log log = LogFactory.getLog(DeviceEventManagementServiceImpl.class);
@ -138,6 +139,7 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
@Override
public Response getDeviceTypeEventDefinition(@PathParam("type") String deviceType) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
EventStreamAdminServiceStub eventStreamAdminServiceStub = null;
try {
if (deviceType == null ||
!DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(deviceType)) {
@ -146,11 +148,10 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
return Response.status(Response.Status.BAD_REQUEST).build();
}
String streamName = getStreamDefinition(deviceType, tenantDomain);
EventStreamAdminServiceStub eventStreamAdminServiceStub = getEventStreamAdminServiceStub();
eventStreamAdminServiceStub = getEventStreamAdminServiceStub();
EventStreamDefinitionDto eventStreamDefinitionDto = eventStreamAdminServiceStub.getStreamDefinitionDto(
streamName + ":" + DEFAULT_STREAM_VERSION);
if (eventStreamDefinitionDto == null) {
eventStreamAdminServiceStub.cleanup();
return Response.status(Response.Status.NO_CONTENT).build();
}
EventStreamAttributeDto[] eventStreamAttributeDtos = eventStreamDefinitionDto.getPayloadData();
@ -161,7 +162,6 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
, AttributeType.valueOf(eventStreamAttributeDto.getAttributeType().toUpperCase())));
}
eventAttributeList.setList(attributes);
eventStreamAdminServiceStub.cleanup();
return Response.ok().entity(eventAttributeList).build();
} catch (AxisFault e) {
log.error("failed to retrieve event definitions for tenantDomain:" + tenantDomain, e);
@ -178,6 +178,8 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
} catch (DeviceManagementException e) {
log.error("Failed to access device management service, tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} finally {
cleanup(eventStreamAdminServiceStub);
}
}
@ -250,6 +252,12 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
public Response deleteDeviceTypeEventDefinitions(@PathParam("type") String deviceType) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
boolean superTenantMode = false;
EventReceiverAdminServiceStub eventReceiverAdminServiceStub = null;
EventPublisherAdminServiceStub eventPublisherAdminServiceStub = null;
EventStreamAdminServiceStub eventStreamAdminServiceStub = null;
EventReceiverAdminServiceStub tenantBasedEventReceiverAdminServiceStub = null;
EventStreamAdminServiceStub tenantBasedEventStreamAdminServiceStub = null;
try {
if (deviceType == null ||
!DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(deviceType)) {
@ -260,43 +268,35 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
String eventReceiverName = getReceiverName(deviceType, tenantDomain);
String eventPublisherName = deviceType.trim().toLowerCase() + "_websocket_publisher";
String streamName = getStreamDefinition(deviceType, tenantDomain);
EventStreamAdminServiceStub eventStreamAdminServiceStub = getEventStreamAdminServiceStub();
eventStreamAdminServiceStub = getEventStreamAdminServiceStub();
if (eventStreamAdminServiceStub.getStreamDefinitionDto(streamName + ":" + DEFAULT_STREAM_VERSION) == null) {
return Response.status(Response.Status.NO_CONTENT).build();
}
eventStreamAdminServiceStub.removeEventStreamDefinition(streamName, DEFAULT_STREAM_VERSION);
EventReceiverAdminServiceCallbackHandler eventReceiverAdminServiceCallbackHandler =
new EventReceiverAdminServiceCallbackHandler() {};
EventPublisherAdminServiceCallbackHandler eventPublisherAdminServiceCallbackHandler =
new EventPublisherAdminServiceCallbackHandler() {};
EventReceiverAdminServiceStub eventReceiverAdminServiceStub = getEventReceiverAdminServiceStub();
eventReceiverAdminServiceStub.startundeployActiveEventReceiverConfiguration(eventReceiverName
eventReceiverAdminServiceStub = getEventReceiverAdminServiceStub();
eventReceiverAdminServiceStub.startundeployInactiveEventReceiverConfiguration(eventReceiverName
, eventReceiverAdminServiceCallbackHandler);
eventStreamAdminServiceStub.removeEventStreamDefinition(streamName, DEFAULT_STREAM_VERSION);
EventPublisherAdminServiceStub eventPublisherAdminServiceStub = getEventPublisherAdminServiceStub();
eventPublisherAdminServiceStub.startundeployActiveEventPublisherConfiguration(eventPublisherName
eventPublisherAdminServiceStub = getEventPublisherAdminServiceStub();
eventPublisherAdminServiceStub.startundeployInactiveEventPublisherConfiguration(eventPublisherName
, eventPublisherAdminServiceCallbackHandler);
eventStreamAdminServiceStub.cleanup();
eventPublisherAdminServiceStub.cleanup();
eventReceiverAdminServiceStub.cleanup();
superTenantMode = true;
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
eventReceiverAdminServiceStub = getEventReceiverAdminServiceStub();
eventStreamAdminServiceStub = getEventStreamAdminServiceStub();
eventReceiverAdminServiceStub.startundeployActiveEventReceiverConfiguration(eventReceiverName
, eventReceiverAdminServiceCallbackHandler);
tenantBasedEventReceiverAdminServiceStub = getEventReceiverAdminServiceStub();
tenantBasedEventStreamAdminServiceStub = getEventStreamAdminServiceStub();
eventStreamAdminServiceStub.removeEventStreamDefinition(streamName, DEFAULT_STREAM_VERSION);
eventReceiverAdminServiceStub.startundeployInactiveEventReceiverConfiguration(eventReceiverName
, eventReceiverAdminServiceCallbackHandler);
eventReceiverAdminServiceStub.cleanup();
eventStreamAdminServiceStub.cleanup();
}
return Response.ok().build();
} catch (AxisFault e) {
@ -318,6 +318,11 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
if (superTenantMode) {
PrivilegedCarbonContext.endTenantFlow();
}
cleanup(eventStreamAdminServiceStub);
cleanup(eventPublisherAdminServiceStub);
cleanup(eventReceiverAdminServiceStub);
cleanup(eventReceiverAdminServiceStub);
cleanup(eventStreamAdminServiceStub);
}
}
@ -367,6 +372,7 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
, String requestedTenantDomain, String deviceType)
throws RemoteException, UserStoreException, JWTClientException {
EventReceiverAdminServiceStub receiverAdminServiceStub = getEventReceiverAdminServiceStub();
try {
String adapterType = "oauth-mqtt";
BasicInputAdapterPropertyDto basicInputAdapterPropertyDtos[];
if (transportType == TransportType.MQTT) {
@ -385,18 +391,21 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
receiverAdminServiceStub.deployJsonEventReceiverConfiguration(eventRecieverName, streamNameWithVersion
, adapterType, null, basicInputAdapterPropertyDtos, false);
}
receiverAdminServiceStub.cleanup();
} finally {
cleanup(receiverAdminServiceStub);
}
}
private void publishStreamDefinitons(String streamName, String version, String deviceType
, EventAttributeList eventAttributes)
throws RemoteException, UserStoreException, JWTClientException {
EventStreamAdminServiceStub eventStreamAdminServiceStub = getEventStreamAdminServiceStub();
try {
EventStreamDefinitionDto eventStreamDefinitionDto = new EventStreamDefinitionDto();
eventStreamDefinitionDto.setName(streamName);
eventStreamDefinitionDto.setVersion(version);
EventStreamAttributeDto eventStreamAttributeDtos[] =
new EventStreamAttributeDto[eventAttributes.getList().size()];
new EventStreamAttributeDto[eventAttributes.getList().size() + 1];
int i = 0;
for (Attribute attribute : eventAttributes.getList()) {
EventStreamAttributeDto eventStreamAttributeDto = new EventStreamAttributeDto();
@ -405,12 +414,11 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
eventStreamAttributeDtos[i] = eventStreamAttributeDto;
i++;
}
EventStreamAttributeDto metaData[] = new EventStreamAttributeDto[1];
EventStreamAttributeDto eventStreamAttributeDto = new EventStreamAttributeDto();
eventStreamAttributeDto.setAttributeName("deviceId");
eventStreamAttributeDto.setAttributeType(AttributeType.STRING.toString());
metaData[0] = eventStreamAttributeDto;
eventStreamDefinitionDto.setMetaData(metaData);
eventStreamAttributeDtos[i] = eventStreamAttributeDto;
eventStreamDefinitionDto.setPayloadData(eventStreamAttributeDtos);
String streamId = streamName + ":" + version;
if (eventStreamAdminServiceStub.getStreamDefinitionDto(streamId) != null) {
@ -418,14 +426,17 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
} else {
eventStreamAdminServiceStub.addEventStreamDefinitionAsDto(eventStreamDefinitionDto);
}
eventStreamAdminServiceStub.cleanup();
} finally {
cleanup(eventStreamAdminServiceStub);
}
}
private void publishEventStore(String streamName, String version, EventAttributeList eventAttributes)
throws RemoteException, UserStoreException, JWTClientException,
EventStreamPersistenceAdminServiceEventStreamPersistenceAdminServiceExceptionException {
EventStreamPersistenceAdminServiceStub eventStreamAdminServiceStub =
EventStreamPersistenceAdminServiceStub eventStreamPersistenceAdminServiceStub =
getEventStreamPersistenceAdminServiceStub();
try {
AnalyticsTable analyticsTable = new AnalyticsTable();
analyticsTable.setRecordStoreName(DEFAULT_EVENT_STORE_NAME);
analyticsTable.setStreamVersion(version);
@ -447,7 +458,7 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
i++;
}
AnalyticsTableRecord analyticsTableRecord = new AnalyticsTableRecord();
analyticsTableRecord.setColumnName("meta_deviceId");
analyticsTableRecord.setColumnName("deviceId");
analyticsTableRecord.setColumnType(AttributeType.STRING.toString().toUpperCase());
analyticsTableRecord.setFacet(false);
analyticsTableRecord.setIndexed(true);
@ -456,20 +467,25 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
analyticsTableRecord.setScoreParam(false);
analyticsTableRecords[i] = analyticsTableRecord;
analyticsTable.setAnalyticsTableRecords(analyticsTableRecords);
eventStreamAdminServiceStub.addAnalyticsTable(analyticsTable);
eventStreamAdminServiceStub.cleanup();
eventStreamPersistenceAdminServiceStub.addAnalyticsTable(analyticsTable);
} finally {
cleanup(eventStreamPersistenceAdminServiceStub);
}
}
private void publishWebsocketPublisherDefinition(String streamNameWithVersion, String deviceType)
throws RemoteException, UserStoreException, JWTClientException {
EventPublisherAdminServiceStub eventPublisherAdminServiceStub = getEventPublisherAdminServiceStub();
try {
String eventPublisherName = deviceType.trim().toLowerCase() + "_websocket_publisher";
if (eventPublisherAdminServiceStub.getActiveEventPublisherConfiguration(eventPublisherName) == null) {
eventPublisherAdminServiceStub.deployJsonEventPublisherConfiguration(eventPublisherName
, streamNameWithVersion, DEFAULT_WEBSOCKET_PUBLISHER_ADAPTER_TYPE, null, null
, null, false);
}
eventPublisherAdminServiceStub.cleanup();
} finally {
cleanup(eventPublisherAdminServiceStub);
}
}
private EventStreamAdminServiceStub getEventStreamAdminServiceStub()
@ -695,15 +711,16 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
, int offset, int limit) throws AnalyticsException {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI();
EventRecords eventRecords = new EventRecords();
int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query);
if (eventCount == 0) {
return null;
eventRecords.setCount(0);
}
List<SearchResultEntry> resultEntries = analyticsDataAPI.search(tenantId, tableName, query, offset, limit,
sortByFields);
List<String> recordIds = getRecordIds(resultEntries);
AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, null, recordIds);
EventRecords eventRecords = new EventRecords();
eventRecords.setCount(eventCount);
eventRecords.setList(AnalyticsDataAPIUtil.listRecords(analyticsDataAPI, response));
return eventRecords;
}
@ -716,4 +733,14 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
return ids;
}
private void cleanup(Stub stub) {
if (stub != null) {
try {
stub.cleanup();
} catch (AxisFault axisFault) {
// do nothing
}
}
}
}

@ -736,6 +736,13 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
log.error(errorMessage);
return Response.status(Response.Status.BAD_REQUEST).build();
}
if (!DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(type)) {
String errorMessage = "Device identifier list is empty";
log.error(errorMessage);
return Response.status(Response.Status.BAD_REQUEST).build();
}
Operation.Type operationType = operationRequest.getOperation().getType();
if (operationType == Operation.Type.COMMAND || operationType == Operation.Type.CONFIG) {
DeviceIdentifier deviceIdentifier;
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
for (String deviceId : operationRequest.getDeviceIdentifiers()) {
@ -747,6 +754,11 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
Activity activity = DeviceMgtAPIUtils.getDeviceManagementService().addOperation(type
, operationRequest.getOperation(), deviceIdentifiers);
return Response.status(Response.Status.CREATED).entity(activity).build();
} else {
String message = "Only Command and Config operation is supported through this api";
return Response.status(Response.Status.NOT_ACCEPTABLE).entity(message).build();
}
} catch (InvalidDeviceException e) {
String errorMessage = "Invalid Device Identifiers found.";
log.error(errorMessage, e);
@ -757,6 +769,11 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
log.error(errorMessage, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build();
} catch (DeviceManagementException e) {
String errorMessage = "Issue in retrieving deivce management service instance";
log.error(errorMessage, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build();
}
}
@ -764,6 +781,11 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@Path("/{type}/{id}/pending/operations")
public Response getPendingOperations(@PathParam("type") String type, @PathParam("id") String deviceId) {
try {
if (!DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(type)) {
String errorMessage = "Device identifier list is empty";
log.error(errorMessage);
return Response.status(Response.Status.BAD_REQUEST).build();
}
List<? extends Operation> operations = DeviceMgtAPIUtils.getDeviceManagementService().getPendingOperations(
new DeviceIdentifier(deviceId, type));
OperationList operationsList = new OperationList();
@ -775,6 +797,11 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
log.error(errorMessage, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build();
} catch (DeviceManagementException e) {
String errorMessage = "Issue in retrieving deivce management service instance";
log.error(errorMessage, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build();
}
}
@ -782,6 +809,11 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@Path("/{type}/{id}/last-pending/operation")
public Response getNextPendingOperation(@PathParam("type") String type, @PathParam("id") String deviceId) {
try {
if (!DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(type)) {
String errorMessage = "Device identifier list is empty";
log.error(errorMessage);
return Response.status(Response.Status.BAD_REQUEST).build();
}
Operation operation = DeviceMgtAPIUtils.getDeviceManagementService().getNextPendingOperation(
new DeviceIdentifier(deviceId, type));
return Response.status(Response.Status.OK).entity(operation).build();
@ -790,6 +822,11 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
log.error(errorMessage, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build();
} catch (DeviceManagementException e) {
String errorMessage = "Issue in retrieving deivce management service instance";
log.error(errorMessage, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build();
}
}
@ -797,6 +834,11 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@Path("/{type}/{id}/operations")
public Response updateOperation(@PathParam("type") String type, @PathParam("id") String deviceId, @Valid Operation operation) {
try {
if (!DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(type)) {
String errorMessage = "Device identifier list is empty";
log.error(errorMessage);
return Response.status(Response.Status.BAD_REQUEST).build();
}
if (operation == null) {
String errorMessage = "Device identifier list is empty";
log.error(errorMessage);
@ -810,6 +852,11 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
log.error(errorMessage, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build();
} catch (DeviceManagementException e) {
String errorMessage = "Issue in retrieving deivce management service instance";
log.error(errorMessage, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(errorMessage).build()).build();
}
}
@ -824,6 +871,11 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
}
try {
if (!DeviceMgtAPIUtils.getDeviceManagementService().getAvailableDeviceTypes().contains(type)) {
String errorMessage = "Device identifier list is empty";
log.error(errorMessage);
return Response.status(Response.Status.BAD_REQUEST).build();
}
List<? extends Operation> operations = DeviceMgtAPIUtils.getDeviceManagementService()
.getOperationsByDeviceAndStatus(new DeviceIdentifier(deviceId, type), status);
OperationList operationsList = new OperationList();

@ -0,0 +1,77 @@
<%
/*
* 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 uri = request.getRequestURI();
var uriMatcher = new URIMatcher(String(uri));
var log = new Log("api/stats-api.jag");
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
if (uriMatcher.match("/{context}/api/stats/paginate")) {
var deviceType = request.getParameter("deviceType");
var deviceId = request.getParameter("deviceId");
var from = request.getParameter("from");
var to = request.getParameter("to");
var index = request.getParameter("start");
var length = request.getParameter("length");
var keys = request.getParameter("attributes");
keys = JSON.parse(keys);
var restAPIEndpoint = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/events/"
+ deviceType + "/" + deviceId + "?offset=" + index +"&limit=" + length + "&from="+ from + "&to=" + to;
serviceInvokers.XMLHttp.get(
restAPIEndpoint,
function (restAPIResponse) {
if (restAPIResponse["status"] == 200 && restAPIResponse["responseText"]) {
var responsePayload = parse(restAPIResponse["responseText"]);
var paginatedResult = {};
paginatedResult["recordsTotal"] = responsePayload["count"];
paginatedResult["recordsFiltered"] = responsePayload["count"];
var records = responsePayload["records"];
var dataSet = [];
for (var i = 0; i < records.length; i++){
var record = records[i];
var timestamp = record["timestamp"];
var dataRow = [];
dataRow.push(timestamp);
for (var j = 0; j < keys.length; j++) {
var key = keys[j];
dataRow.push(record.values[key]);
}
//dataSet.push(dataRow);
dataSet.push(dataRow);
}
paginatedResult["data"] = dataSet;
response["status"] = restAPIResponse["status"];
response["content"] = paginatedResult;
} else {
response["status"] = 204;
var paginatedResult = {};
var dataSet = [];
paginatedResult["recordsTotal"] = 0;
paginatedResult["recordsFiltered"] = 0;
paginatedResult["data"] = dataSet;
response["content"] = paginatedResult;
}
}
);
}
%>

@ -176,7 +176,9 @@
"perm:ios:get-restrictions",
"perm:ios:wipe-data",
"perm:admin",
"perm:devicetype:deployment"
"perm:devicetype:deployment",
"perm:device-types:events",
"perm:device-types:events:view"
],
"isOAuthEnabled": true,
"backendRestEndpoints": {

@ -21,8 +21,12 @@ function onRequest(context) {
var deviceType = context.uriParams.deviceType;
var deviceName = request.getParameter("deviceName");
var deviceId = request.getParameter("deviceId");
var unitName = utility.getTenantedDeviceUnitName(deviceType, "analytics-view");
if (!unitName) {
unitName = "cdmf.unit.default.device.type.analytics-view";
}
return {
"deviceAnalyticsViewUnitName": utility.getTenantedDeviceUnitName(deviceType, "analytics-view"),
"deviceAnalyticsViewUnitName": unitName,
"deviceType": deviceType,
"deviceName": deviceName,
"deviceId": deviceId

@ -103,7 +103,14 @@ function setDateTime(from, to) {
// Implement drawGraph_<device type name> method in your UI unit for analytics.
var deviceTypes = $("#device-type-details").data("devicetypes");
for (var i = 0; i < deviceTypes.length; i++){
try{
window["drawGraph_" + deviceTypes](parseInt(from / 1000), parseInt(to / 1000));
}catch(e){
}
try{
window["drawTable"](parseInt(from / 1000), parseInt(to / 1000));
}catch(e){
}
}
}

@ -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.
}}
<span id="operation-details" data-endpoint="{{operationEndpoint}}" data-deviceid="{{device.deviceIdentifier}}">
{{#if control_operations}}
<div class="wr-operations" style="height: 87px; display: block;">
<style>
::-webkit-input-placeholder {
color: #B8B8B8;
}
::-moz-placeholder {
color: #B8B8B8;
}
:-ms-input-placeholder {
color: #B8B8B8;
}
input:-moz-placeholder {
color: #B8B8B8;
}
</style>
{{#each control_operations}}
<a href="javascript:operationSelect('{{operation}}')">
<i class="fw fw-service"></i>
<span>{{name}}</span>
</a>
<div class="operation" data-operation-code="{{operation}}">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h3>
<span class="fw-stack">
<i class="fw fw-circle-outline fw-stack-2x"></i>
<i class="fw fw-service fw-stack-1x"></i>
</span>
{{name}}
<br>
</h3>
<h4>
{{description}}
<br>
</h4>
<form id="form-{{operation}}" style="padding-bottom: 20px;"-->
<select id="operation-type" class="form-control" onChange="operationTypeChage(this)">
<option value="CONFIG">Config</option>
<option value="COMMAND">Command</option>
</select>
<br />
<input type="hidden" id="operation-code" value="{{operation}}" />
<textarea id="operation-payload" placeholder="payload" class="form-control" rows="10" cols="70"></textarea>
<br />
<button id="btnSend" type="button" onclick="submitForm('form-{{operation}}')" class="btn btn-default">&nbsp;&nbsp;&nbsp;&nbsp;Send
to Device&nbsp;&nbsp;&nbsp;&nbsp;</button>
<label id="lblSending" class="wr-input-label hidden"><i
class="fw fw-lifecycle fw-spin fw-2x"></i> Sending..</label>
<label id="lblSent" class="wr-input-label hidden"><i
class="fw fw-check fw-2x"></i> Sent</label>
</form>
</div>
</div>
</div>
</div>
{{/each}}
</div>
{{else}}
<div align="center">
<h4 style="color: #D8000C"><i class="icon fw fw-error" style="color: #D8000C"></i>
Operations Loading Failed!</h4>
</div>
{{/if}}
<div id="operation-response-template" style="display: none">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h3>
<span class="fw-stack">
<i class="fw fw-circle-outline fw-stack-2x"></i>
<i id="status-icon" class="fw fw-error fw-stack-1x"></i>
</span>
<br>
</h3>
<h4>
<span id="title"></span>
<br>
</h4>
<span id="description"></span>
</div>
</div>
</div>
</div>
{{#zone "bottomJs"}}
{{js "js/operation-bar.js"}}
{{/zone}}

@ -0,0 +1,29 @@
/*
* 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.
*/
function onRequest(context) {
var log = new Log("operation.js");
var deviceType = context.uriParams.deviceType;
var operationModule = require("/app/modules/business-controllers/operation.js")["operationModule"];
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var restAPIEndpoint = devicemgtProps["backendRestEndpoints"]["deviceMgt"]
+ "/devices/" + deviceType + "/operations";
var device = context.unit.params.device;
var features = context.unit.params.features;
return {"control_operations": features, "device": device, "operationEndpoint": restAPIEndpoint};
}

@ -0,0 +1,116 @@
/*
* 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.
*/
/*
* On operation click function.
* @param selection: Selected operation
*/
function operationSelect(selection) {
$(modalPopupContent).addClass("operation-data");
$(modalPopupContent).html($(" .operation[data-operation-code=" + selection + "]").html());
$(modalPopupContent).data("operation-code", selection);
showPopup();
}
function submitForm(formId) {
var form = $("#" + formId);
var operationDetails = $("#operation-details");
var deviceId = operationDetails.data("deviceid");
var operationEndpoint = operationDetails.data("endpoint");
console.log(deviceId);
console.log(operationEndpoint);
var contentType = "application/json";
var payload = {};
var devices=[];
devices.push(deviceId);
payload["deviceIdentifiers"] = devices;
var operation = {};
operation["code"] = form.find("#operation-code").val();
operation["type"]= form.find("#operation-type").val();
operation["status"] = "IN_PROGRESS";
operation["control"] = "REPEAT";
operation["payLoad"] = form.find("#operation-payload").val();
operation["enabled"] = true;
payload["operation"] = operation;
//setting responses callbacks
var defaultStatusClasses = "fw fw-stack-1x";
var content = $("#operation-response-template").find(".content");
var title = content.find("#title");
var statusIcon = content.find("#status-icon");
var description = content.find("#description");
var successCallBack = function (response) {
var res = response;
try {
res = JSON.parse(response).messageFromServer;
} catch (err) {
//do nothing
}
title.html("Operation Triggered!");
statusIcon.attr("class", defaultStatusClasses + " fw-check");
description.html(res);
$(modalPopupContent).html(content.html());
};
var errorCallBack = function (response) {
console.log(response);
title.html("An Error Occurred!");
statusIcon.attr("class", defaultStatusClasses + " fw-error");
var reason = (response.responseText == "null")?response.statusText:response.responseText;
description.html(reason);
$(modalPopupContent).html(content.html());
};
invokerUtil.post(operationEndpoint, payload, successCallBack, errorCallBack, contentType);
}
$(document).on('submit', 'form', function (e) {
e.preventDefault();
var postOperationRequest = $.ajax({
url: $(this).attr("action") + '&' + $(this).serialize(),
method: "post"
});
var btnSubmit = $('#btnSend', this);
btnSubmit.addClass('hidden');
var lblSending = $('#lblSending', this);
lblSending.removeClass('hidden');
var lblSent = $('#lblSent', this);
postOperationRequest.done(function (data) {
lblSending.addClass('hidden');
lblSent.removeClass('hidden');
setTimeout(function () {
hidePopup();
}, 3000);
});
postOperationRequest.fail(function (jqXHR, textStatus) {
lblSending.addClass('hidden');
lblSent.addClass('hidden');
});
});
function operationTypeChage(selectElement) {
if (selectElement.value == "COMMAND") {
$("#operation-payload").hide();
} else {
$("#operation-payload").show();
}
}

@ -0,0 +1,65 @@
{{!
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.
}}
<table class="table table-responsive table-striped" id="members">
<tbody>
<tr role="row" class="odd">
<td class="sorting_1" style="padding:10px 15px;">Model</td>
<td style="padding:10px 15px;">TODO</td>
</tr>
<tr role="row" class="even">
<td class="sorting_1" style="padding:10px 15px;">Status</td>
<td style="padding:10px 15px;">
{{#if permissions.CHANGE_DEVICE_STATUS}}
{{#equal device.status "ACTIVE"}}<span><i id="statusIcon"
class="fw fw-success icon-success"></i>
<a href="#" id="status" data-type="select" data-pk="1"
data-title="Select status"
selectedValue="Active"></a>
</span>{{/equal}}
{{#equal device.status "INACTIVE"}}<span><i id="statusIcon"
class="fw fw-warning icon-warning"></i>
<a href="#" id="status" data-type="select" data-pk="1"
data-title="Select status"
selectedValue="Inactive"></a>
</span>{{/equal}}
{{#equal device.status "BLOCKED"}}<span><i id="statusIcon"
class="fw fw-remove icon-danger"></i>
<a href="#" id="status" data-type="select" data-pk="1"
data-title="Select status"
selectedValue="Blocked"></a>
</span>{{/equal}}
{{#equal device.status "REMOVED"}}<span><i id="statusIcon"
class="fw fw-delete icon-danger"></i>
<a href="#" id="status" data-type="select" data-pk="1"
data-title="Select status"
selectedValue="Removed"></a>
</span>{{/equal}}
{{else}}
{{#equal device.status "ACTIVE"}}<span><i
class="fw fw-success icon-success"></i> Active</span>{{/equal}}
{{#equal device.status "INACTIVE"}}<span><i
class="fw fw-warning icon-warning"></i> Inactive</span>{{/equal}}
{{#equal device.status "BLOCKED"}}<span><i
class="fw fw-remove icon-danger"></i> Blocked</span>{{/equal}}
{{#equal device.status "REMOVED"}}<span><i
class="fw fw-delete icon-danger"></i> Removed</span>{{/equal}}
{{/if}}
</td>
</tr>
</tbody>
</table>

@ -0,0 +1,23 @@
/*
* 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.
*/
function onRequest (context) {
var log = new Log("overview-section.js");
var device = context.unit.params.device;
return {"device" : device};
}

@ -0,0 +1,47 @@
{{!
Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
WSO2 Inc. licenses this file to you under the Apache License,
Version 2.0 (the "License"); you may not use this file except
in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
}}
{{unit "cdmf.unit.data-tables-extended"}}
<span id="device-details" data-devices="{{devices}}" data-devicename="{{device.name}}"
data-deviceid="{{device.deviceIdentifier}}"
data-devicetype="{{device.type}}"
data-appcontext="{{@app.context}}" data-attributes="{{attributes}}"></span>
<div id="device-div-chart" data-backend-api-url= {{backendApiUri}}>
{{#if attributes}}
<table class="table table-striped table-hover table-bordered display data-table"
id="stats-table">
<thead>
<tr id="header-rows">
<td>Timestamp</td>
{{#each attributes}}
<td>{{this}}</td>
{{/each}}
</tr>
</thead>
<tbody>
</tbody>
</table>
{{else}}
<div id="warn-config"><h1>Analytics Not Configured</h1> </div>
{{/if}}
</div>
{{#zone "bottomJs"}}
{{js "js/device.js"}}
{{/zone}}

@ -0,0 +1,71 @@
/*
* 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.
*/
function onRequest(context) {
var deviceType = context.uriParams.deviceType;
var deviceId = request.getParameter("deviceId");
var keys = [];
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) {
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
var device = deviceModule.viewDevice(deviceType, deviceId);
var restAPIEndpoint = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"]
+ "/events/" + deviceType;
serviceInvokers.XMLHttp.get(
restAPIEndpoint,
function (restAPIResponse) {
if (restAPIResponse["status"] == 200 && restAPIResponse["responseText"]) {
var eventAttributes = parse(restAPIResponse["responseText"]);
if (eventAttributes.attributes.length > 0) {
for (var i = 0; i < eventAttributes.attributes.length; i++) {
var attribute = eventAttributes.attributes[i];
if (attribute['name'] == "deviceId") {
continue;
}
keys.push(attribute['name']);
}
}
}
}
);
if (device && device.status != "error") {
if (keys.length === 0 || keys.length === undefined) {
return {
"device": device.content,
"backendApiUri": "/api/device-mgt/v1.0/events/" + deviceType
};
} else {
return {
"device": device.content,
"backendApiUri": "/api/device-mgt/v1.0/events/" + deviceType,
"attributes": keys
};
}
} else {
response.sendError(404, "Device Id " + deviceId + " of type " + deviceType + " cannot be found!");
exit();
}
}
}

@ -0,0 +1,74 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
var InitiateViewOption = null;
var deviceId = null;
var deviceType = null;
var fromTime = null;
var toTime = null;
var keys = null;
function drawTable(from, to) {
var device = $("#device-details");
deviceId = device.data("deviceid");
deviceType = device.data("devicetype");
keys = device.data("attributes").split(",");
fromTime = from * 1000;
toTime = to * 1000;
if ( $.fn.dataTable.isDataTable( '#stats-table' ) ) {
var table = $('#stats-table').DataTable();
table.clear().draw();
table.ajax.reload();
}
else {
$("#stats-table").datatables_extended({
serverSide: true,
processing: false,
searching: false,
ordering: false,
pageLength: 100,
order: [],
ajax: {
url: "/devicemgt/api/stats/paginate",
data: buildAjaxData
}
});
}
}
function buildAjaxData (){
var settings = $("#stats-table").dataTable().fnSettings();
var obj = {
//default params
"draw" : settings.iDraw,
"start" : settings._iDisplayStart,
"length" : settings._iDisplayLength,
"columns" : "",
"order": "",
"deviceType" : deviceType,
"deviceId" : deviceId,
"from": fromTime,
"to" : toTime,
"attributes" : JSON.stringify(keys)
};
return obj;
}

@ -23,34 +23,50 @@
</style>
{{/zone}}
{{#zone "overview-section"}}
<div style="background: #11375B; color: #fff; padding: 10px; margin-bottom: 5px">
Device Overview - {{label}}</div>
{{unit "cdmf.unit.default.device.overview-section" device=device}}
{{/zone}}
{{#zone "device-thumbnail"}}
<img src="{{@unit.publicUri}}/images/deviceType.png"/>
{{/zone}}
{{#zone "device-opetations"}}
{{#if features}}
<div style="background: #11375B; color: #fff; padding: 10px; margin-bottom: 5px">
Operations
</div>
<div class="add-margin-top-4x">
operation comes here
{{unit "cdmf.unit.default.device.operation-bar" device=device features=features}}
</div>
{{/if}}
{{/zone}}
{{#zone "device-view-tabs"}}
{{#if attributes}}
<li class="active"><a class="list-group-item" href="#device_statistics" role="tab"
data-toggle="tab" aria-controls="device_statistics">Device
Statistics</a>
</li>
{{/if}}
{{#if features}}
<li><a class="list-group-item" href="#event_log" role="tab" data-toggle="tab"
aria-controls="event_log">Operations Log</a></li>
{{/if}}
{{/zone}}
{{#zone "device-view-tab-contents"}}
{{#if attributes}}
<div class="panel panel-default tab-pane active"
id="device_statistics" role="tabpanel" aria-labelledby="device_statistics">
<div class="panel-heading">Device Statistics</div>
unit "cdmf.unit.device.type.senseme.realtime.analytics-view" device=device
<div class="panel-heading">Realtime Statistics</div>
{{unit "cdmf.unit.default.device.type.realtime.analytics-view" device=device attributes=attributes}}
</div>
{{/if}}
{{#if features}}
<div class="panel panel-default tab-pane" id="event_log" role="tabpanel"
aria-labelledby="event_log">
<div class="panel-heading">Operations Log <span><a href="#"
@ -74,4 +90,5 @@
</div>
</div>
</div>
{{/if}}
{{/zone}}

@ -15,11 +15,53 @@
* specific language governing permissions and limitations
* under the License.
*/
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
function onRequest(context) {
var log = new Log("device-view.js");
var deviceType = context.uriParams.deviceType;
var deviceId = request.getParameter("id");
var attributes = [];
var featureList = [];
log.error(featureList);
var restAPIEndpoint = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"]
+ "/events/" + deviceType;
serviceInvokers.XMLHttp.get(
restAPIEndpoint,
function (restAPIResponse) {
if (restAPIResponse["status"] == 200 && restAPIResponse["responseText"]) {
var eventAttributes = parse(restAPIResponse["responseText"]);
if (eventAttributes.attributes.length > 0) {
for (var i = 0; i < eventAttributes.attributes.length; i++) {
var attribute = eventAttributes.attributes[i];
if (attribute['name'] == "deviceId") {
continue;
}
attributes.push(attribute['name']);
}
}
}
}
);
var featureEndpoint = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"]
+ "/device-types/" + deviceType + "/features";
var featuresList = serviceInvokers.XMLHttp.get(featureEndpoint, function (responsePayload) {
var features = JSON.parse(responsePayload.responseText);
var feature;
for (var i = 0; i < features.length; i++) {
feature = {};
feature["operation"] = features[i].code;
feature["name"] = features[i].name;
feature["description"] = features[i].description;
}
featureList.push(feature);
}, function (responsePayload) {
featureList = null;
}
);
var autoCompleteParams = [
{"name" : "deviceId", "value" : deviceId}
];
@ -28,7 +70,13 @@ function onRequest(context) {
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
var device = deviceModule.viewDevice(deviceType, deviceId);
if (device && device.status != "error") {
return {"device": device.content, "autoCompleteParams" : autoCompleteParams, "encodedFeaturePayloads": ""};
if (attributes.length === 0 || attributes.length === undefined) {
return {"device": device.content, "autoCompleteParams" : autoCompleteParams
, "encodedFeaturePayloads": "", "features":featureList};
} else {
return {"device": device.content, "autoCompleteParams" : autoCompleteParams
, "encodedFeaturePayloads": "", "attributes": attributes, "features":featureList};
}
} else {
response.sendError(404, "Device Id " + deviceId + " of type " + deviceType + " cannot be found!");
exit();

@ -0,0 +1,44 @@
{{!
Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
WSO2 Inc. licenses this file to you under the Apache License,
Version 2.0 (the "License"); you may not use this file except
in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
}}
{{unit "cdmf.unit.lib.rickshaw-graph"}}
<div id="div-chart" data-websocketurl="{{websocketEndpoint}}" data-attributes="{{attributes}}">
<table class="table table-responsive table-striped" id="members">
<tbody>
{{#each attributes}}
<tr role="row" class="odd">
<td class="sorting_1" style="padding:10px 15px;">{{this}}</td>
<td id="{{this}}-value" style="padding:10px 15px;">-</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
<a class="padding-left"
href="{{@app.context}}/device/{{device.type}}/analytics?deviceId={{device.deviceIdentifier}}&deviceName={{device.name}}">
<span class="fw-stack">
<i class="fw fw-circle-outline fw-stack-2x"></i>
<i class="fw fw-statistics fw-stack-1x"></i>
</span> View Device Analytics
</a>
<!-- /statistics -->
{{#zone "bottomJs"}}
{{js "js/moment.min.js"}}
{{js "js/socket.io.min.js"}}
{{js "js/device-stats.js"}}
{{/zone}}

@ -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.
*/
function onRequest(context) {
var log = new Log("stats.js");
var carbonServer = require("carbon").server;
var device = context.unit.params.device;
var attributes = context.unit.params.attributes;
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var constants = require("/app/modules/constants.js");
var websocketEndpoint = devicemgtProps["wssURL"].replace("https", "wss");
var jwtService = carbonServer.osgiService(
'org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService');
var jwtClient = jwtService.getJWTClient();
var encodedClientKeys = session.get(constants["ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS"]);
var token = "";
var user = userModule.getCarbonUser();
var tenantDomain = user.domain;
if (encodedClientKeys) {
var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"];
var resp = tokenUtil.decode(encodedClientKeys).split(":");
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {});
if (tokenPair) {
token = tokenPair.accessToken;
}
if (tenantDomain == "carbon.super") {
websocketEndpoint = websocketEndpoint + "/secured-websocket/" + tenantDomain + "." + device.type + "/1.0.0?"
+ "deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type + "&websocketToken=" + token;
} else {
websocketEndpoint = websocketEndpoint + "/t/" + tenantDomain + "/secured-websocket/" + tenantDomain
+ "." + device.type + "/1.0.0?" + "deviceId=" + device.deviceIdentifier + "&deviceType="
+ device.type + "&websocketToken=" + token;
}
}
return {"device": device, "websocketEndpoint": websocketEndpoint, "attributes": attributes};
}

@ -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.
*/
var ws;
var attributes = null;
$(window).load(function () {
var div = $("#div-chart");
var websocketUrl = div.data("websocketurl");
attributes = div.data("attributes").split(",");
connect(websocketUrl)
});
$(window).unload(function () {
disconnect();
});
//websocket connection
function connect(target) {
if ('WebSocket' in window) {
ws = new WebSocket(target);
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket(target);
} else {
console.log('WebSocket is not supported by this browser.');
}
if (ws) {
ws.onmessage = function (webSocketData) {
var data = JSON.parse(webSocketData.data);
var payloadData = data["event"]["payloadData"];
for (var i = 0; i < attributes.length; i++){
$("#" + attributes[i] +"-value").text(payloadData[attributes[i]]);
}
};
}
}
function disconnect() {
if (ws != null) {
ws.close();
ws = null;
}
}

@ -134,6 +134,32 @@
<br>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 padding-double grey-bg">
<h3 class="uppercase">Topic to publish data for analytics : {{tenantDomain}}/{{deviceType}}/&lt;device_id&gt;/events</h3>
<h3 class="uppercase">Topic to publish data to an external system : {{tenantDomain}}/{{deviceType}}/&lt;device_id&gt;/proxy</h3>
<h3 class="uppercase">Topic to listen for operation: {{tenantDomain}}/{{deviceType}}/&lt;device_id&gt;/operation/#</h3>
<hr>
<ul class="list-unstyled">
<li class="padding-top-double">
{{tenantDomain}}/{{deviceType}}/&lt;device_id&gt;/operation/command/&lt;feature_code&gt;
</li>
<li class="padding-top-double">
{{tenantDomain}}/{{deviceType}}/&lt;device_id&gt;/operation/config/&lt;feature_code&gt;
</li>
<li class="padding-top-double">
{{tenantDomain}}/{{deviceType}}/&lt;device_id&gt;/operation/profile/&lt;feature_code&gt;
</li>
<li class="padding-top-double">
{{tenantDomain}}/{{deviceType}}/&lt;device_id&gt;/operation/policy/policy_bundle
</li>
<li class="padding-top-double">
{{tenantDomain}}/{{deviceType}}/&lt;device_id&gt;/operation/policy/policy_revoke
</li>
</ul>
<br>
<br>
</div>
{{#zone "topCss"}}
{{css "css/styles.css"}}
{{/zone}}

@ -18,7 +18,11 @@
function onRequest(context) {
var deviceType = context.uriParams.deviceType;
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var user = userModule.getCarbonUser();
var tenantDomain = user.domain;
return {
"deviceType": deviceType
"deviceType": deviceType,
"tenantDomain": tenantDomain
};
}

@ -54,6 +54,10 @@
{
"url": "/api/operation/*",
"path": "/api/operation-api.jag"
},
{
"url": "/api/stats/*",
"path": "/api/stats-api.jag"
}
],
"errorPages": {

Loading…
Cancel
Save