Android Open Source - latrobe-datacapture-dir Master Service






From Project

Back to project page latrobe-datacapture-dir.

License

The source code is released under:

MIT License

If you think the Android project latrobe-datacapture-dir listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.example.DataCaptureApp;
//from  w  w w . j  ava 2s .com
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.HandlerThread;
import com.example.DataCaptureApp.data.*;
import com.example.DataCaptureApp.services.BluetoothConnectivityService;
import com.example.DataCaptureApp.services.DataStoreService;
import com.example.DataCaptureApp.services.RemoteConnectivityService;
import com.example.DataCaptureApp.services.SensorSampleService;
import com.example.DataCaptureApp.transforms.*;
import com.example.DataCaptureApp.utils.BroadcastDataSource;
import com.example.DataCaptureApp.utils.DataEventHandler;

/**
 * Created by Tom on 21/09/2014.
 */
public class MasterService extends DataService
{
    private static final String NOTIF_TITLE = "Data Capture Master";
    private static final int NOTIF_ID = 5;
    public static final String KEY_SLAVE_PACK = "slave";
    public static final String KEY_MASTER_PACK = "master";
    public static final String KEY_TIMESTAMP = "timestamp";
    public static final String KEY_SESSION = "session";
    public static final String KEY_USER = "user";
    public static final String KEY_ARRAY_COLLECT = "datapoint";
    public static final String KEY_TIMESTAMP_COPY = KEY_TIMESTAMP + "Copy";
    public static final String KEY_ORIENTATION_DIFF = "calcOrientationDistance";
    public static final String KEY_SENSOR_ROTATION = "rotData";
    public static final String KEY_SENSOR_MAGNETOMETER = "magData";
    public static final String KEY_SENSOR_ACCELEROMETER = "accData";
    public static final String KEY_SENSOR_GYROSCOPE = "gyroData";
    public static final String KEY_EVENT_FIELD = "dataField";
    public static final String KEY_EVENT_LABEL = "label";
    public static final String KEY_EVENT_TYPE = "constraintType";
    public static final String KEY_EVENT_VALUE = "constraintValue";
    public static final String KEY_EVENT_SEVERITY = "severity";

    public static final String CONFIG_ARRAY_COLLECT_COUNT = "arrayCollectCount";
    public static final String CONFIG_USER_ID = KEY_USER;
    public static final String CONFIG_SESSION_ID = "sessionId";
    public static final String CONFIG_EVENT_DATA = "event";

    public static final String HANDLE_TYPE = "physio";
    public static final String THREAD_NAME = "dataThread";

    private static boolean mRunning = false;

    private DataStoreService mDataStoreService;
    private DataServiceConnection mDataStoreServiceConn = new DataServiceConnection(DataStoreService.class);

    private BluetoothConnectivityService mBluetoothService;
    private DataServiceConnection mBluetoothServiceConn = new DataServiceConnection(BluetoothConnectivityService.class);

    private SensorSampleService mSensorService;
    private DataServiceConnection mSensorServiceConn = new DataServiceConnection(SensorSampleService.class);

    private RemoteConnectivityService mRemoteService;
    private DataServiceConnection mRemoteServiceConn = new DataServiceConnection(RemoteConnectivityService.class);

    private IntervalAggregatorDataTransform mAggregator;
    private BroadcastDataSource mBroadcastSource = new BroadcastDataSource();
    private ArrayCollectDataTransform mArrayCollector;
    private long mStartTime;
    private long mFinishTime;
    private String mSessionId;
    private String mUserId;
    private int mArrayCollectCount;
    private boolean mIsSampling = false;
    private Data mEventData;


    private HandlerThread mThread;
    private DataEventHandler mSlaveToThreadHandler;
    private DataEventHandler mMasterToThreadHandler;
    private DataEventHandler mPersistFromThreadHandler;
    private DataEventHandler mRemoteFromThreadHandler;

    private NotificationManager mNotificationMgr;
    private Notification mNotification;



    @Override
    public boolean onUnbind(Intent intent)
    {
        logd("Unbinding");
        setDataListener(this);
        setEventListener(this);
        return true;
    }

