Blame | Last modification | View Log | Download | RSS feed
package IEEERobotics.IOIOAI.VT;import ioio.lib.api.IOIO;import ioio.lib.api.IOIOFactory;import ioio.lib.api.exception.ConnectionLostException;import ioio.lib.api.exception.IncompatibilityException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.LinkedList;import java.util.List;import com.viewpagerindicator.TitlePageIndicator;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.preference.PreferenceManager;import android.support.v4.view.ViewPager;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.LinearLayout;import android.widget.ProgressBar;import android.widget.ScrollView;import android.widget.TextView;import android.widget.TableRow.LayoutParams;public class IOIORoboticsActivity extends Activity {// Static IOIO instance so other activities can access itpublic static IOIO IOIOInstance_;public static Context context_;public static List<String> subTitles_ = new LinkedList<String>();public static List<View> subViews_ = new LinkedList<View>();// Connection and activity related variablesprivate static Boolean _connected = false;private static Handler _handler = new Handler();private Boolean _connectionReset = true;private Thread _connectionMonitor;private TextView _statusText;private ProgressBar _statusProgressBar;private LinearLayout _logLayout;private ViewPagerAdapter _pageAdapter;private ViewPager _pager;private TitlePageIndicator _pageIndicator;// Debugging stuffprivate Boolean _debugMode;private DebugCode _debuggingCode;// AI stuffprivate AICode _AICode;// Motor Control classprivate MotorControl _motorControl;// Item ID for custom menu itemsprivate static int menuToggleDebugMonitoring = Menu.FIRST;private static int menuOpenSettings = Menu.FIRST+1;private static int menuReset = Menu.FIRST+2;private static int menuClearLog = Menu.FIRST+3;private static int _connectionCheckInterval = 500; // in ms// /** Called when the menu button is first pressed (creates the blank menu) */// @Override// public boolean onCreateOptionsMenu(Menu menu) {// MenuInflater inflater = getMenuInflater();// // Inflate a blank menu as we will populate it ourselves// inflater.inflate(R.menu.mainmenu, menu);// return true;// }/** Called when the menu button is pressed, populates the menu with options */@Overridepublic boolean onPrepareOptionsMenu(Menu menu) {// Clear existing menus and create a new one based on current statemenu.clear();if (_debugMode)menu.add(0, menuToggleDebugMonitoring, 0, "Turn On Robotics AI");elsemenu.add(0, menuToggleDebugMonitoring, 0, "Turn On Debug Mode");if (_connected)menu.add(0, menuReset, 0, "Reset IOIO Board");elsemenu.add(0, menuReset, 0, "Remove Debug Tabs");menu.add(0, menuClearLog, 0, "Clear Logs");menu.add(0, menuOpenSettings, 0, "Settings");return super.onPrepareOptionsMenu(menu);}/** Handles what to do when a menu item is selected */@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// // Disable certain menu options if IOIO board is not connected// if (item.getItemId() == menuReset &&// !_connected) {// Toast.makeText(this, "IOIO board not connected", Toast.LENGTH_SHORT).show();// return true;// };// Otherwise handle menu selectionsif (item.getItemId() == menuToggleDebugMonitoring) {if (_debugMode) {_debugMode = false;logMessage("Operating mode changed to AI");if (_connected)hardReset();} else {_debugMode = true;logMessage("Operating mode changed to Debug");if (_connected)hardReset();}return true;} else if (item.getItemId() == menuOpenSettings) {startActivity(new Intent(this, GlobalPreferenceActivity.class));return true;} else if (item.getItemId() == menuReset) {if (_connected)hardReset();else {if (_debuggingCode != null) {removeDebugView();}}return true;} else if (item.getItemId() == menuClearLog) {_logLayout.removeAllViews();return true;} else {return super.onOptionsItemSelected(item);}}/** Called when the application is started */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);// Grab the local context so other classes can use it to create viewscontext_ = this.getApplicationContext();// Get local pointers to views_pageAdapter = new ViewPagerAdapter(this);_pager = (ViewPager)findViewById(R.id.viewpager);_pageIndicator = (TitlePageIndicator)findViewById(R.id.indicator);_statusText = (TextView)findViewById(R.id.statusText);_statusProgressBar = (ProgressBar)findViewById(R.id.progressBar);_pager.setAdapter(_pageAdapter);_pageIndicator.setViewPager(_pager);createLogView();// Get default/saved debug modeif (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("pref_StartInDebug", true))_debugMode = true;else_debugMode = false;// Print out current debug statusif (_debugMode)logMessage("Debug mode is currently on");elselogMessage("Debug mode is currently off");// Start connection monitoring thread for the IOIO boardconnectToIOIOBoard();}/** Called when the application is stopped */@Overridepublic void onDestroy() {super.onDestroy();connectionReset();if (_debuggingCode != null) {removeDebugView();}_connectionMonitor.interrupt();IOIOInstance_.disconnect();_connected = false;}/** Starts the thread that monitors the connection to the IOIO board */private void connectToIOIOBoard() {// Create a new thread to monitor the connection status to the IOIO board_connectionMonitor = new Thread(new Runnable() {@Overridepublic void run() {while (true) {try {// Check if a new instance of IOIO needs to be created// Reset is only triggered when a disconnect happensif (_connectionReset) {updateStatus("Waiting to connect to the IOIO board...");toggleProgressOn();IOIOInstance_ = IOIOFactory.create();_connectionReset = false;}// Check if thread should keep runningif (Thread.currentThread().isInterrupted()) {break;}// Attempt to connect to the IOIO board// If the board was disconnected, ConnectionLostException is thrown while waitingIOIOInstance_.waitForConnect();// Do stuff when the first connection to the board is madeif (!_connected) {updateStatus("Connected to the IOIO board");Thread.sleep(200);connectionSuccess();}_connected = true;toggleProgressOff();Thread.sleep(_connectionCheckInterval);} catch (ConnectionLostException e) {// Reset the connection so reconnection attempts can be made_connected = false;_connectionReset = true;connectionReset();updateStatus("Connection to the IOIO board has be lost");} catch (IncompatibilityException e) {// Throw error and quit_connected = false;_connectionReset = true;connectionReset();updateStatus("Connected IOIO board is incompatible");} catch (InterruptedException e) {break;}}}});_connectionMonitor.start();}/** Called when the connection to the IOIO board succeeds */private void connectionSuccess() {_handler.post(new Runnable() {@Overridepublic void run() {// If debug mode is enabled, run the debug code to create graphsif (_debugMode) {startDebugMode();} else {startAIMode();}}});}/** Called when the connection to the IOIO board has been reset */private void connectionReset() {_handler.post(new Runnable() {@Overridepublic void run() {// If the debugger code was running, stop the updating threadif (_debuggingCode != null)_debuggingCode.stopPollingThread();if (_AICode != null)_AICode.stopPollingThread();if (_motorControl != null) {_motorControl.disconnect();}}});}/** Creates the first layout for the ViewPager */private void createLogView() {if (subTitles_.contains("Logger")) {removeView(subViews_.get(subTitles_.indexOf("Logger")));subTitles_.remove("Logger");}_logLayout = new LinearLayout(this);_logLayout.setOrientation(LinearLayout.VERTICAL);_logLayout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));ScrollView scroller = new ScrollView(this);scroller.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));scroller.addView(_logLayout);addView("Logger", scroller);}/** Creates a new page in the ViewPager */private void addView(String name, View view) {// Add the view and label to the listssubTitles_.add(subTitles_.size(), name);subViews_.add(subViews_.size(), view);// Update the screen with the new views_pageAdapter.notifyDataSetChanged();_pageIndicator.notifyDataSetChanged();}/** Removes a page in the ViewPager */private void removeView(View view) {if (subViews_.contains(view)) {// Change the main view to the first one (logger)_pager.setCurrentItem(0);// Remove the view and label from the listssubTitles_.remove(subViews_.indexOf(view));subViews_.remove(view);// Update the screen with the new views_pageAdapter.notifyDataSetChanged();_pageIndicator.notifyDataSetChanged();}}/** Start point for code to execute in Debug Mode */private void startDebugMode() {// Run debug code to create graphslogMessage("Executing Debug Mode");// On first run, create inputs and viewsif (_debuggingCode == null) {_debuggingCode = new DebugCode(this);addView("Graphs", _debuggingCode.getView());}if (_motorControl == null) {_motorControl = new MotorControl(this);addView("Motor", _motorControl.getDebugView());}_debuggingCode.Run();// _motorControl.Run();}/** Call to stop the debug code and remove all associated views */private void removeDebugView() {removeView(_debuggingCode.getView());removeView(_motorControl.getDebugView());if (_debuggingCode != null) {// _debuggingCode.stopPollingThread();_debuggingCode = null;}if (_motorControl != null) {_motorControl = null;}}/** Start point for code to execut`e in AI Mode */private void startAIMode() {// Remove the debug views if they existif (_debuggingCode != null) {removeDebugView();}logMessage("Executing AI Mode");_AICode = new AICode(this);_AICode.Run();}/*** A hard reset is exactly like physically powering off the IOIO* board and powering it back on. As a result, the connection* with the IOIO will drop and the IOIO instance will become* disconnected and unusable. The board will perform a full reboot,* including going through the bootloader sequence, i.e. an attempt* to update the board's firmware will be made.*/private void hardReset() {try {IOIOInstance_.hardReset();} catch (ConnectionLostException e) {_connected = false;_connectionReset = true;connectionReset();updateStatus("Hard reset executed on the IOIO board");}}/** Sets the status TextView to the provided message */private void updateStatus(final String message) {_handler.post(new Runnable() {@Overridepublic void run() {logMessage(message);_statusText.setText("Status: " + message);}});}/** Appends the provided message to the beginning of the log TextView */public void logMessage(final String message) {_handler.post(new Runnable() {@Overridepublic void run() {// Get the current timeSimpleDateFormat dateFormat = new SimpleDateFormat("[HH:mm:ss]");Date now = new Date();String currentTime = dateFormat.format(now);// Log message with the current time appended to the frontString msg = currentTime + " " + message;TextView tv = new TextView(context_);tv.setText(msg);_logLayout.addView(tv,0);}});}/** Returns the current connection state */public Boolean getConnected() {return _connected;}/** Toggles the visibility of the status ProgressBar */private void toggleProgressOn() {_handler.post(new Runnable() {@Overridepublic void run() {_statusProgressBar.setVisibility(View.VISIBLE);}});}/** Toggles the visibility of the status ProgressBar */private void toggleProgressOff() {_handler.post(new Runnable() {@Overridepublic void run() {_statusProgressBar.setVisibility(View.GONE);}});}}