diff --git a/.gitignore b/.gitignore index cd8838ac6d..ac1222119b 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/build.gradle b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/build.gradle new file mode 100644 index 0000000000..1fd0aa8186 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/build.gradle @@ -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' + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/AndroidManifest.xml b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..5a799fbdad --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/AndroidManifest.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/RegisterActivity.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/RegisterActivity.java new file mode 100644 index 0000000000..fceeeeedec --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/RegisterActivity.java @@ -0,0 +1,183 @@ +/* + * 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.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.EditText; + +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 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; + + @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. + String username = mUsernameView.getText().toString(); + String password = mPasswordView.getText().toString(); + 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 { + SenseClient client = new SenseClient(getApplicationContext()); + LocalRegistry.addServerURL(getBaseContext(), hostname); + String deviceId = SenseUtils.generateDeviceId(getBaseContext(), getContentResolver()); + boolean registerStatus = client.register(username, password, deviceId); + if (registerStatus) { + LocalRegistry.addUsername(getApplicationContext(), username); + LocalRegistry.addDeviceId(getApplicationContext(), deviceId); + LocalRegistry.addMqttPort(getApplicationContext(), Integer.parseInt(mqttPort)); + MQTTTransportHandler mqttTransportHandler = AndroidSenseMQTTHandler.getInstance(this); + if (!mqttTransportHandler.isConnected()) { + mqttTransportHandler.connect(); + } + SenseScheduleReceiver senseScheduleReceiver = new SenseScheduleReceiver(); + senseScheduleReceiver.clearAbortBroadcast(); + senseScheduleReceiver.onReceive(this, null); + + DataPublisherReceiver dataUploaderReceiver = new DataPublisherReceiver(); + dataUploaderReceiver.clearAbortBroadcast(); + dataUploaderReceiver.onReceive(this, null); + + Intent intent = new Intent(getApplicationContext(), ActivitySelectSensor.class); + startActivity(intent); + } + showProgress(false); + } + } + + @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); + } + } + +} + diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/constants/SenseConstants.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/constants/SenseConstants.java new file mode 100644 index 0000000000..70d847802a --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/constants/SenseConstants.java @@ -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.constants; + +public class SenseConstants { + public final static String DEVICE_TYPE = "android_sense"; + public final static String REGISTER_CONTEXT = "/android_sense_mgt"; + 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; + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/DataPublisherReceiver.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/DataPublisherReceiver.java new file mode 100644 index 0000000000..b09d15a889 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/DataPublisherReceiver.java @@ -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); + } + +} \ No newline at end of file diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/DataPublisherService.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/DataPublisherService.java new file mode 100644 index 0000000000..41853f8cda --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/DataPublisherService.java @@ -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 = "Data Publisher"; + 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 events = new ArrayList<>(); + //retreive sensor data. + List 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 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 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 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; + } +} \ No newline at end of file diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/Event.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/Event.java new file mode 100644 index 0000000000..e7ceea0631 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/Event.java @@ -0,0 +1,219 @@ +package org.wso2.carbon.iot.android.sense.data.publisher; + +import org.json.JSONException; +import org.json.JSONObject; + +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; + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/AndroidSenseMQTTHandler.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/AndroidSenseMQTTHandler.java new file mode 100644 index 0000000000..5ae9b37391 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/AndroidSenseMQTTHandler.java @@ -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. + *

+ * 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. + // = [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 { + + } + +} + diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/transport/MQTTTransportHandler.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/transport/MQTTTransportHandler.java new file mode 100644 index 0000000000..689138d729 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/transport/MQTTTransportHandler.java @@ -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). + *