    @Override
    public void onCreate()
    {
        super.onCreate();
        logd("Created");

        mRunning = true;

        mNotificationMgr = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

        mNotification = buildNotification("Running...", R.drawable.ic_action_refresh_w);
    }

    @Override
    public void onDestroy()
    {
        mRunning = false;
    }

    @Override
    protected void doStart()
    {
        bindServices();
        // Log config data
        logd("Configuration: " + mConfig.toJson());
        mArrayCollectCount = mConfig.get(CONFIG_ARRAY_COLLECT_COUNT);
        mUserId = mConfig.get(CONFIG_USER_ID);
        mSessionId = mConfig.get(CONFIG_SESSION_ID);
        mEventData = mConfig.get(CONFIG_EVENT_DATA);
        mThread = new HandlerThread(THREAD_NAME);
        mThread.start();
    }

    @Override
    public void stop()
    {
        mRunning = false;
        super.stop();
    }

    @Override
    protected void doStop()
    {
        mRunning = false;
        // Flush remaining data in array collector (if remote is active)
        if(mRemoteService != null && mArrayCollector != null && mRemoteService.getState() == State.STARTED)
        {
            if (mArrayCollector != null && !mArrayCollector.isEmpty())
                mArrayCollector.flush();
            if(mDataStoreService != null)
            {
                mDataStoreService.delete(mSessionId, System.currentTimeMillis());
            }
        }
        // Stop all active services
        if(mDataStoreService != null)
            mDataStoreService.stop();
        if(mBluetoothService != null)
            mBluetoothService.stop();
        if(mSensorService != null)
            mSensorService.stop();
        if(mRemoteService != null)
            mRemoteService.stop();
        // Stop the helper thread
        if(mThread != null && mThread.isAlive())
            mThread.quit();
        // Unbind all services
        unbindServices();
    }

    @Override
    protected boolean isValidConfig(Data config)
    {
        boolean containsArrayCount = config.contains(CONFIG_ARRAY_COLLECT_COUNT, Integer.class);
        boolean containsUserId = config.contains(CONFIG_USER_ID, String.class);
        boolean containsSessionId = config.contains(CONFIG_SESSION_ID, String.class);
        boolean containsEventData = config.contains(CONFIG_EVENT_DATA, Data.class);
        if(!containsArrayCount || !containsUserId || !containsSessionId || !containsEventData)
            return false;
        int arrayCount = config.get(CONFIG_ARRAY_COLLECT_COUNT);
        if(arrayCount < 1)
            return false;
        return true;
    }

    @Override
    public void onData(IDataSource source, Data data)
    {
        super.onData(source, data);
        if(source == mPersistFromThreadHandler)
        {
            if(mDataListener != null)
                mDataListener.onData(this, data);
        }
        else if(source == mRemoteFromThreadHandler)
        {
            logd("Data from RemoteService");
            Data originalData = data.get(RemoteConnectivityService.KEY_RESPONSE_DATA);
            Object[] datapoints = originalData.get(KEY_ARRAY_COLLECT);
            long minTime = Long.MIN_VALUE;
            long maxTime = Long.MAX_VALUE;
            for(Object datapoint : datapoints)
            {
                long timestamp = ((Data)datapoint).get(KEY_TIMESTAMP);
                if(timestamp < minTime)
                    minTime = timestamp;
                if(timestamp > maxTime)
                    maxTime = timestamp;
            }
            mDataStoreService.delete(mSessionId, minTime, maxTime);
        }
    }

    @Override
    public void onEvent(IEventSource source, Event event, Object arg)
    {
        if(source == this)
            handleSelfEvent(event, arg);
        else if(source == mBluetoothService)
            handleBluetoothEvent(event, arg);
        else if(source == mEventListener)
            handleListenerEvent(event, arg);
        else if(source == mRemoteService || source == mSensorService || source == mDataStoreService)
        {
            switch(event)
            {
                case FAILED:
                    failed((arg == null) ? "Unknown" : arg.toString());
                    break;
                case STOPPING:
                    break;
                case STARTED:
                    if(isAllStarted())
                        changeState(State.STARTED);
            }
        }
        else if(source == mBluetoothServiceConn)
            handleBluetoothService((BluetoothConnectivityService)arg);
        else if(source == mSensorServiceConn)
            handleSensorService((SensorSampleService) arg);
        else if(source == mDataStoreServiceConn)
            handleDataStoreService((DataStoreService) arg);
        else if(source == mRemoteServiceConn)
            handleRemoteService((RemoteConnectivityService) arg);
    }

