edu.mit.media.funf.funfohmage.MainPipeline.java Source code

Java tutorial

Introduction

Here is the source code for edu.mit.media.funf.funfohmage.MainPipeline.java

Source

/**
 * Funf: Open Sensing Framework
 * Copyright (C) 2010-2011 Nadav Aharony, Wei Pan, Alex Pentland. 
 * Acknowledgments: Alan Gardner
 * Contact: nadav@media.mit.edu
 * 
 * This file is part of Funf.
 * 
 * Funf is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of 
 * the License, or (at your option) any later version. 
 * 
 * Funf is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 * See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public 
 * License along with Funf. If not, see <http://www.gnu.org/licenses/>.
 */
package edu.mit.media.funf.funfohmage;

import static edu.mit.media.funf.AsyncSharedPrefs.async;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.joda.time.DateTimeZone;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.ohmage.Config;
import org.ohmage.OhmageApi;
import org.ohmage.SharedPreferencesHelper;
import org.ohmage.Utilities;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
//import android.util.Log;
import edu.mit.media.funf.IOUtils;
import edu.mit.media.funf.Utils;
import edu.mit.media.funf.configured.ConfiguredPipeline;
import edu.mit.media.funf.configured.FunfConfig;
import edu.mit.media.funf.probe.Probe;
import edu.mit.media.funf.storage.BundleSerializer;
import edu.mit.media.funf.storage.NameValueDatabaseService;
import edu.ucla.cens.systemlog.ISystemLog;
import edu.ucla.cens.systemlog.Log;

public class MainPipeline extends ConfiguredPipeline {

    public static String TAG = "FunfBGCollector";
    public static final String MAIN_CONFIG = "main_config";
    public static final String START_DATE_KEY = "START_DATE";

    public static final String ACTION_RUN_ONCE = "RUN_ONCE";
    public static final String RUN_ONCE_PROBE_NAME = "PROBE_NAME";

    //FunfOhmage
    //Stores data until data from all the sensors for the current dutycycle is received
    String locationProbe_data = null;
    String wifiProbe_data = null;
    String accelerometerSensorProbe_data = null;
    private OhmageApi mApi;
    private SensorDataSource datasource;