+ * 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 { + 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; + } +} \ No newline at end of file diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/transport/TransportHandler.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/transport/TransportHandler.java new file mode 100644 index 0000000000..88efba9a48 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/transport/TransportHandler.java @@ -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 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 { + // 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). + *

+ * + * @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. + *

+ * + * @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(); +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/transport/TransportHandlerException.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/transport/TransportHandlerException.java new file mode 100644 index 0000000000..c52ca2ed0a --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/data/publisher/mqtt/transport/TransportHandlerException.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.iot.android.sense.data.publisher.mqtt.transport; + +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); + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/SenseScheduleReceiver.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/SenseScheduleReceiver.java new file mode 100644 index 0000000000..41ff9feffa --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/SenseScheduleReceiver.java @@ -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); + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/SenseService.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/SenseService.java new file mode 100644 index 0000000000..69285234f7 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/SenseService.java @@ -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(); + } +} \ No newline at end of file diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/DataReader.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/DataReader.java new file mode 100644 index 0000000000..1d8e422044 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/DataReader.java @@ -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 { +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Location/LocationData.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Location/LocationData.java new file mode 100644 index 0000000000..3f5de2888f --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Location/LocationData.java @@ -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; + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Location/LocationDataReader.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Location/LocationDataReader.java new file mode 100644 index 0000000000..b8d3a4e586 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Location/LocationDataReader.java @@ -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 = "Location Data"; + + 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"); + } + } + + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/SenseDataCollector.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/SenseDataCollector.java new file mode 100644 index 0000000000..2febb8ba20 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/SenseDataCollector.java @@ -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(); + } + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Sensor/SensorData.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Sensor/SensorData.java new file mode 100644 index 0000000000..abdfeb1555 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Sensor/SensorData.java @@ -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; + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Sensor/SensorDataReader.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Sensor/SensorDataReader.java new file mode 100644 index 0000000000..4f4697e50c --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/Sensor/SensorDataReader.java @@ -0,0 +1,115 @@ +/* + * 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 senseDataStruct = new HashMap<>(); + private Vector sensorVector = new Vector<>(); + Context ctx; + private List sensorList = new ArrayList<>(); + private SupportedSensors supportedSensors = SupportedSensors.getInstance(); + + public SensorDataReader(Context context) { + ctx = context; + SharedPreferences sharedPreferences = ctx.getSharedPreferences(SupportedSensors.SELECTED_SENSORS, Context + .MODE_MULTI_PROCESS); + Set 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(this.getClass().getName(), "Sensor Name " + sensor.getName() + ", Type " + sensor.getType() + " " + + ", sensorValue :" + sensorInfo.getSensorValues()); + } + } catch (Throwable e) { + Log.d(this.getClass().getName(), "error on sensors"); + } + + } + mSensorManager.unregisterListener(this); + } + + public Vector getSensorData() { + try { + TimeUnit.MILLISECONDS.sleep(1000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + Log.e(SensorDataReader.class.getName(), 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(this.getClass().getName(), "running -sensorDataMap"); + Vector sensorDatas = getSensorData(); + for (SensorData data : sensorDatas) { + SenseDataHolder.getSensorDataHolder().add(data); + } + } + + public void selectedSensorList(Set set) { + if (set != null) { + String[] sensorsSet = set.toArray(new String[set.size()]); + for (String s : sensorsSet) { + sensorList.add(mSensorManager.getDefaultSensor(supportedSensors.getType(s.toLowerCase()))); + } + } + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/battery/BatteryData.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/battery/BatteryData.java new file mode 100644 index 0000000000..666e02a85f --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/battery/BatteryData.java @@ -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; + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/battery/BatteryDataReceiver.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/battery/BatteryDataReceiver.java new file mode 100644 index 0000000000..9fffa1c157 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/event/streams/battery/BatteryDataReceiver.java @@ -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)); + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/ActivitySelectSensor.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/ActivitySelectSensor.java new file mode 100644 index 0000000000..053b7e38ce --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/ActivitySelectSensor.java @@ -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 selectedSensorSet = new HashSet<>(); + private ListView listView; + private SensorManager sensorManager; + private ArrayList 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); + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/datastore/TempStore.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/datastore/TempStore.java new file mode 100644 index 0000000000..2e53438347 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/datastore/TempStore.java @@ -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 sensorDataMap = new ConcurrentHashMap<>(); + + /** + * Array List which is used to populate the List view. + */ + public static ArrayList sensorArrayList = new ArrayList<>(); + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/event/RealTimeSensorChangeReceiver.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/event/RealTimeSensorChangeReceiver.java new file mode 100644 index 0000000000..c231ac87ee --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/event/RealTimeSensorChangeReceiver.java @@ -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()); + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/event/realtimesensor/RealTimeSensor.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/event/realtimesensor/RealTimeSensor.java new file mode 100644 index 0000000000..6a71739dc7 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/event/realtimesensor/RealTimeSensor.java @@ -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; + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/event/realtimesensor/RealTimeSensorReader.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/event/realtimesensor/RealTimeSensorReader.java new file mode 100644 index 0000000000..fc4b474e65 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/event/realtimesensor/RealTimeSensorReader.java @@ -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) { + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/sensorlisting/AvailableSensorsInDevice.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/sensorlisting/AvailableSensorsInDevice.java new file mode 100644 index 0000000000..726c8cded2 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/sensorlisting/AvailableSensorsInDevice.java @@ -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 sensor_List = supportedSensors.getSensorList(); + Set sensorSet = new HashSet<>(); + List 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(); + } + + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/sensorlisting/SupportedSensors.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/sensorlisting/SupportedSensors.java new file mode 100644 index 0000000000..6d57e6d704 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/sensorlisting/SupportedSensors.java @@ -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 sensorList = new ArrayList<>(); + private static HashMap sensorTypeMap = new HashMap<>(); + private static HashMap 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 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); + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/view/adaptor/SensorViewAdaptor.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/view/adaptor/SensorViewAdaptor.java new file mode 100644 index 0000000000..d2d852226d --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/view/adaptor/SensorViewAdaptor.java @@ -0,0 +1,97 @@ +/* + * 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 + */ + +//TODO : Add the location and battery data sections. +public class SensorViewAdaptor extends BaseAdapter { + + private Context context; + private List data; + + public SensorViewAdaptor(Context context, List 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; + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/view/sensor/selector/SelectSensorDialog.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/view/sensor/selector/SelectSensorDialog.java new file mode 100644 index 0000000000..5c163c8021 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/realtimeviewer/view/sensor/selector/SelectSensorDialog.java @@ -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 + *

+ * 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 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 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 sensorset) { + CharSequence[] seq; + String[] seq2 = sensorset.toArray(new String[sensorset.size()]); + seq = Arrays.copyOf(seq2, seq2.length); + return seq; + } + + public Set getSet() { + return this.selectedSensorSet; + } + + public interface SensorListListener { + void onDialogPositiveClick(SelectSensorDialog dialog); + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/IVoiceControl.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/IVoiceControl.java new file mode 100644 index 0000000000..83b702d456 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/IVoiceControl.java @@ -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(); +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/WordRecognitionActivity.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/WordRecognitionActivity.java new file mode 100644 index 0000000000..903b6c3a8e --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/WordRecognitionActivity.java @@ -0,0 +1,132 @@ +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; + +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); + } + + }); + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/ListeningActivity.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/ListeningActivity.java new file mode 100644 index 0000000000..db37583b58 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/ListeningActivity.java @@ -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(); + } +} + + diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/ProcessWords.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/ProcessWords.java new file mode 100644 index 0000000000..9933904a57 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/ProcessWords.java @@ -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 { + private static volatile double threshold = 80; + private static volatile Map 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 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(); + } + + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/StringSimilarity.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/StringSimilarity.java new file mode 100644 index 0000000000..a44e304f42 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/StringSimilarity.java @@ -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()]; + } + + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/VoiceRecognitionListener.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/VoiceRecognitionListener.java new file mode 100644 index 0000000000..52ce8d52ff --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/VoiceRecognitionListener.java @@ -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 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) { } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/WordData.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/WordData.java new file mode 100644 index 0000000000..fb76eab24f --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/speech/detector/util/WordData.java @@ -0,0 +1,47 @@ +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; + } + + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/LocalRegistry.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/LocalRegistry.java new file mode 100644 index 0000000000..e9d3d430f7 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/LocalRegistry.java @@ -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; + } + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseClient.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseClient.java new file mode 100644 index 0000000000..173525b825 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseClient.java @@ -0,0 +1,85 @@ +/* + * 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 java.util.Map; +import java.util.concurrent.ExecutionException; + +/** + * 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 boolean register(String username, String password, String deviceId) { + Map response = registerWithTimeWait(username, password, deviceId); + String responseStatus = response.get("status"); + if (responseStatus.trim().contains(SenseConstants.Request.REQUEST_SUCCESSFUL)) { + Toast.makeText(context, "Device Registered", Toast.LENGTH_LONG).show(); + return true; + } else if (responseStatus.trim().contains(SenseConstants.Request.REQUEST_CONFLICT)) { + Toast.makeText(context, "Login Successful", Toast.LENGTH_LONG).show(); + return true; + } else { + Toast.makeText(context, "Authentication failed, please check your credentials and try again.", Toast + .LENGTH_LONG).show(); + + return false; + } + } + + public Map registerWithTimeWait(String username, String password, String deviceId) { + for (int i = 1; i <= SenseConstants.Request.MAX_ATTEMPTS; i++) { + Log.d(TAG, "Attempt #" + i + " to register"); + try { + SenseClientAsyncExecutor senseClientAsyncExecutor = new SenseClientAsyncExecutor(context); + String endpoint = LocalRegistry.getServerURL(context); + senseClientAsyncExecutor.execute(username, password, deviceId, endpoint); + Map 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; + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseClientAsyncExecutor.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseClientAsyncExecutor.java new file mode 100644 index 0000000000..56842f6b2b --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseClientAsyncExecutor.java @@ -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> { + + 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 doInBackground(String... parameters) { + if (android.os.Debug.isDebuggerConnected()) + android.os.Debug.waitForDebugger(); + String response; + Map response_params = new HashMap<>(); + String username = parameters[0]; + String password = parameters[1]; + String deviceId = parameters[2]; + String endpoint = parameters[3]; + Map 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, "https://192.168.56.1:8243" + 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; + } + + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseDataHolder.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseDataHolder.java new file mode 100644 index 0000000000..463cf8ab9f --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseDataHolder.java @@ -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 sensorDataHolder; + private static List batteryDataHolder; + private static List locationDataHolder; + private static List wordDataHolder; + + public static List getSensorDataHolder(){ + if(sensorDataHolder == null){ + sensorDataHolder = new CopyOnWriteArrayList<>(); + } + return sensorDataHolder; + } + + public static List getBatteryDataHolder(){ + if(batteryDataHolder == null){ + batteryDataHolder = new CopyOnWriteArrayList<>(); + } + return batteryDataHolder; + } + + public static List getLocationDataHolder(){ + if(locationDataHolder == null){ + locationDataHolder = new CopyOnWriteArrayList<>(); + } + return locationDataHolder; + } + + public static List 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; + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseUtils.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseUtils.java new file mode 100644 index 0000000000..956e780def --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseUtils.java @@ -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(); + + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseWakeLock.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseWakeLock.java new file mode 100644 index 0000000000..1a6a36bbbe --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/SenseWakeLock.java @@ -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"); + } + +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/AccessTokenInfo.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/AccessTokenInfo.java new file mode 100644 index 0000000000..65170970bf --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/AccessTokenInfo.java @@ -0,0 +1,40 @@ +package org.wso2.carbon.iot.android.sense.util.dto; + +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; + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/AndroidSenseManagerService.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/AndroidSenseManagerService.java new file mode 100644 index 0000000000..0cbf26bd28 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/AndroidSenseManagerService.java @@ -0,0 +1,13 @@ +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; + +public interface AndroidSenseManagerService { + + @Path("devices/{device_id}") + @POST + boolean register(@PathParam("device_id") String deviceId, @QueryParam("deviceName") String deviceName); +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/ApiApplicationRegistrationService.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/ApiApplicationRegistrationService.java new file mode 100644 index 0000000000..e8cd26148b --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/ApiApplicationRegistrationService.java @@ -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); +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/ApiRegistrationProfile.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/ApiRegistrationProfile.java new file mode 100644 index 0000000000..433ef707b8 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/ApiRegistrationProfile.java @@ -0,0 +1,64 @@ +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; + } +} \ No newline at end of file diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/DynamicClientRegistrationService.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/DynamicClientRegistrationService.java new file mode 100644 index 0000000000..aa409673a8 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/DynamicClientRegistrationService.java @@ -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); +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/OAuthApplicationInfo.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/OAuthApplicationInfo.java new file mode 100644 index 0000000000..4bf5bf354f --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/OAuthApplicationInfo.java @@ -0,0 +1,44 @@ +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; + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/OAuthRequestInterceptor.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/OAuthRequestInterceptor.java new file mode 100644 index 0000000000..32aac77c98 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/OAuthRequestInterceptor.java @@ -0,0 +1,26 @@ +package org.wso2.carbon.iot.android.sense.util.dto; + + +import feign.RequestInterceptor; +import feign.RequestTemplate; + +import static feign.Util.checkNotNull; + +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); + } +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/RegistrationProfile.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/RegistrationProfile.java new file mode 100644 index 0000000000..046c112a38 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/RegistrationProfile.java @@ -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; + } + +} \ No newline at end of file diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/TokenIssuerService.java b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/TokenIssuerService.java new file mode 100644 index 0000000000..570aeda7f3 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/java/org/wso2/carbon/iot/android/sense/util/dto/TokenIssuerService.java @@ -0,0 +1,16 @@ +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; + +@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); +} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/mic.png b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/mic.png new file mode 100644 index 0000000000..c799610295 Binary files /dev/null and b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/mic.png differ diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/pushtoserver.png b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/pushtoserver.png new file mode 100644 index 0000000000..3dc93ed290 Binary files /dev/null and b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/pushtoserver.png differ diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/sensor.png b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/sensor.png new file mode 100644 index 0000000000..a73fb4ee5b Binary files /dev/null and b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/sensor.png differ diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/side_nav_bar.xml b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/side_nav_bar.xml new file mode 100644 index 0000000000..5dcda64085 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/drawable/side_nav_bar.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/layout/activity_activity_select_sensor.xml b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/layout/activity_activity_select_sensor.xml new file mode 100644 index 0000000000..0650eddb59 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/layout/activity_activity_select_sensor.xml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/layout/activity_register.xml b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/layout/activity_register.xml new file mode 100644 index 0000000000..a02e11ade1 --- /dev/null +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.agent/app/src/main/res/layout/activity_register.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + +