nrec.basil.wimuconsole.SensorSettingsActivity.java Source code

Java tutorial

Introduction

Here is the source code for nrec.basil.wimuconsole.SensorSettingsActivity.java

Source

/**********************************************************************************
 *  The MIT License (MIT)                                                        *
 *                                                                                *
 *  Copyright (c) 2014 Carnegie Mellon University                                 *
 *                                                                                *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy  *
 *  of this software and associated documentation files (the "Software"), to deal *
 *  in the Software without restriction, including without limitation the rights  *
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell     *
 *  copies of the Software, and to permit persons to whom the Software is         *
 *  furnished to do so, subject to the following conditions:                      *
 *                                                                                *
 *  The above copyright notice and this permission notice shall be included in    *
 *  all copies or substantial portions of the Software.                           *
 *                                                                                *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR    *
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,      *
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE   *
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER        *
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN     *
 *  THE SOFTWARE.                                                                 *
 **********************************************************************************/
/**
 * @file   SensorSettingsActivity.java
 * @brief  Activity to modify bluetooth IMU settings
 * @author M. George
 */
package nrec.basil.wimuconsole;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.DecimalFormat;
import java.util.Arrays;

import nrec.basil.wimuconsole.BluetoothService;
import nrec.basil.wimuconsole.R;

import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;

public class SensorSettingsActivity extends FragmentActivity implements ActionBar.OnNavigationListener {
    /***************************************/
    /***    APPLICATION LEVEL SETTINGS   ***/
    /***************************************/
    private static final String TAG = "wImuConsole-SensorSettings";
    private static final boolean D = true;
    // Key for saving and restoring the action bar dropdown
    private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";

    /***************************************/
    /***        BLUETOOTH SETTINGS       ***/
    /***************************************/
    // Bluetooth adapter, services and settings
    private BluetoothAdapter mBluetoothAdapter = null;
    public static BluetoothService mBluetoothService = null;
    private String mConnectedDeviceName = null;

    // Key values for bluetooth message passing
    public static final String DEVICE_NAME = "device_name";
    public static final String TOAST = "toast";

    // Bluetooth thread handler message IDs
    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_TOAST = 5;

    // List of IMUs that can be connected to
    Spinner imuSpinner;
    private String wImuMacAddress = null;

    // Intent request codes
    private static final int REQUEST_ENABLE_BT = 3;

    /***************************************/
    /***         BASIL SETTINGS          ***/
    /***************************************/
    private static final byte[] basilStart = new byte[26];
    private static final byte[] basilStop = new byte[26];
    private static final byte[] basilReset = new byte[26];

    public static double mCurrentLatitude = 0.0;
    public static double mCurrentLongitude = 0.0;

    public boolean mLoggingOn = false;
    public String mLogFileName = null;