    @Override
    public void setEventListener(IEventListener listener)
    {
        super.setEventListener(listener);
        if(listener == this && mRunning)
        {
            startForeground(NOTIF_ID, mNotification);
        }
        else
        {
            stopForeground(true);
        }
    }

    private void startSampling()
    {
        if(mState == State.STARTED)
        {
            mStartTime = System.currentTimeMillis();
            prepareDataPipeline();
            mSensorService.startSampling();
            mBluetoothService.write(Event.ACTION_START);
            mIsSampling = true;
        }
    }

    private void stopSampling()
    {
        if(mState == State.STARTED && mIsSampling)
        {
            mFinishTime = System.currentTimeMillis();
            mSensorService.stopSampling();
            mBluetoothService.write(Event.ACTION_STOP);
            mIsSampling = false;
        }
    }

    public boolean isSampling()
    {
        return mIsSampling;
    }

    public static boolean isRunning()
    {
        return mRunning;
    }

    private void bindServices()
    {
        mDataStoreServiceConn.bind(this, this);
        mBluetoothServiceConn.bind(this, this);
        mSensorServiceConn.bind(this, this);
        mRemoteServiceConn.bind(this, this);
    }

    private void unbindServices()
    {
        mDataStoreServiceConn.unbind();
        mBluetoothServiceConn.unbind();
        mSensorServiceConn.unbind();
        mRemoteServiceConn.unbind();
    }

    private void handleDataStoreService(DataStoreService service)
    {
        mDataStoreService = service;
        mDataStoreService.setDataListener(MasterService.this);
        mDataStoreService.setEventListener(MasterService.this);
        try
        {
            mDataStoreService.start(mConfig);
        }
        catch(FailedInitialisationException e)
        {
            failed("Failed to start DataStoreService! " + e.getMessage());
        }
    }

    private void handleSensorService(SensorSampleService service)
    {
        mSensorService = service;
        mSensorService.setDataListener(MasterService.this);
        mSensorService.setEventListener(MasterService.this);
        try
        {
            mSensorService.start(mConfig);
        } catch (FailedInitialisationException e)
        {
            failed("SensorService failed to initialise: " + e.getMessage());
        }
    }

    private void handleBluetoothService(BluetoothConnectivityService service)
    {
        mBluetoothService = service;
        mBluetoothService.setDataListener(MasterService.this);
        mBluetoothService.setEventListener(MasterService.this);
        try
        {
            mBluetoothService.start(mConfig);
        }
        catch(FailedInitialisationException e)
        {
            failed("BluetoothService failed to initialise: " + e.getMessage());
        }
    }

    private void handleRemoteService(RemoteConnectivityService service)
    {
        mRemoteService = service;
        mRemoteService.setDataListener(this);
        mRemoteService.setEventListener(this);
        try
        {
            mRemoteService.start(mConfig);
        }
        catch(FailedInitialisationException e)
        {
            failed("RemoteConnectivityService failed to initialise: " + e.getMessage());
        }
    }

    private void handleBluetoothEvent(Event event, Object arg)
    {
        switch(event)
        {
            case FAILED:
                // Bluetooth connection has closed, service has failed
                failed(arg == null ? "Unknown Bluetooth error!" : arg.toString());
                break;
            case STARTED:
                // Bluetooth connection established, send slave config
                mBluetoothService.write(mConfig);
                break;
            case STOPPING:
                // Bluetooth connection stopped
                if(mState != State.STOPPING)
                    stop();
                break;
            case SLAVE_READY:
                // Slave service has started correctly
                if(isAllStarted())
                    changeState(State.STARTED);
                break;
            case SLAVE_STOPPED:
                // Slave service is stopping correctly
                logd("Slave service stopping!");
                break;
        }
    }

