Resolve conflicts

revert-dabc3590
NuwanSameera 9 years ago
commit f8c4b6413c

7
.gitignore vendored

@ -22,3 +22,10 @@ target
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Android Studio
.gradle
build/
# Local configuration file (sdk path, etc)
local.properties

@ -0,0 +1,46 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion '22.0.1'
defaultConfig {
applicationId "agent.sense.android.iot.carbon.wso2.org.wso2_senseagent"
minSdkVersion 19
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
applicationVariants.all { variant ->
variant.outputs.each { output ->
def newName = output.outputFile.name
newName = newName.replace("app-", "androidsense")
newName = newName.replace("release", "")
//noinspection GroovyAssignabilityCheck
output.outputFile = new File(output.outputFile.parent, newName)
}
}
}
}
packagingOptions {
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
}
productFlavors {
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.android.support:design:22.2.1'
compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.0.2'
compile 'com.github.rholder:snowball-stemmer:1.3.0.581.1'
compile 'commons-codec:commons-codec:1.4'
compile 'com.netflix.feign:feign-jaxrs:8.16.0'
compile 'com.netflix.feign:feign-jackson:8.16.0'
}

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="agent.sense.android.iot.carbon.wso2.org.wso2_senseagent" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.BATTERY_STATS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-sdk android:minSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@mipmap/wso2logo"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="org.wso2.carbon.iot.android.sense.RegisterActivity"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize|stateVisible" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="org.wso2.carbon.iot.android.sense.event.SenseService"
android:enabled="true"
android:label="@string/app_name" >
</service>
<service
android:name="org.wso2.carbon.iot.android.sense.data.publisher.DataPublisherService"
android:enabled="true"
android:label="@string/app_name" >
</service>
<receiver android:name="org.wso2.carbon.iot.android.sense.event.SenseScheduleReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</receiver>
<receiver
android:name="org.wso2.carbon.iot.android.sense.event.streams.battery.BatteryDataReceiver"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED" />
</intent-filter>
</receiver>
<activity
android:name="org.wso2.carbon.iot.android.sense.realtimeviewer.ActivitySelectSensor"
android:label="My Sensors"
android:theme="@style/AppTheme.NoActionBar" >
</activity>
<activity
android:name="org.wso2.carbon.iot.android.sense.speech.detector.WordRecognitionActivity"
android:label="Speech Recongnizer"
android:theme="@style/AppTheme.NoActionBar" >
</activity>
</application>
</manifest>

@ -0,0 +1,215 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import org.wso2.carbon.iot.android.sense.data.publisher.DataPublisherReceiver;
import org.wso2.carbon.iot.android.sense.data.publisher.mqtt.AndroidSenseMQTTHandler;
import org.wso2.carbon.iot.android.sense.data.publisher.mqtt.transport.MQTTTransportHandler;
import org.wso2.carbon.iot.android.sense.event.SenseScheduleReceiver;
import org.wso2.carbon.iot.android.sense.realtimeviewer.ActivitySelectSensor;
import org.wso2.carbon.iot.android.sense.realtimeviewer.sensorlisting.AvailableSensorsInDevice;
import org.wso2.carbon.iot.android.sense.realtimeviewer.sensorlisting.SupportedSensors;
import org.wso2.carbon.iot.android.sense.util.LocalRegistry;
import org.wso2.carbon.iot.android.sense.util.SenseClient;
import org.wso2.carbon.iot.android.sense.util.SenseUtils;
import org.wso2.carbon.iot.android.sense.util.dto.RegisterInfo;
import agent.sense.android.iot.carbon.wso2.org.wso2_senseagent.R;
/**
* A login screen that offers to register the device.
*/
public class RegisterActivity extends Activity {
private EditText mUsernameView;
private EditText mPasswordView;
private EditText mHostView;
private EditText mMqttPortView;
private View mProgressView;
private View mLoginFormView;
private Handler mUiHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSharedPreferences(SupportedSensors.SELECTED_SENSORS, 0).edit().clear().apply();
if (LocalRegistry.isExist(getApplicationContext())) {
Intent intent = new Intent(getApplicationContext(), ActivitySelectSensor.class);
startActivity(intent);
}
setContentView(R.layout.activity_register);
mUsernameView = (EditText) findViewById(R.id.username);
mPasswordView = (EditText) findViewById(R.id.password);
mHostView = (EditText) findViewById(R.id.hostname);
mMqttPortView = (EditText) findViewById(R.id.mqttPort);
AvailableSensorsInDevice availableSensorsInDevice = new AvailableSensorsInDevice(getApplicationContext());
availableSensorsInDevice.setContent();
Button deviceRegisterButton = (Button) findViewById(R.id.device_register_button);
deviceRegisterButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
attemptLogin();
}
});
mLoginFormView = findViewById(R.id.login_form);
mProgressView = findViewById(R.id.login_progress);
}
public void attemptLogin() {
showProgress(true);
// Reset errors.
mUsernameView.setError(null);
mPasswordView.setError(null);
// Store values at the time of the login attempt.
final String username = mUsernameView.getText().toString();
final String password = mPasswordView.getText().toString();
final String hostname = mHostView.getText().toString();
String mqttPort = mMqttPortView.getText().toString();
boolean cancel = false;
View focusView = null;
// Check for a valid password, if the user entered one.
if (!TextUtils.isEmpty(password)) {
// mPasswordView.setError(getString(R.string.error_invalid_password));
focusView = mPasswordView;
//cancel = true;
}
// Check for a valid username .
if (TextUtils.isEmpty(username)) {
mUsernameView.setError(getString(R.string.error_field_required));
focusView = mUsernameView;
cancel = true;
}
if (TextUtils.isEmpty(username)) {
mHostView.setError(getString(R.string.error_field_required));
focusView = mHostView;
cancel = true;
}
if (cancel) {
focusView.requestFocus();
} else {
final int mqttPortNo= Integer.parseInt(mqttPort);
Thread myThread = new Thread(new Runnable() {
@Override
public void run() {
SenseClient client = new SenseClient(getApplicationContext());
LocalRegistry.addServerURL(getBaseContext(), hostname);
String deviceId = SenseUtils.generateDeviceId(getBaseContext(), getContentResolver());
final RegisterInfo registerStatus = client.register(username, password, deviceId, mUiHandler);
mUiHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), registerStatus.getMsg(), Toast.LENGTH_LONG).show();
}
});
if (registerStatus.isRegistered()) {
LocalRegistry.addUsername(getApplicationContext(), username);
LocalRegistry.addDeviceId(getApplicationContext(), deviceId);
LocalRegistry.addMqttPort(getApplicationContext(), mqttPortNo);
MQTTTransportHandler mqttTransportHandler = AndroidSenseMQTTHandler.getInstance(getApplicationContext());
if (!mqttTransportHandler.isConnected()) {
mqttTransportHandler.connect();
}
SenseScheduleReceiver senseScheduleReceiver = new SenseScheduleReceiver();
senseScheduleReceiver.clearAbortBroadcast();
senseScheduleReceiver.onReceive(getApplicationContext(), null);
DataPublisherReceiver dataUploaderReceiver = new DataPublisherReceiver();
dataUploaderReceiver.clearAbortBroadcast();
dataUploaderReceiver.onReceive(getApplicationContext(), null);
mUiHandler.post(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(getApplicationContext(), ActivitySelectSensor.class);
startActivity(intent);
}
});
}
mUiHandler.post(new Runnable() {
@Override
public void run() {
showProgress(false);
}
});
}
});
myThread.start();
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public void showProgress(final boolean show) {
// On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
// for very easy animations. If available, use these APIs to fade-in
// the progress spinner.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
mLoginFormView.animate().setDuration(shortAnimTime).alpha(
show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
}
});
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
mProgressView.animate().setDuration(shortAnimTime).alpha(
show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
}
});
} else {
// The ViewPropertyAnimator APIs are not available, so simply show
// and hide the relevant UI components.
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
}
}
}

@ -0,0 +1,36 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.constants;
/**
* This hold constants related to android_sense.
*/
public class SenseConstants {
public final static String DEVICE_TYPE = "android_sense";
public final static String REGISTER_CONTEXT = "/android_sense";
public final static String DCR_CONTEXT = "/dynamic-client-web";
public final static String TOKEN_ISSUER_CONTEXT = "/oauth2";
public final static String API_APPLICATION_REGISTRATION_CONTEXT = "/api-application-registration";
public static final int MQTT_BROKER_PORT = 1883;
public static final String EVENT_LISTENER_STARTED = "xxStartedxx";
public static final String EVENT_LISTENER_FINISHED = "xxFinishedxx";
public static final String EVENT_LISTENER_ONGOING = "xxOngoingxx";
public final class Request {
public final static String REQUEST_SUCCESSFUL = "200";
public final static String REQUEST_CONFLICT = "409";
public final static int MAX_ATTEMPTS = 2;
}
}

@ -0,0 +1,36 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.data.publisher;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* This creates and AlarmManagerService that triggers the data uploader service with a 30 seconds interval.
*/
public class DataPublisherReceiver extends BroadcastReceiver {
private static int ALARM_INTERVAL = 30000;
@Override
public void onReceive(Context context, Intent intent) {
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, DataPublisherService.class);
PendingIntent pending = PendingIntent.getService(context, 0, i, 0);
service.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), ALARM_INTERVAL, pending);
}
}

@ -0,0 +1,171 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.data.publisher;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.wso2.carbon.iot.android.sense.data.publisher.mqtt.AndroidSenseMQTTHandler;
import org.wso2.carbon.iot.android.sense.data.publisher.mqtt.transport.MQTTTransportHandler;
import org.wso2.carbon.iot.android.sense.data.publisher.mqtt.transport.TransportHandlerException;
import org.wso2.carbon.iot.android.sense.constants.SenseConstants;
import org.wso2.carbon.iot.android.sense.event.streams.Location.LocationData;
import org.wso2.carbon.iot.android.sense.event.streams.Sensor.SensorData;
import org.wso2.carbon.iot.android.sense.event.streams.battery.BatteryData;
import org.wso2.carbon.iot.android.sense.speech.detector.util.ProcessWords;
import org.wso2.carbon.iot.android.sense.speech.detector.util.WordData;
import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
import org.wso2.carbon.iot.android.sense.util.LocalRegistry;
//import org.wso2.carbon.iot.android.sense.util.SenseClient;
import java.util.ArrayList;
import java.util.List;
/**
* This is an android service which publishes the data to the server.
*/
public class DataPublisherService extends Service {
private static final String TAG = DataPublisherService.class.getName();
private static String KEY_TAG = "key";
private static String TIME_TAG = "time";
private static String VALUE_TAG = "value";
public static Context context;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = this;
Log.d(TAG, "service started");
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
List<Event> events = new ArrayList<>();
//retreive sensor data.
List<SensorData> sensorDataMap = SenseDataHolder.getSensorDataHolder();
for (SensorData sensorData : sensorDataMap) {
Event event = new Event();
event.setTimestamp(sensorData.getTimestamp());
switch (sensorData.getSensorType()) {
case Sensor.TYPE_ACCELEROMETER:
event.setAccelerometer(sensorData.getSensorValues());
break;
case Sensor.TYPE_MAGNETIC_FIELD:
event.setMagnetic(sensorData.getSensorValues());
break;
case Sensor.TYPE_GYROSCOPE:
event.setGyroscope(sensorData.getSensorValues());
break;
case Sensor.TYPE_LIGHT:
event.setLight(sensorData.getSensorValues()[0]);
break;
case Sensor.TYPE_PRESSURE:
event.setPressure(sensorData.getSensorValues()[0]);
break;
case Sensor.TYPE_PROXIMITY:
event.setProximity(sensorData.getSensorValues()[0]);
break;
case Sensor.TYPE_GRAVITY:
event.setGravity(sensorData.getSensorValues());
break;
case Sensor.TYPE_ROTATION_VECTOR:
event.setGravity(sensorData.getSensorValues());
break;
}
events.add(event);
}
SenseDataHolder.resetSensorDataHolder();
//retreive batter data.
List<BatteryData> batteryDataMap = SenseDataHolder.getBatteryDataHolder();
for (BatteryData batteryData : batteryDataMap) {
Event event = new Event();
event.setTimestamp(batteryData.getTimestamp());
event.setBattery(batteryData.getLevel());
events.add(event);
}
SenseDataHolder.resetBatteryDataHolder();
//retreive location data.
List<LocationData> locationDataMap = SenseDataHolder.getLocationDataHolder();
for (LocationData locationData : locationDataMap) {
Event event = new Event();
event.setTimestamp(locationData.getTimeStamp());
event.setGps(new double[]{locationData.getLatitude(), locationData.getLongitude()});
events.add(event);
}
SenseDataHolder.resetLocationDataHolder();
//retreive words
ProcessWords.cleanAndPushToWordMap();
List<WordData> wordDatMap = SenseDataHolder.getWordDataHolder();
for (WordData wordData : wordDatMap) {
if (wordData.getOccurences() == 0) {
continue;
}
for (int i = 0; i < wordData.getOccurences(); i++) {
Event event = new Event();
event.setTimestamp(wordData.getTimestamp());
event.setWord(wordData.getWord());
String word = wordData.getWord();
String status = word;
if ((!word.equals(SenseConstants.EVENT_LISTENER_STARTED)) && (!word.equals(SenseConstants
.EVENT_LISTENER_FINISHED))) {
status = SenseConstants.EVENT_LISTENER_ONGOING;
}
event.setWordStatus(status);
events.add(event);
}
}
SenseDataHolder.resetWordDataHolder();
//publish the data
if (events.size() > 0) {
String user = LocalRegistry.getUsername(context);
String deviceId = LocalRegistry.getDeviceId(context);
JSONArray jsonArray = new JSONArray();
for (Event event : events) {
event.setOwner(user);
event.setDeviceId(deviceId);
jsonArray.put(event.getEvent());
}
MQTTTransportHandler mqttTransportHandler = AndroidSenseMQTTHandler.getInstance(context);
if (!mqttTransportHandler.isConnected()) {
mqttTransportHandler.connect();
}
mqttTransportHandler.publishDeviceData(user, deviceId, jsonArray.toString());
}
} catch (JSONException e) {
Log.e(TAG, "Json Data Parsing Exception", e);
} catch (TransportHandlerException e) {
Log.e(TAG, "Data Publish Failed", e);
}
}
};
Thread dataUploaderThread = new Thread(runnable);
dataUploaderThread.start();
return Service.START_NOT_STICKY;
}
}

@ -0,0 +1,222 @@
package org.wso2.carbon.iot.android.sense.data.publisher;
import org.json.JSONException;
import org.json.JSONObject;
/**
* This hold the definition of the stream that android sense is publishing to.
*/
public class Event {
private String owner;
private String deviceId;
private String type;
private float battery;
private double gps[]; //lat,long
private float accelerometer[]; //x,y,z
private float magnetic[]; //x,y,z
private float gyroscope[]; //x,y,z
private float light;
private float pressure;
private float proximity;
private float gravity[];
private float rotation[];
private String wordSessionId;
private String word;
private String wordStatus;
private long timestamp;
private float getBattery() {
return battery;
}
public void setBattery(float battery) {
this.type = "battery";
this.battery = battery;
}
private double[] getGps() {
return gps != null ? gps : new double[]{0, 0};
}
public void setGps(double[] gps) {
this.type = "gps";
this.gps = gps;
}
private float[] getAccelerometer() {
return accelerometer != null ? accelerometer : new float[]{0, 0, 0};
}
public void setAccelerometer(float[] accelerometer) {
this.type = "accelerometer";
this.accelerometer = accelerometer;
}
private float[] getMagnetic() {
return magnetic != null ? magnetic : new float[]{0, 0, 0};
}
public void setMagnetic(float[] magnetic) {
this.type = "magnetic";
this.magnetic = magnetic;
}
private float[] getGyroscope() {
return gyroscope != null ? gyroscope : new float[]{0, 0, 0};
}
public void setGyroscope(float[] gyroscope) {
this.type = "gyroscope";
this.gyroscope = gyroscope;
}
public float getLight() {
return light;
}
public void setLight(float light) {
this.type = "light";
this.light = light;
}
public float getPressure() {
return pressure;
}
public void setPressure(float pressure) {
this.type = "pressure";
this.pressure = pressure;
}
public float getProximity() {
return proximity;
}
public void setProximity(float proximity) {
this.type = "proximity";
this.proximity = proximity;
}
private float[] getGravity() {
return gravity != null ? gravity : new float[]{0, 0, 0};
}
public void setGravity(float gravity[]) {
this.type = "gravity";
this.gravity = gravity;
}
private float[] getRotation() {
return rotation != null ? rotation : new float[]{0, 0, 0};
}
public void setRotation(float rotation[]) {
this.type = "rotation";
this.rotation = rotation;
}
private String getWordSessionId() {
return wordSessionId != null ? wordSessionId : "";
}
public void setWordSessionId(String wordSessionId) {
this.wordSessionId = wordSessionId;
}
private String getWord() {
return word != null ? word : "";
}
public void setWord(String word) {
this.type = "word";
this.word = word;
}
private long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
private String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
private String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getWordStatus() {
return wordStatus != null ? wordStatus : "";
}
public void setWordStatus(String wordStatus) {
this.wordStatus = wordStatus;
}
public JSONObject getEvent() throws JSONException {
JSONObject jsonEvent = new JSONObject();
JSONObject jsonMetaData = new JSONObject();
jsonMetaData.put("owner", getOwner());
jsonMetaData.put("deviceId", getDeviceId());
jsonMetaData.put("type", type);
jsonMetaData.put("timestamp", getTimestamp());
jsonEvent.put("metaData", jsonMetaData);
JSONObject jsonPayloadData = new JSONObject();
jsonPayloadData.put("battery", getBattery());
//gps
double gpsEvents[] = getGps();
jsonPayloadData.put("gps_lat", gpsEvents[0]);
jsonPayloadData.put("gps_long", gpsEvents[1]);
//acceleromter
float events[] = getAccelerometer();
jsonPayloadData.put("accelerometer_x", events[0]);
jsonPayloadData.put("accelerometer_y", events[1]);
jsonPayloadData.put("accelerometer_z", events[2]);
//magnetic
events = getMagnetic();
jsonPayloadData.put("magnetic_x", events[0]);
jsonPayloadData.put("magnetic_y", events[1]);
jsonPayloadData.put("magnetic_z", events[2]);
//gyroscope
events = getGyroscope();
jsonPayloadData.put("gyroscope_x", events[0]);
jsonPayloadData.put("gyroscope_y", events[1]);
jsonPayloadData.put("gyroscope_z", events[2]);
jsonPayloadData.put("light", getLight());
jsonPayloadData.put("pressure", getPressure());
jsonPayloadData.put("proximity", getProximity());
//gravity
events = getGravity();
jsonPayloadData.put("gravity_x", events[0]);
jsonPayloadData.put("gravity_y", events[1]);
jsonPayloadData.put("gravity_z", events[2]);
//rotation
events = getRotation();
jsonPayloadData.put("rotation_x", events[0]);
jsonPayloadData.put("rotation_y", events[1]);
jsonPayloadData.put("rotation_z", events[2]);
//word
jsonPayloadData.put("word", getWord());
jsonPayloadData.put("word_sessionId", getWordSessionId());
jsonPayloadData.put("word_status", getWordStatus());
jsonEvent.put("payloadData", jsonPayloadData);
return jsonEvent;
}
}