    /***************************************/
    /***            CONSTANTS            ***/
    /***************************************/
    private static final double R2D = 180.0 / 3.141519;
    private static final double D2R = 1.0 / R2D;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sensor_settings);

        // Set up the action bar to show a dropdown list which will
        // contain the various sensors that can be configured.  Some
        // sensors are local (camera) some are remote bluetooth devices
        // (IMU, Barometer etc.)
        final ActionBar actionBar = getActionBar();
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

        // Set up the dropdown list navigation in the action bar.
        actionBar.setListNavigationCallbacks(
                // Specify a SpinnerAdapter to populate the dropdown list.
                new ArrayAdapter<String>(actionBar.getThemedContext(), android.R.layout.simple_list_item_1,
                        android.R.id.text1, getResources().getStringArray(R.array.sensors_list)),
                this);

        // Specify a SpinnerAdapter to populate the wIMU list
        ArrayAdapter<CharSequence> imuAdapter = ArrayAdapter.createFromResource(this, R.array.wimu_list,
                android.R.layout.simple_spinner_item);
        imuAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        imuSpinner = (Spinner) findViewById(R.id.wimulist);
        imuSpinner.setAdapter(imuAdapter);

        // Load the BASIL start/stop/reset commands
        InputStream input = getResources().openRawResource(R.raw.basilstart);
        try {
            input.read(basilStart, 0, 26);
        } catch (IOException e) {
            Log.e(TAG, "Could not read BASIL start command", e);
        }
        input = getResources().openRawResource(R.raw.basilstop);
        try {
            input.read(basilStop, 0, 26);
        } catch (IOException e) {
            Log.e(TAG, "Could not read BASIL stop command", e);
        }
        input = getResources().openRawResource(R.raw.basilreset);
        try {
            input.read(basilReset, 0, 26);
        } catch (IOException e) {
            Log.e(TAG, "Could not read BASIL reset command", e);
        }

        // Get the default filename for logging
        EditText logfilename = (EditText) findViewById(R.id.logfilename);
        mLogFileName = logfilename.toString();

        // Get local Bluetooth adapter
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // If the adapter is null, then Bluetooth is not supported
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        if (D)
            Log.e(TAG, "++ ON START ++");
        // Nothing to do here for the moment
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        case REQUEST_ENABLE_BT:
            // When the request to enable Bluetooth returns
            if (resultCode == Activity.RESULT_OK) {
                mBluetoothService = new BluetoothService(this, mHandler);
            } else {
                // User did not enable Bluetooth or an error occurred
                Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
                finish();
            }
        }
    }

    // Send a BASIL start message to the connected IMU
    public void connectToImu(View view) {
        // If BT is not on, request that it be enabled.
        // setupChat() will then be called during onActivityResult
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
            return;
        } else {
            if (mBluetoothService == null) {
                // Initialize the BluetoothChatService to perform bluetooth connections
                mBluetoothService = new BluetoothService(this, mHandler);
            }
        }

        // Get the IMU MAC address from our list
        String address = imuSpinner.getSelectedItem().toString();
        // Get the BluetoothDevice object
        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        // Attempt to connect to the device
        mBluetoothService.connect(device, false);
    }

    // Send a BASIL start message to the connected IMU
    public void sendBasilStartMsg(View view) {
        // Check that we're actually connected before trying anything
        if (mBluetoothService.getState() != BluetoothService.STATE_CONNECTED) {
            Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
            return;
        }

        // Check that there's actually something to send
        if (basilStart.length > 0) {
            // Get the message bytes and tell the BluetoothChatService to write
            mBluetoothService.write(basilStart);
        }
    }

    // Send a BASIL stop message to the connected IMU
    public void sendBasilStopMsg(View view) {
        // Check that we're actually connected before trying anything
        if (mBluetoothService.getState() != BluetoothService.STATE_CONNECTED) {
            Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
            return;
        }

        // Check that there's actually something to send
        if (basilStop.length > 0) {
            if (D)
                Log.d(TAG, "Sending BASIL Stop");
            // Get the message bytes and tell the BluetoothChatService to write
            mBluetoothService.write(basilStop);
        }
    }

    // Send a BASIL reset message to the connected IMU
    public void sendBasilResetMsg(View view) {
        // Check that we're actually connected before trying anything
        if (mBluetoothService.getState() != BluetoothService.STATE_CONNECTED) {
            Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
            return;
        }

        // Check that there's actually something to send
        if (basilReset.length > 0) {
            // Get the message bytes and tell the BluetoothChatService to write
            mBluetoothService.write(basilReset);
        }
    }

    // Start or stop logging data
    public void toggleLogging(View view) {
        // Check that we're actually connected before trying anything
        if (mBluetoothService.getState() != BluetoothService.STATE_CONNECTED) {
            Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
            return;
        }
        if (mLoggingOn == false) {
            mLoggingOn = true;
            // Set the filename with current name field
            EditText logfilename = (EditText) findViewById(R.id.logfilename);
            mLogFileName = logfilename.getText().toString();

            mBluetoothService.startLogging(mLogFileName);

            // Change the button to "Stop"
            Button b = (Button) findViewById(R.id.logbutton);
            b.setText("Stop");
        } else {
            mLoggingOn = false;
            mBluetoothService.stopLogging();
            // Display INS data
            Button b = (Button) findViewById(R.id.logbutton);
            b.setText("Start");
        }
    }

    // The Handler that gets information back from the BluetoothChatService
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_STATE_CHANGE:
                if (D)
                    Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                switch (msg.arg1) {
                case BluetoothService.STATE_CONNECTED:
                    //setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
                    //mConversationArrayAdapter.clear();
                    break;
                case BluetoothService.STATE_CONNECTING:
                    //setStatus(R.string.title_connecting);
                    break;
                case BluetoothService.STATE_LISTEN:
                case BluetoothService.STATE_NONE:
                    //setStatus(R.string.title_not_connected);
                    break;
                }
                break;
            case MESSAGE_WRITE:
                byte[] writeBuf = (byte[]) msg.obj;
                // construct a string from the buffer
                //String writeMessage = new String(writeBuf);
                //if (D) Log.d(TAG, writeMessage);
                //TextView t = (TextView)findViewById(R.id.bufferdump);
                //t.setText(writeMessage);
                //mConversationArrayAdapter.add("Me:  " + writeMessage);
                break;
            case MESSAGE_READ:
                byte[] readBuf = (byte[]) msg.obj;
                if (D)
                    Log.d(TAG, "Message Buffer: " + msg.arg1);
                byte[] ins = new byte[101];
                ins = Arrays.copyOf(readBuf, msg.arg1);
                // construct a string from the valid bytes in the buffer
                displayInsData(ins);
                //String readMessage = new String(readBuf, 0, msg.arg1);
                //TextView t = (TextView)findViewById(R.id.bufferdump);
                //t.setText(readMessage);
                //mConversationArrayAdapter.add(mConnectedDeviceName+":  " + readMessage);
                break;
            case MESSAGE_DEVICE_NAME:
                // save the connected device's name
                mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
                Toast.makeText(getApplicationContext(), "Connected to " + mConnectedDeviceName, Toast.LENGTH_SHORT)
                        .show();
                break;
            case MESSAGE_TOAST:
                Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show();
                break;
            }
        }
    };

    private void displayInsData(byte[] ins) {
        TextView t;
        DecimalFormat form = new DecimalFormat("##0.00");
        ByteBuffer insbuffer = ByteBuffer.wrap(ins);
        insbuffer.order(ByteOrder.LITTLE_ENDIAN);
        // Display INS data
        t = (TextView) findViewById(R.id.statusreport);
        String status = null;
        byte stat = insbuffer.get(22);
        if (D)
            Log.d(TAG, "INS Status: " + stat);
        switch (stat) {
        case 0:
            status = "Calibrating";
            break;
        case 1:
            status = "Aligning";
            break;
        case 2:
            status = "Navigating";
            break;
        case 3:
            status = "Invalid Data";
            break;
        case 4:
            status = "Stopped";
            break;
        }
        t.setText(status);

        t = (TextView) findViewById(R.id.solutionreport);
        String solution = null;
        solution = String.format("%8s", Integer.toBinaryString(insbuffer.get(23) & 0xFF)).replace(' ', '0');
        t.setText(solution);

        t = (TextView) findViewById(R.id.px);
        mCurrentLatitude = insbuffer.getDouble(25);
        t.setText(form.format(insbuffer.getDouble(25)));
        t = (TextView) findViewById(R.id.py);
        mCurrentLongitude = insbuffer.getDouble(33);
        t.setText(form.format(insbuffer.getDouble(33)));
        t = (TextView) findViewById(R.id.pz);
        t.setText(form.format(insbuffer.getDouble(41)));
        t = (TextView) findViewById(R.id.vx);
        t.setText(form.format(insbuffer.getDouble(49)));
        t = (TextView) findViewById(R.id.vy);
        t.setText(form.format(insbuffer.getDouble(57)));
        t = (TextView) findViewById(R.id.vz);
        t.setText(form.format(insbuffer.getDouble(65)));
        t = (TextView) findViewById(R.id.ox);
        t.setText(form.format(insbuffer.getDouble(73) * R2D));
        t = (TextView) findViewById(R.id.oy);
        t.setText(form.format(insbuffer.getDouble(81) * R2D));
        t = (TextView) findViewById(R.id.oz);
        t.setText(form.format(insbuffer.getDouble(89) * R2D));
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        // Restore the previously serialized current dropdown position.
        if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
            getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        // Serialize the current dropdown position.
        outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar().getSelectedNavigationIndex());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.sensor_settings, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.actionbar_map_view:
            startActivity(new Intent(this, MapActivity.class));
            break;
        case R.id.actionbar_camera_settings:
            startActivity(new Intent(this, CameraActivity.class));
            break;
        default:
            break;
        }

        return true;
    }

    @Override
    public boolean onNavigationItemSelected(int position, long id) {
        // When the given dropdown item is selected, show its contents in the
        // container view.
        //if (position == 0){
        //    startActivity(new Intent(this, MainActivity.class));
        //}
        //else{
        //    startActivity(new Intent(this, MapActivity.class));
        //}
        //Fragment fragment = new DummySectionFragment();
        //Bundle args = new Bundle();
        //args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
        //fragment.setArguments(args);
        //getSupportFragmentManager().beginTransaction()
        //        .replace(R.id.container, fragment).commit();
        return true;
    }

    /**
     * A dummy fragment representing a section of the app, but that simply
     * displays dummy text.
     */
    public static class DummySectionFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        public static final String ARG_SECTION_NUMBER = "section_number";

        public DummySectionFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_ins_settings, container, false);
            TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label);
            dummyTextView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
            return rootView;
        }
    }

}