    private void handleSelfEvent(Event event, Object arg)
    {
        String newText = null;
        int resId = R.drawable.ic_action_refresh_w;
        switch(event)
        {
            case STARTING:
                newText = "Starting...";
                break;
            case STARTED:
                newText = "Connected";
                break;
            case STOPPING:
                newText = "Stopped";
                break;
            case FAILED:
                String reason = arg == null ? "Unknown reason" : arg.toString();
                newText = "Failed: " + (arg == null ? "Unknown reason" : arg.toString());
                resId = R.drawable.ic_action_warning_w;
                break;
            case ACTION_START:
                newText = "Sensor sampling in progress";
                break;
            case ACTION_STOP:
                newText = "Sensor sampling paused";
                break;
        }
        if(newText != null)
        {
            mNotification = buildNotification(newText, resId);
            mNotificationMgr.notify(NOTIF_ID, mNotification);
        }
    }

    private void handleListenerEvent(Event event, Object arg)
    {
        switch(event)
        {
            case ACTION_START:
                startSampling();
                break;
            case ACTION_STOP:
                stopSampling();
                break;
        }
    }

    private Notification buildNotification(String newText, int iconResId)
    {
        Intent notifIntent = new Intent(this, MasterActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notifIntent, 0);

        Notification.Builder builder = new Notification.Builder(this)
                .setContentTitle(NOTIF_TITLE)
                .setContentText(newText)
                .setSmallIcon(iconResId)
                .setContentIntent(contentIntent);

        return builder.getNotification();
    }