@ -0,0 +1,241 @@
/*
* 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.wso2.carbon.iot.android.sense.data.publisher.mqtt;
import android.content.Context;
import android.util.Log;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.wso2.carbon.iot.android.sense.data.publisher.mqtt.transport.MQTTTransportHandler;
import org.wso2.carbon.iot.android.sense.data.publisher.mqtt.transport.TransportHandlerException;
import org.wso2.carbon.iot.android.sense.constants.SenseConstants;
import org.wso2.carbon.iot.android.sense.speech.detector.util.ProcessWords;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
/**
* This is an example for the use of the MQTT capabilities provided by the IoT-Server. This example depicts the use
* of MQTT Transport for the Android Sense device-type. This class extends the abstract class
* "MQTTTransportHandler". "MQTTTransportHandler" consists of the MQTT client specific functionality and implements
* the "TransportHandler" interface. The actual functionality related to the "TransportHandler" interface is
* implemented here, in this concrete class. Whilst the abstract class "MQTTTransportHandler" is intended to provide
* the common MQTT functionality, this class (which is its extension) provides the implementation specific to the
* MQTT communication of the Device-Type (Android Sense) in concern.
* <p/>
* Hence, the methods of this class are implementation of the "TransportHandler" interface which handles the device
* specific logic to connect-to, publish-to, process-incoming-messages-from and disconnect-from the MQTT broker
* listed in the configurations.
*/
public class AndroidSenseMQTTHandler extends MQTTTransportHandler {
private static final String TAG = "AndroidSenseMQTTHandler";
private static volatile AndroidSenseMQTTHandler mInstance;
/**
* return a sigleton Instance
* @param context is the android context object.
* @return AndroidSenseMQTTHandler.
*/
public static AndroidSenseMQTTHandler getInstance(Context context) {
if (mInstance == null) {
Class clazz = AndroidSenseMQTTHandler.class;
synchronized (clazz) {
if (mInstance == null) {
mInstance = new AndroidSenseMQTTHandler(context);
}
}
}
return mInstance;
}
/**
* Default constructor for the AndroidSenseMQTTHandler.
*/
private AndroidSenseMQTTHandler(Context context) {
super(context);
}
/**
* {@inheritDoc}
* AndroidSense device-type specific implementation to connect to the MQTT broker and subscribe to a topic.
* This method is called to initiate a MQTT communication.
*/
@Override
public void connect() {
Runnable connector = new Runnable() {
public void run() {
while (!isConnected()) {
try {
connectToQueue();
} catch (TransportHandlerException e) {
Log.e(TAG, "Connection to MQTT Broker at: " + mqttBrokerEndPoint + " failed", e);
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
Log.e(TAG, "MQTT-Connector: Thread Sleep Interrupt Exception.", ex);
}
}
try {
subscribeToQueue();
} catch (TransportHandlerException e) {
Log.w(TAG, "Subscription to MQTT Broker at: " + mqttBrokerEndPoint + " failed", e);
}
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.setDaemon(true);
connectorThread.start();
}
/**
* {@inheritDoc}
* AndroidSense device-type specific implementation to process incoming messages. This is the specific
* method signature of the overloaded "processIncomingMessage" method that gets called from the messageArrived()
* callback of the "MQTTTransportHandler".
*/
@Override
public void processIncomingMessage(MqttMessage mqttMessage, String... messageParams) {
if (messageParams.length != 0) {
// owner and the deviceId are extracted from the MQTT topic to which the message was received.
// <Topic> = [ServerName/Owner/DeviceType/DeviceId/#]
String topic = messageParams[0];
String[] topicParams = topic.split("/");
String owner = topicParams[1];
String deviceId = topicParams[3];
Log.d(TAG, "Received MQTT message for: [OWNER-" + owner + "] & [DEVICE.ID-" + deviceId + "]");
String msg;
msg = mqttMessage.toString();
Log.d(TAG, "MQTT: Received Message [" + msg + "] topic: [" + topic + "]");
if (topic.contains("threshold")) {
try {
ProcessWords.setThreshold(Integer.parseInt(msg));
} catch (NumberFormatException e) {
Log.e(TAG, "Invalid threshold value " + msg);
}
} else if (topic.contains("words")) {
String words[] = msg.split(" ");
ProcessWords.addWords(Arrays.asList(words));
} else if (topic.contains("remove")) {
String words[] = msg.split(" ");
for (String word: words) {
ProcessWords.removeWord(word);
}
}
} else {
String errorMsg =
"MQTT message [" + mqttMessage.toString() + "] was received without the topic information.";
Log.w(TAG, errorMsg);
}
}
/**
* {@inheritDoc}
* AndroidSense device-type specific implementation to publish data to the device. This method calls the
* {@link #publishToQueue(String, MqttMessage)} method of the "MQTTTransportHandler" class.
*/
@Override
public void publishDeviceData(String... publishData) throws TransportHandlerException {
if (publishData.length != 3) {
String errorMsg = "Incorrect number of arguments received to SEND-MQTT Message. " +
"Need to be [owner, deviceId, content]";
Log.e(TAG, errorMsg);
throw new TransportHandlerException(errorMsg);
}
String deviceOwner = publishData[0];
String deviceId = publishData[1];
String resource = publishData[2];
MqttMessage pushMessage = new MqttMessage();
String publishTopic = "wso2/" + SenseConstants.DEVICE_TYPE + "/" + deviceId + "/data";
String actualMessage = resource;
pushMessage.setPayload(actualMessage.getBytes(StandardCharsets.UTF_8));
pushMessage.setQos(DEFAULT_MQTT_QUALITY_OF_SERVICE);
pushMessage.setRetained(false);
publishToQueue(publishTopic, pushMessage);
}
/**
* {@inheritDoc}
* Android Sense device-type specific implementation to disconnect from the MQTT broker.
*/
@Override
public void disconnect() {
Runnable stopConnection = new Runnable() {
public void run() {
while (isConnected()) {
try {
closeConnection();
} catch (MqttException e) {
Log.w(TAG, "Unable to 'STOP' MQTT connection at broker at: " + mqttBrokerEndPoint
+ " for device-type - " + SenseConstants.DEVICE_TYPE, e);
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
Log.e(TAG, "MQTT-Terminator: Thread Sleep Interrupt Exception at device-type - " +
SenseConstants.DEVICE_TYPE, e1);
}
}
}
}
};
Thread terminatorThread = new Thread(stopConnection);
terminatorThread.setDaemon(true);
terminatorThread.start();
}
/**
* {@inheritDoc}
*/
@Override
public void publishDeviceData() {
// nothing to do
}
@Override
public void publishDeviceData(MqttMessage publishData) throws TransportHandlerException {
}
/**
* {@inheritDoc}
*/
@Override
public void processIncomingMessage() {
// nothing to do
}
@Override
public void processIncomingMessage(MqttMessage message) throws TransportHandlerException {
}
}

@ -0,0 +1,385 @@
/*
* 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.wso2.carbon.iot.android.sense.data.publisher.mqtt.transport;
import android.content.Context;
import android.util.Log;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.wso2.carbon.iot.android.sense.constants.SenseConstants;
import org.wso2.carbon.iot.android.sense.util.LocalRegistry;
import java.nio.charset.StandardCharsets;
/**
* This is an abstract class that implements the "TransportHandler" interface. The interface is an abstraction for
* the core functionality with regards to device-server communication regardless of the Transport protocol. This
* specific class contains the MQTT-Transport specific implementations. The class implements utility methods for the
* case of a MQTT communication. However, this "abstract class", even-though it implements the "TransportHandler"
* interface, does not contain the logic relevant to the interface methods. The specific functionality of the
* interface methods are intended to be implemented by the concrete class that extends this abstract class and
* utilizes the MQTT specific functionality (ideally a device API writer who would like to communicate to the device
* via MQTT Protocol).
* <p/>
* This class contains the Device-Management specific implementation for all the MQTT functionality. This includes
* connecting to a MQTT Broker & subscribing to the appropriate MQTT-topic, action plan upon losing connection or
* successfully delivering a message to the broker and upon receiving a MQTT message. Makes use of the 'Paho-MQTT'
* library provided by Eclipse Org.
*/
public abstract class MQTTTransportHandler implements MqttCallback, TransportHandler<MqttMessage> {
private static final String TAG = "MQTTTransportHandler";
private MqttClient client;
private String clientId;
private MqttConnectOptions options; // options to be set to the client-connection.
// topic to which a will-message is automatically published by the broker upon the device losing its connection.
private String clientWillTopic;
protected String mqttBrokerEndPoint;
protected int timeoutInterval; // interval to use for reconnection attempts etc.
protected String subscribeTopic;
// Quality of Service Levels for MQTT Subscription and Publishing.
public static final int QoS_0 = 0; // At-Most Once
@SuppressWarnings("unused")
public static final int QoS_1 = 1; // At-Least Once
public static final int QoS_2 = 2; // Exactly Once
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = QoS_0;
// Prefix to the Will-Topic to which a message is published if client loses its connection.
private static final String DISCONNECTION_WILL_TOPIC_PREFIX = "Disconnection/";
// Will-Message of the client to be published if connection is lost.
private static final String DISCONNECTION_WILL_MSG = "Lost-Connection";
/**
* Constructor for the MQTTTransportHandler which takes in the owner, type of the device and the MQTT Broker URL
* and the topic to subscribe.
* @param context activity context.
*/
protected MQTTTransportHandler(Context context) {
String username = LocalRegistry.getUsername(context);
String deviceId = LocalRegistry.getDeviceId(context);
this.clientId = deviceId + ":" + SenseConstants.DEVICE_TYPE;
this.subscribeTopic = "wso2/" + SenseConstants.DEVICE_TYPE + "/" + deviceId + "/command/#";
this.clientWillTopic = DISCONNECTION_WILL_TOPIC_PREFIX + SenseConstants.DEVICE_TYPE;
this.mqttBrokerEndPoint = "tcp://" + LocalRegistry.getServerHost(context) + ":" + LocalRegistry.getMqttPort(context);
this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
setUsernameAndPassword(LocalRegistry.getAccessToken(context), "");
this.initMQTTClient();
}
/**
* Constructor for the MQTTTransportHandler which takes in the owner, type of the device and the MQTT Broker URL
* and the topic to subscribe. Additionally this constructor takes in the reconnection-time interval between
* successive attempts to connect to the broker.
*
* @param deviceOwner the owner of the device.
* @param deviceType the CDMF Device-Type of the device.
* @param mqttBrokerEndPoint the IP/URL of the MQTT broker endpoint.
* @param subscribeTopic the MQTT topic to which the client is to be subscribed
* @param intervalInMillis the time interval in MILLI-SECONDS between attempts to connect to the broker.
*/
protected MQTTTransportHandler(String deviceOwner, String deviceType,
String mqttBrokerEndPoint, String subscribeTopic, int intervalInMillis) {
this.clientId = deviceOwner + ":" + deviceType;
this.subscribeTopic = subscribeTopic;
this.clientWillTopic = DISCONNECTION_WILL_TOPIC_PREFIX + deviceType;
this.mqttBrokerEndPoint = mqttBrokerEndPoint;
this.timeoutInterval = intervalInMillis;
this.initMQTTClient();
}
/**
* Initializes the MQTT-Client. Creates a client using the given MQTT-broker endpoint and the clientId (which is
* constructed by a concatenation of [deviceOwner]:[deviceType]). Also sets the client's options parameter with
* the clientWillTopic (in-case of connection failure) and other info. Also sets the callback to this current class.
*/
private void initMQTTClient() {
try {
client = new MqttClient(this.mqttBrokerEndPoint, clientId, null);
Log.i(TAG, "MQTT client was created with ClientID : " + clientId);
} catch (MqttException ex) {
String errorMsg = "Initializing the MQTT Client failed.";
Log.e(TAG, errorMsg, ex);
}
options = new MqttConnectOptions();
options.setKeepAliveInterval(120); // set the keep alive interval to 120 seconds by default.
options.setCleanSession(true); // sets clean session to true by default.
setDisconnectionWillForClient(QoS_2, true); // sets default will-topic & msg with QoS 2 and retained true.
client.setCallback(this); // callback for MQTT events are set to `this` object.
}
/**
* @param qos the Quality of Service at which the last-will-message is to be published.
* @param isRetained indicate whether to retain the last-will-message.
* @see MQTTTransportHandler#setDisconnectionWillForClient(String, String, int, boolean). Uses the default values
* for Will-Topic and Will-Message.
*/
protected void setDisconnectionWillForClient(int qos, boolean isRetained) {
this.setDisconnectionWillForClient(clientWillTopic, DISCONNECTION_WILL_MSG, qos, isRetained);
}
/**
* Sets the [Will] option in the default options-set of the MQTT Client. A will-topic, will-message is parsed
* along with the QoS and the retained flag. When the client loses its connection to the broker, the broker
* publishes the will-message to the will-topic, to itself.
*
* @param willTopic the topic to which the last will message is to be published when client exists ungracefully.
* @param willMsg the message to be published upon client's ungraceful exit from the broker.
* @param qos the Quality of Service at which the last-will-message is to be published.
* @param isRetained indicate whether to retain the last-will-message.
*/
protected void setDisconnectionWillForClient(String willTopic, String willMsg, int qos, boolean isRetained) {
this.options.setWill(willTopic, willMsg.getBytes(StandardCharsets.UTF_8), qos, isRetained);
}
/**
* Sets the [Clean-Session] option in the default options-set of the MQTT Client. It is set to `true` by default.
*
* @param setCleanSession `true` indicates that the session details can be cleared/cleaned upon disconnection,
* `false` indicates that the session details are to be persisted if the client disconnects.
*/
@SuppressWarnings("unused")
protected void setClientCleanSession(boolean setCleanSession) {
this.options.setCleanSession(setCleanSession);
}
/**
* Sets the [Username] & [Password] options in the default options-set of the MQTT Client. By default these
* values are not set.
*
* @param username the username to be used by the client to connect to the broker.
* @param password the password to be used by the client to connect to the broker.
*/
@SuppressWarnings("unused")
protected void setUsernameAndPassword(String username, String password) {
this.options.setUserName(username);
this.options.setPassword(password.toCharArray());
}
/**
* Connects to the MQTT-Broker at the endpoint specified in the constructor to this class using default the
* MQTT-options.
*
* @throws TransportHandlerException in the event of 'Connecting to' the MQTT broker fails.
*/
protected void connectToQueue() throws TransportHandlerException {
this.connectToQueue(options);
}
/**
* Connects to the MQTT-Broker at the endpoint specified in the constructor to this class using the MQTT-Options
* passed.
*
* @param options options to be used by the client for this connection. (username, password, clean-session, etc)
* @throws TransportHandlerException in the event of 'Connecting to' the MQTT broker fails.
*/
protected void connectToQueue(MqttConnectOptions options) throws TransportHandlerException {
try {
client.connect(options);
Log.d(TAG, "MQTT Client connected to queue at: " + this.mqttBrokerEndPoint);
} catch (MqttException ex) {
String errorMsg = "MQTT Exception occured whilst connecting to queue at [" + this.mqttBrokerEndPoint + "]";
Log.e(TAG, errorMsg);
throw new TransportHandlerException(errorMsg, ex);
}
}
/**
* @throws TransportHandlerException in the event of 'Subscribing to' the MQTT broker fails.
* @see MQTTTransportHandler#subscribeToQueue(int). Uses default QoS of 1.
*/
protected void subscribeToQueue() throws TransportHandlerException {
this.subscribeToQueue(QoS_0);
}
/**
* Subscribes to the MQTT-Topic specified in the constructor to this class.
*
* @throws TransportHandlerException in the event of 'Subscribing to' the MQTT broker fails.
*/
protected void subscribeToQueue(int qos) throws TransportHandlerException {
try {
client.subscribe(subscribeTopic, qos);
Log.d(TAG, "Client [" + clientId + "] subscribed to topic: " + subscribeTopic);
} catch (MqttException ex) {
String errorMsg = "MQTT Exception occurred whilst client [" + clientId + "] tried to subscribe to " +
"topic: [" + subscribeTopic + "]";
Log.e(TAG, errorMsg);
throw new TransportHandlerException(errorMsg, ex);
}
}
/**
* @param topic the topic to which the message is to be published.
* @param payLoad the message (payload) of the MQTT publish action.
* @see MQTTTransportHandler#publishToQueue(String, String, int, boolean)
*/
@SuppressWarnings("unused")
protected void publishToQueue(String topic, String payLoad) throws TransportHandlerException {
publishToQueue(topic, payLoad, DEFAULT_MQTT_QUALITY_OF_SERVICE, false);
}
/**
* @param topic the topic to which the message is to be published.
* @param message the message (payload) of the MQTT publish action as a `MQTTMessage`.
* @throws TransportHandlerException if any error occurs whilst trying to publish to the MQTT Queue.
* @see MQTTTransportHandler#publishToQueue(String, String, int, boolean)
*/
protected void publishToQueue(String topic, MqttMessage message) throws TransportHandlerException {
try {
client.publish(topic, message);
Log.d(TAG, "Message: " + message.toString() + " to MQTT topic [" + topic + "] published successfully");
} catch (MqttException ex) {
String errorMsg = "MQTT Client Error whilst client [" + clientId + "] tried to publish to queue at " +
"[" + mqttBrokerEndPoint + "] under topic [" + topic + "]";
Log.e(TAG, errorMsg);
throw new TransportHandlerException(errorMsg, ex);
}
}
/**
* This method is used to publish messages to the MQTT-Endpoint to which this client is connected to. It is via
* publishing to this broker that the messages are communicated to the device. This is an overloaded method with
* different parameter combinations. This method invokes the publish method provided by the MQTT-Client library.
*
* @param topic the topic to which the message is to be published.
* @param payLoad the message (payload) of the MQTT publish action.
* @param qos the Quality-of-Service of the current publish action.
* Could be 0(At-most once), 1(At-least once) or 2(Exactly once)
* @param retained indicate whether to retain the publish-message in the event of no subscribers.
* @throws TransportHandlerException if any error occurs whilst trying to publish to the MQTT Queue.
*/
protected void publishToQueue(String topic, String payLoad, int qos, boolean retained)
throws TransportHandlerException {
try {
client.publish(topic, payLoad.getBytes(StandardCharsets.UTF_8), qos, retained);
Log.d(TAG, "Message: " + payLoad + " to MQTT topic [" + topic + "] published successfully");
} catch (MqttException ex) {
String errorMsg = "MQTT Client Error whilst client [" + clientId + "] tried to publish to queue at " +
"[" + mqttBrokerEndPoint + "] under topic [" + topic + "]";
Log.e(TAG, errorMsg);
throw new TransportHandlerException(errorMsg, ex);
}
}
/**
* Checks whether the connection to the MQTT-Broker exists.
*
* @return `true` if the client is connected to the MQTT-Broker, else `false`.
*/
@Override
public boolean isConnected() {
return client.isConnected();
}
/**
* Callback method which is triggered once the MQTT client losers its connection to the broker. Spawns a new
* thread that executes necessary actions to try and reconnect to the endpoint.
*
* @param throwable a Throwable Object containing the details as to why the failure occurred.
*/
@Override
public void connectionLost(Throwable throwable) {
Log.w(TAG, "Connection for client: " + this.clientId + " to " + this.mqttBrokerEndPoint + " was lost." +
"\nThis was due to - " + throwable.getMessage());
Thread reconnectThread = new Thread() {
public void run() {
connect();
}
};
reconnectThread.setDaemon(true);
reconnectThread.start();
}
/**
* Callback method which is triggered upon receiving a MQTT Message from the broker. Spawns a new thread that
* executes any actions to be taken with the received message.
*
* @param topic the MQTT-Topic to which the received message was published to and the client subscribed to.
* @param mqttMessage the actual MQTT-Message that was received from the broker.
*/
@Override
public void messageArrived(final String topic, final MqttMessage mqttMessage) {
Log.d(TAG, "Got an MQTT message '" + mqttMessage.toString() + "' for topic '" + topic + "'.");
Thread messageProcessorThread = new Thread() {
public void run() {
try {
processIncomingMessage(mqttMessage, topic);
} catch (TransportHandlerException e) {
Log.e(TAG, "An error occurred when trying to process received MQTT message [" + mqttMessage + "] " +
"for topic [" + topic + "].", e);
}
}
};
messageProcessorThread.setDaemon(true);
messageProcessorThread.start();
}
/**
* Callback method which gets triggered upon successful completion of a message delivery to the broker.
*
* @param iMqttDeliveryToken the MQTT-DeliveryToken which includes the details about the specific message delivery.
*/
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
String topic = iMqttDeliveryToken.getTopics()[0];
String client = iMqttDeliveryToken.getClient().getClientId();
try {
if (iMqttDeliveryToken.isComplete()) {
if (iMqttDeliveryToken.getMessage() != null) {
String message = iMqttDeliveryToken.getMessage().toString();
Log.d(TAG, "Message to client [" + client + "] under topic (" + topic +
") was delivered successfully with the delivery message: '" + message + "'");
} else {
Log.d(TAG, "Message to client [" + client + "] under topic (" + topic +
") was delivered successfully.");
}
} else {
Log.w(TAG, "FAILED: Delivery of MQTT message to [" + client + "] under topic [" + topic + "] failed.");
}
} catch (MqttException e) {
Log.w(TAG, "Error occurred whilst trying to read the message from the MQTT delivery token.");
}
}
/**
* Closes the connection to the MQTT Broker.
*/
public void closeConnection() throws MqttException {
if (client != null && isConnected()) {
client.disconnect();
}
}
/**
* Fetches the default options set for the MQTT Client
*
* @return the options that are currently set for the client.
*/
public MqttConnectOptions getOptions() {
return options;
}
}

