de.tudarmstadt.dvs.myhealthassistant.myhealthhub.services.InternalSensorService.java Source code

Java tutorial

Introduction

Here is the source code for de.tudarmstadt.dvs.myhealthassistant.myhealthhub.services.InternalSensorService.java

Source

/* Copyright (C) 2014 TU Darmstadt, Hessen, Germany.
 * Department of Computer Science Databases and Distributed Systems
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.tudarmstadt.dvs.myhealthassistant.myhealthhub.services;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.IMyHealthHubRemoteService;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.R;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.AbstractChannel;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.Event;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.sensorreadings.SensorReadingEvent;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.sensorreadings.environmental.raw.AmbientLightEvent;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.sensorreadings.environmental.raw.AmbientPressureEvent;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.sensorreadings.environmental.raw.HumidityEvent;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.sensorreadings.environmental.raw.ProximityEvent;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.sensorreadings.environmental.raw.TemperatureEvent;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.sensorreadings.physical.AccDeviceSensorEvent;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.sensorreadings.physical.GyroscopeSensorEvent;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.events.sensorreadings.physical.MagneticSensorEvent;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.graphActivities.Coordinate;
import de.tudarmstadt.dvs.myhealthassistant.myhealthhub.services.transformationmanager.database.LocalTransformationDBMS;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.text.format.DateUtils;
import android.util.Log;

/**
 * 
 * @author HieuHa
 * 
 *         A service that listens to SensorEvent, and sends the received Events
 *         out (advertises those for any subscription)
 */
public class InternalSensorService extends Service implements SensorEventListener {

    private static final String TAG = InternalSensorService.class.getSimpleName();
    private SensorManager mSensorManager;
    private SharedPreferences pref;
    private static final long timespan = DateUtils.MINUTE_IN_MILLIS; // FIXME if
    // needed

