package kr.ac.kaist.resl.sensorservice;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Service;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.IBinder;
import android.provider.Settings;
public class SensorService extends Service implements SensorEventListener {
private SensorManager sensorManager =null;
public static String message="";
private Map<String, Object> sensorValues;
private FileThread fileThread;
private RemoteThread remoteThread;
String androidId;
public SensorService() {
}
@Override
public IBinder onBind(Intent intent) { throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
androidId = android.provider.Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
}
@Override
public void onStart(Intent intent, int startId) {
if( sensorManager == null ) sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
for( int i = 0 ; i < sensors.size() ; i++ )
{
sensorManager.registerListener(this, sensors.get(i), SensorManager.SENSOR_DELAY_NORMAL);
}
sensorValues = new HashMap<String, Object>();
sensorValues.put("android_id", androidId);
}
@Override
public void onDestroy() {
if( sensorManager != null )
sensorManager.unregisterListener(this);
fileThread.cont = false;
remoteThread.cont = false;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@SuppressWarnings("deprecation")
@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
if( event.sensor.getType() == Sensor.TYPE_ACCELEROMETER )
{
//Sensor : 1
/*
* All values are in SI units (m/s^2)
values[0]: Acceleration minus Gx on the x-axis
values[1]: Acceleration minus Gy on the y-axis
values[2]: Acceleration minus Gz on the z-axis
*/
//sensorValues.put("accelerometer.x", values[0]);
//sensorValues.put("accelerometer.y", values[1]);
//sensorValues.put("accelerometer.z", values[2]);
}else if( event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD )
{
//Sensor : 2
/*
* All values are in micro-Tesla (uT) and measure the ambient magnetic field in the X, Y and Z axis.
*/
//sensorValues.put("magnetic_field.x", values[0]);
//sensorValues.put("magnetic_field.y", values[1]);
//sensorValues.put("magnetic_field.z", values[2]);
}else if( event.sensor.getType() == Sensor.TYPE_ORIENTATION )
{
//Sensor : 3
//Deprecated
float fDigit = (float)values[0]%10;
float valueFloat = (float)values[0] - fDigit;
if( valueFloat < 0 )
sensorValues.put("orientation", 0);
else
sensorValues.put("orientation", valueFloat);
}else if( event.sensor.getType() == Sensor.TYPE_GYROSCOPE)
{
//Sensor : 4
/*
values[0]: Angular speed around the x-axis
values[1]: Angular speed around the y-axis
values[2]: Angular speed around the z-axis
*/
//sensorValues.put("gyroscope.x", values[0]);
//sensorValues.put("gyroscope.y", values[1]);
//sensorValues.put("gyroscope.z", values[2]);
}else if( event.sensor.getType() == Sensor.TYPE_LIGHT)
{
//Sensor : 5
float fDigit = (float)values[0]%10;
float valueFloat = (float)values[0] - fDigit;
if( valueFloat < 0 )
sensorValues.put("light", 0);
else
sensorValues.put("light", valueFloat);
}else if( event.sensor.getType() == Sensor.TYPE_PRESSURE)
{
//Sensor : 6
//Atmospheric pressure in hPa (millibar)
sensorValues.put("pressure", values[0]);
}else if( event.sensor.getType() == Sensor.TYPE_TEMPERATURE)
{
//Sensor : 7
//Ambient light level in SI lux units
sensorValues.put("temperature", values[0]);
}
else if( event.sensor.getType() == Sensor.TYPE_PROXIMITY)
{
//Sensor : 8
// values[0]: Proximity sensor distance measured in centimeters
// G2 may support binary / near / far
sensorValues.put("proximity", values[0]);
}else if( event.sensor.getType() == Sensor.TYPE_GRAVITY)
{
//Sensor : 9
//A three dimensional vector indicating the direction and magnitude of gravity. Units are m/s^2. The coordinate system is the same as is used by the acceleration sensor.
//Note: When the device is at rest, the output of the gravity sensor should be identical to that of the accelerometer.
//sensorValues.put("gravity.x", values[0]);
//sensorValues.put("gravity.y", values[1]);
//sensorValues.put("gravity.z", values[2]);
}else if( event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION)
{
//Sensor : 10
// acceleration = gravity + linear-acceleration
//sensorValues.put("linear_acceleration.x", values[0]);
//sensorValues.put("linear_acceleration.y", values[1]);
//sensorValues.put("linear_acceleration.z", values[2]);
}else if( event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR)
{
//Sensor : 11
/*
values[0]: x*sin(θ/2)
values[1]: y*sin(θ/2)
values[2]: z*sin(θ/2)
values[3]: cos(θ/2)
values[4]: estimated heading Accuracy (in radians) (-1 if unavailable)
*/
//sensorValues.put("rotation_vector.xsin", values[0]);
//sensorValues.put("rotation_vector.ysin", values[1]);
//sensorValues.put("rotation_vector.zsin", values[2]);
//sensorValues.put("rotation_vector.cos", values[3]);
//sensorValues.put("rotation_vector.accuracy", values[4]);
}else if( event.sensor.getType() == Sensor.TYPE_RELATIVE_HUMIDITY)
{
//Sensor : 12
sensorValues.put("relative_humidity", values[0]);
}else if( event.sensor.getType() == Sensor.TYPE_AMBIENT_TEMPERATURE)
{
//Sensor : 13
sensorValues.put("ambient_temperature", values[0]);
}
else if( event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED)
{
//Sensor : 14
}else if( event.sensor.getType() == Sensor.TYPE_GAME_ROTATION_VECTOR)
{
//Sensor : 15
}else if( event.sensor.getType() == Sensor.TYPE_GYROSCOPE_UNCALIBRATED)
{
//Sensor : 16
}else if( event.sensor.getType() == Sensor.TYPE_SIGNIFICANT_MOTION)
{
//Sensor : 17
// Not work
}else if( event.sensor.getType() == Sensor.TYPE_STEP_DETECTOR)
{
//Sensor : 18
}else if( event.sensor.getType() == Sensor.TYPE_STEP_COUNTER )
{
//Sensor : 19
sensorValues.put("step_counter", values[0]);
}else if( event.sensor.getType() == Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR )
{
//Sensor : 20
}
else if( event.sensor.getType() == 33171000)
{
//Sensor : Basic Gestures
//Cannot Understand
}else if( event.sensor.getType() == 33171002)
{
//Sensor : Facing
sensorValues.put("facing", values[0]);
}else if( event.sensor.getType() == 33171003)
{
//Sensor : Tilt
}else if( event.sensor.getType() == 33171006)
{
//Sensor : AMD
}else if( event.sensor.getType() == 33171007)
{
//Sensor : RMD
}else if( event.sensor.getType() == 33171008)
{
//Sensor : VMD
}else if( event.sensor.getType() == 33171009)
{
//Sensor : Pedometer
}else if( event.sensor.getType() == 33171010)
{
//Sensor : Pedestrian-activitiy-monitor
}else if( event.sensor.getType() == 33171011)
{
//Sensor : Motion Accelerometer
}
if( fileThread == null )
{
fileThread = new FileThread();
fileThread.start();
}
if( remoteThread == null )
{
remoteThread = new RemoteThread();
remoteThread.start();
}
}
public class RemoteThread extends Thread
{
public boolean cont;
public Map<String, Object> prevValues;
public RemoteThread()
{
cont = true;
prevValues = new HashMap<String, Object>();
}
public void run()
{
try {
while(cont)
{
SensorService.message = getJSON(sensorValues, prevValues);
if( message != null )
{
new HttpAsyncTask().execute(message);
}
cloneMaps(sensorValues, prevValues);
Thread.sleep(MainActivity.period*1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void cloneMaps(Map<String, Object> source, Map<String, Object> target)
{
Iterator<String> iter = source.keySet().iterator();
while( iter.hasNext() )
{
String key = (String)iter.next();
Object value = source.get(key);
target.put(key, value);
}
}
public class FileThread extends Thread
{
public boolean cont;
public FileThread()
{
cont = true;
}
public void run()
{
try {
while(cont)
{
if( isExternalStorageWritable() )
{
String strToSave = getJSON(sensorValues);
if( strToSave != null )
writeToSDFile("Sensor", strToSave);
}
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public String getJSON(Map<String, Object> sensorValues) throws JSONException
{
Iterator<String> iter = sensorValues.keySet().iterator();
JSONObject ret = new JSONObject();
while( iter.hasNext() )
{
String key = (String)iter.next();
Object value = sensorValues.get(key);
ret.put(key, value);
}
return ret.toString();
}
public String getJSON(Map<String, Object> sensorValues, Map<String, Object> prevValues) throws JSONException
{
Iterator<String> iter = sensorValues.keySet().iterator();
JSONObject ret = new JSONObject();
String android_id = "default";
while( iter.hasNext() )
{
String key = (String)iter.next();
Object value = sensorValues.get(key);
if( value instanceof Float )
{
if( prevValues.containsKey(key) )
{
Float prevValue = (Float)prevValues.get(key);
if( !((Float)value).toString().equals(prevValue.toString()) )
{
ret.put(key, (Float)value);
}
}
}
else if( value instanceof String )
{
android_id = (String)value;
}
}
if( ret.length() != 0 )
{
ret.put("android_id", android_id);
return ret.toString();
}
return null;
}
private class HttpAsyncTask extends AsyncTask<String, Integer, Double>{
@Override
protected Double doInBackground(String... params) {
try {
postData(params[0]);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
public void postData(String message) throws ClientProtocolException, IOException
{
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(MainActivity.URL);
StringEntity params = new StringEntity(message);
post.setEntity(params);
client.execute(post);
}
public boolean isExternalStorageWritable(){
String state = Environment.getExternalStorageState();
if( Environment.MEDIA_MOUNTED.equals( state)){
return true;
}
return false;
}
private void writeToSDFile(String fileName, String message){
// Find the root of the external storage.
// See http://developer.android.com/guide/topics/data/data- storage.html#filesExternal
File root = android.os.Environment.getExternalStorageDirectory();
// See http://stackoverflow.com/questions/3551821/android-write-to-sd-card-folder
File dir = new File (root.getAbsolutePath() + "/SensorService");
dir.mkdirs();
File file = new File(dir, fileName+".json");
try {
FileOutputStream f = new FileOutputStream(file);
PrintWriter pw = new PrintWriter(f);
pw.print(message);
pw.flush();
pw.close();
f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}