@ -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.wso2.carbon.iot.android.sense.data.publisher.mqtt.transport;
/**
* This interface consists of the core functionality related to the transport between any device and the server. The
* interface is an abstraction, regardless of the underlying protocol used for the transport. Implementation of this
* interface by any class that caters a specific protocol (ex: HTTP, XMPP, MQTT, CoAP) would ideally have methods
* specific to the protocol used for communication and other methods that implement the logic related to the devices
* using the protocol. The methods of the interface are identified as generic ones for implementing transport
* protocols for device communication. The implementation can utilize the appropriate method signatures applicable for
* intended protocol.
*
* @param <T> an object of the message type specific to the protocol implemented. To be set to 'String' if there
* isn't anything specific.
*/
public interface TransportHandler<T> {
// a default timeout interval to be used for the protocol specific connections
int DEFAULT_TIMEOUT_INTERVAL = 5000; // millis ~ 5 sec
/**
* Implements the underlying connect mechanism specific to the protocol enabled by the interface. An object of a
* class that implements this interface would call this method before any communication is started via the
* intended protocol.
*/
void connect();
/**
* Used to check whether a connection (via the implemented protocol) to the external-endpoint exists. Ideally
* used to verify that the connection persists and to spawn a reconnection attempt if not.
*
* @return 'true' if connection is already made & exists, else 'false'.
*/
boolean isConnected();
/**
* @throws TransportHandlerException in the event of any exceptions that occur whilst processing the message.
* @see TransportHandler#processIncomingMessage(Object, String...)
*/
void processIncomingMessage() throws TransportHandlerException;
/**
* @param message the message (of the type specific to the protocol) received from the device.
* @throws TransportHandlerException
* @see TransportHandler#processIncomingMessage(Object, String...)
*/
void processIncomingMessage(T message) throws TransportHandlerException;
/**
* This is an overloaded method with three different method-signatures. This method is used to process any
* incoming messages via the implemented protocol. It would ideally be invoked at a point where a message
* received event is activated (Ex: `MessageArrived` callback in Eclipse-Paho-MQTT Client & `PacketListener`(s)
* in XMPP).
* <p/>
*
* @param message the message (of the type specific to the protocol) received from the device.
* @param messageParams one or more other parameters received as part-of & relevant-to the message (Ex: MQTT Topic).
* @throws TransportHandlerException in the event of any exceptions that occur whilst processing the message.
*/
void processIncomingMessage(T message, String... messageParams) throws TransportHandlerException;
/**
* @throws TransportHandlerException in the event of any exceptions that occur whilst sending the message.
* @see TransportHandler#publishDeviceData(String...)
*/
void publishDeviceData() throws TransportHandlerException;
/**
* @param publishData the message (of the type specific to the protocol) to be sent to the device.
* @throws TransportHandlerException in the event of any exceptions that occur whilst sending the message.
* @see TransportHandler#publishDeviceData(String...)
*/
void publishDeviceData(T publishData) throws TransportHandlerException;
/**
* This is an overloaded method with three different method-signatures. This method is used to publish messages
* to an external-endpoint/device via the implemented protocol. It could in itself call the (communicating)
* external-endpoint or invoke any method provided by the protocol specific library.
* <p/>
*
* @param publishData one or more parameters specific to the message and the data to be sent.
* @throws TransportHandlerException in the event of any exceptions that occur whilst sending the message.
*/
void publishDeviceData(String... publishData) throws TransportHandlerException;
/**
* Implements the underlying disconnect mechanism specific to the protocol enabled by the interface. An object of a
* class that implements this interface would call this method upon completion of all communication. In the case of
* the IoT-Server invoking this would only be required if the server shuts-down.
*/
void disconnect();
}

@ -0,0 +1,59 @@
/*
* 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.wso2.carbon.iot.android.sense.data.publisher.mqtt.transport;
/**
* This exception will be thrown when the mqtt transport fails.
*/
public class TransportHandlerException extends Exception {
private static final long serialVersionUID = 2736466230451105440L;
private String errorMessage;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public TransportHandlerException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public TransportHandlerException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public TransportHandlerException(String msg) {
super(msg);
setErrorMessage(msg);
}
public TransportHandlerException() {
super();
}
public TransportHandlerException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,42 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.event;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import java.util.Calendar;
/**
* This is a service which triggers to collect
*/
public class SenseScheduleReceiver extends BroadcastReceiver {
private static final int ALARM_INTERVAL = 5000;
@Override
public void onReceive(Context context, Intent intent) {
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, SenseService.class);
PendingIntent pending = PendingIntent.getService(context, 0, i, 0);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 30);
service.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), ALARM_INTERVAL, pending);
}
}

@ -0,0 +1,63 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.event;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import org.wso2.carbon.iot.android.sense.event.streams.SenseDataCollector;
import org.wso2.carbon.iot.android.sense.event.streams.battery.BatteryDataReceiver;
import org.wso2.carbon.iot.android.sense.util.LocalRegistry;
import org.wso2.carbon.iot.android.sense.util.SenseWakeLock;
/**
* This service caters to initiate the data collection.
*/
public class SenseService extends Service {
public static Context context;
@Override
public void onCreate() {
super.onCreate();
SenseWakeLock.acquireWakeLock(this);
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
context = this;
if (!LocalRegistry.isExist(context)) return Service.START_NOT_STICKY;
//Below triggers the data collection for sensors,location and battery.
SenseDataCollector Sensor = new SenseDataCollector(this, SenseDataCollector.DataType.SENSOR);
SenseDataCollector Location = new SenseDataCollector(this, SenseDataCollector.DataType.LOCATION);
registerReceiver(new BatteryDataReceiver(), new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
//service will not be stopped until we manually stop the service
return Service.START_NOT_STICKY;
}
@Override
public void onDestroy() {
SenseWakeLock.releaseCPUWakeLock();
super.onDestroy();
}
}

@ -0,0 +1,21 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.event.streams;
/**
* this class extended by each data reader implementation, where the data store logic is implemented in thread.
*/
public abstract class DataReader implements Runnable {
}

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.event.streams.Location;
import java.util.Date;
/**
* This defines the data structure of the location data that is been collected.
*/
public class LocationData {
private double latitude; // latitude
private double longitude; // longitude
private long timestamp;
LocationData(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
timestamp = new Date().getTime();
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public long getTimeStamp() {
return timestamp;
}
public void setTimeStamp(long timeStamp) {
timestamp = timeStamp;
}
}

@ -0,0 +1,169 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.event.streams.Location;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import org.wso2.carbon.iot.android.sense.event.streams.DataReader;
import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
import java.util.concurrent.TimeUnit;
/**
* This is used to retrieve the location data using GPS and used Network connection to increase the accuracy.
*/
public class LocationDataReader extends DataReader implements LocationListener {
protected LocationManager locationManager;
private Context mContext;
private boolean canGetLocation = false;
private static final String TAG = LocationDataReader.class.getName();
Location location; // location
double latitude; // latitude
double longitude; // longitude
public LocationDataReader(Context context) {
mContext = context;
getLocation();
}
public Location getLocation() {
locationManager = (LocationManager) mContext.getSystemService(mContext.LOCATION_SERVICE);
// getting GPS status
boolean isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
boolean isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
} else {
this.canGetLocation = true;
// First get location from Network Provider
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 0, 0, this);
// MIN_TIME_BW_UPDATES,
// MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, this);
//MIN_TIME_BW_UPDATES,
//MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d(TAG, "GPS Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
return location;
}
public boolean canGetLocation() {
return this.canGetLocation;
}
public void stopUsingGPS() {
if (locationManager != null) {
locationManager.removeUpdates(LocationDataReader.this);
}
}
public double getLatitude() {
if (location != null) {
latitude = location.getLatitude();
}
// return latitude
return latitude;
}
/**
* Function to get longitude
*/
public double getLongitude() {
if (location != null) {
longitude = location.getLongitude();
}
// return longitude
return longitude;
}
@Override
public void onLocationChanged(Location arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
@Override
public void run() {
Log.d(TAG, "running -Location");
try {
TimeUnit.MILLISECONDS.sleep(10000);
double lat = getLatitude();
double longit = getLongitude();
if (lat != 0 && longit != 0) {
SenseDataHolder.getLocationDataHolder().add(new LocationData(getLatitude(), getLongitude()));
}
} catch (InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
Log.e(TAG, " Location Data Retrieval Failed");
}
}
}

@ -0,0 +1,44 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.event.streams;
import android.content.Context;
import org.wso2.carbon.iot.android.sense.event.streams.Location.LocationDataReader;
import org.wso2.carbon.iot.android.sense.event.streams.Sensor.SensorDataReader;
/**
* This class triggered by service to collect the sensor data.
*/
public class SenseDataCollector {
public enum DataType {
SENSOR, LOCATION
}
public SenseDataCollector(Context ctx, DataType dt) {
DataReader dr = null;
switch (dt) {
case SENSOR:
dr = new SensorDataReader(ctx);
break;
case LOCATION:
dr = new LocationDataReader(ctx);
break;
}
if (dr != null) {
Thread DataCollector = new Thread(dr);
DataCollector.start();
}
}
}

@ -0,0 +1,102 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.event.streams.Sensor;
import android.hardware.SensorEvent;
import org.wso2.carbon.iot.android.sense.realtimeviewer.sensorlisting.SupportedSensors;
import java.util.Date;
/**
* This defines the data structure of the sensor data that is been collected.
* look at http://developer.android.com/guide/topics/sensors/sensors_overview.html for field description.
*/
public class SensorData {
private int sensorType;
private String sensorName;
private String sensorVendor;
private float sensorValues[];
private int accuracyStatus;
private long timestamp;
private String collectTimestamp;
private SupportedSensors supportedSensors = SupportedSensors.getInstance();
SensorData(SensorEvent event) {
sensorValues = event.values;
accuracyStatus = event.accuracy;
collectTimestamp = String.valueOf(event.timestamp);
timestamp = new Date().getTime();
sensorName = supportedSensors.getType(event.sensor.getType()).toUpperCase();
sensorVendor = event.sensor.getVendor();
sensorType = event.sensor.getType();
}
public int getSensorType() {
return sensorType;
}
public void setSensorType(int sensorType) {
this.sensorType = sensorType;
}
public String getSensorName() {
return sensorName;
}
public void setSensorName(String sensorName) {
this.sensorName = sensorName;
}
public String getSensorVendor() {
return sensorVendor;
}
public void setSensorVendor(String sensorVendor) {
this.sensorVendor = sensorVendor;
}
public float[] getSensorValues() {
return sensorValues;
}
public void setSensorValues(float sensorValues[]) {
this.sensorValues = sensorValues;
}
public int getAccuracyStatus() {
return accuracyStatus;
}
public void setAccuracyStatus(int accuracyStatus) {
this.accuracyStatus = accuracyStatus;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getCollectTimestamp() {
return collectTimestamp;
}
public void setCollectTimestamp(String collectTimestamp) {
this.collectTimestamp = collectTimestamp;
}
}

@ -0,0 +1,116 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.event.streams.Sensor;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import org.wso2.carbon.iot.android.sense.event.streams.DataReader;
import org.wso2.carbon.iot.android.sense.realtimeviewer.sensorlisting.SupportedSensors;
import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.TimeUnit;
/**
* This is used to retrieve the sensor data.
*/
public class SensorDataReader extends DataReader implements SensorEventListener {
private SensorManager mSensorManager;
private Map<String, SensorData> senseDataStruct = new HashMap<>();
private Vector<SensorData> sensorVector = new Vector<>();
Context ctx;
private List<Sensor> sensorList = new ArrayList<>();
private SupportedSensors supportedSensors = SupportedSensors.getInstance();
private static final String TAG = SensorDataReader.class.getName();
public SensorDataReader(Context context) {
ctx = context;
SharedPreferences sharedPreferences = ctx.getSharedPreferences(SupportedSensors.SELECTED_SENSORS, Context
.MODE_MULTI_PROCESS);
Set<String> selectedSet = sharedPreferences.getStringSet(SupportedSensors.SELECTED_SENSORS_BY_USER, null);
mSensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
selectedSensorList(selectedSet);
for (Sensor sensor : sensorList) {
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
private void collectSensorData() {
for (Sensor sensor : sensorList) {
try {
if (senseDataStruct.containsKey(sensor.getName())) {
SensorData sensorInfo = senseDataStruct.get(sensor.getName());
sensorVector.add(sensorInfo);
Log.d(TAG, "Sensor Name " + sensor.getName() + ", Type " + sensor.getType() + " " +
", sensorValue :" + sensorInfo.getSensorValues());
}
} catch (Throwable e) {
Log.d(TAG, "error on sensors");
}
}
mSensorManager.unregisterListener(this);
}
public Vector<SensorData> getSensorData() {
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.e(TAG, e.getMessage());
}
collectSensorData();
return sensorVector;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
senseDataStruct.put(event.sensor.getName(), new SensorData(event));
}
@Override
public void run() {
Log.d(TAG, "running -sensorDataMap");
Vector<SensorData> sensorDatas = getSensorData();
for (SensorData data : sensorDatas) {
SenseDataHolder.getSensorDataHolder().add(data);
}
}
public void selectedSensorList(Set<String> set) {
if (set != null) {
String[] sensorsSet = set.toArray(new String[set.size()]);
for (String s : sensorsSet) {
sensorList.add(mSensorManager.getDefaultSensor(supportedSensors.getType(s.toLowerCase())));
}
}
}
}

@ -0,0 +1,124 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.event.streams.battery;
import android.content.Intent;
import android.os.BatteryManager;
import java.util.Date;
/**
* This defines the data structure of the battery data that is been collected.
* look at http://developer.android.com/reference/android/os/BatteryManager.html for field description.
*/
public class BatteryData {
private int health;
private int level;
private int plugged;
private int present;
private int scale;
private int status;
private int temperature;
private int voltage;
private long timestamp;
BatteryData(Intent intent) {
timestamp = new Date().getTime();
health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, 0);
level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
present = intent.getExtras().getBoolean(BatteryManager.EXTRA_PRESENT) ? 1 : 0;
scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, 0);
String technology = intent.getExtras().getString(BatteryManager.EXTRA_TECHNOLOGY);
temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);
voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public int getPlugged() {
return plugged;
}
public void setPlugged(int plugged) {
this.plugged = plugged;
}
public int getPresent() {
return present;
}
public void setPresent(int present) {
this.present = present;
}
public int getScale() {
return scale;
}
public void setScale(int scale) {
this.scale = scale;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public int getTemperature() {
return temperature;
}
public void setTemperature(int temperature) {
this.temperature = temperature;
}
public int getVoltage() {
return voltage;
}
public void setVoltage(int voltage) {
this.voltage = voltage;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.event.streams.battery;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
/**
* Whenever the battery level changes This receiver will be triggered.
*/
public class BatteryDataReceiver extends BroadcastReceiver {
/**
* when the data is retreived then its added to a inmemory map.
*
* @param context of the reciever.
* @param intent of the reciver
*/
@Override
public void onReceive(Context context, Intent intent) {
SenseDataHolder.getBatteryDataHolder().add(new BatteryData(intent));
}
}

@ -0,0 +1,280 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.realtimeviewer;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import org.wso2.carbon.iot.android.sense.RegisterActivity;
import org.wso2.carbon.iot.android.sense.data.publisher.DataPublisherReceiver;
import org.wso2.carbon.iot.android.sense.data.publisher.DataPublisherService;
import org.wso2.carbon.iot.android.sense.event.SenseScheduleReceiver;
import org.wso2.carbon.iot.android.sense.event.SenseService;
import org.wso2.carbon.iot.android.sense.realtimeviewer.datastore.TempStore;
import org.wso2.carbon.iot.android.sense.realtimeviewer.event.RealTimeSensorChangeReceiver;
import org.wso2.carbon.iot.android.sense.realtimeviewer.event.realtimesensor.RealTimeSensorReader;
import org.wso2.carbon.iot.android.sense.realtimeviewer.sensorlisting.SupportedSensors;
import org.wso2.carbon.iot.android.sense.realtimeviewer.view.adaptor.SensorViewAdaptor;
import org.wso2.carbon.iot.android.sense.realtimeviewer.view.sensor.selector.SelectSensorDialog;
import org.wso2.carbon.iot.android.sense.speech.detector.WordRecognitionActivity;
import org.wso2.carbon.iot.android.sense.util.LocalRegistry;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import agent.sense.android.iot.carbon.wso2.org.wso2_senseagent.R;
/**
* Activity for selecting sensors available in the device
*/
public class ActivitySelectSensor extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, SelectSensorDialog.SensorListListener {
private SharedPreferences sharedPreferences;
private SelectSensorDialog sensorDialog = new SelectSensorDialog();
private Set<String> selectedSensorSet = new HashSet<>();
private ListView listView;
private SensorManager sensorManager;
private ArrayList<Sensor> sensors = new ArrayList<>();
private RealTimeSensorReader sensorReader = null;
private RealTimeSensorChangeReceiver realTimeSensorChangeReceiver = new RealTimeSensorChangeReceiver();
private SupportedSensors supportedSensors = SupportedSensors.getInstance();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity_select_sensor);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
listView = (ListView) findViewById(R.id.senseListContainer);
registerReceiver(realTimeSensorChangeReceiver, new IntentFilter("sensorDataMap"));
//Publish data
FloatingActionButton fbtnPublishData = (FloatingActionButton) findViewById(R.id.publish);
fbtnPublishData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Publishing data started", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
DataPublisherReceiver dataPublisherReceiver = new DataPublisherReceiver();
dataPublisherReceiver.clearAbortBroadcast();
dataPublisherReceiver.onReceive(getApplicationContext(), null);
}
});
FloatingActionButton fbtnAddSensors = (FloatingActionButton) findViewById(R.id.addSensors);
fbtnAddSensors.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sensorDialog.show(getFragmentManager(), "Sensor List");
}
});
FloatingActionButton fbtnSpeechRecongnizer = (FloatingActionButton) findViewById(R.id.speech);
fbtnSpeechRecongnizer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EditText sessionIdText = (EditText) findViewById(R.id.sessionId);
String sessionId = sessionIdText.getText().toString();
if (!sessionId.isEmpty()) {
Intent intent = new Intent(getApplicationContext(), WordRecognitionActivity.class);
intent.putExtra("sessionId", sessionId);
startActivity(intent);
} else {
Toast.makeText(ActivitySelectSensor.this, "Please type a session id value", Toast.LENGTH_SHORT)
.show();
}
}
});
sharedPreferences = getSharedPreferences(SupportedSensors.SELECTED_SENSORS, 0);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_select_sensor, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_deEnroll) {
/**
* unregister the sensors and broadcast receivers.
* */
unregisterSensors();
unregisterReceivers();
if (!LocalRegistry.isExist(getApplicationContext())) {
Intent activity = new Intent(getApplicationContext(), RegisterActivity.class);
startActivity(activity);
}
LocalRegistry.removeUsername(getApplicationContext());
LocalRegistry.removeDeviceId(getApplicationContext());
LocalRegistry.removeServerURL(getApplicationContext());
LocalRegistry.setExist(false);
//Stop the current running background services.
stopService(new Intent(this, SenseService.class)); //Stop sensor reading service
stopService(new Intent(this, DataPublisherService.class)); //Stop data uploader service
Intent registerActivity = new Intent(getApplicationContext(), RegisterActivity.class);
registerActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(registerActivity);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.select) {
sensorDialog.show(getFragmentManager(), "Sensor List");
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
@Override
public void onDialogPositiveClick(SelectSensorDialog dialog) {
Log.d("Selected sensors", dialog.getSet().toString());
selectedSensorSet = dialog.getSet();
update();
unregisterSensors();
SenseScheduleReceiver senseScheduleReceiver = new SenseScheduleReceiver();
senseScheduleReceiver.clearAbortBroadcast();
senseScheduleReceiver.onReceive(this, null);
/**
* Get the selected sensors
* Register them
* */
SensorViewAdaptor adaptor1 = new SensorViewAdaptor(getApplicationContext(), TempStore.sensorArrayList);
adaptor1.notifyDataSetChanged();
sensorReader = new RealTimeSensorReader(this, adaptor1);
getSensors();
for (Sensor s : sensors) {
sensorManager.registerListener(sensorReader, s, SensorManager.SENSOR_DELAY_NORMAL);
}
realTimeSensorChangeReceiver.updateOnChange(adaptor1);
listView.setAdapter(adaptor1);
}
public void update() {
Log.d("Update", "Set the values to Shared Preferences");
TempStore.sensorArrayList.clear();
TempStore.sensorDataMap.clear();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putStringSet(SupportedSensors.SELECTED_SENSORS_BY_USER, selectedSensorSet);
editor.apply();
}
public void getSensors() {
sensors.clear();
for (String sensor : selectedSensorSet.toArray(new String[selectedSensorSet.size()])) {
sensors.add(sensorManager.getDefaultSensor(supportedSensors.getType(sensor.toLowerCase())));
}
}
/**
* This method will unregister all the registered sensors.
*/
public void unregisterSensors() {
if (sensors.size() > 0) {
for (Sensor s : sensors) {
System.out.println(s.getName() + " Unregistered!");
sensorManager.unregisterListener(sensorReader, s);
}
}
}
/**
* This method unregisters the real-time broadcast receiver.
*/
public void unregisterReceivers() {
unregisterReceiver(realTimeSensorChangeReceiver);
}
}

@ -0,0 +1,37 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.realtimeviewer.datastore;
import org.wso2.carbon.iot.android.sense.realtimeviewer.event.realtimesensor.RealTimeSensor;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Class to store the real time sensor readings.
*/
public class TempStore {
/**
* Hash map which is used to store sensor values with the sensor names.
*/
public static ConcurrentMap<String, RealTimeSensor> sensorDataMap = new ConcurrentHashMap<>();
/**
* Array List which is used to populate the List view.
*/
public static ArrayList<RealTimeSensor> sensorArrayList = new ArrayList<>();
}

@ -0,0 +1,41 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.realtimeviewer.event;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.wso2.carbon.iot.android.sense.realtimeviewer.datastore.TempStore;
import org.wso2.carbon.iot.android.sense.realtimeviewer.view.adaptor.SensorViewAdaptor;
/**
* This class is to detect the sensor change event and update the sensor array list.
* And update the view adaptor which is used to show the sensors list in the Android List view.
*/
public class RealTimeSensorChangeReceiver extends BroadcastReceiver {
SensorViewAdaptor adaptor;
public void updateOnChange(SensorViewAdaptor adaptor) {
this.adaptor = adaptor;
}
@Override
public void onReceive(Context context, Intent intent) {
TempStore.sensorArrayList.clear();
TempStore.sensorArrayList.addAll(TempStore.sensorDataMap.values());
}
}

@ -0,0 +1,88 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.realtimeviewer.event.realtimesensor;
import android.support.annotation.NonNull;
/**
* The class to store the sensor data captured by the RealTimeSensorReader.
*/
public class RealTimeSensor implements Comparable {
/**
* Name of the sensor.
*/
private String name;
/**
* The X value reading of the sensor.
*/
private String valueX;
/**
* The Y value reading of the sensor.
*/
private String valueY;
/**
* The Y value reading of the sensor.
*/
private String valueZ;
public RealTimeSensor() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValueX() {
return valueX;
}
public void setValueX(String valueX) {
this.valueX = valueX;
}
public String getValueY() {
return valueY;
}
public void setValueY(String valueY) {
this.valueY = valueY;
}
public String getValueZ() {
return valueZ;
}
public void setValueZ(String valueZ) {
this.valueZ = valueZ;
}
@Override
public String toString() {
return this.valueX + ", " + valueY + ", " + valueZ;
}
@Override
public int compareTo(@NonNull Object another) {
return this.toString().contains(another.toString()) ? 1 : 0;
}
}

@ -0,0 +1,62 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.realtimeviewer.event.realtimesensor;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import org.wso2.carbon.iot.android.sense.realtimeviewer.datastore.TempStore;
import org.wso2.carbon.iot.android.sense.realtimeviewer.sensorlisting.SupportedSensors;
import org.wso2.carbon.iot.android.sense.realtimeviewer.view.adaptor.SensorViewAdaptor;
/**
* This class reads the sensor values in real time.
*/
public class RealTimeSensorReader implements SensorEventListener {
private Context context;
private SensorViewAdaptor adaptor;
private SupportedSensors supportedSensors = SupportedSensors.getInstance();
public RealTimeSensorReader(Context context, SensorViewAdaptor adaptor) {
this.context = context;
this.adaptor = adaptor;
}
@Override
public void onSensorChanged(SensorEvent event) {
RealTimeSensor realTimeSensor = new RealTimeSensor();
realTimeSensor.setName(supportedSensors.getType(event.sensor.getType()).toUpperCase());
realTimeSensor.setValueX(event.values[0] + "");
realTimeSensor.setValueY(event.values[1] + "");
realTimeSensor.setValueZ(event.values[2] + "");
TempStore.sensorDataMap.put(supportedSensors.getType(event.sensor.getType()), realTimeSensor);
Intent intent = new Intent();
intent.setAction("sensorDataMap");
context.sendBroadcast(intent);
adaptor.notifyDataSetChanged();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}

@ -0,0 +1,65 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.realtimeviewer.sensorlisting;
import android.content.Context;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Class to save the list of sensors that are available in the device, which are supported by the iot server.
* This list will be saved in Shared preferences so that app can use this data when needed.
*/
public class AvailableSensorsInDevice {
private SharedPreferences sensorPreference;
/**
* The Android sensor manager which is used to get the sensors available in device.
*/
private SensorManager mSensorManager;
public AvailableSensorsInDevice(Context context) {
this.sensorPreference = context.getSharedPreferences(SupportedSensors.AVAILABLE_SENSORS, 0);
this.mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
}
/**
* This method filters the pre defined sensor types from sensors available in device and sets them in Shared
* preferences.
*/
public void setContent() {
SupportedSensors supportedSensors = SupportedSensors.getInstance();
List<String> sensor_List = supportedSensors.getSensorList();
Set<String> sensorSet = new HashSet<>();
List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
for (String sen : sensor_List) {
if (sensors.contains(mSensorManager.getDefaultSensor(supportedSensors.getType(sen.toLowerCase())))) {
sensorSet.add(sen);
}
}
SharedPreferences.Editor editor = this.sensorPreference.edit();
editor.putStringSet(SupportedSensors.GET_AVAILABLE_SENSORS, sensorSet);
editor.apply();
}
}

@ -0,0 +1,120 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.realtimeviewer.sensorlisting;
import android.hardware.Sensor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Class to store the supported sensorDataMap types.
*/
public class SupportedSensors {
//For set user selected sensors. Will be used by sensorDataMap reading and dialog
public static String SELECTED_SENSORS = "Selected";
public static String SELECTED_SENSORS_BY_USER = "userSelection";
//For setting the available sensors in the device in dialog and AvailableSensorsInDevice
public static String AVAILABLE_SENSORS = "Sensors";
public static String GET_AVAILABLE_SENSORS = "getAvailableSensors";
public static final int SUPPORTED_SENSOR_COUNT = 10;
private static List<String> sensorList = new ArrayList<>();
private static HashMap<String, Integer> sensorTypeMap = new HashMap<>();
private static HashMap<Integer, String> typeSensorMap = new HashMap<>();
private static SupportedSensors supportedSensors = new SupportedSensors();
private SupportedSensors() {
this.setList();
this.setSensorTypeMap();
this.setTypeSensorMap();
}
public static SupportedSensors getInstance() {
return supportedSensors;
}
/**
* Set the supported sensor types by the IOT server.
*/
private void setList() {
sensorList.add("Accelerometer");
sensorList.add("Magnetometer");
sensorList.add("Gravity");
sensorList.add("Rotation Vector");
sensorList.add("Pressure");
sensorList.add("Light");
sensorList.add("Gyroscope");
sensorList.add("Proximity");
}
/**
* Populate the hash map which has Sensor name as the key and the sensor type as the value.
*/
private void setSensorTypeMap() {
sensorTypeMap.put("accelerometer", Sensor.TYPE_ACCELEROMETER);
sensorTypeMap.put("magnetometer", Sensor.TYPE_MAGNETIC_FIELD);
sensorTypeMap.put("gravity", Sensor.TYPE_GRAVITY);
sensorTypeMap.put("rotation vector", Sensor.TYPE_GAME_ROTATION_VECTOR);
sensorTypeMap.put("pressure", Sensor.TYPE_PRESSURE);
sensorTypeMap.put("gyroscope", Sensor.TYPE_GYROSCOPE);
sensorTypeMap.put("light", Sensor.TYPE_LIGHT);
sensorTypeMap.put("proximity", Sensor.TYPE_PROXIMITY);
}
/**
* Populates the hash map which has Sensor type as the key and sensor name as the value.
*/
private void setTypeSensorMap() {
typeSensorMap.put(Sensor.TYPE_ACCELEROMETER, "accelerometer");
typeSensorMap.put(Sensor.TYPE_MAGNETIC_FIELD, "magnetometer");
typeSensorMap.put(Sensor.TYPE_GRAVITY, "gravity");
typeSensorMap.put(Sensor.TYPE_GAME_ROTATION_VECTOR, "rotation vector");
typeSensorMap.put(Sensor.TYPE_PRESSURE, "pressure");
typeSensorMap.put(Sensor.TYPE_GYROSCOPE, "gyroscope");
typeSensorMap.put(Sensor.TYPE_LIGHT, "light");
typeSensorMap.put(Sensor.TYPE_PROXIMITY, "proximity");
}
/**
* Method to get the supported sensor list.
*
* @return the list of sensors supported by the iot server.
*/
public List<String> getSensorList() {
return sensorList;
}
/**
* @param sensor The name of the sensor.
* @return The integer representing the type of the sensor,
*/
public int getType(String sensor) {
return sensorTypeMap.get(sensor);
}
/**
* @param type The type of the sensor.
* @return The sensor name related to the given sensor type.
*/
public String getType(int type) {
return typeSensorMap.get(type);
}
}

@ -0,0 +1,95 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.realtimeviewer.view.adaptor;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import org.wso2.carbon.iot.android.sense.realtimeviewer.event.realtimesensor.RealTimeSensor;
import java.util.List;
import agent.sense.android.iot.carbon.wso2.org.wso2_senseagent.R;
/**
* Adaptor for populate the ListView.
* Takes list of Sensor readings
*/
public class SensorViewAdaptor extends BaseAdapter {
private Context context;
private List<RealTimeSensor> data;
public SensorViewAdaptor(Context context, List<RealTimeSensor> data) {
this.context = context;
this.data = data;
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view;
if (convertView == null) {
view = inflater.inflate(R.layout.display_sensor_values, parent, false);
holder = new ViewHolder();
holder.name = (TextView) view.findViewById(R.id.name);
holder.valuesX = (TextView) view.findViewById(R.id.X);
holder.valuesY = (TextView) view.findViewById(R.id.Y);
holder.valuesZ = (TextView) view.findViewById(R.id.Z);
view.setTag(holder);
} else {
view = convertView;
holder = (ViewHolder) view.getTag();
}
RealTimeSensor data = this.data.get(position);
holder.name.setText(data.getName());
holder.valuesX.setText(data.getValueX());
holder.valuesY.setText(data.getValueY());
holder.valuesZ.setText(data.getValueZ());
return view;
}
private class ViewHolder {
public TextView name;
public TextView valuesX;
public TextView valuesY;
public TextView valuesZ;
}
}

@ -0,0 +1,147 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.realtimeviewer.view.sensor.selector;
import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import org.wso2.carbon.iot.android.sense.realtimeviewer.sensorlisting.SupportedSensors;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* Functionality
* <p/>
* Show the list of available sensors in a list
* Get the user selections
* Put them in to shared preferences
*/
public class SelectSensorDialog extends DialogFragment {
protected boolean[] selections = new boolean[SupportedSensors.SUPPORTED_SENSOR_COUNT];
Activity activity;
SensorListListener sensorListListener;
private Set<String> selectedSensorSet = new HashSet<>();
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Select Sensors");
activity = getActivity();
SharedPreferences preferences = getActivity().getSharedPreferences(SupportedSensors.AVAILABLE_SENSORS, Context.
MODE_MULTI_PROCESS);
Set<String> set = preferences.getStringSet(SupportedSensors.GET_AVAILABLE_SENSORS, null);
final CharSequence[] sequence = getSequence(set);
final boolean[] pos = new boolean[selections.length];
final boolean[] neg = new boolean[selections.length];
builder.setMultiChoiceItems(sequence, selections, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
selectedSensorSet.add(sequence[which].toString());
pos[which] = true;
} else {
selectedSensorSet.remove(sequence[which].toString());
neg[which] = true;
}
}
});
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("Click", "Ok");
//call sensorDataMap reading class
sensorListListener.onDialogPositiveClick(SelectSensorDialog.this);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("Click", "Cancel");
for (int i = 0; i < SupportedSensors.SUPPORTED_SENSOR_COUNT; i++) {
if (pos[i])
selections[i] = false;
if (neg[i])
selections[i] = true;
}
}
});
return builder.create();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onDetach() {
super.onDetach();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
sensorListListener = (SensorListListener) getActivity();
} catch (ClassCastException ex) {
throw new ClassCastException(activity.toString() + " must implement the SensorListener");
}
}
@Override
public void onStart() {
super.onStart();
}
/**
* Interface to be implemented by the parent
*/
public CharSequence[] getSequence(Set<String> sensorset) {
CharSequence[] seq;
String[] seq2 = sensorset.toArray(new String[sensorset.size()]);
seq = Arrays.copyOf(seq2, seq2.length);
return seq;
}
public Set<String> getSet() {
return this.selectedSensorSet;
}
public interface SensorListListener {
void onDialogPositiveClick(SelectSensorDialog dialog);
}
}

@ -0,0 +1,32 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.speech.detector;
/**
* This interface is used to retrieve the voice commands and restart the listenting service
*/
public interface IVoiceControl {
/**
* This will be executed when a voice command was found
* @param voiceCommands
*/
public abstract void processVoiceCommands(String... voiceCommands);
/**
* This will be executed after a voice command was processed to keep the recognition service activated
*/
public void restartListeningService();
public void finish();
}

@ -0,0 +1,148 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.speech.detector;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import org.wso2.carbon.iot.android.sense.constants.SenseConstants;
import org.wso2.carbon.iot.android.sense.realtimeviewer.ActivitySelectSensor;
import org.wso2.carbon.iot.android.sense.speech.detector.util.ListeningActivity;
import org.wso2.carbon.iot.android.sense.speech.detector.util.ProcessWords;
import org.wso2.carbon.iot.android.sense.speech.detector.util.VoiceRecognitionListener;
import org.wso2.carbon.iot.android.sense.speech.detector.util.WordData;
import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
import agent.sense.android.iot.carbon.wso2.org.wso2_senseagent.R;
/**
* This is main activity for word recognition.
*/
public class WordRecognitionActivity extends ListeningActivity {
Button setThreasholdButton;
Button addWordButton;
Button removeWordButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_speech_sense_main);
context = getApplicationContext(); // Needs to be set
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
VoiceRecognitionListener.getInstance().setListener(this); // Here we set the current listener
addListenerOnSetThreasholdButton();
addListenerOnAddWordButton();
addListenerOnRemoveWordButton();
String sessionId = getIntent().getStringExtra("sessionId");
ProcessWords.setSessionId(sessionId);
FloatingActionButton fbtnSpeechRecongnizer = (FloatingActionButton) findViewById(R.id.sensorChange);
fbtnSpeechRecongnizer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
WordData wordData = new WordData(ProcessWords.getSessionId(), SenseConstants.EVENT_LISTENER_FINISHED, 1);
SenseDataHolder.getWordDataHolder().add(wordData);
stopListening();
Intent intent = new Intent(getApplicationContext(), ActivitySelectSensor.class);
startActivity(intent);
}
});
Long tsLong = System.currentTimeMillis() / 1000;
WordData wordData = new WordData(sessionId, SenseConstants.EVENT_LISTENER_STARTED, 1);
SenseDataHolder.getWordDataHolder().add(wordData);
startListening(); // starts listening
}
@Override
public void onBackPressed() {
}
@Override
public void processVoiceCommands(String... voiceCommands) {
if(voiceCommands==null || voiceCommands.length==0){
return;
}
ProcessWords processWords = new ProcessWords(this);
processWords.execute(voiceCommands);
restartListeningService();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_deEnroll) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void addListenerOnSetThreasholdButton() {
setThreasholdButton = (Button) findViewById(R.id.setThreshold);
setThreasholdButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
String thresholdString = ((EditText) findViewById(R.id.editThreashold)).getText().toString();
try{
ProcessWords.setThreshold(Integer.parseInt(thresholdString));
} catch (NumberFormatException e) {
Toast.makeText(WordRecognitionActivity.this, "Invalid Threshold - " + thresholdString, Toast.LENGTH_SHORT).show();
}
}
});
}
public void addListenerOnAddWordButton() {
addWordButton = (Button) findViewById(R.id.addWord);
addWordButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
String word = ((EditText) findViewById(R.id.wordText)).getText().toString();
ProcessWords.addWord(word);
Toast.makeText(WordRecognitionActivity.this, word + " is added to the list", Toast.LENGTH_SHORT).show();
}
});
}
public void addListenerOnRemoveWordButton() {
removeWordButton = (Button) findViewById(R.id.removeWord);
removeWordButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
String word = ((EditText) findViewById(R.id.wordText)).getText().toString();
Toast.makeText(WordRecognitionActivity.this, word + " is removed from the list", Toast.LENGTH_SHORT).show();
ProcessWords.removeWord(word);
}
});
}
}