    @Override
    public void onCreate() {
        // The service is being created
        Log.e(TAG, "onCreate");

        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

        if (pref.getBoolean(getResources().getString(R.string.in_acc), false)) {
            Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (pref.getBoolean(getResources().getString(R.string.in_lig), false)) {
            Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (pref.getBoolean(getResources().getString(R.string.in_pres), false)) {
            Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (pref.getBoolean(getResources().getString(R.string.in_prox), false)) {
            Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (pref.getBoolean(getResources().getString(R.string.in_mag), false)) {
            Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (pref.getBoolean(getResources().getString(R.string.in_gyrs), false)) {
            Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (pref.getBoolean(getResources().getString(R.string.in_grav), false)) {
            Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (pref.getBoolean(getResources().getString(R.string.in_hum), false)) {
            Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_RELATIVE_HUMIDITY);
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (pref.getBoolean(getResources().getString(R.string.in_lin_acc), false)) {
            Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }
        if (pref.getBoolean(getResources().getString(R.string.in_tem), false)) {
            Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
            mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
        }

    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind Service");
        return iservicestub;
    }

    private IMyHealthHubRemoteService.Stub iservicestub = new IMyHealthHubRemoteService.Stub() {

        @Override
        public int getStatus() throws RemoteException {
            // Write here, code to be executed in background
            Log.d(TAG, "Hello World From Remote Service!!");
            return 0;
        }
    };

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnBind Service");
        // All clients unbound
        // super.onUnbind(intent);

        return true;
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");

        if (mSensorManager != null) {
            // unregister all sensors
            mSensorManager.unregisterListener(this);
        } else
            Log.e(TAG, "mSensorManager is null!");

        // The service is no longer used and is being destroyed
        // stopForeground(true);

        super.onDestroy();
    }

    // ###############################################################################
    // SensorListerner Side
    @Override
    public void onAccuracyChanged(Sensor arg0, int arg1) {
        // not needed
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (pref == null)
            pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

        int mSensorType = event.sensor.getType();
        if (mSensorType == Sensor.TYPE_ACCELEROMETER) {

            int x = Math.round(event.values[0]);
            int y = Math.round(event.values[1]);
            int z = Math.round(event.values[2]);

            // using ACCELEROMETER_KNEE only as a demonstration,
            // in practice new event can be created
            AccDeviceSensorEvent accEvt = new AccDeviceSensorEvent("eventID", getTimestamp(), "producerID",
                    SensorReadingEvent.ACCELEROMETER_ON_DEVICE, getTimestamp(), x, y, z, x, y, z);

            sendToChannel(accEvt, AbstractChannel.RECEIVER); // for external
            // apps
            // subscription
            gotAccEvent(getTimestamp(), Sensor.TYPE_ACCELEROMETER, x, y, z); // for
            // on device
            // graphViews
            // using
        }

        else if (mSensorType == Sensor.TYPE_LIGHT) {

            float x = event.values[0];

            // using ambientLightEvent only as a demonstration,
            // in practice new event can be created
            AmbientLightEvent lightEvnt = new AmbientLightEvent("eventID", getTimestamp(), "producerID",
                    SensorReadingEvent.AMBIENT_LIGHT, getTimestamp(), "location", "object", x,
                    AmbientLightEvent.UNIT_LUX);
            sendToChannel(lightEvnt, AbstractChannel.RECEIVER);
            gotLightEvent(getTimestamp(), Sensor.TYPE_LIGHT, x);

        }

        else if (mSensorType == Sensor.TYPE_PRESSURE) {
            float x = event.values[0];
            AmbientPressureEvent temEvnt = new AmbientPressureEvent("eventID", getTimestamp(), "producerID",
                    SensorReadingEvent.AMBIENT_PRESSURE, getTimestamp(), "location", "object", x,
                    AmbientPressureEvent.UNIT_HPA);
            sendToChannel(temEvnt, AbstractChannel.RECEIVER);
            gotLightEvent(getTimestamp(), Sensor.TYPE_PRESSURE, x);
        }

        else if (mSensorType == Sensor.TYPE_PROXIMITY) {
            float x = event.values[0];
            ProximityEvent evnt = new ProximityEvent("eventID", getTimestamp(), "producerID",
                    SensorReadingEvent.PROXIMITY, getTimestamp(), "location", "object", x, "");
            sendToChannel(evnt, AbstractChannel.RECEIVER);
            gotLightEvent(getTimestamp(), Sensor.TYPE_PROXIMITY, x);
        }

        else if (mSensorType == Sensor.TYPE_AMBIENT_TEMPERATURE) {
            float x = event.values[0];
            TemperatureEvent evnt = new TemperatureEvent("eventID", getTimestamp(), "producerID",
                    SensorReadingEvent.ROOM_TEMPERATURE, getTimestamp(), "location", "object", x,
                    TemperatureEvent.UNIT_CELSIUS);
            sendToChannel(evnt, AbstractChannel.RECEIVER);
            gotLightEvent(getTimestamp(), Sensor.TYPE_AMBIENT_TEMPERATURE, x);
        }

        else if (mSensorType == Sensor.TYPE_RELATIVE_HUMIDITY) {
            float x = event.values[0];
            HumidityEvent evnt = new HumidityEvent("eventID", getTimestamp(), "producerID",
                    SensorReadingEvent.HUMIDITY, getTimestamp(), "location", "object", x);
            sendToChannel(evnt, AbstractChannel.RECEIVER);
            gotLightEvent(getTimestamp(), Sensor.TYPE_RELATIVE_HUMIDITY, x);
        }

        else if (mSensorType == Sensor.TYPE_GYROSCOPE) {

            int x = Math.round(event.values[0]);
            int y = Math.round(event.values[1]);
            int z = Math.round(event.values[2]);

            GyroscopeSensorEvent gSEvnt = new GyroscopeSensorEvent("eventID", getTimestamp(), "producerID",
                    SensorReadingEvent.GYROSCOPE, getTimestamp(), x, y, z, x, y, z);
            sendToChannel(gSEvnt, AbstractChannel.RECEIVER);
            gotAccEvent(getTimestamp(), Sensor.TYPE_GYROSCOPE, x, y, z);

        }

        else if (mSensorType == Sensor.TYPE_MAGNETIC_FIELD) {
            int x = Math.round(event.values[0]);
            int y = Math.round(event.values[1]);
            int z = Math.round(event.values[2]);

            MagneticSensorEvent gSEvnt = new MagneticSensorEvent("eventID", getTimestamp(), "producerID",
                    SensorReadingEvent.MAGNETIC_FIELD, getTimestamp(), x, y, z, x, y, z);
            sendToChannel(gSEvnt, AbstractChannel.RECEIVER);
            gotAccEvent(getTimestamp(), Sensor.TYPE_MAGNETIC_FIELD, x, y, z);

        }

        else if (mSensorType == Sensor.TYPE_LINEAR_ACCELERATION) {
            int x = Math.round(event.values[0]);
            int y = Math.round(event.values[1]);
            int z = Math.round(event.values[2]);

            // using ACCELEROMETER_KNEE only as a demonstration,
            // in practice new event can be created
            AccDeviceSensorEvent accEvt = new AccDeviceSensorEvent("eventID", getTimestamp(), "producerID",
                    SensorReadingEvent.ACCELEROMETER_ON_DEVICE, getTimestamp(), x, y, z, x, y, z);

            sendToChannel(accEvt, AbstractChannel.RECEIVER);
            gotAccEvent(getTimestamp(), Sensor.TYPE_LINEAR_ACCELERATION, x, y, z);
        }

    }

    private String getTimestamp() {
        return (String) android.text.format.DateFormat.format(dateFormat, new java.util.Date());
    }

    private void sendToChannel(Event evt, String channel) {
        Intent i = new Intent();
        i.putExtra(Event.PARCELABLE_EXTRA_EVENT_TYPE, evt.getEventType());
        i.putExtra(Event.PARCELABLE_EXTRA_EVENT, evt);
        i.setAction(channel);
        //      getApplicationContext().sendBroadcast(i);
        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
    }

    // ###############################################################################
    // working with SensorEvent
    // normally a new app can subscript to myHealthHub to receive these events

    private static final String dateFormat = "yyyy-MM-dd_kk:mm:ss";
    private static String lastAddedLightData = "";
    private ArrayList<Coordinate> listLightData;
    private double readingLightValue;
    private int lightDataCounter;

    private void gotLightEvent(String dateOfMeasurement, int typeId, float value) {
        //      if (lastAddedLightData == null || lastAddedLightData.isEmpty()) {
        //         lastAddedLightData = dateOfMeasurement;
        //         listLightData = new ArrayList<Coordinate>();
        //         readingLightValue = 0.0d;
        //         lightDataCounter = 1;
        //      } else {
        //         if (timeDiff(lastAddedLightData, dateOfMeasurement, timespan)) {
        //            // after each min the added up data being divided by
        //            // average and stored
        //            double yValue = readingLightValue / lightDataCounter;
        //            String xValue = dateOfMeasurement;
        //
        //            if (listLightData == null)
        //               listLightData = new ArrayList<Coordinate>();
        //            
        //            listLightData.add(new Coordinate(xValue, yValue));
        //
        //            // store to dbs each 10 min (when size of list reach xxx0)
        //            if (listLightData.size() % 10 == 0) {
        //               addTrafficToDB(dateOfMeasurement, typeId, listLightData); // add
        //                                                            // only
        //                                                            // 10
        //                                                            // data
        //                                                            // to
        //                                                            // dbs
        //               listLightData = new ArrayList<Coordinate>();
        //            }
        //            // the data being reset after that
        //            readingLightValue = Double.parseDouble(Float.toString(value));
        //            lightDataCounter = 1;
        //
        //            lastAddedLightData = dateOfMeasurement;
        //         } else {
        //            // within a minute value being added up only
        //            readingLightValue += Double.parseDouble(Float.toString(value));
        //            lightDataCounter++;
        //
        //         }
        //      }
    }

    private static String lastAddedAccData = "";
    private ArrayList<Double> accValues = new ArrayList<Double>();
    private ArrayList<Coordinate> listAccData;

    private void gotAccEvent(String dateOfMeasurement, int typeId, int x, int y, int z) {
        //      if (lastAddedAccData == null || lastAddedAccData.isEmpty()) {
        //         lastAddedAccData = dateOfMeasurement;
        //         listAccData = new ArrayList<Coordinate>();
        //         accValues = new ArrayList<Double>();
        //      } else {
        //         if (timeDiff(lastAddedAccData, dateOfMeasurement, timespan)) {
        //
        //            String xValue = dateOfMeasurement;
        //            double mean = 0.0d;
        //            double variance = 0.0d;
        //            int n = accValues.size();
        //            for (double b : accValues) {
        //               mean += b;
        //            }
        //            mean = mean / n;
        //            for (double b : accValues) {
        //               variance += (mean - b) * (mean - b);
        //            }
        //            variance = variance / n;
        //
        //            double yValue = variance;
        //            // double yValue = Math.sqrt(variance); // standard Deviation
        //            
        //            if (listAccData == null)
        //               listAccData = new ArrayList<Coordinate>();
        //            
        //            listAccData.add(new Coordinate(xValue, yValue));
        //            
        //            // store to dbs each 10 min (when size of list reach 10)
        //            if (listAccData.size() % 10 == 0) { //
        //               addTrafficToDB(dateOfMeasurement, typeId, listAccData);
        //               listAccData = new ArrayList<Coordinate>();
        //            }
        //
        //            // the data being reset after each min
        //            accValues = new ArrayList<Double>();
        //
        //            lastAddedAccData = dateOfMeasurement;
        //         } else {
        //            // within a minute value being added up only
        //            // readingAccValue += Math.sqrt(x * x + y * y + z * z);
        //            accValues.add(Math.sqrt(x * x + y * y + z * z));
        //         }
        //      }
    }

    /**
     * calculate the difference in minutes between two dates in millisecond
     * 
     * @param first
     * @param second
     * @param timespan
     *            : the different of (e.g, ONE minute, ONE day...)
     * @return true if two dates are difference by time span
     */
    public boolean timeDiff(String firstDate, String secondDate, long timespan) {
        SimpleDateFormat dfDate = new SimpleDateFormat(dateFormat);

        try {
            Date first = dfDate.parse(firstDate);
            Date second = dfDate.parse(secondDate);

            long diff = ((second.getTime() / timespan) - (first.getTime() / timespan));

            return (diff < 1) ? false : true;

        } catch (ParseException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
        }

        return false;
    }

    private LocalTransformationDBMS transformationDB;

    private void addTrafficToDB(String timeOfMeasurement, int typeID, ArrayList<Coordinate> listData) {

        ArrayList<String> dateToAdd = new ArrayList<String>();

        transformationDB = new LocalTransformationDBMS(this.getApplicationContext());
        transformationDB.open();
        ArrayList<String> databaseListData = transformationDB.getAllAvalDate();
        // add to traffic table
        Log.e(TAG, "Add traffic to table with type:" + typeID + "; " + timeOfMeasurement);
        for (Coordinate d : listData) {
            String date = getDayFromDate(d.getX(), dateFormat, "dd-MM-yyyy");
            double xDouble = convertTimeToDouble(d.getX(), dateFormat, "kk.mm");
            transformationDB.addTraffic(date, typeID, xDouble, d.getY());
            if (!databaseListData.contains(date) && !dateToAdd.contains(date)) {
                dateToAdd.add(date);
            }
        }
        for (String s : dateToAdd) {
            transformationDB.addDateOfTraffic(s, -1);
        }
        transformationDB.close();
    }

    private String getDayFromDate(String timeOfMeasurement, String dateFormat, String applyPattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);

        try {
            Date today = sdf.parse(timeOfMeasurement);
            sdf.applyPattern(applyPattern);

            return sdf.format(today);

        } catch (ParseException e) {
            e.printStackTrace();
            Log.e(TAG, e.toString());
        }
        return "";
    }

    private static double convertTimeToDouble(String fullTime, String dateFormat, String applyPattern) {
        SimpleDateFormat fullDate = new SimpleDateFormat(dateFormat);
        SimpleDateFormat timeDate = new SimpleDateFormat(applyPattern);

        try {
            Date now = fullDate.parse(fullTime);
            String strDate = timeDate.format(now);
            double parseDate = Double.parseDouble(strDate);
            if (parseDate >= 24.00d)
                return parseDate - 24;
            return parseDate;

        } catch (ParseException e) {
            Log.e(TAG, e.toString());
            e.printStackTrace();
        }

        return Double.parseDouble("00.00");
    }
}