From 7a715c2ac81cfc3bad5d9570796a2d898e15a15c Mon Sep 17 00:00:00 2001 From: Menaka Madushanka Date: Tue, 15 Dec 2015 12:39:01 +0530 Subject: [PATCH 1/5] Android Sense device view changes and agent download --- .../service/impl/AndroidSenseService.java | 101 ++++++++++++++++++ .../src/main/webapp/WEB-INF/cxf-servlet.xml | 10 +- .../org.wso2.iot.devices.light_1.0.0.json | 4 +- .../type-view.hbs | 35 +++--- .../src/main/resources/p2.inf | 4 + 5 files changed, 127 insertions(+), 27 deletions(-) diff --git a/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseService.java b/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseService.java index f6f0a4897e..3ce546c3da 100644 --- a/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseService.java +++ b/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseService.java @@ -29,16 +29,27 @@ import org.wso2.carbon.device.mgt.iot.DeviceManagement; import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants; import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.DeviceJSON; import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.SensorJSON; +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.controlqueue.xmpp.XmppAccount; +import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig; +import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppServerClient; +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.sensormgt.SensorDataManager; import org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord; +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.*; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.Date; +import java.util.UUID; public class AndroidSenseService { @@ -206,6 +217,96 @@ public class AndroidSenseService { } + @Path("manager/device/{sketch_type}/download") + @GET + @Produces("application/octet-stream") + public Response downloadSketch(@QueryParam("owner") String owner, + @QueryParam("deviceName") String customDeviceName, + @PathParam("sketch_type") String sketchType) { + //TODO:: null check customDeviceName at UI level + try { + ZipArchive zipFile = createDownloadFile(owner, customDeviceName, sketchType); + Response.ResponseBuilder rb = Response.ok(zipFile.getZipFile()); + rb.header("Content-Disposition", + "attachment; filename=\"" + zipFile.getFileName() + "\""); + return rb.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(); + } + + } + + private ZipArchive createDownloadFile(String owner, String customDeviceName, 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(); + + TokenClient accessTokenClient = new TokenClient(AndroidSenseConstants.DEVICE_TYPE); + AccessTokenInfo accessTokenInfo = accessTokenClient.getAccessToken(owner, deviceId); + + //create token + String accessToken = accessTokenInfo.getAccess_token(); + String refreshToken = accessTokenInfo.getRefresh_token(); + //adding registering data + + XmppAccount newXmppAccount = new XmppAccount(); + newXmppAccount.setAccountName(owner + "_" + deviceId); + newXmppAccount.setUsername(deviceId); + newXmppAccount.setPassword(accessToken); + newXmppAccount.setEmail(deviceId + "@wso2.com"); + + XmppServerClient xmppServerClient = new XmppServerClient(); + xmppServerClient.initControlQueue(); + boolean status; + + if (XmppConfig.getInstance().isEnabled()) { + status = xmppServerClient.createXMPPAccount(newXmppAccount); + if (!status) { + String msg = + "XMPP Account was not created for device - " + deviceId + " of owner - " + + owner + + ".XMPP might have been disabled in org.wso2.carbon.device.mgt.iot" + + ".common.config.server.configs"; + log.warn(msg); + throw new DeviceManagementException(msg); + } + } + + //Register the device with CDMF + String deviceName = customDeviceName + "_" + deviceId; + status = register(deviceId, owner); + + 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.downloadSketch(owner, SUPER_TENANT, sketchType, deviceId, deviceName, + accessToken, refreshToken); + zipFile.setDeviceId(deviceId); + return zipFile; + } + + 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); + } + + /* Service to push all the sensor data collected by the Android Called by the Android device */ @Path("controller/sensordata") diff --git a/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/webapp/WEB-INF/cxf-servlet.xml index 8b00045b87..4a40628a99 100644 --- a/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/webapp/WEB-INF/cxf-servlet.xml +++ b/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -18,14 +18,16 @@ + xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core" + 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 http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"> + + + diff --git a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.analytics/Light/Eventstream_light_1.0.0/org.wso2.iot.devices.light_1.0.0.json b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.analytics/Light/Eventstream_light_1.0.0/org.wso2.iot.devices.light_1.0.0.json index 253f0b0c0d..f9da446f8a 100644 --- a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.analytics/Light/Eventstream_light_1.0.0/org.wso2.iot.devices.light_1.0.0.json +++ b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.analytics/Light/Eventstream_light_1.0.0/org.wso2.iot.devices.light_1.0.0.json @@ -1,8 +1,8 @@ { "name": "org.wso2.iot.devices.light", "version": "1.0.0", - "nickName": "light Data", - "description": "light data received from the Device", + "nickName": "Light Data", + "description": "Light data received from the Device", "metaData": [ {"name":"owner","type":"STRING"}, {"name":"deviceType","type":"STRING"}, diff --git a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/type-view.hbs b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/type-view.hbs index c1b918464c..1de91dcc59 100644 --- a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/type-view.hbs +++ b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/type-view.hbs @@ -14,13 +14,8 @@
  • - Raspberry Pi (Internet Enabled)
  • -
  • - DHT11 Temperature Sensor
  • -
  • - LED
  • -
  • - Buzzer(3v)
  • + Android device +

@@ -168,14 +163,11 @@

Get your device ready


    -
  • 01 Set up your RaspberryPi device - as shown in the schematic below and get the FireAlarm setup.
  • +
  • 01 Download the agent apk
  • + +
  • 02 Install the app in your Android device.
  • -
  • 02 Connect a monitor to your - RaspberryPi via the HDMI cable to get a UI view of the device.
  • -
  • 03 Get the RaspberryPi to connect - to the internet (via Ethernet or Wifi) and note its IP_ADDRESS

@@ -186,16 +178,17 @@

Internet of Things Foundation Quickstart connection


    -
  • 01 Click on the 'Create - DEB' button above to get the download link for the FireAlarm setup files
  • +
  • 01 Start the IOT server
  • + +
  • 02 Connect the device to the network
  • + +
  • 03 Start the Android Sense app in your device.
  • + +
  • 04 Fill the login form with the credentials (Use server URL as https://'<'YOUR_HOST'>':9443 and click on Enroll Device button.
  • -
  • 02 (The following commands can - be issued by directly typing into the terminal of the device or by an 'ssh' login - from a remote PC)
  • +
  • 05 Once the device is enrolled, click on the + button to select the sensors.
  • -
  • 03 Download the FireAlarm setup - files using the following command: 'curl -k < url_link_received_from_the_above_step >> - Agent.zip'
    This will download a zip file named 'Agent.zip'
  • +
  • 06 Click on the Publish data button to publish the sensor readings to the IOT server.

diff --git a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/p2.inf b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/p2.inf index c2d035006e..4e535d9015 100644 --- a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/p2.inf +++ b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/p2.inf @@ -8,3 +8,7 @@ org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../conf org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.androidsense_${feature.version}/datasources/,target:${installFolder}/../../conf/datasources/devicemgt,overwrite:true);\ org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/jaggeryapps/);\ org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.androidsense_${feature.version}/jaggeryapps/,target:${installFolder}/../../deployment/server/jaggeryapps/,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../resources/sketches/);\ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../resources/sketches/android_sense/);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.androidsense_${feature.version}/agent/,target:${installFolder}/../../resources/sketches/android_sense/,overwrite:true);\ + From fb0818f963d5e3edb74cd228d65d4ad3c7960dff Mon Sep 17 00:00:00 2001 From: Menaka Madushanka Date: Wed, 16 Dec 2015 18:36:13 +0530 Subject: [PATCH 2/5] Android Sense device view changes and agent download --- .../service/impl/AndroidSenseService.java | 87 ++---------------- .../impl/AndroidSenseManagerService.java | 6 +- .../{androidsene.apk => androidsense.apk} | Bin .../public/js/download.js | 12 +-- .../type-view.hbs | 81 +++++++--------- 5 files changed, 48 insertions(+), 138 deletions(-) rename features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/agent/{androidsene.apk => androidsense.apk} (100%) diff --git a/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseService.java b/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseService.java index 3ce546c3da..3699154040 100644 --- a/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseService.java +++ b/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense.api/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/service/impl/AndroidSenseService.java @@ -40,12 +40,14 @@ import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager; import org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord; import org.wso2.carbon.device.mgt.iot.util.ZipArchive; import org.wso2.carbon.device.mgt.iot.util.ZipUtil; +import org.wso2.carbon.utils.CarbonUtils; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.*; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.io.File; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Date; @@ -220,93 +222,24 @@ public class AndroidSenseService { @Path("manager/device/{sketch_type}/download") @GET @Produces("application/octet-stream") - public Response downloadSketch(@QueryParam("owner") String owner, - @QueryParam("deviceName") String customDeviceName, - @PathParam("sketch_type") String sketchType) { + public Response downloadSketch(@PathParam("sketch_type") String sketchType) { //TODO:: null check customDeviceName at UI level try { - ZipArchive zipFile = createDownloadFile(owner, customDeviceName, sketchType); - Response.ResponseBuilder rb = Response.ok(zipFile.getZipFile()); + + String sep = File.separator; + String sketchFolder = "repository" + sep + "resources" + sep + "sketches" + sep + "android_sense" + sep; + String archivesPath = CarbonUtils.getCarbonHome() + sep + sketchFolder; + + Response.ResponseBuilder rb = Response.ok(new File(archivesPath+sep+"androidsense.apk")); rb.header("Content-Disposition", - "attachment; filename=\"" + zipFile.getFileName() + "\""); + "attachment; filename=\"" + "androidsense.apk" + "\""); return rb.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(); - } - - } - - private ZipArchive createDownloadFile(String owner, String customDeviceName, 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(); - - TokenClient accessTokenClient = new TokenClient(AndroidSenseConstants.DEVICE_TYPE); - AccessTokenInfo accessTokenInfo = accessTokenClient.getAccessToken(owner, deviceId); - - //create token - String accessToken = accessTokenInfo.getAccess_token(); - String refreshToken = accessTokenInfo.getRefresh_token(); - //adding registering data - - XmppAccount newXmppAccount = new XmppAccount(); - newXmppAccount.setAccountName(owner + "_" + deviceId); - newXmppAccount.setUsername(deviceId); - newXmppAccount.setPassword(accessToken); - newXmppAccount.setEmail(deviceId + "@wso2.com"); - - XmppServerClient xmppServerClient = new XmppServerClient(); - xmppServerClient.initControlQueue(); - boolean status; - - if (XmppConfig.getInstance().isEnabled()) { - status = xmppServerClient.createXMPPAccount(newXmppAccount); - if (!status) { - String msg = - "XMPP Account was not created for device - " + deviceId + " of owner - " + - owner + - ".XMPP might have been disabled in org.wso2.carbon.device.mgt.iot" + - ".common.config.server.configs"; - log.warn(msg); - throw new DeviceManagementException(msg); - } - } - - //Register the device with CDMF - String deviceName = customDeviceName + "_" + deviceId; - status = register(deviceId, owner); - - 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.downloadSketch(owner, SUPER_TENANT, sketchType, deviceId, deviceName, - accessToken, refreshToken); - zipFile.setDeviceId(deviceId); - return zipFile; - } - - 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); } - /* Service to push all the sensor data collected by the Android Called by the Android device */ @Path("controller/sensordata") diff --git a/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/plugin/impl/AndroidSenseManagerService.java b/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/plugin/impl/AndroidSenseManagerService.java index 765ddd2ee2..8ed1eb2bac 100644 --- a/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/plugin/impl/AndroidSenseManagerService.java +++ b/components/device-mgt-iot-androidsense/org.wso2.carbon.device.mgt.iot.androidsense/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/plugin/impl/AndroidSenseManagerService.java @@ -19,17 +19,17 @@ public class AndroidSenseManagerService implements DeviceManagementService { return AndroidSenseConstants.DEVICE_TYPE; } - @Override +// @Override public String getProviderTenantDomain() { return "carbon.super"; } - @Override +// @Override public boolean isSharedWithAllTenants() { return true; } - @Override +// @Override public String[] getSharedTenantsDomain() { return new String[0]; } diff --git a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/agent/androidsene.apk b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/agent/androidsense.apk similarity index 100% rename from features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/agent/androidsene.apk rename to features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/agent/androidsense.apk diff --git a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/public/js/download.js b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/public/js/download.js index ec7a6f642a..decb8e9e53 100644 --- a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/public/js/download.js +++ b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/public/js/download.js @@ -132,20 +132,10 @@ function attachEvents() { }); } +//Device owner removed. function downloadAgent() { $('#downloadForm').submit(); - var deviceName; - $('.new-device-name').each(function () { - if (this.value != "") { - deviceName = this.value; - } - }); - if (deviceName && deviceName.length >= 4) { - setTimeout(function () { - hidePopup(); - }, 1000); - } } function doAction(data) { diff --git a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/type-view.hbs b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/type-view.hbs index 1de91dcc59..efa5faaff7 100644 --- a/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/type-view.hbs +++ b/features/device-mgt-iot-androidsense-feature/org.wso2.carbon.device.mgt.iot.androidsense.feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.type-view/type-view.hbs @@ -2,7 +2,7 @@

Android Sense


Connect your Android device - to the WSO2 device cloud.

+ to the WSO2 device cloud.

@@ -17,43 +17,11 @@ Android device -
- - Download - -
- -
+
+ + Enroll Device +