@ -0,0 +1,125 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.speech.detector.util;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.widget.Toast;
import org.wso2.carbon.iot.android.sense.speech.detector.IVoiceControl;
/**
* This Activity Contols the Speech Recognizer Activity.
*/
public abstract class ListeningActivity extends Activity implements IVoiceControl {
protected SpeechRecognizer sr;
protected Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
/**
* Starts the listening service.
*/
protected void startListening() {
initSpeech();
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
sr.startListening(intent);
}
/**
* Stop the listening service.
*/
protected void stopListening() {
if (sr != null) {
sr.stopListening();
sr.cancel();
sr.destroy();
}
sr = null;
}
/**
* Initialize the speech.
*/
protected void initSpeech() {
if (sr == null) {
sr = SpeechRecognizer.createSpeechRecognizer(this);
if (!SpeechRecognizer.isRecognitionAvailable(context)) {
Toast.makeText(context, "Speech Recognition is not available",
Toast.LENGTH_LONG).show();
finish();
}
sr.setRecognitionListener(VoiceRecognitionListener.getInstance());
}
}
@Override
public void finish() {
stopListening();
super.finish();
}
@Override
protected void onStop() {
stopListening();
super.onStop();
}
@Override
protected void onDestroy() {
if (sr != null) {
sr.stopListening();
sr.cancel();
sr.destroy();
}
super.onDestroy();
}
@Override
protected void onPause() {
if(sr!=null){
sr.stopListening();
sr.cancel();
sr.destroy();
}
sr = null;
super.onPause();
}
/**
* Is abstract so the inheriting classes need to implement it. Here you put your code which should be executed once
* a command was found
*/
@Override
public abstract void processVoiceCommands(String ... voiceCommands);
@Override
public void restartListeningService() {
stopListening();
startListening();
}
}

@ -0,0 +1,193 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.speech.detector.util;
import android.app.Activity;
import android.os.AsyncTask;
import android.widget.EditText;
import org.apache.commons.codec.language.Soundex;
import org.wso2.carbon.iot.android.sense.event.streams.Location.LocationData;
import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.tartarus.snowball.ext.englishStemmer;
import agent.sense.android.iot.carbon.wso2.org.wso2_senseagent.R;
/**
* This class process the words form required words with the recongnized words to check whether it matches with the
* certain threshold.
*/
public class ProcessWords extends AsyncTask<String, Void, String> {
private static volatile double threshold = 80;
private static volatile Map<String, WordData> wordDataMap = new ConcurrentHashMap<>();
private static String sessionId = "default";
private static Soundex soundex = new Soundex();
Activity activity;
public ProcessWords(Activity activity) {
this.activity = activity;
}
/**
* Add the list of words which are used for reference.
* @param wordlist that needs to be looked upon in the speech
*/
public static void addWords(List<String> wordlist) {
for (String word : wordlist) {
if (!wordDataMap.keySet().contains(word) && !word.isEmpty()) {
wordDataMap.put(word, new WordData(sessionId, word, 0));
}
}
}
/**
* Process the recognized word list.
* @param voiceCommands word lists.
*/
private void processTexts(String... voiceCommands) {
for (String requiredWord : wordDataMap.keySet()) {
int maxOccurunce = 0;
for (String command : voiceCommands) {
int occurence = 0;
for (String word : command.split(" ")) {
if (StringSimilarity.similarity(requiredWord, word) > threshold) {
occurence++;
continue;
}
if (soundex.encode(requiredWord).equals(soundex.encode(word))) {
occurence++;
continue;
}
if (StringSimilarity.similarity(requiredWord, stem(word)) > threshold) {
occurence++;
continue;
}
}
if (maxOccurunce < occurence) {
maxOccurunce = occurence;
}
}
if (maxOccurunce > 0) {
WordData wordData = wordDataMap.get(requiredWord);
wordData.addOccurences(maxOccurunce);
wordDataMap.put(requiredWord, wordData);
}
}
}
/**
* Check for distance between the referenced and recognized words.
* @param params
* @return
*/
@Override
protected String doInBackground(String... params) {
processTexts(params);
publishProgress();
return "";
}
/**
* update it in the UI.
* @param values words list.
*/
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
EditText content = (EditText) activity.findViewById(R.id.command);
String text = "";
for (String key : ProcessWords.wordDataMap.keySet()) {
text = text + key + " - " + ProcessWords.wordDataMap.get(key).getOccurences() + "\n";
}
content.setText(text);
EditText thresholdText = (EditText) activity.findViewById(R.id.editThreashold);
thresholdText.setText("" + threshold);
}
/**
* set the threshold to determine the distance.
* @param threshold to determine the distance.
*/
public static synchronized void setThreshold(int threshold) {
ProcessWords.threshold = threshold;
}
/**
*
* @param sessionId for each listening session.
*/
public static synchronized void setSessionId(String sessionId) {
ProcessWords.sessionId = sessionId;
}
/**
*
* retrieve sessionId for each listening session.
*/
public static synchronized String getSessionId() {
return ProcessWords.sessionId;
}
/**
* @param word that is used for refrerence.
*/
public static synchronized void addWord(String word) {
if (!wordDataMap.keySet().contains(word) && !word.isEmpty()) {
wordDataMap.put(word, new WordData(sessionId, word, 0));
}
}
/**
*
* @param word that needs to be removed from the reference list.
*/
public static synchronized void removeWord(String word) {
cleanAndPushToWordMap();
wordDataMap.remove(word);
}
/**
* clean in memory content and pubish it to the server.
*/
public static synchronized void cleanAndPushToWordMap() {
for (String word : wordDataMap.keySet()) {
WordData wordData = wordDataMap.get(word);
SenseDataHolder.getWordDataHolder().add(wordData);
wordDataMap.put(word, new WordData(sessionId, word, 0));
}
}
/**
* apply porter stem algorithm
* @param word to be stemmed.
* @return
*/
private static String stem(String word)
{
englishStemmer stemmer = new englishStemmer();
stemmer.setCurrent(word);
boolean result = stemmer.stem();
if (!result)
{
return word;
}
return stemmer.getCurrent();
}
}

@ -0,0 +1,67 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.speech.detector.util;
/**
* Calculates the similarity of strings.
*/
public class StringSimilarity {
/**
* Calculates the similarity (a number within 0 and 1) between two strings.
*/
public static double similarity(String s1, String s2) {
String longer = s1, shorter = s2;
if (s1.length() < s2.length()) { // longer should always have greater length
longer = s2;
shorter = s1;
}
int longerLength = longer.length();
if (longerLength == 0) {
return 1.0; /* both strings are zero length */
}
return ((longerLength - editDistance(longer, shorter)) / (double) longerLength) * 100;
}
// Example implementation of the Levenshtein Edit Distance
// See http://rosettacode.org/wiki/Levenshtein_distance#Java
private static int editDistance(String s1, String s2) {
s1 = s1.toLowerCase();
s2 = s2.toLowerCase();
int[] costs = new int[s2.length() + 1];
for (int i = 0; i <= s1.length(); i++) {
int lastValue = i;
for (int j = 0; j <= s2.length(); j++) {
if (i == 0)
costs[j] = j;
else {
if (j > 0) {
int newValue = costs[j - 1];
if (s1.charAt(i - 1) != s2.charAt(j - 1))
newValue = Math.min(Math.min(newValue, lastValue),
costs[j]) + 1;
costs[j - 1] = lastValue;
lastValue = newValue;
}
}
}
if (i > 0)
costs[s2.length()] = lastValue;
}
return costs[s2.length()];
}
}

@ -0,0 +1,80 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.speech.detector.util;
import android.os.Bundle;
import android.speech.RecognitionListener;
import android.speech.SpeechRecognizer;
import org.wso2.carbon.iot.android.sense.speech.detector.IVoiceControl;
import java.util.ArrayList;
/**
* This triggers android voice recognition listener.
*/
public class VoiceRecognitionListener implements RecognitionListener {
private static VoiceRecognitionListener instance = null;
IVoiceControl listener; // This is your running activity (we will initialize it later)
public static VoiceRecognitionListener getInstance() {
if (instance == null) {
instance = new VoiceRecognitionListener();
}
return instance;
}
private VoiceRecognitionListener() { }
public void setListener(IVoiceControl listener) {
this.listener = listener;
}
public void processVoiceCommands(String... voiceCommands) {
listener.processVoiceCommands(voiceCommands);
}
// This method will be executed when voice commands were found
public void onResults(Bundle data) {
ArrayList<String> matches = data.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
String[] commands = new String[matches.size()];
commands = matches.toArray(commands);
processVoiceCommands(commands);
}
// User starts speaking
public void onBeginningOfSpeech() {
System.out.println("Starting to listen");
}
public void onBufferReceived(byte[] buffer) { }
// User finished speaking
public void onEndOfSpeech() {
System.out.println("Waiting for result...");
}
// If the user said nothing the service will be restarted
public void onError(int error) {
if (listener != null) {
listener.restartListeningService();
}
}
public void onEvent(int eventType, Bundle params) { }
public void onPartialResults(Bundle partialResults) { }
public void onReadyForSpeech(Bundle params) { }
public void onRmsChanged(float rmsdB) { }
}

@ -0,0 +1,60 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.speech.detector.util;
/**
* This defines the data structure of the word data.
*/
public class WordData {
/**
* timestamp for all the occurences
*/
private long timestamp;
private int occurences;
private String word;
private String sessionId;
public WordData(String sessionId, String word, int occurences) {
this.timestamp = System.currentTimeMillis() / 1000;
this.occurences = occurences;
this.word = word;
this.sessionId = sessionId;
}
public long getTimestamp() {
return timestamp;
}
public int getOccurences() {
return occurences;
}
public String getWord() {
return word;
}
public String getSessionId() {
return sessionId;
}
/**
* @param occurences for the word and then add the timestamp for each occurences.
*/
public void addOccurences(int occurences) {
this.occurences = this.occurences + occurences;
this.timestamp = System.currentTimeMillis() / 1000;
}
}

@ -0,0 +1,225 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import org.wso2.carbon.iot.android.sense.constants.SenseConstants;
import org.wso2.carbon.iot.android.sense.data.publisher.mqtt.transport.MQTTTransportHandler;
import java.net.MalformedURLException;
import java.net.URL;
/**
* This is used to store the values in either in memory or in shared preferences.
*/
public class LocalRegistry {
private static final String SENSE_SHARED_PREFERENCES = "senseSharedPreferences";
private static final String USERNAME_KEY = "usernameKey";
private static final String DEVICE_ID_KEY = "deviceIdKey";
private static final String SERVER_HOST_KEY = "serverHostKey";
private static final String ACCESS_TOKEN_KEY = "accessTokenKey";
private static final String REFRESH_TOKEN_KEY = "refreshTokenKey";
private static final String MQTT_PORT_KEY = "mqttPort";
private static boolean exists = false;
private static String username;
private static String deviceId;
private static String serverURL;
private static MQTTTransportHandler mqttTransportHandler;
private static String accessToken;
private static String refreshToken;
private static int mqttPort;
public static boolean isExist(Context context) {
if (!exists) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
String username = sharedpreferences.getString(USERNAME_KEY, "");
String deviceId = sharedpreferences.getString(DEVICE_ID_KEY, "");
exists = (username != null && !username.isEmpty() && deviceId != null && !deviceId.isEmpty());
}
return exists;
}
public static void setExist(boolean status) {
exists = status;
}
public static void addUsername(Context context, String username) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(USERNAME_KEY, username);
editor.commit();
LocalRegistry.username = username;
}
public static String getUsername(Context context) {
if (LocalRegistry.username == null || username.isEmpty()) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
LocalRegistry.username = sharedpreferences.getString(USERNAME_KEY, "");
}
return LocalRegistry.username;
}
public static void removeUsername(Context context) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.clear();
editor.remove(USERNAME_KEY);
editor.commit();
LocalRegistry.username = null;
}
public static void addDeviceId(Context context, String deviceId) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(DEVICE_ID_KEY, deviceId);
editor.commit();
LocalRegistry.deviceId = deviceId;
}
public static void removeDeviceId(Context context) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.remove(DEVICE_ID_KEY);
editor.clear();
editor.commit();
LocalRegistry.deviceId = null;
}
public static String getDeviceId(Context context) {
if (LocalRegistry.deviceId == null || LocalRegistry.deviceId.isEmpty()) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
LocalRegistry.deviceId = sharedpreferences.getString(DEVICE_ID_KEY, "");
}
return LocalRegistry.deviceId;
}
public static void addServerURL(Context context, String host) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(SERVER_HOST_KEY, host);
editor.commit();
LocalRegistry.serverURL = host;
}
public static void removeServerURL(Context context) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.remove(SERVER_HOST_KEY);
editor.clear();
editor.commit();
LocalRegistry.serverURL = null;
}
public static String getServerURL(Context context) {
if (LocalRegistry.serverURL == null || LocalRegistry.serverURL.isEmpty()) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
LocalRegistry.serverURL = sharedpreferences.getString(SERVER_HOST_KEY, "");
}
return LocalRegistry.serverURL;
}
public static void addAccessToken(Context context, String accessToken) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(ACCESS_TOKEN_KEY, accessToken);
editor.commit();
LocalRegistry.accessToken = accessToken;
}
public static void removeAccessToken(Context context) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.remove(ACCESS_TOKEN_KEY);
editor.clear();
editor.commit();
LocalRegistry.accessToken = null;
}
public static String getAccessToken(Context context) {
if (LocalRegistry.accessToken == null || LocalRegistry.accessToken.isEmpty()) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
LocalRegistry.accessToken = sharedpreferences.getString(ACCESS_TOKEN_KEY, "");
}
return LocalRegistry.accessToken;
}
public static void addRefreshToken(Context context, String refreshToken) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(REFRESH_TOKEN_KEY, refreshToken);
editor.commit();
LocalRegistry.refreshToken = refreshToken;
}
public static void removeRefreshToken(Context context) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.remove(REFRESH_TOKEN_KEY);
editor.clear();
editor.commit();
LocalRegistry.refreshToken = null;
}
public static String getRefreshToken(Context context) {
if (LocalRegistry.refreshToken == null || LocalRegistry.refreshToken.isEmpty()) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
LocalRegistry.refreshToken = sharedpreferences.getString(REFRESH_TOKEN_KEY, "");
}
return LocalRegistry.refreshToken;
}
public static void addMqttPort(Context context, int port) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putInt(MQTT_PORT_KEY, port);
editor.commit();
LocalRegistry.mqttPort = port;
}
public static void removeMqttPort(Context context) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.remove(MQTT_PORT_KEY);
editor.clear();
editor.commit();
LocalRegistry.mqttPort = 0;
}
public static int getMqttPort(Context context) {
if (LocalRegistry.mqttPort == 0) {
SharedPreferences sharedpreferences = context.getSharedPreferences(SENSE_SHARED_PREFERENCES, Context.MODE_PRIVATE);
LocalRegistry.mqttPort = sharedpreferences.getInt(MQTT_PORT_KEY, SenseConstants.MQTT_BROKER_PORT);
}
return LocalRegistry.mqttPort;
}
public static String getServerHost(Context context) {
URL url = null;
String urlString = getServerURL(context);
try {
url = new URL(urlString);
return url.getHost();
} catch (MalformedURLException e) {
Log.e("Host ", "Invalid urlString :" + urlString);
return null;
}
}
}

@ -0,0 +1,86 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
import org.wso2.carbon.iot.android.sense.constants.SenseConstants;
import org.wso2.carbon.iot.android.sense.util.dto.RegisterInfo;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.logging.Handler;
/**
* This Client is used for http communication with the server.
*/
public class SenseClient {
private final static String TAG = "SenseService Client";
private Context context;
public SenseClient(Context context) {
this.context = context;
}
/**
* Enroll the device.
*
* @param username
* @param password
* @param deviceId
* @return
*/
public RegisterInfo register(String username, String password, String deviceId, android.os.Handler mUiHandler) {
Map<String, String> response = registerWithTimeWait(username, password, deviceId);
String responseStatus = response.get("status");
RegisterInfo registerInfo = new RegisterInfo();
if (responseStatus.trim().contains(SenseConstants.Request.REQUEST_SUCCESSFUL)) {
registerInfo.setMsg("Device Registered");
registerInfo.setIsRegistered(true);
return registerInfo;
} else if (responseStatus.trim().contains(SenseConstants.Request.REQUEST_CONFLICT)) {
registerInfo.setMsg("Login Successful");
registerInfo.setIsRegistered(true);
return registerInfo;
} else {
registerInfo.setMsg("Authentication failed, please check your credentials and try again.");
registerInfo.setIsRegistered(false);
return registerInfo;
}
}
public Map<String, String> registerWithTimeWait(String username, String password, String deviceId) {
try {
SenseClientAsyncExecutor senseClientAsyncExecutor = new SenseClientAsyncExecutor(context);
String endpoint = LocalRegistry.getServerURL(context);
senseClientAsyncExecutor.execute(username, password, deviceId, endpoint);
Map<String, String> response = senseClientAsyncExecutor.get();
if (response != null) {
return response;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.e("Send Sensor Data", "Thread Interruption for endpoint " + LocalRegistry.getServerURL(context));
} catch (ExecutionException e) {
Log.e("Send Sensor Data", "Failed to push data to the endpoint " + LocalRegistry.getServerURL(context));
}
return null;
}
}

@ -0,0 +1,163 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import org.wso2.carbon.iot.android.sense.constants.SenseConstants;
import org.wso2.carbon.iot.android.sense.util.dto.AccessTokenInfo;
import org.wso2.carbon.iot.android.sense.util.dto.AndroidSenseManagerService;
import org.wso2.carbon.iot.android.sense.util.dto.ApiApplicationRegistrationService;
import org.wso2.carbon.iot.android.sense.util.dto.ApiRegistrationProfile;
import org.wso2.carbon.iot.android.sense.util.dto.DynamicClientRegistrationService;
import org.wso2.carbon.iot.android.sense.util.dto.OAuthApplicationInfo;
import org.wso2.carbon.iot.android.sense.util.dto.OAuthRequestInterceptor;
import org.wso2.carbon.iot.android.sense.util.dto.RegistrationProfile;
import org.wso2.carbon.iot.android.sense.util.dto.TokenIssuerService;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import feign.Client;
import feign.Feign;
import feign.FeignException;
import feign.auth.BasicAuthRequestInterceptor;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import feign.jaxrs.JAXRSContract;
public class SenseClientAsyncExecutor extends AsyncTask<String, Void, Map<String, String>> {
private final static String TAG = "SenseService Client";
private static final String STATUS = "status";
private final static String DEVICE_NAME = Build.MANUFACTURER + " " + Build.MODEL;
private Context context;
public SenseClientAsyncExecutor(Context context) {
this.context = context;
}
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
Client disableHostnameVerification = new Client.Default(getTrustedSSLSocketFactory(), new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
@Override
protected Map<String, String> doInBackground(String... parameters) {
if (android.os.Debug.isDebuggerConnected())
android.os.Debug.waitForDebugger();
String response;
Map<String, String> response_params = new HashMap<>();
String username = parameters[0];
String password = parameters[1];
String deviceId = parameters[2];
String endpoint = parameters[3];
Map<String, String> responseMap = new HashMap<>();
responseMap.put(STATUS, "200");
try {
//DynamicClientRegistraiton.
DynamicClientRegistrationService dynamicClientRegistrationService = Feign.builder()
.client(disableHostnameVerification).contract(new
JAXRSContract()).encoder(new JacksonEncoder()).decoder(new JacksonDecoder())
.target(DynamicClientRegistrationService.class, endpoint + SenseConstants.DCR_CONTEXT);
RegistrationProfile registrationProfile = new RegistrationProfile();
String applicationName = "android-sense:" + deviceId;
registrationProfile.setOwner(username);
registrationProfile.setClientName(applicationName);
registrationProfile.setCallbackUrl("");
registrationProfile.setGrantType("password refresh_token client_credentials");
registrationProfile.setApplicationType("device");
registrationProfile.setTokenScope("production");
OAuthApplicationInfo oAuthApplicationInfo = dynamicClientRegistrationService.register(registrationProfile);
//PasswordGrantType
TokenIssuerService tokenIssuerService = Feign.builder().client(disableHostnameVerification).requestInterceptor(
new BasicAuthRequestInterceptor(oAuthApplicationInfo.getClient_id(), oAuthApplicationInfo.getClient_secret()))
.contract(new JAXRSContract()).encoder(new JacksonEncoder()).decoder(new JacksonDecoder())
.target(TokenIssuerService.class, endpoint + SenseConstants.TOKEN_ISSUER_CONTEXT);
AccessTokenInfo accessTokenInfo = tokenIssuerService.getToken("password", username, password);
//ApiApplicationRegistration
ApiApplicationRegistrationService apiApplicationRegistrationService = Feign.builder().client(disableHostnameVerification)
.requestInterceptor(new OAuthRequestInterceptor(accessTokenInfo.getAccess_token()))
.contract(new JAXRSContract()).encoder(new JacksonEncoder()).decoder(new JacksonDecoder())
.target(ApiApplicationRegistrationService.class, endpoint + SenseConstants.API_APPLICATION_REGISTRATION_CONTEXT);
ApiRegistrationProfile apiRegistrationProfile = new ApiRegistrationProfile();
apiRegistrationProfile.setApplicationName(applicationName);
apiRegistrationProfile.setConsumerKey(oAuthApplicationInfo.getClient_id());
apiRegistrationProfile.setConsumerSecret(oAuthApplicationInfo.getClient_secret());
apiRegistrationProfile.setIsAllowedToAllDomains(false);
apiRegistrationProfile.setIsMappingAnExistingOAuthApp(true);
apiRegistrationProfile.setTags(new String[]{SenseConstants.DEVICE_TYPE});
String replyMsg = apiApplicationRegistrationService.register(apiRegistrationProfile);
//DeviceRegister
AndroidSenseManagerService androidSenseManagerService = Feign.builder().client(disableHostnameVerification)
.requestInterceptor(new OAuthRequestInterceptor(accessTokenInfo.getAccess_token()))
.contract(new JAXRSContract()).encoder(new JacksonEncoder()).decoder(new JacksonDecoder())
.target(AndroidSenseManagerService.class, endpoint + SenseConstants.REGISTER_CONTEXT);
boolean registered = androidSenseManagerService.register(deviceId, DEVICE_NAME);
if (registered) {
LocalRegistry.addAccessToken(context, accessTokenInfo.getAccess_token());
LocalRegistry.addRefreshToken(context, accessTokenInfo.getRefresh_token());
}
return responseMap;
} catch (FeignException e) {
responseMap.put(STATUS, "" + e.status());
return responseMap;
}
}
private SSLSocketFactory getTrustedSSLSocketFactory() {
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
return sc.getSocketFactory();
} catch (KeyManagementException | NoSuchAlgorithmException e) {
Log.e(SenseClientAsyncExecutor.class.getName(), "Invalid Certificate");
return null;
}
}
}

@ -0,0 +1,78 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util;
import org.wso2.carbon.iot.android.sense.event.streams.Location.LocationData;
import org.wso2.carbon.iot.android.sense.event.streams.Sensor.SensorData;
import org.wso2.carbon.iot.android.sense.event.streams.battery.BatteryData;
import org.wso2.carbon.iot.android.sense.speech.detector.util.WordData;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* This holds the sensor,battery and location data inmemory.
*/
public class SenseDataHolder {
private static List<SensorData> sensorDataHolder;
private static List<BatteryData> batteryDataHolder;
private static List<LocationData> locationDataHolder;
private static List<WordData> wordDataHolder;
public static List<SensorData> getSensorDataHolder(){
if(sensorDataHolder == null){
sensorDataHolder = new CopyOnWriteArrayList<>();
}
return sensorDataHolder;
}
public static List<BatteryData> getBatteryDataHolder(){
if(batteryDataHolder == null){
batteryDataHolder = new CopyOnWriteArrayList<>();
}
return batteryDataHolder;
}
public static List<LocationData> getLocationDataHolder(){
if(locationDataHolder == null){
locationDataHolder = new CopyOnWriteArrayList<>();
}
return locationDataHolder;
}
public static List<WordData> getWordDataHolder(){
if(wordDataHolder == null){
wordDataHolder = new CopyOnWriteArrayList<>();
}
return wordDataHolder;
}
public static void resetSensorDataHolder(){
sensorDataHolder = null;
}
public static void resetBatteryDataHolder(){
batteryDataHolder = null;
}
public static void resetLocationDataHolder(){
locationDataHolder = null;
}
public static void resetWordDataHolder() {
wordDataHolder = null;
}
}

@ -0,0 +1,46 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util;
import android.content.ContentResolver;
import android.content.Context;
import android.telephony.TelephonyManager;
import java.util.UUID;
public class SenseUtils {
/**
* this generate the device Id
*
* @param baseContext
* @param contentResolver
* @return
*/
//http://stackoverflow.com/questions/2785485/is-there-a-unique-android-device-id
public static String generateDeviceId(Context baseContext, ContentResolver contentResolver) {
final TelephonyManager tm = (TelephonyManager) baseContext.getSystemService(Context.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, androidId;
tmDevice = String.valueOf(tm.getDeviceId());
tmSerial = String.valueOf(tm.getSimSerialNumber());
androidId = String.valueOf(android.provider.Settings.Secure.getString(contentResolver, android.provider.Settings.Secure.ANDROID_ID));
UUID deviceUuid = new UUID(androidId.hashCode(), ((long) tmDevice.hashCode() << 32) | tmSerial.hashCode());
return deviceUuid.toString();
}
}

@ -0,0 +1,47 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util;
import android.content.Context;
import android.os.PowerManager;
import android.util.Log;
/**
* It doesnt let the phone goto sleep.
*/
public class SenseWakeLock {
private static PowerManager.WakeLock wakeLock;
private static String TAG = "Wake Lock";
public static void acquireWakeLock(Context context) {
Log.i(SenseWakeLock.class.getSimpleName(), "Acquire CPU wakeup lock start");
if (wakeLock == null) {
Log.i(TAG, "CPU wakeUp log is not null");
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SenseWakeLock");
}
wakeLock.acquire();
}
public static void releaseCPUWakeLock() {
if (wakeLock != null) {
wakeLock.release();
wakeLock = null;
}
Log.i(TAG, "Release wakeup");
}
}

@ -0,0 +1,57 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util.dto;
/**
* This hold access token info that returned from the api call
*/
public class AccessTokenInfo {
public String token_type;
public String expires_in;
public String refresh_token;
public String access_token;
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
public String getExpires_in() {
return expires_in;
}
public void setExpires_in(String expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
}

@ -0,0 +1,30 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util.dto;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
/**
* This holds the android manager service definition that is used with netflix feign.
*/
public interface AndroidSenseManagerService {
@Path("/enrollment/devices/{device_id}")
@POST
boolean register(@PathParam("device_id") String deviceId, @QueryParam("deviceName") String deviceName);
}

@ -0,0 +1,25 @@
package org.wso2.carbon.iot.android.sense.util.dto;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* This is the application registration service that exposed for apimApplicationRegistration
*/
@Path("/register")
public interface ApiApplicationRegistrationService {
/**
* This method is used to register api application
*
* @param registrationProfile contains the necessary attributes that are needed in order to register an app.
*/
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
String register(ApiRegistrationProfile registrationProfile);
}

@ -0,0 +1,78 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util.dto;
/**
* This class represents the data that are required to register
* the oauth application.
*/
public class ApiRegistrationProfile {
public String applicationName;
public String tags[];
public boolean isAllowedToAllDomains;
public String consumerKey;
public String consumerSecret;
public boolean isMappingAnExistingOAuthApp;
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public boolean isAllowedToAllDomains() {
return isAllowedToAllDomains;
}
public void setIsAllowedToAllDomains(boolean isAllowedToAllDomains) {
this.isAllowedToAllDomains = isAllowedToAllDomains;
}
public boolean isMappingAnExistingOAuthApp() {
return isMappingAnExistingOAuthApp;
}
public void setIsMappingAnExistingOAuthApp(boolean isMappingAnExistingOAuthApp) {
this.isMappingAnExistingOAuthApp = isMappingAnExistingOAuthApp;
}
public String getConsumerKey() {
return consumerKey;
}
public void setConsumerKey(String consumerKey) {
this.consumerKey = consumerKey;
}
public String getConsumerSecret() {
return consumerSecret;
}
public void setConsumerSecret(String consumerSecret) {
this.consumerSecret = consumerSecret;
}
}

@ -0,0 +1,40 @@
/*
* 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.wso2.carbon.iot.android.sense.util.dto;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/register")
public interface DynamicClientRegistrationService {
/**
* This method is used to register an Oauth application.
*
* @param profile contains the necessary attributes that are
* needed in order to register an app.
* @return Status 200 if success including consumerKey and consumerSecret.
*/
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
OAuthApplicationInfo register(RegistrationProfile profile);
}

@ -0,0 +1,58 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util.dto;
/**
* This class represents an OAuth application populated with necessary data.
*/
public class OAuthApplicationInfo {
public String client_id;
public String client_name;
public String callback_url;
public String client_secret;
public String getClient_id() {
return client_id;
}
public void setClient_id(String client_id) {
this.client_id = client_id;
}
public String getClient_name() {
return client_name;
}
public void setClient_name(String client_name) {
this.client_name = client_name;
}
public String getCallback_url() {
return callback_url;
}
public void setCallback_url(String callback_url) {
this.callback_url = callback_url;
}
public String getClient_secret() {
return client_secret;
}
public void setClient_secret(String client_secret) {
this.client_secret = client_secret;
}
}

@ -0,0 +1,43 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util.dto;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import static feign.Util.checkNotNull;
/**
* This is a request interceptor to add oauth token header.
*/
public class OAuthRequestInterceptor implements RequestInterceptor {
private final String headerValue;
/**
* Creates an interceptor that authenticates all requests with the specified OAUTH token
*
* @param token the access token to use for authentication
*/
public OAuthRequestInterceptor(String token) {
checkNotNull(token, "access_token");
headerValue = "Bearer " + token;
}
@Override
public void apply(RequestTemplate template) {
template.header("Authorization", headerValue);
}
}

@ -0,0 +1,40 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util.dto;
/**
* This holds the data related to registration.
*/
public class RegisterInfo {
private boolean isRegistered;
private String msg;
public boolean isRegistered() {
return isRegistered;
}
public void setIsRegistered(boolean isRegistered) {
this.isRegistered = isRegistered;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

@ -0,0 +1,67 @@
package org.wso2.carbon.iot.android.sense.util.dto;
/**
* This class represents the data that are required to register
* the oauth application.
*/
public class RegistrationProfile {
public String callbackUrl;
public String clientName;
public String tokenScope;
public String owner;
public String grantType;
public String applicationType;
private static final String TAG = RegistrationProfile.class.getSimpleName();
public String getCallbackUrl() {
return callbackUrl;
}
public void setCallbackUrl(String callBackUrl) {
this.callbackUrl = callBackUrl;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getTokenScope() {
return tokenScope;
}
public void setTokenScope(String tokenScope) {
this.tokenScope = tokenScope;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getGrantType() {
return grantType;
}
public void setGrantType(String grantType) {
this.grantType = grantType;
}
public String getApplicationType() {
return applicationType;
}
public void setApplicationType(String applicationType) {
this.applicationType = applicationType;
}
}

@ -0,0 +1,33 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*
*/
package org.wso2.carbon.iot.android.sense.util.dto;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
/**
* This hold the api defintion that is used as a contract with netflix feign.
*/
@Path("/token")
public interface TokenIssuerService {
@POST
@Produces(MediaType.APPLICATION_JSON)
AccessTokenInfo getToken(@QueryParam("grant_type") String grant, @QueryParam("username") String username,
@QueryParam("password") String password);
}

@ -0,0 +1,9 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:startColor="#c7b681"
android:centerColor="#bc8d43"
android:endColor="#da800c"
android:type="linear"
android:angle="135"/>
</shape>

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout"
android:layout_width="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true" tools:openDrawer="start">
<include layout="@layout/app_bar_activity_select_sensor" android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView android:id="@+id/nav_view"
android:layout_width="wrap_content" android:layout_height="match_parent"
android:layout_gravity="start" android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_activity_select_sensor"
app:menu="@menu/activity_activity_select_sensor_drawer" />
</android.support.v4.widget.DrawerLayout>

@ -0,0 +1,79 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:gravity="center_horizontal"
android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" tools:context="org.wso2.carbon.iot.android.sense.RegisterActivity">
<!-- Login progress -->
<ProgressBar android:id="@+id/login_progress" style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp" android:visibility="gone" />
<ScrollView android:id="@+id/login_form" android:layout_width="match_parent"
android:layout_height="211dp"
android:fillViewport="false">
<LinearLayout android:id="@+id/email_login_form" android:layout_width="match_parent"
android:layout_height="wrap_content" android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" android:hint="@string/prompt_username"
android:id="@+id/username"
android:inputType="text"
android:maxLines="1" android:singleLine="true"
android:text="admin"/>
<EditText android:id="@+id/password" android:layout_width="match_parent"
android:layout_height="wrap_content" android:hint="@string/prompt_password"
android:inputType="textPassword"
android:maxLines="1" android:singleLine="true"
android:text="admin"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" android:hint="@string/hostname"
android:id="@+id/hostname"
android:text="https://localhost:9443"
android:inputType="text"
android:maxLines="1" android:singleLine="true"/>
<Button android:id="@+id/device_register_button" style="?android:textAppearanceSmall"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:text="@string/action_sign_in"
android:textStyle="bold" />
</LinearLayout>
</ScrollView>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="MQTT Port"
android:id="@+id/textView4"
android:layout_gravity="center_horizontal"/>
<EditText
android:layout_width="350dp"
android:layout_height="wrap_content"
android:hint="@string/hostname"
android:id="@+id/mqttPort"
android:text="1883"
android:inputType="text"
android:maxLines="1"
android:singleLine="true"
android:layout_gravity="right"/>
</LinearLayout>

@ -0,0 +1,16 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="org.wso2.carbon.iot.android.sense.UnregisterActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="De-enroll Device"
android:id="@+id/unregister"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>

@ -0,0 +1,86 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<TextView
android:text="@string/speakup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:ems="10"
android:id="@+id/command"
android:layout_below="@+id/textView"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editThreashold"
android:text="Threshold"
android:inputType="number"
android:layout_below="@+id/addWord"
android:layout_alignParentLeft="true"
android:layout_alignEnd="@+id/setThreshold"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Set Threshold"
android:id="@+id/setThreshold"
android:layout_alignBottom="@+id/editThreashold"
android:layout_alignParentEnd="true"
android:layout_toEndOf="@+id/removeWord"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/wordText"
android:text="word"
android:layout_below="@+id/command"
android:layout_alignParentStart="true"
android:layout_marginTop="123dp"
android:layout_alignParentEnd="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Word"
android:id="@+id/addWord"
android:layout_alignTop="@+id/removeWord"
android:layout_alignParentEnd="true"
android:layout_toEndOf="@+id/removeWord"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Remove Word"
android:id="@+id/removeWord"
android:layout_below="@+id/wordText"
android:layout_alignParentLeft="true"
android:layout_alignEnd="@+id/textView"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/sensorChange"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:src="@drawable/sensor"
android:layout_marginLeft="@dimen/fab_margin"
android:layout_marginRight="@dimen/fab_margin"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"/>
</RelativeLayout>

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="org.wso2.carbon.iot.android.sense.realtimeviewer.ActivitySelectSensor">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_activity_select_sensor"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/publish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:adjustViewBounds="false"
android:src="@drawable/pushtoserver"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/speech"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/mic"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/addSensors"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_input_add"/>
</android.support.design.widget.CoordinatorLayout>

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/app_bar_activity_select_sensor"
tools:context="org.wso2.carbon.iot.android.sense.realtimeviewer.ActivitySelectSensor"
android:id="@+id/parentContainer">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" android:hint="@string/sessionId"
android:id="@+id/sessionId"
android:inputType="text"
android:maxLines="1" android:singleLine="true"/>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/senseListContainer"
android:layout_below="@+id/sessionId">
</ListView>
</RelativeLayout>

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/name"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="23dp"
android:textColor="#c12323" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/X"
android:textColor="#000000"
android:textStyle="italic"
android:layout_marginTop="19dp"
android:layout_below="@+id/name"
android:layout_centerHorizontal="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/Y"
android:textColor="#000000"
android:textStyle="italic"
android:layout_marginTop="23dp"
android:layout_below="@+id/X"
android:layout_alignStart="@+id/X" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/Z"
android:textColor="#000000"
android:textStyle="italic"
android:layout_marginTop="21dp"
android:layout_below="@+id/Y"
android:layout_alignStart="@+id/Y" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView2"
android:layout_below="@+id/Z"
android:layout_marginTop="23dp"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true" />
</RelativeLayout>

@ -0,0 +1,10 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.wso2.carbon.iot.android.sense.util.SelectSensorDialog">
<!-- TODO: Update blank fragment layout -->
<TextView android:layout_width="match_parent" android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark" android:orientation="vertical"
android:gravity="bottom">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing" android:text="WSO2 Sense Agent"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="wso2.com" android:id="@+id/textView" />
</LinearLayout>

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/select" android:icon="@android:drawable/ic_menu_agenda"
android:title="Sensors" />
<item android:id="@+id/speech_recognizer" android:icon="@android:drawable/ic_menu_agenda"
android:title="Speech Recognizer" />
<!--<group android:checkableBehavior="single">-->
<!-- -->
<!--</group>-->
<!--<item android:title="Communicate">-->
<!--<menu>-->
<!--<item android:id="@+id/nav_share" android:icon="@android:drawable/ic_menu_share"-->
<!--android:title="Share" />-->
<!--<item android:id="@+id/nav_send" android:icon="@android:drawable/ic_menu_send"-->
<!--android:title="Send" />-->
<!--</menu>-->
<!--</item>-->
</menu>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_deEnroll" android:title="@string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
</menu>

@ -0,0 +1,7 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.wso2.carbon.iot.android.sense.UnregisterActivity">
<item android:id="@+id/action_deEnroll" android:title="@string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
</menu>

@ -0,0 +1,8 @@
<resources>>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>

@ -0,0 +1,6 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

@ -0,0 +1,4 @@
<resources>
<string name="username"></string>
<bool name="registered">false</bool>
</resources>

@ -0,0 +1,9 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="nav_header_vertical_spacing">16dp</dimen>
<dimen name="nav_header_height">160dp</dimen>
<dimen name="fab_margin">16dp</dimen>
</resources>

@ -0,0 +1,14 @@
<resources>
<string name="app_name">WSO2-SenseAgent</string>
<string name="title_activity_sense_settings">Sense Settings</string>
<string name="hostname">Server URL https://host:9443</string>
<string name="speakup">Speakup to capture the words</string>
<string name="action_settings">DeEnroll</string>
<string name="title_activity_activity_select_sensor">ActivitySelectSensor</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>

@ -0,0 +1,13 @@
<resources>
<!-- Strings related to login -->
<string name="prompt_username">Username</string>
<string name="prompt_password">Password</string>
<string name="action_sign_in">Register Device</string>
<string name="action_sign_in_short">Sign in</string>
<string name="sessionId">sessionId</string>
<string name="error_invalid_username">This email address is invalid</string>
<string name="error_invalid_password">This password is too short</string>
<string name="error_incorrect_password">This password is incorrect</string>
<string name="error_field_required">This field is required</string>
</resources>

@ -0,0 +1,14 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

@ -0,0 +1,21 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
maven { url 'https://repo.eclipse.org/content/repositories/paho-releases/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
maven { url 'https://repo.eclipse.org/content/repositories/paho-releases/' }
}
}

@ -0,0 +1,6 @@
#Fri Dec 11 10:25:01 IST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.iot.agents</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.androidsense.agent</artifactId>
<version>1.0.0</version>
<name>Android Sense</name>
<description>Android Sense</description>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<executions>
<execution>
<id>Gradle Build</id>
<phase>generate-sources</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>./gradlew</executable>
<arguments>
<argument>assembleRelease</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -46,24 +46,14 @@
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<scope>provided</scope>
</dependency>
<!--MQTT -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<scope>provided</scope>
</dependency>
<!--IOT -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
<version>4.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot</artifactId>
@ -100,12 +90,6 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
@ -174,9 +158,19 @@
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics</groupId>
<artifactId>org.wso2.carbon.analytics.api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.webapp.publisher</artifactId>
<artifactId>org.wso2.carbon.apimgt.application.extension</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

@ -38,167 +38,13 @@ import javax.ws.rs.core.Response;
@API(name = "android_sense", version = "1.0.0", context = "/android_sense", tags = {"android_sense"})
public interface AndroidSenseControllerService {
/**
* Service to push all the sensor data collected by the Android. Called by the Android device
*
* @param dataMsg The json string containing sensor readings
*/
@Path("device/sensors")
@POST
@Consumes(MediaType.APPLICATION_JSON)
Response addSensorData(DeviceData dataMsg);
/**
* End point which is called by Front-end js to get Light sensor readings from the server.
*
* @param deviceId The registered device id
* @return This method returns a SensorRecord object.
*/
@Path("device/{deviceId}/sensors/light")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "light", name = "Light", description = "Read Light data from the device", type = "monitor")
Response getLightData(@PathParam("deviceId") String deviceId);
/**
* End point which is called by Front-end js to get Battery data from the server.
*
* @param deviceId The registered device id
* @return This method returns a SensorRecord object.
*/
@Path("device/{deviceId}/sensors/battery")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "battery", name = "Battery", description = "Read Battery data from the device", type = "monitor")
Response getBattery(@PathParam("deviceId") String deviceId);
/**
* End point which is called by Front-end js to get GPS data from the server.
*
* @param deviceId The registered device id call to this API.
* @return This method returns a SensorRecord object.
*/
@Path("device/{deviceId}/sensors/gps")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "gps", name = "gps", description = "Read GPS data from the device", type = "monitor")
Response getGPS(@PathParam("deviceId") String deviceId);
/**
* End point which is called by Front-end js to get Magnetic data readings from the server.
*
* @param deviceId The registered device id
* call to this API.
* @return This method returns a SensorRecord object.
*/
@Path("device/{deviceId}/sensors/magnetic")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "magnetic", name = "Magnetic", description = "Read Magnetic data from the device", type = "monitor")
Response readMagnetic(@PathParam("deviceId") String deviceId);
/**
* End point which is called by Front-end js to get Accelerometer data from the server.
*
* @param deviceId The registered device id
* @return This method returns a SensorRecord object.
*/
@Path("device/{deviceId}/sensors/accelerometer")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "accelerometer", name = "Accelerometer", description = "Read Accelerometer data from the device",
type = "monitor")
Response readAccelerometer(@PathParam("deviceId") String deviceId);
/**
* End point which is called by Front-end js to get Rotation data from the server.
*
* @param deviceId The registered device id
* @return This method returns a SensorRecord object.
*/
@Path("device/{deviceId}/sensors/rotation")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "rotation", name = "Rotation", description = "Read Rotational Vector data from the device",
type = "monitor")
Response readRotation(@PathParam("deviceId") String deviceId);
/**
* End point which is called by Front-end js to get Proximity data from the server.
*
* @param deviceId The registered device id
* @return This method returns a SensorRecord object.
*/
@Path("device/{deviceId}/sensors/proximity")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "proximity", name = "Proximity", description = "Read Proximity data from the device",
type = "monitor")
Response readProximity(@PathParam("deviceId") String deviceId);
/**
* End point which is called by Front-end js to get Gyroscope data from the server.
*
* @param deviceId The registered device id
* @return This method returns a SensorRecord object.
*/
@Path("device/{deviceId}/sensors/gyroscope")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "gyroscope", name = "Gyroscope", description = "Read Gyroscope data from the device",
type = "monitor")
Response readGyroscope(@PathParam("deviceId") String deviceId);
/**
* End point which is called by Front-end js to get Pressure data from the server.
*
* @param deviceId The registered device id
* @return This method returns a SensorRecord object.
*/
@Path("device/{deviceId}/sensors/pressure")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "pressure", name = "Pressure", description = "Read Pressure data from the device", type = "monitor")
Response readPressure(@PathParam("deviceId") String deviceId);
/**
* End point which is called by Front-end js to get Gravity data from the server.
*
* @param deviceId The registered device id
* @return This method returns a SensorRecord object.
*/
@Path("device/{deviceId}/sensors/gravity")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "gravity", name = "Gravity",
description = "Read Gravity data from the device", type = "monitor")
Response readGravity(@PathParam("deviceId") String deviceId);
@Path("device/{deviceId}/sensors/words")
@GET
@Consumes("application/json")
@Produces("application/json")
@Feature(code = "words", name = "Words", description = "Get the key words and occurrences",
type = "monitor")
Response getWords(@PathParam("deviceId") String deviceId, @QueryParam("sessionId") String sessionId);
/**
* End point to send the key words to the device
*
* @param deviceId The registered device Id.
* @param keywords The key words to be sent. (Comma separated values)
*/
@Path("device/{deviceId}/sensors/words")
@Path("device/{deviceId}/words")
@POST
@Feature(code = "keywords", name = "Add Keywords", description = "Send keywords to the device",
type = "operation")
@ -210,13 +56,13 @@ public interface AndroidSenseControllerService {
* @param deviceId The registered device Id.
* @param threshold The key words to be sent. (Comma separated values)
*/
@Path("device/{deviceId}/sensors/words/threshold")
@Path("device/{deviceId}/words/threshold")
@POST
@Feature(code = "threshold", name = "Add a Threshold", description = "Set a threshold for word in the device",
type = "operation")
Response sendThreshold(@PathParam("deviceId") String deviceId, @FormParam("threshold") String threshold);
@Path("device/{deviceId}/sensors/words")
@Path("device/{deviceId}/words")
@DELETE
@Feature(code = "remove", name = "Remove Keywords", description = "Remove the keywords",
type = "operation")
@ -225,7 +71,8 @@ public interface AndroidSenseControllerService {
/**
* Retrieve Sensor data for the device type
*/
@Path("stats/device/{deviceId}/sensors/{sensorName}")
@Path("stats/{deviceId}/sensors/{sensorName}")
@GET
@Consumes("application/json")
@Produces("application/json")

@ -20,26 +20,36 @@ package org.wso2.carbon.device.mgt.iot.androidsense.service.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.analytics.dataservice.commons.SORT;
import org.wso2.carbon.analytics.dataservice.commons.SortByField;
import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.analytics.data.publisher.AnalyticsDataRecord;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DeviceManagementAnalyticsException;
import org.wso2.carbon.device.mgt.analytics.data.publisher.service.DeviceAnalyticsService;
import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.Feature;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.transport.AndroidSenseMQTTConnector;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.DeviceData;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.SensorData;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.SensorRecord;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
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 org.wso2.carbon.device.mgt.iot.service.IoTServerStartupListener;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
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.Response;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
@ -50,267 +60,9 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
private static Log log = LogFactory.getLog(AndroidSenseControllerServiceImpl.class);
private static AndroidSenseMQTTConnector androidSenseMQTTConnector;
/**
* Fetches the `AndroidSenseMQTTConnector` specific to this Android Sense controller service.
*
* @return the 'AndroidSenseMQTTConnector' instance bound to the 'AndroidSenseMQTTConnector' variable of
* this service.
*/
@SuppressWarnings("Unused")
public AndroidSenseMQTTConnector getAndroidSenseMQTTConnector() {
return androidSenseMQTTConnector;
}
/**
* Sets the `AndroidSenseMQTTConnector` variable of this Android Sense controller service.
*
* @param androidSenseMQTTConnector a 'AndroidSenseMQTTConnector' object that handles all MQTT related
* communications of any connected Android Sense device-type
*/
@SuppressWarnings("Unused")
public void setAndroidSenseMQTTConnector(final AndroidSenseMQTTConnector androidSenseMQTTConnector) {
Runnable connector = new Runnable() {
public void run() {
if (waitForServerStartup()) {
return;
}
AndroidSenseControllerServiceImpl.androidSenseMQTTConnector = androidSenseMQTTConnector;
if (MqttConfig.getInstance().isEnabled()) {
androidSenseMQTTConnector.connect();
} else {
log.warn("MQTT disabled in 'devicemgt-config.xml'. Hence, VirtualFireAlarmMQTTConnector not started.");
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.setDaemon(true);
connectorThread.start();
}
private boolean waitForServerStartup() {
while (!IoTServerStartupListener.isServerReady()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return true;
}
}
return false;
}
public Response addSensorData(DeviceData dataMsg) {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx
.getOSGiService(DeviceAnalyticsService.class, null);
SensorData[] sensorData = dataMsg.values;
String streamDef = null;
Object payloadData[] = null;
String sensorName = null;
for (SensorData sensor : sensorData) {
switch (sensor.key) {
case "battery":
streamDef = AndroidSenseConstants.BATTERY_STREAM_DEFINITION;
payloadData = new Float[]{Float.parseFloat(sensor.value)};
sensorName = AndroidSenseConstants.SENSOR_BATTERY;
break;
case "GPS":
streamDef = AndroidSenseConstants.GPS_STREAM_DEFINITION;
String gpsValue = sensor.value;
String gpsValuesString[] = gpsValue.split(",");
Float gpsValues[] = new Float[2];
gpsValues[0] = Float.parseFloat(gpsValuesString[0]);
gpsValues[1] = Float.parseFloat(gpsValuesString[0]);
payloadData = gpsValues;
sensorName = AndroidSenseConstants.SENSOR_GPS;
break;
default:
try {
int androidSensorId = Integer.parseInt(sensor.key);
String value = sensor.value;
String sensorValueString[] = value.split(",");
Float sensorValues[] = new Float[1];
switch (androidSensorId) {
case 1:
streamDef = AndroidSenseConstants.ACCELEROMETER_STREAM_DEFINITION;
sensorValues[0] = Float.parseFloat(sensorValueString[0]) *
Float.parseFloat(sensorValueString[0]) * Float.parseFloat(sensorValueString[0]);
payloadData = sensorValues;
sensorName = AndroidSenseConstants.SENSOR_ACCELEROMETER;
break;
case 2:
streamDef = AndroidSenseConstants.MAGNETIC_STREAM_DEFINITION;
sensorValues[0] = Float.parseFloat(sensorValueString[0]) *
Float.parseFloat(sensorValueString[0]) * Float.parseFloat(sensorValueString[0]);
payloadData = sensorValues;
sensorName = AndroidSenseConstants.SENSOR_MAGNETIC;
break;
case 4:
streamDef = AndroidSenseConstants.GYROSCOPE_STREAM_DEFINITION;
sensorValues[0] = Float.parseFloat(sensorValueString[0]) *
Float.parseFloat(sensorValueString[0]) * Float.parseFloat(sensorValueString[0]);
payloadData = sensorValues;
sensorName = AndroidSenseConstants.SENSOR_GYROSCOPE;
break;
case 5:
streamDef = AndroidSenseConstants.LIGHT_STREAM_DEFINITION;
sensorName = AndroidSenseConstants.SENSOR_LIGHT;
payloadData = new Float[]{Float.parseFloat(sensorValueString[0])};
break;
case 6:
streamDef = AndroidSenseConstants.PRESSURE_STREAM_DEFINITION;
sensorName = AndroidSenseConstants.SENSOR_PRESSURE;
payloadData = new Float[]{Float.parseFloat(sensorValueString[0])};
break;
case 8:
streamDef = AndroidSenseConstants.PROXIMITY_STREAM_DEFINITION;
sensorName = AndroidSenseConstants.SENSOR_PROXIMITY;
payloadData = new Float[]{Float.parseFloat(sensorValueString[0])};
break;
case 9:
streamDef = AndroidSenseConstants.GRAVITY_STREAM_DEFINITION;
sensorValues[0] = Float.parseFloat(sensorValueString[0]) *
Float.parseFloat(sensorValueString[0]) * Float.parseFloat(sensorValueString[0]);
payloadData = sensorValues;
sensorName = AndroidSenseConstants.SENSOR_GRAVITY;
break;
case 11:
streamDef = AndroidSenseConstants.ROTATION_STREAM_DEFINITION;
sensorValues[0] = Float.parseFloat(sensorValueString[0]) *
Float.parseFloat(sensorValueString[0]) * Float.parseFloat(sensorValueString[0]);
payloadData = sensorValues;
sensorName = AndroidSenseConstants.SENSOR_ROTATION;
break;
}
} catch (NumberFormatException e) {
log.error("Invalid sensor value is sent from the device");
continue;
}
}
Object metaData[] = {dataMsg.owner, AndroidSenseConstants.DEVICE_TYPE, dataMsg.deviceId, sensor.time};
if (streamDef != null && payloadData != null && payloadData.length > 0) {
try {
SensorDataManager.getInstance()
.setSensorRecord(dataMsg.deviceId, sensorName, sensor.value, sensor.time);
deviceAnalyticsService.publishEvent(streamDef, "1.0.0", metaData, new Object[0], payloadData);
} catch (DataPublisherConfigurationException e) {
return Response.status(Response.Status.UNSUPPORTED_MEDIA_TYPE.getStatusCode()).build();
}
}
}
return Response.ok().build();
}
public Response getLightData(String deviceId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
.SENSOR_LIGHT);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response getBattery(String deviceId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
.SENSOR_BATTERY);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response getGPS(String deviceId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
.SENSOR_GPS);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response readMagnetic(String deviceId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, AndroidSenseConstants
.SENSOR_MAGNETIC);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response readAccelerometer(String deviceId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_ACCELEROMETER);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response readRotation(String deviceId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_ROTATION);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response readProximity(String deviceId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_PROXIMITY);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response readGyroscope(String deviceId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_GYROSCOPE);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response readPressure(String deviceId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_PRESSURE);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response readGravity(String deviceId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_GRAVITY);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response getWords(String deviceId, String sessionId) {
try {
SensorRecord sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId,
AndroidSenseConstants.SENSOR_WORDCOUNT);
return Response.ok().entity(sensorRecord).build();
} catch (DeviceControllerException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
}
}
public Response sendKeyWords(String deviceId, String keywords) {
@Path("device/{deviceId}/words")
@POST
public Response sendKeyWords(@PathParam("deviceId") String deviceId, @FormParam("keywords") String keywords) {
try {
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
androidSenseMQTTConnector.publishDeviceData(username, deviceId, "add", keywords);
@ -320,7 +72,9 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
}
}
public Response sendThreshold(String deviceId, String threshold) {
@Path("device/{deviceId}/words/threshold")
@POST
public Response sendThreshold(@PathParam("deviceId") String deviceId, @FormParam("threshold") String threshold) {
try {
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
androidSenseMQTTConnector.publishDeviceData(username, deviceId, "threshold", threshold);
@ -330,7 +84,9 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
}
}
public Response removeKeyWords(String deviceId, String words) {
@Path("device/{deviceId}/words")
@DELETE
public Response removeKeyWords(@PathParam("deviceId") String deviceId, @QueryParam("words") String words) {
try {
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
androidSenseMQTTConnector.publishDeviceData(username, deviceId, "remove", words);
@ -340,59 +96,36 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
}
}
public Response getAndroidSenseDeviceStats(String deviceId, String sensor, long from, long to) {
@Path("stats/{deviceId}/sensors/{sensorName}")
@GET
@Consumes("application/json")
@Produces("application/json")
public Response getAndroidSenseDeviceStats(@PathParam("deviceId") String deviceId, @PathParam("sensorName") String sensor,
@QueryParam("from") long from, @QueryParam("to") long to) {
String fromDate = String.valueOf(from);
String toDate = String.valueOf(to);
String user = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
List<SensorData> sensorDatas = new ArrayList<>();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx
.getOSGiService(DeviceAnalyticsService.class, null);
String query = "owner:" + user + " AND deviceId:" + deviceId + " AND deviceType:" +
AndroidSenseConstants.DEVICE_TYPE + " AND time : [" + fromDate + " TO " + toDate + "]";
if (sensor.equals(AndroidSenseConstants.SENSOR_WORDCOUNT)) {
query = "owner:" + user + " AND deviceId:" + deviceId;
}
String sensorTableName = getSensorEventTableName(sensor);
List<SensorRecord> sensorDatas;
try {
List<AnalyticsDataRecord> records = deviceAnalyticsService.getAllEventsForDevice(sensorTableName, query);
if (sensor.equals(AndroidSenseConstants.SENSOR_WORDCOUNT)) {
for (AnalyticsDataRecord record : records) {
SensorData sensorData = new SensorData();
sensorData.setKey((String) record.getValue("word"));
sensorData.setTime((long) record.getValue("occurence"));
sensorData.setValue((String) record.getValue("sessionId"));
sensorDatas.add(sensorData);
}
List<SortByField> sortByFields = new ArrayList<>();
SortByField sortByField = new SortByField("time", SORT.ASC, false);
sortByFields.add(sortByField);
sensorDatas = APIUtil.getAllEventsForDevice(sensorTableName, query, sortByFields);
} else {
Collections.sort(records, new Comparator<AnalyticsDataRecord>() {
@Override
public int compare(AnalyticsDataRecord o1, AnalyticsDataRecord o2) {
long t1 = (Long) o1.getValue("time");
long t2 = (Long) o2.getValue("time");
if (t1 < t2) {
return -1;
} else if (t1 > t2) {
return 1;
} else {
return 0;
}
}
});
for (AnalyticsDataRecord record : records) {
SensorData sensorData = new SensorData();
sensorData.setTime((long) record.getValue("time"));
sensorData.setValue("" + (float) record.getValue(sensor));
sensorDatas.add(sensorData);
}
sensorDatas = APIUtil.getAllEventsForDevice(sensorTableName, query, null);
}
SensorData[] sensorDetails = sensorDatas.toArray(new SensorData[sensorDatas.size()]);
return Response.ok().entity(sensorDetails).build();
} catch (DeviceManagementAnalyticsException e) {
return Response.ok().entity(sensorDatas).build();
} catch (AnalyticsException e) {
String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query;
log.error(errorMsg);
SensorData[] senserDetails = sensorDatas.toArray(new SensorData[sensorDatas.size()]);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(senserDetails).build();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(errorMsg).build();
}
}
@ -440,4 +173,60 @@ public class AndroidSenseControllerServiceImpl implements AndroidSenseController
}
return sensorEventTableName;
}
/**
* Fetches the `AndroidSenseMQTTConnector` specific to this Android Sense controller service.
*
* @return the 'AndroidSenseMQTTConnector' instance bound to the 'AndroidSenseMQTTConnector' variable of
* this service.
*/
@SuppressWarnings("Unused")
public AndroidSenseMQTTConnector getAndroidSenseMQTTConnector() {
return androidSenseMQTTConnector;
}
/**
* Sets the `AndroidSenseMQTTConnector` variable of this Android Sense controller service.
*
* @param androidSenseMQTTConnector a 'AndroidSenseMQTTConnector' object that handles all MQTT related
* communications of any connected Android Sense device-type
*/
@SuppressWarnings("Unused")
public void setAndroidSenseMQTTConnector(final AndroidSenseMQTTConnector androidSenseMQTTConnector) {
Runnable connector = new Runnable() {
public void run() {
if (waitForServerStartup()) {
return;
}
//The delay is added till the server starts up.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
AndroidSenseControllerServiceImpl.androidSenseMQTTConnector = androidSenseMQTTConnector;
if (MqttConfig.getInstance().isEnabled()) {
synchronized (androidSenseMQTTConnector) {
androidSenseMQTTConnector.connect();
}
} else {
log.warn("MQTT disabled in 'devicemgt-config.xml'. Hence, VirtualFireAlarmMQTTConnector not started.");
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.setDaemon(true);
connectorThread.start();
}
private boolean waitForServerStartup() {
while (!IoTServerStartupListener.isServerReady()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return true;
}
}
return false;
}
}

@ -30,33 +30,33 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
@Path("enrollment")
@DeviceType(value = "android_sense")
@API(name = "android_sense_mgt", version = "1.0.0", context = "/android_sense_mgt", tags = {"android_sense"})
public interface AndroidSenseManagerService {
@Path("device/{device_id}")
@Path("/devices/{device_id}")
@POST
Response register(@PathParam("device_id") String deviceId, @QueryParam("deviceName") String deviceName);
@Path("devices/{device_id}")
@Path("/devices/{device_id}")
@DELETE
Response removeDevice(@PathParam("device_id") String deviceId);
@Path("devices/{device_id}")
@Path("/devices/{device_id}")
@PUT
Response updateDevice(@PathParam("device_id") String deviceId, @QueryParam("name") String name);
@Path("devices/{device_id}")
@Path("/devices/{device_id}")
@GET
@Consumes("application/json")
@Produces("application/json")
Response getDevice(@PathParam("device_id") String deviceId);
@Path("devices/{sketch_type}/download")
@Path("/devices/download")
@GET
@Produces("application/octet-stream")
Response downloadSketch(@PathParam("sketch_type") String sketchType);
Response downloadSketch();
}

@ -27,15 +27,28 @@ import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
import org.wso2.carbon.utils.CarbonUtils;
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.Response;
import java.io.File;
import java.util.Date;
@Path("enrollment")
public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerService {
private static Log log = LogFactory.getLog(AndroidSenseManagerServiceImpl.class);
public Response register(String deviceId, String deviceName) {
@Path("/devices/{device_id}")
@POST
public Response register(@PathParam("device_id") String deviceId, @QueryParam("deviceName") String deviceName) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(AndroidSenseConstants.DEVICE_TYPE);
@ -53,19 +66,23 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
device.setName(deviceName);
device.setType(AndroidSenseConstants.DEVICE_TYPE);
enrolmentInfo.setOwner(APIUtil.getAuthenticatedUser());
enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.BYOD);
device.setEnrolmentInfo(enrolmentInfo);
boolean added = APIUtil.getDeviceManagementService().enrollDevice(device);
if (added) {
return Response.ok().build();
APIUtil.registerApiAccessRoles(APIUtil.getAuthenticatedUser());
return Response.ok(true).build();
} else {
return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).build();
return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).entity(false).build();
}
} catch (DeviceManagementException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(false).build();
}
}
public Response removeDevice(String deviceId) {
@Path("/devices/{device_id}")
@DELETE
public Response removeDevice(@PathParam("device_id") String deviceId) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(AndroidSenseConstants.DEVICE_TYPE);
@ -81,7 +98,9 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
}
}
public Response updateDevice(String deviceId, String name) {
@Path("/devices/{device_id}")
@PUT
public Response updateDevice(@PathParam("device_id") String deviceId, @QueryParam("name") String name) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(AndroidSenseConstants.DEVICE_TYPE);
@ -102,7 +121,11 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
}
}
public Response getDevice(String deviceId) {
@Path("/devices/{device_id}")
@GET
@Consumes("application/json")
@Produces("application/json")
public Response getDevice(@PathParam("device_id") String deviceId) {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(AndroidSenseConstants.DEVICE_TYPE);
@ -114,7 +137,10 @@ public class AndroidSenseManagerServiceImpl implements AndroidSenseManagerServic
}
}
public Response downloadSketch(String sketchType) {
@Path("/devices/download")
@GET
@Produces("application/octet-stream")
public Response downloadSketch() {
try {
String sep = File.separator;
String sketchFolder = "repository" + sep + "resources" + sep + "sketches" + sep + "android_sense" + sep;

@ -18,27 +18,23 @@
package org.wso2.carbon.device.mgt.iot.androidsense.service.impl.transport;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
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.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey;
import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
import org.wso2.carbon.device.mgt.analytics.data.publisher.service.DeviceAnalyticsService;
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.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.DeviceData;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.SensorData;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
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 org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.user.api.UserStoreException;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
@ -48,6 +44,8 @@ public class AndroidSenseMQTTConnector extends MQTTTransportHandler {
private static Log log = LogFactory.getLog(AndroidSenseMQTTConnector.class);
private static String subscribeTopic = AndroidSenseConstants.MQTT_SUBSCRIBE_WORDS_TOPIC;
private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5);
private static final String KEY_TYPE = "PRODUCTION";
private static final String EMPTY_STRING = "";
private AndroidSenseMQTTConnector() {
super(iotServerSubscriber, AndroidSenseConstants.DEVICE_TYPE,
@ -59,7 +57,25 @@ public class AndroidSenseMQTTConnector extends MQTTTransportHandler {
Runnable connector = new Runnable() {
public void run() {
while (!isConnected()) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
AndroidSenseConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
try {
String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(applicationUsername);
APIManagementProviderService apiManagementProviderService = APIUtil
.getAPIManagementProviderService();
String[] tags = {AndroidSenseConstants.DEVICE_TYPE};
ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
AndroidSenseConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true);
JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
String scopes = "device_type_" + AndroidSenseConstants.DEVICE_TYPE + " device_mqtt_connector";
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
apiApplicationKey.getConsumerSecret(), applicationUsername, scopes);
//create token
String accessToken = accessTokenInfo.getAccessToken();
setUsernameAndPassword(accessToken, EMPTY_STRING);
connectToQueue();
subscribeToQueue();
} catch (TransportHandlerException e) {
@ -69,6 +85,17 @@ public class AndroidSenseMQTTConnector extends MQTTTransportHandler {
} catch (InterruptedException ex) {
log.error("MQTT-Subscriber: Thread Sleep Interrupt Exception.", ex);
}
}catch (JWTClientException e) {
log.error("Failed to retrieve token from JWT Client.", e);
return;
} catch (UserStoreException e) {
log.error("Failed to retrieve the user.", e);
return;
} catch (APIManagerException e) {
log.error("Failed to create an application and generate keys.", e);
return;
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}
@ -125,189 +152,7 @@ public class AndroidSenseMQTTConnector extends MQTTTransportHandler {
@Override
public void processIncomingMessage(MqttMessage mqttMessage, String... strings) throws TransportHandlerException {
String[] topic = strings[0].split("/");
String deviceId = topic[3];
if (log.isDebugEnabled()) {
log.debug("Received MQTT message for: & [DEVICE.ID-" + deviceId + "]");
}
try {
Gson gson = new Gson();
String actualMessage = mqttMessage.toString();
DeviceData deviceData = gson.fromJson(actualMessage, DeviceData.class);
SensorData[] sensorData = deviceData.values;
String streamDef = null;
Object payloadData[] = null;
String sensorName = null;
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceManagementProviderService deviceManagementProviderService =
(DeviceManagementProviderService) ctx.getOSGiService(DeviceManagementProviderService.class, null);
if (deviceManagementProviderService != null) {
DeviceIdentifier identifier = new DeviceIdentifier(deviceId, AndroidSenseConstants.DEVICE_TYPE);
Device device = deviceManagementProviderService.getDevice(identifier);
if (device != null) {
String owner = device.getEnrolmentInfo().getOwner();
ctx.setUsername(owner);
ctx.setTenantDomain(MultitenantUtils.getTenantDomain(owner), true);
} else {
return;
}
} else {
return;
}
ctx.setTenantDomain("carbon.super", true);
for (SensorData sensor : sensorData) {
if (sensor.key.equals("battery")) {
streamDef = AndroidSenseConstants.BATTERY_STREAM_DEFINITION;
payloadData = new Float[]{Float.parseFloat(sensor.value)};
sensorName = AndroidSenseConstants.SENSOR_BATTERY;
} else if (sensor.key.equals("GPS")) {
streamDef = AndroidSenseConstants.GPS_STREAM_DEFINITION;
String gpsValue = sensor.value;
String gpsValuesString[] = gpsValue.split(",");
Float gpsValues[] = new Float[2];
gpsValues[0] = Float.parseFloat(gpsValuesString[0]);
gpsValues[1] = Float.parseFloat(gpsValuesString[0]);
payloadData = gpsValues;
sensorName = AndroidSenseConstants.SENSOR_GPS;
} else if (sensor.key.equals("word")) {
try {
streamDef = AndroidSenseConstants.WORD_COUNT_STREAM_DEFINITION;
String[] values = sensor.value.split(",");
String sessionId = values[0];
String keyword = values[1];
int occurrence = Integer.parseInt(values[2]);
String status = values[3];
sensorName = AndroidSenseConstants.SENSOR_WORDCOUNT;
if (occurrence > 0) {
payloadData = new Object[]{sessionId, keyword, status};
for (int i = 0; i < occurrence; i++) {
Long timestamp = Long.parseLong(values[3 + occurrence]);
publishDataToDAS(deviceId, timestamp, sensorName, streamDef,
sensor.value, payloadData);
}
continue;
}
} catch (ArrayIndexOutOfBoundsException e) {
log.error(
"Timestamp does not match the occurence sensor values are sent from the device.");
}
continue;
} else {
try {
int androidSensorId = Integer.parseInt(sensor.key);
String sensorValue = sensor.value;
String sensorValuesString[] = sensorValue.split(",");
Float sensorValues[] = new Float[1];
switch (androidSensorId) {
case 1:
streamDef = AndroidSenseConstants.ACCELEROMETER_STREAM_DEFINITION;
sensorValues[0] = Float.parseFloat(sensorValuesString[0]) * Float.parseFloat(
sensorValuesString[0]) * Float.
parseFloat(sensorValuesString[0]);
payloadData = sensorValues;
sensorName = AndroidSenseConstants.SENSOR_ACCELEROMETER;
break;
case 2:
streamDef = AndroidSenseConstants.MAGNETIC_STREAM_DEFINITION;
sensorValues[0] = Float.parseFloat(sensorValuesString[0]) * Float.parseFloat(
sensorValuesString[0]) * Float.
parseFloat(sensorValuesString[0]);
payloadData = sensorValues;
sensorName = AndroidSenseConstants.SENSOR_MAGNETIC;
break;
case 4:
streamDef = AndroidSenseConstants.GYROSCOPE_STREAM_DEFINITION;
sensorValues[0] = Float.parseFloat(sensorValuesString[0]) * Float.parseFloat(
sensorValuesString[0]) * Float.
parseFloat(sensorValuesString[0]);
payloadData = sensorValues;
sensorName = AndroidSenseConstants.SENSOR_GYROSCOPE;
break;
case 5:
streamDef = AndroidSenseConstants.LIGHT_STREAM_DEFINITION;
sensorName = AndroidSenseConstants.SENSOR_LIGHT;
payloadData = new Float[]{Float.parseFloat(sensorValuesString[0])};
break;
case 6:
streamDef = AndroidSenseConstants.PRESSURE_STREAM_DEFINITION;
sensorName = AndroidSenseConstants.SENSOR_PRESSURE;
payloadData = new Float[]{Float.parseFloat(sensorValuesString[0])};
break;
case 8:
streamDef = AndroidSenseConstants.PROXIMITY_STREAM_DEFINITION;
sensorName = AndroidSenseConstants.SENSOR_PROXIMITY;
payloadData = new Float[]{Float.parseFloat(sensorValuesString[0])};
break;
case 9:
streamDef = AndroidSenseConstants.GRAVITY_STREAM_DEFINITION;
sensorValues[0] = Float.parseFloat(sensorValuesString[0]) * Float.parseFloat(
sensorValuesString[0]) * Float.
parseFloat(sensorValuesString[0]);
payloadData = sensorValues;
sensorName = AndroidSenseConstants.SENSOR_GRAVITY;
break;
case 11:
streamDef = AndroidSenseConstants.ROTATION_STREAM_DEFINITION;
sensorValues[0] = Float.parseFloat(sensorValuesString[0]) * Float.parseFloat(
sensorValuesString[0]) * Float.
parseFloat(sensorValuesString[0]);
payloadData = sensorValues;
sensorName = AndroidSenseConstants.SENSOR_ROTATION;
break;
}
} catch (NumberFormatException e) {
log.error("Invalid sensor values are sent from the device.");
continue;
}
}
publishDataToDAS(deviceId, sensor.time, sensorName, streamDef, sensor.value, payloadData);
}
} catch (JsonSyntaxException e) {
throw new TransportHandlerException("Invalid message format " + mqttMessage.toString());
} catch (DeviceManagementException e) {
throw new TransportHandlerException("Invalid device id " + deviceId);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
private void publishDataToDAS(String deviceId, Long time, String sensorName,
String streamDefinition, String sensorValue, Object payloadData[]) {
try {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceManagementProviderService deviceManagementProviderService = (DeviceManagementProviderService) ctx
.getOSGiService(DeviceManagementProviderService.class, null);
if (deviceManagementProviderService != null) {
DeviceIdentifier identifier = new DeviceIdentifier(deviceId, AndroidSenseConstants.DEVICE_TYPE);
Device device = deviceManagementProviderService.getDevice(identifier);
if (device != null) {
String owner = device.getEnrolmentInfo().getOwner();
ctx.setTenantDomain(MultitenantUtils.getTenantDomain(owner), true);
DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx
.getOSGiService(DeviceAnalyticsService.class, null);
if (deviceAnalyticsService != null) {
Object metaData[] = {owner, AndroidSenseConstants.DEVICE_TYPE, deviceId, time};
if (streamDefinition != null && payloadData != null && payloadData.length > 0) {
try {
SensorDataManager.getInstance().setSensorRecord(deviceId, sensorName, sensorValue, time);
deviceAnalyticsService.publishEvent(streamDefinition, "1.0.0", metaData,
new Object[0], payloadData);
} catch (DataPublisherConfigurationException e) {
log.error("Data publisher configuration failed - " + e);
}
}
}
}
}
} catch (DeviceManagementException e) {
log.error("Failed to load device management service.", e);
}
}
/**

@ -2,8 +2,27 @@ package org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.analytics.api.AnalyticsDataAPI;
import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDataResponse;
import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDrillDownRequest;
import org.wso2.carbon.analytics.dataservice.commons.SearchResultEntry;
import org.wso2.carbon.analytics.dataservice.commons.SortByField;
import org.wso2.carbon.analytics.dataservice.core.AnalyticsDataServiceUtils;
import org.wso2.carbon.analytics.datasource.commons.Record;
import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.user.core.service.RealmService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This class provides utility functions used by REST-API.
@ -11,6 +30,7 @@ import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
public class APIUtil {
private static Log log = LogFactory.getLog(APIUtil.class);
private static Object lock = new Object();
public static String getAuthenticatedUser() {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
@ -33,4 +53,142 @@ public class APIUtil {
}
return deviceManagementProviderService;
}
public static AnalyticsDataAPI getAnalyticsDataAPI() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
AnalyticsDataAPI analyticsDataAPI =
(AnalyticsDataAPI) ctx.getOSGiService(AnalyticsDataAPI.class, null);
if (analyticsDataAPI == null) {
String msg = "Analytics api service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return analyticsDataAPI;
}
public static List<SensorRecord> getAllEventsForDevice(String tableName, String query, List<SortByField> sortByFields) throws AnalyticsException {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI();
int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query);
if (eventCount == 0) {
return null;
}
AnalyticsDrillDownRequest drillDownRequest = new AnalyticsDrillDownRequest();
drillDownRequest.setQuery(query);
drillDownRequest.setTableName(tableName);
drillDownRequest.setRecordCount(eventCount);
if (sortByFields != null) {
drillDownRequest.setSortByFields(sortByFields);
}
List<SearchResultEntry> resultEntries = analyticsDataAPI.drillDownSearch(tenantId, drillDownRequest);
List<String> recordIds = getRecordIds(resultEntries);
AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, null, recordIds);
Map<String, SensorRecord> sensorDatas = createSensorData(AnalyticsDataServiceUtils.listRecords(
analyticsDataAPI, response));
List<SensorRecord> sortedSensorData = getSortedSensorData(sensorDatas, resultEntries);
return sortedSensorData;
}
private static List<String> getRecordIds(List<SearchResultEntry> searchResults) {
List<String> ids = new ArrayList<>();
for (SearchResultEntry searchResult : searchResults) {
ids.add(searchResult.getId());
}
return ids;
}
public static List<SensorRecord> getSortedSensorData(Map<String, SensorRecord> sensorDatas,
List<SearchResultEntry> searchResults) {
List<SensorRecord> sortedRecords = new ArrayList<>();
for (SearchResultEntry searchResultEntry : searchResults) {
sortedRecords.add(sensorDatas.get(searchResultEntry.getId()));
}
return sortedRecords;
}
/**
* Creates the SensorDatas from records.
*
* @param records the records
* @return the Map of SensorRecord <id, SensorRecord>
*/
public static Map<String, SensorRecord> createSensorData(List<Record> records) {
Map<String, SensorRecord> sensorDatas = new HashMap<>();
for (Record record : records) {
SensorRecord sensorData = createSensorData(record);
sensorDatas.put(sensorData.getId(), sensorData);
}
return sensorDatas;
}
/**
* Create a SensorRecord object out of a Record object
*
* @param record the record object
* @return SensorRecord object
*/
public static SensorRecord createSensorData(Record record) {
SensorRecord recordBean = new SensorRecord();
recordBean.setId(record.getId());
recordBean.setValues(record.getValues());
return recordBean;
}
public static APIManagementProviderService getAPIManagementProviderService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
APIManagementProviderService apiManagementProviderService =
(APIManagementProviderService) ctx.getOSGiService(APIManagementProviderService.class, null);
if (apiManagementProviderService == null) {
String msg = "API management provider service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return apiManagementProviderService;
}
public static JWTClientManagerService getJWTClientManagerService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
JWTClientManagerService jwtClientManagerService =
(JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
if (jwtClientManagerService == null) {
String msg = "JWT Client manager service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return jwtClientManagerService;
}
public static void registerApiAccessRoles(String user) {
UserStoreManager userStoreManager = null;
try {
userStoreManager = getUserStoreManager();
if (userStoreManager != null) {
synchronized (lock) {
String[] userList = new String[]{user};
if (!userStoreManager.isExistingRole(Constants.DEFAULT_ROLE_NAME)) {
userStoreManager.addRole(Constants.DEFAULT_ROLE_NAME, userList, Constants.DEFAULT_PERMISSION);
}
}
}
} catch (UserStoreException e) {
log.error("error on wso2 user component");
}
}
private static UserStoreManager getUserStoreManager() throws UserStoreException {
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
return getRealmService().getTenantUserRealm(tenantId).getUserStoreManager();
}
public static RealmService getRealmService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
RealmService realmService =
(RealmService) ctx.getOSGiService(RealmService.class, null);
if (realmService == null) {
String msg = "JWT Client manager service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return realmService;
}
}

@ -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.wso2.carbon.device.mgt.iot.androidsense.service.impl.util;
import org.wso2.carbon.user.core.Permission;
import org.wso2.carbon.user.core.authorization.TreeNode;
/**
* This hold the constants related to android sense.
*/
public class Constants {
private static final String DEFAULT_PERMISSION_RESOURCE = "/_system/governance/permission/admin/device-mgt/android_sense/user";
public static final String DEFAULT_ROLE_NAME = "android_sense_user";
public static final Permission DEFAULT_PERMISSION[] = new Permission[]{new Permission(Constants.DEFAULT_PERMISSION_RESOURCE,
TreeNode.Permission.UI_EXECUTE.toString())};
}

@ -1,3 +1,21 @@
/*
* 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.wso2.carbon.device.mgt.iot.androidsense.service.impl.util;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;

@ -1,3 +1,21 @@
/*
* 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.wso2.carbon.device.mgt.iot.androidsense.service.impl.util;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
@ -12,33 +30,32 @@ import javax.xml.bind.annotation.XmlRootElement;
@JsonIgnoreProperties(ignoreUnknown = true)
public class SensorData {
@XmlElement public Long time;
@XmlElement public String key;
public String getValue() {
return value;
}
@XmlElement public Long time;
@XmlElement public String key;
@XmlElement public String value;
public void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public String getKey() {
return key;
}
public void setValue(String value) {
this.value = value;
}
public void setKey(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public Long getTime() {
return time;
}
public void setKey(String key) {
this.key = key;
}
public void setTime(Long time) {
this.time = time;
}
public Long getTime() {
return time;
}
@XmlElement public String value;
public void setTime(Long time) {
this.time = time;
}
}

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

Loading…
Cancel
Save