    //FunfOhmage
    public void setOhmageApi(OhmageApi api) {
        mApi = api;
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (ACTION_RUN_ONCE.equals(intent.getAction())) {
            String probeName = intent.getStringExtra(RUN_ONCE_PROBE_NAME);
            runProbeOnceNow(probeName);
        } else {
            super.onHandleIntent(intent);
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.setAppName("funfohmagetrial");
        //funfohmage
        if (!Log.isConnected()) {
            Log.i("dony", "Connecting to Log");
            bindService(new Intent(ISystemLog.class.getName()), Log.SystemLogConnection, Context.BIND_AUTO_CREATE);
        }
        Log.i("dony", "Log Starting in service");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (Log.isConnected()) {
            unbindService(Log.SystemLogConnection);
        }
    }

    @Override
    public BundleSerializer getBundleSerializer() {
        return new BundleToJson();
    }

    public static class BundleToJson implements BundleSerializer {
        public String serialize(Bundle bundle) {
            return JsonUtils.getGson().toJson(Utils.getValues(bundle));
        }

    }

    //   @Override
    //   public void onDataReceived(Bundle data) {
    //      super.onDataReceived(data);
    //      incrementCount();
    //   }

    //   public static final String SCAN_COUNT_KEY = "SCAN_COUNT";
    //   
    //   public static long getScanCount(Context context) {
    //      return getSystemPrefs(context).getLong(SCAN_COUNT_KEY, 0L);
    //   }

    public static final String DATABASE_COUNT_KEY = "DATABASE_COUNT";

    public static long getdbCount(Context context) {
        return getSystemPrefs(context).getLong(DATABASE_COUNT_KEY, 0L);
    }

    //   private void incrementCount() {
    //      boolean success = false;
    //      while(!success) { 
    //         SharedPreferences.Editor editor = getSystemPrefs().edit();
    //         editor.putLong(SCAN_COUNT_KEY, getScanCount(this) + 1L);
    //         success = editor.commit();
    //      }
    //   }

    @Override
    public void onStatusReceived(Probe.Status status) {
        super.onStatusReceived(status);
        // Fill this in with extra behaviors on status received
    }

    @Override
    public void onDetailsReceived(Probe.Details details) {
        super.onDetailsReceived(details);
        // Fill this in with extra behaviors on details received
    }

    public static boolean isEnabled(Context context) {
        return getSystemPrefs(context).getBoolean(ENABLED_KEY, true);
    }

    @Override
    public SharedPreferences getSystemPrefs() {
        return getSystemPrefs(this);
    }

    public static SharedPreferences getSystemPrefs(Context context) {
        return async(context.getSharedPreferences(MainPipeline.class.getName() + "_system", MODE_PRIVATE));
    }

    @Override
    public FunfConfig getConfig() {
        return getMainConfig(this);
    }

    /**
     * Easy access to Funf config.  
     * As long as this service is running, changes will be automatically picked up.
     * @param context
     * @return
     */
    public static FunfConfig getMainConfig(Context context) {
        FunfConfig config = getConfig(context, MAIN_CONFIG);
        if (config.getName() == null) {
            String jsonString = getStringFromAsset(context, "default_config.json");
            if (jsonString == null) {
                Log.e(TAG, "Error loading default config.  Using blank config.");
                jsonString = "{}";
            }
            try {
                config.edit().setAll(jsonString).commit();
            } catch (JSONException e) {
                Log.e(TAG, "Error parsing default config", e);
            }
        }
        return config;
    }

    public static String getStringFromAsset(Context context, String filename) {
        InputStream is = null;
        try {
            is = context.getAssets().open(filename);
            return IOUtils.inputStreamToString(is, Charset.defaultCharset().name());
        } catch (IOException e) {
            Log.e(TAG, "Unable to read asset to string", e);
            return null;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    Log.e(TAG, "Unable to close asset input stream", e);
                }
            }
        }
    }

    public void runProbeOnceNow(final String probeName) {
        FunfConfig config = getMainConfig(this);
        ArrayList<Bundle> updatedRequests = new ArrayList<Bundle>();
        Bundle[] existingRequests = config.getDataRequests(probeName);
        if (existingRequests != null) {
            for (Bundle existingRequest : existingRequests) {
                updatedRequests.add(existingRequest);
            }
        }

        Bundle oneTimeRequest = new Bundle();
        oneTimeRequest.putLong(Probe.Parameter.Builtin.PERIOD.name, 0L);
        updatedRequests.add(oneTimeRequest);

        Intent request = new Intent(Probe.ACTION_REQUEST);
        request.setClassName(this, probeName);
        request.putExtra(Probe.CALLBACK_KEY, getCallback());
        request.putExtra(Probe.REQUESTS_KEY, updatedRequests);
        startService(request);
    }

    @Override
    public void onDataReceived(Bundle data) {
        String dataJson = getBundleSerializer().serialize(data);
        String probeName = data.getString(Probe.PROBE);
        long timestamp = data.getLong(Probe.TIMESTAMP, 0L);
        Bundle b = new Bundle();
        b.putString(NameValueDatabaseService.DATABASE_NAME_KEY, getPipelineName());
        b.putLong(NameValueDatabaseService.TIMESTAMP_KEY, timestamp);
        b.putString(NameValueDatabaseService.NAME_KEY, probeName);
        b.putString(NameValueDatabaseService.VALUE_KEY, dataJson);

        //Funf Ohmage
        //Log.w("dony","ts:"+timestamp);
        Log.w("dony", "name:" + probeName);
        //Log.w("dony","data:"+dataJson);

        if (probeName.endsWith("LocationProbe"))
            locationProbe_data = dataJson;
        else if (probeName.endsWith("WifiProbe"))
            wifiProbe_data = dataJson;
        else if (probeName.endsWith("AccelerometerSensorProbe"))
            accelerometerSensorProbe_data = dataJson;
        else
            Log.w("dony", "Received:" + probeName);

        if (locationProbe_data != null && wifiProbe_data != null && accelerometerSensorProbe_data != null) {
            Log.w("dony", "ts: All data received");
            uploadRequest(accelerometerSensorProbe_data, locationProbe_data, wifiProbe_data);
            Log.v("dony", "location:" + locationProbe_data);
            Log.v("dony", "wifi:" + wifiProbe_data);
            Log.v("dony", "acc:" + accelerometerSensorProbe_data);
            locationProbe_data = null;
            wifiProbe_data = null;
            accelerometerSensorProbe_data = null;
        }

        //Intent i = new Intent(this, getDatabaseServiceClass());
        //i.setAction(DatabaseService.ACTION_RECORD);
        //i.putExtras(b);
        //startService(i);
    }

    public void uploadRequest(String accelerometer, String location, String wifi) {
        //      Intent intent = new Intent(MainPipeline.this, UploadService.class);
        //      intent.setData(Responses.CONTENT_URI);
        //      intent.putExtra(UploadService.EXTRA_UPLOAD_MOBILITY, true);
        //      WakefulIntentService.sendWakefulWork(MobilityActivity.this, intent);
        uploadMobility(accelerometer, location, wifi);
    }

    private void uploadMobility(String accelerometer, String location, String wifi) {
        if (mApi == null)
            setOhmageApi(new OhmageApi(this));
        //sendBroadcast(new Intent(UploadService.MOBILITY_UPLOAD_STARTED));

        boolean uploadSensorData = true;

        SharedPreferencesHelper helper = new SharedPreferencesHelper(this);

        String username = helper.getUsername();
        String hashedPassword = helper.getHashedPassword();
        long uploadAfterTimestamp = helper.getLastMobilityUploadTimestamp();
        if (uploadAfterTimestamp == 0) {
            uploadAfterTimestamp = helper.getLoginTimestamp();
        }
        Log.w("dony", "user name" + username);
        //Log.w("dony","hashed"+hashedPassword);
        //Log.w("dony","uploadTS"+uploadAfterTimestamp);

        Long now = System.currentTimeMillis();
        //Cursor c = MobilityInterface.getMobilityCursor(this, uploadAfterTimestamp);

        OhmageApi.UploadResponse response = new OhmageApi.UploadResponse(OhmageApi.Result.SUCCESS, null);

        JSONArray mobilityJsonArray = new JSONArray();
        JSONObject mobilityPointJson = new JSONObject();

        try {
            JSONObject acc_json = new JSONObject(accelerometer);
            JSONObject location_json = new JSONObject(location);
            JSONObject wifi_json = new JSONObject(wifi);

            JSONObject location_inner_json = location_json.getJSONObject("LOCATION");

            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //         Long time = Long.parseLong(c.getString(c.getColumnIndex(MobilityInterface.KEY_TIME)));
            //         if (i == limit - 1) 
            //         {
            //            uploadAfterTimestamp = time;
            //         }

            UUID id = UUID.randomUUID();
            mobilityPointJson.put("id", id.toString());
            mobilityPointJson.put("time", System.currentTimeMillis());
            mobilityPointJson.put("timezone", DateTimeZone.getDefault().getID());
            mobilityPointJson.put("mode", "still");
            if (uploadSensorData) {
                mobilityPointJson.put("subtype", "sensor_data");
                JSONObject dataJson = new JSONObject();
                dataJson.put("mode", "still");

                if (location_inner_json.getBoolean("mHasSpeed")) {
                    try {
                        double speed = Double.parseDouble(location_inner_json.getString("mSpeed"));
                        dataJson.put("speed", speed);
                    } catch (NumberFormatException e) {
                        dataJson.put("speed", (double) (-1));
                    } catch (JSONException e) {
                        dataJson.put("speed", (double) (-1));
                    }
                } else {
                    dataJson.put("speed", (float) (-1));
                }

                JSONArray x_array = acc_json.getJSONArray("X");
                JSONArray y_array = acc_json.getJSONArray("Y");
                JSONArray z_array = acc_json.getJSONArray("Z");
                JSONArray ts_array = acc_json.getJSONArray("EVENT_TIMESTAMP");

                JSONArray accel_data_array = new JSONArray();

                int start_index = 0;
                long ts_end = 0;
                if (ts_array.length() > 0) {
                    ts_end = ts_array.getLong(ts_array.length() - 1);
                }

                for (int i = ts_array.length() - 2; i >= 0; i--) {
                    if ((ts_end - ts_array.getLong(i)) > 1000000000L) {
                        start_index = i;
                        //Log.i("dony","Stopping at : "+start_index);
                        continue;
                    }
                    //Log.i("dony","diff "+(ts_end - ts_array.getLong(i))/1000000L);
                }

                //Log.i("dony","Number of values: "+(x_array.length()- start_index));
                //Log.i("dony","Total Number of values: "+x_array.length());

                for (int i = start_index; i < x_array.length(); i++) {
                    JSONObject accel_data_json = new JSONObject();
                    accel_data_json.put("x", x_array.getDouble(i));
                    accel_data_json.put("y", y_array.getDouble(i));
                    accel_data_json.put("z", z_array.getDouble(i));
                    accel_data_array.put(accel_data_json);
                }

                dataJson.put("accel_data", accel_data_array);

                JSONObject wifiJson = new JSONObject();
                //            wifiJson.put("time", wifi_json.getLong("TIMESTAMP"));
                wifiJson.put("time", System.currentTimeMillis());
                wifiJson.put("timezone", DateTimeZone.getDefault().getID());
                JSONArray scan_array = wifi_json.getJSONArray("SCAN_RESULTS");
                JSONArray scan_data_array = new JSONArray();

                for (int i = 0; i < scan_array.length(); i++) {
                    JSONObject scan_element_json = new JSONObject();
                    JSONObject scan_input_json = scan_array.getJSONObject(i);

                    scan_element_json.put("ssid", scan_input_json.getString("BSSID"));
                    scan_element_json.put("strength", scan_input_json.getDouble("level"));
                    scan_data_array.put(scan_element_json);
                }
                wifiJson.put("scan", scan_data_array);
                dataJson.put("wifi_data", wifiJson);

                mobilityPointJson.put("data", dataJson);
            } else {
                mobilityPointJson.put("subtype", "mode_only");
                mobilityPointJson.put("mode", "still");
            }

            //String locationStatus = c.getString(c.getColumnIndex(MobilityInterface.KEY_STATUS));

            JSONObject locationJson = new JSONObject();

            if (location_inner_json.getBoolean("mHasAccuracy")) {
                mobilityPointJson.put("location_status", "valid");
                locationJson.put("accuracy", location_inner_json.getDouble("mAccuracy"));
            } else {
                mobilityPointJson.put("location_status", "inaccurate");
                locationJson.put("accuracy", "NaN");
            }

            try {
                locationJson.put("latitude", location_inner_json.getDouble("mLatitude"));
            } catch (NumberFormatException e) {
                locationJson.put("latitude", "NaN");
            } catch (JSONException e) {
                locationJson.put("latitude", "NaN");
            }

            try {
                locationJson.put("longitude", location_inner_json.getDouble("mLongitude"));
            } catch (NumberFormatException e) {
                locationJson.put("longitude", "NaN");
            } catch (JSONException e) {
                locationJson.put("longitude", "NaN");
            }

            locationJson.put("provider", location_inner_json.getString("mProvider"));

            try {
                locationJson.put("accuracy", location_inner_json.getDouble("mAccuracy"));
            } catch (NumberFormatException e) {
                locationJson.put("accuracy", "NaN");
            } catch (JSONException e) {
                locationJson.put("accuracy", "NaN");
            }

            //         locationJson.put("time",  location_json.getLong("TIMESTAMP"));
            locationJson.put("time", location_inner_json.getDouble("mTime"));
            locationJson.put("timezone", DateTimeZone.getDefault().getID());

            mobilityPointJson.put("location", locationJson);
            mobilityJsonArray.put(mobilityPointJson);

        } catch (JSONException e) {
            Log.e(TAG, "error creating mobility json", e);
            //         if(isBackground)
            //            NotificationHelper.showMobilityErrorNotification(this);
            throw new RuntimeException(e);
        }

        TAG = "dony";

        //Database Test
        datasource = new SensorDataSource(this);
        datasource.open();
        String dataToUpload = mobilityJsonArray.toString();
        Boolean currentData_bool = true;

        SensorData tempData = null;
        while (true) {
            response = mApi.mobilityUpload(Config.DEFAULT_SERVER_URL, username, hashedPassword,
                    OhmageApi.CLIENT_NAME, dataToUpload);

            SharedPreferences.Editor editor = getSystemPrefs().edit();
            editor.putLong(DATABASE_COUNT_KEY, datasource.count());
            editor.commit();
            Log.i(TAG, "Number of database points:" + datasource.count());

            if (response.getResult().equals(OhmageApi.Result.SUCCESS)) {
                Log.i(TAG, "Successfully uploaded 1 mobility points:" + dataToUpload);
                if (currentData_bool) {
                    currentData_bool = false;
                    Log.i(TAG, "Finished current. Starting past");
                } else {
                    Log.i(TAG, " data to be deleted: " + tempData.getData());
                    datasource.deleteData(tempData);
                    Log.i(TAG, "Successfully uploaded 1 past");
                }

                helper.putLastMobilityUploadTimestamp(uploadAfterTimestamp);
                List<SensorData> values = datasource.getAllData();
                if (values == null || values.size() == 0)
                    break;
                else {
                    tempData = values.get(0);
                    dataToUpload = tempData.getData();
                }
                Log.i(TAG, "number of values:" + values.size() + " data: " + tempData.getData());
            } else {
                Log.e(TAG, "Failed to upload mobility points. Cancelling current round of mobility uploads.");

                switch (response.getResult()) {
                case FAILURE:
                    Log.e(TAG, "Upload failed due to error codes: "
                            + Utilities.stringArrayToString(response.getErrorCodes(), ", "));

                    boolean isAuthenticationError = false;
                    boolean isUserDisabled = false;

                    for (String code : response.getErrorCodes()) {
                        if (code.charAt(1) == '2') {
                            isAuthenticationError = true;

                            if (code.equals("0201")) {
                                isUserDisabled = true;
                            }
                        }
                    }

                    if (isUserDisabled) {
                        new SharedPreferencesHelper(this).setUserDisabled(true);
                    }

                    //               if (isBackground) 
                    //               {
                    //                  if (isAuthenticationError) {
                    //                     NotificationHelper.showAuthNotification(this);
                    //                  } else {
                    //                     NotificationHelper.showMobilityErrorNotification(this);
                    //                  }
                    //               }

                    break;

                case INTERNAL_ERROR:
                    Log.e(TAG, "Upload failed due to unknown internal error");
                    //               if (isBackground)
                    //                  NotificationHelper.showMobilityErrorNotification(this);
                    break;

                case HTTP_ERROR:
                    Log.e(TAG, "Upload failed due to network error");
                    break;
                }

                if (currentData_bool) {
                    datasource.createData(dataToUpload);
                    Log.i(TAG, "Storing in database");
                }
                Log.i(TAG, "Breaking due to Error");

                break;
            }
        }

        datasource.close();

        //sendBroadcast(new Intent(UploadService.MOBILITY_UPLOAD_FINISHED));
    }
}