    private void prepareDataPipeline()
    {
        // Slave pipeline from bluetooth to aggregation
        ArithmeticDataTransform timestampCorrector = new ArithmeticDataTransform(KEY_TIMESTAMP, mBluetoothService.getTimeOffset(), ArithmeticDataTransform.Operation.Subtract);
        FieldCopyDataTransform slaveTimestampCopy = new FieldCopyDataTransform(KEY_TIMESTAMP, KEY_TIMESTAMP_COPY);
        String[] timestampCopyField = { KEY_TIMESTAMP_COPY };
        FieldModifyDataTransform slavePrepend = new FieldModifyDataTransform(KEY_SLAVE_PACK, timestampCopyField, true, true);
        String[] timestampField = { KEY_TIMESTAMP };
        PackDataTransform slavePack = new PackDataTransform(KEY_SLAVE_PACK, timestampCopyField);
        FieldRenameDataTransform slaveTimestampRestore = new FieldRenameDataTransform(timestampCopyField, timestampField);

        // Create array splitters for master sensor data
        String[] sensorKeys = mConfig.get(SensorSampleService.CONFIG_SENSOR_KEYS);
        String[] splitKeys = { "X", "Y", "Z", "W" };
        DataTransform[] arraySplits = new DataTransform[sensorKeys.length];
        for(int i = 0; i < sensorKeys.length; ++i)
            arraySplits[i] = new ArraySplitDataTransform(sensorKeys[i], splitKeys, true);
        // Master pipeline from array splits to aggregation
        FieldCopyDataTransform masterTimestampCopy = new FieldCopyDataTransform(slaveTimestampCopy);
        FieldModifyDataTransform masterPrepend = new FieldModifyDataTransform(KEY_MASTER_PACK, timestampCopyField, true, true);
        PackDataTransform masterPack = new PackDataTransform(KEY_MASTER_PACK, timestampCopyField);
        FieldRenameDataTransform masterTimestampRestore = new FieldRenameDataTransform(slaveTimestampRestore);

        // Aggregator
        String[] aggregatorKeys = {KEY_SLAVE_PACK, KEY_MASTER_PACK};
        int intervalTime = 1000 / (Integer)mConfig.get(SensorSampleService.CONFIG_SAMPLE_RATE); // 1000ms divided by the sampleRate = intervalTime
        mAggregator = new IntervalAggregatorDataTransform(KEY_TIMESTAMP, intervalTime, mStartTime, aggregatorKeys);

        // Pipeline after aggregation until after data persistence
        UnpackDataTransform slaveUnpack = new UnpackDataTransform(KEY_SLAVE_PACK);
        UnpackDataTransform masterUnpack = new UnpackDataTransform(KEY_MASTER_PACK);
        SetDataTransform setSessionId = new SetDataTransform(KEY_SESSION, mSessionId);
        String[] masterFields = { "masterRotDataX", "masterRotDataY", "masterRotDataZ", "masterRotDataW"};
        String[] slaveFields = { "slaveRotDataX", "slaveRotDataY", "slaveRotDataZ", "slaveRotDataW" };
        String[] differenceFields = { "calcDiffOrientationX", "calcDiffOrientationY", "calcDiffOrientationZ", "calcDiffOrientationW"};

        QuaternionDifferenceDataTransform kneeAngle = new QuaternionDifferenceDataTransform(masterFields, slaveFields, differenceFields, KEY_ORIENTATION_DIFF);
        RemoveDataTransform removeSessionId = new RemoveDataTransform(KEY_SESSION);
        SetDataTransform setSessionId2 = new SetDataTransform(KEY_SESSION, mSessionId);
        mArrayCollector = new ArrayCollectDataTransform(mArrayCollectCount, KEY_ARRAY_COLLECT);
        SetDataTransform setUserId = new SetDataTransform(KEY_USER, mUserId);
        Data[] events = new Data[] { mEventData };
        SetDataTransform setEventData = new SetDataTransform(CONFIG_EVENT_DATA, events);
        // Create the broadcast data source
        mBroadcastSource = new BroadcastDataSource();

        // Thread and handler to handle data as soon as possible (using handler as 'source' - because why not)
        mSlaveToThreadHandler = new DataEventHandler(null, mThread.getLooper());
        mMasterToThreadHandler = new DataEventHandler(null, mThread.getLooper());
        // Handler to allow data to return to UI thread at completion of pipeline
        mPersistFromThreadHandler = new DataEventHandler(null, getMainLooper());
        mRemoteFromThreadHandler = new DataEventHandler(null, getMainLooper());

        // Set the pipeline - slave until aggregator
        mBluetoothService.setDataListener(mSlaveToThreadHandler);
        mSlaveToThreadHandler.setDataListener(timestampCorrector);
        DataTransform.pipeline(timestampCorrector, slaveTimestampCopy, slavePrepend, slavePack, slaveTimestampRestore, mAggregator);

        // Master until aggregator
        mSensorService.setDataListener(mMasterToThreadHandler);
        mMasterToThreadHandler.setDataListener(arraySplits[0]);
        DataTransform.pipeline(arraySplits);
        DataTransform.pipeline(arraySplits[arraySplits.length-1], masterTimestampCopy, masterPrepend, masterPack, masterTimestampRestore, mAggregator);

        // Aggregator to broadcast to master (via handler attached back to main thread)
        DataTransform.pipeline(mAggregator, slaveUnpack, masterUnpack, setSessionId, kneeAngle);
        kneeAngle.setDataListener(mDataStoreService);
        mDataStoreService.setDataListener(mBroadcastSource);
        mBroadcastSource.setDataListener(mPersistFromThreadHandler);
        // Broadcast to master via remoteService
        mBroadcastSource.setDataListener(removeSessionId);
        DataTransform.pipeline(removeSessionId, mArrayCollector, setSessionId2, setUserId, setEventData);
        setEventData.setDataListener(mRemoteService);
        mRemoteService.setDataListener(mRemoteFromThreadHandler);

        mPersistFromThreadHandler.setDataListener(this);
        mRemoteFromThreadHandler.setDataListener(this);
    }

    private boolean isAllStarted()
    {
        boolean sensorStarted = mSensorService != null && mSensorService.getState() == State.STARTED;
        boolean remoteStarted = mRemoteService != null && mRemoteService.getState() == State.STARTED;
        boolean dataStoreStarted = mDataStoreService != null && mDataStoreService.getState() == State.STARTED;
        boolean bluetoothStarted = mBluetoothService != null && mBluetoothService.getState() == State.STARTED;
        return sensorStarted && remoteStarted && dataStoreStarted && bluetoothStarted;
    }
}




