Connecting to the IOIO via Bluetooth

According to the official documentation,the IOIO can be connected to an android device (api level 7+) via a Bluetooth dongle since Bootloader V3.0 + App V3.10. After reading this is decided to buy a Bluetooth dongle. As soon as I received it, I quickly thumbed though the documentation again and found that I only needed to add the Bluetooth permission. So I updated my IOIO Truck project, and pushed it to the android device. At this point all I had to do is pair IOIO to the android device, and start the IOIO Truck application. Once started, I discovered that it wasn’t connecting! So I started investigating…

I quickly learned that the IOIOThread can only handle one type of connection (per thread). So this means that you need 2 IOIOThreads if you wan to connect via USB and Bluetooth. After reading more of the documentation, I noticed that if I used AbstractIOIOActivty, I would not of had a problem. AbstractIOIOActivity maintains a collection of threads that maintain the different connections.

Since my application uses the android compatibility library and map views, I could not simply extend AbstractIOIOActivity. So I decided to Create my own IOIOManager class based off of AbstractIOIOActivity and slightly modify my existing IOIOThread class.

/**
 * IOIOManager.java
 * @date Jan 21, 2012
 * @author ricky barrette
 * @author Twenty Codes, LLC
 * 
 * Copyright 2012 Richard Barrette
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *		http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.TwentyCodes.android.ioio;

import ioio.lib.bluetooth.BluetoothIOIOConnectionDiscovery;
import ioio.lib.util.IOIOConnectionDiscovery;
import ioio.lib.util.SocketIOIOConnectionDiscovery;
import ioio.lib.util.IOIOConnectionDiscovery.IOIOConnectionSpec;

import java.util.Collection;
import java.util.LinkedList;

import android.util.Log;

/**
 * This class manages the IOIO connectivity threads. It is based on the AbstractIOIOActivity
 * Remember that onConnected(), loop(), and onDisconnected() are called from the one of the IOIO threads
 * @author ricky barrette
 */
public abstract class IOIOManager implements IOIOListener{

	private static final String TAG = "IOIOManager";
	private Collection mThreads = new LinkedList();

	/**
	 * Aborts the IOIO connectivity threads and joins them
	 * @throws InterruptedException
	 * @author ricky barrette
	 */
	public void abort() throws InterruptedException {
		for (IOIOThread thread : mThreads)
			thread.abort();
		joinAllThreads();
	}

	/**
	 * Joins all the threads
	 * @throws InterruptedException
	 * @author ricky barrette
	 */
	private void joinAllThreads() throws InterruptedException {
		for (IOIOThread thread : mThreads)
			thread.join();
	}

	/**
	 * Creates all the required IOIO connectivity threads
	 * @author ricky barrette
	 */
	private void createAllThreads() {
		mThreads.clear();
		Collection specs = getConnectionSpecs();
		for (IOIOConnectionSpec spec : specs)
			mThreads.add(new IOIOThread(spec.className, spec.args, this));
	}

	/**
	 * Starts IOIO connectivity threads
	 * @author ricky barrette
	 */
	public void start() {
		createAllThreads();
		for (IOIOThread thread : mThreads)
			thread.start();
	}

	/**
	 * @return
	 * @author Ytai Ben-Tsvi
	 */
	private Collection getConnectionSpecs() {
		Collection result = new LinkedList();
		addConnectionSpecs(SocketIOIOConnectionDiscovery.class.getName(),result);
		addConnectionSpecs(BluetoothIOIOConnectionDiscovery.class.getName(), result);
		return result;
	}

	/**
	 * @param discoveryClassName
	 * @param result
	 * @author Ytai Ben-Tsvi
	 */
	private void addConnectionSpecs(String discoveryClassName, Collection result) {
		try {
			Class< ?> cls = Class.forName(discoveryClassName);
			IOIOConnectionDiscovery discovery = (IOIOConnectionDiscovery) cls.newInstance();
			discovery.getSpecs(result);
		} catch (ClassNotFoundException e) {
			Log.d(TAG, "Discovery class not found: " + discoveryClassName+ ". Not adding.");
		} catch (Exception e) {
			Log.w(TAG,"Exception caught while discovering connections - not adding connections of class "+ discoveryClassName, e);
		}
	}
	
	/**
	 * @param isStatLedEnabled the isStatLedEnabled to set
	 * @author ricky barrette
	 */
	public void setStatLedEnabled(boolean isStatLedEnabled) {
		for(IOIOThread thread : mThreads)
			thread.setStatLedEnabled(isStatLedEnabled);
	}

	/**
	 * Sets the update interval of the IOIO thread
	 * @param ms
	 * @author ricky barrette
	 */
	public void setUpdateInverval(long ms){
		for(IOIOThread thread : mThreads)
			thread.setUpdateInverval(ms);
	}

}

Using the IOIOManager is simple, You just need to create an object that extends it, then you can manage it just like you would a single IOIO Thread.

Here is an example clip from my Test Activity

/**
 * Called when the application is paused. We want to disconnect with the
 * IOIO at this point, as the user is no longer interacting with our
 * application.
 */
@Override
protected void onPause() {
	try {
		mIOIOManager.abort();
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	super.onPause();
}

/**
 * Called when the application is being resumed
 * We want to create a new IOIOManager and start it
 */
@Override
protected void onResume() {
	super.onResume();
	mIOIOManager = new IOIOTruckManager();
	mIOIOManager.start();
}

Here is a quick video demonstrating my test

All code is available here

Leave a Reply