Java Source Code List

com.example.DataCaptureApp.AdvConfigActivity.java
com.example.DataCaptureApp.ConfigActivity.java
com.example.DataCaptureApp.MasterActivity.java
com.example.DataCaptureApp.MasterService.java
com.example.DataCaptureApp.SlaveActivity.java
com.example.DataCaptureApp.SlaveService.java
com.example.DataCaptureApp.data.DataServiceConnection.java
com.example.DataCaptureApp.data.DataService.java
com.example.DataCaptureApp.data.DataTransform.java
com.example.DataCaptureApp.data.Data.java
com.example.DataCaptureApp.data.Event.java
com.example.DataCaptureApp.data.FailedInitialisationException.java
com.example.DataCaptureApp.data.IDataEventListener.java
com.example.DataCaptureApp.data.IDataListener.java
com.example.DataCaptureApp.data.IDataSource.java
com.example.DataCaptureApp.data.IDataTransform.java
com.example.DataCaptureApp.data.IEventListener.java
com.example.DataCaptureApp.data.IEventSource.java
com.example.DataCaptureApp.services.BluetoothConnectivityService.java
com.example.DataCaptureApp.services.BluetoothThread.java
com.example.DataCaptureApp.services.DataDbContract.java
com.example.DataCaptureApp.services.DataDbHelper.java
com.example.DataCaptureApp.services.DataStoreService.java
com.example.DataCaptureApp.services.HttpThread.java
com.example.DataCaptureApp.services.RemoteConnectivityService.java
com.example.DataCaptureApp.services.SensorSampleService.java
com.example.DataCaptureApp.services.SensorSampler.java
com.example.DataCaptureApp.testing.BluetoothActivity.java
com.example.DataCaptureApp.testing.DataStoreActivity.java
com.example.DataCaptureApp.testing.DataTester.java
com.example.DataCaptureApp.testing.IServiceListener.java
com.example.DataCaptureApp.testing.MainService.java
com.example.DataCaptureApp.testing.MasterTestActivity.java
com.example.DataCaptureApp.testing.RandomService.java
com.example.DataCaptureApp.testing.RemoteActivity.java
com.example.DataCaptureApp.testing.SensorSampleActivity.java
com.example.DataCaptureApp.testing.ServiceTestActivity.java
com.example.DataCaptureApp.testing.SlaveTestActivity.java
com.example.DataCaptureApp.testing.TestActivity.java
com.example.DataCaptureApp.transforms.AggregatorDataTransform.java
com.example.DataCaptureApp.transforms.ArithmeticDataTransform.java
com.example.DataCaptureApp.transforms.ArrayCollectDataTransform.java
com.example.DataCaptureApp.transforms.ArraySplitDataTransform.java
com.example.DataCaptureApp.transforms.DeserialiseDataTransform.java
com.example.DataCaptureApp.transforms.FieldCopyDataTransform.java
com.example.DataCaptureApp.transforms.FieldModifyDataTransform.java
com.example.DataCaptureApp.transforms.FieldRenameDataTransform.java
com.example.DataCaptureApp.transforms.IntervalAggregatorDataTransform.java
com.example.DataCaptureApp.transforms.PackDataTransform.java
com.example.DataCaptureApp.transforms.QuaternionDifferenceDataTransform.java
com.example.DataCaptureApp.transforms.RemoveDataTransform.java
com.example.DataCaptureApp.transforms.SetDataTransform.java
com.example.DataCaptureApp.transforms.UnpackDataTransform.java
com.example.DataCaptureApp.utils.BroadcastDataSource.java
com.example.DataCaptureApp.utils.ByteUtils.java
com.example.DataCaptureApp.utils.DataEventHandler.java
com.example.DataCaptureApp.utils.DataHandlerThread.java
com.example.DataCaptureApp.utils.JSONReader.java
com.example.DataCaptureApp.utils.Quaternion.java
com.example.DataCaptureApp.utils.SerialisationUtils.java