IOIOLib Application Framework

Ytai Ben-Tsvi edited this page Aug 20, 2015 · 6 revisions

IOIOLib Application Framework

This page will introduce you to some basic concepts of authoring IOIO-based applications, using the utilities provided with the IOIO Java-based software bundle. Regardless of wether you are developing Android applications or PC applications, the IOIOLib Core API is exactly the same and the provided application frameworks share many of the concepts and code. We will cover only the application frameworks here.

##Life-Cycle of a IOIO Connection and the IOIOLooper Interface

Whenever a IOIO application starts, the application framework will determine all the possible connections to IOIO boards. These can be all the IOIO boards that are paired over Bluetooth, certain USB-based connections that can potentially be used, etc. The specifics are platform-dependent. For each such possible connection, the framework will callback a client-provided createLooper() method, through which the client will typically (but not necessarily) interact with the IOIO board. The client may reject a certain possible connection by returning null from this method. The IOIOLooper is a simple interface that allows the client to be notified when a IOIO connection has been established or closed and be provided with context for execution of IOIO-related code outside of the application's main execution context.

For each such a IOIOLooper returned by the client, the framework will create a dedicated thread, on which the looper methods will be invoked. This thread will have roughly the following logic:

  • Wait for a IOIO connection to get established.

  • Check that the firmware version running on the IOIO is compatible with the IOIOLib version we are running.

  • If compatible:

    • Call the setup() method of the IOIOLooper, providing it with an instance of a IOIO interface for working with the IOIO during this connection lifetime. From this method, the client will typically open I/O pins and do any per-connection initialization.
    • Repeatedly call the loop() method of the IOIOLooper. From this method the client will typically execute any ongoing IOIO-related tasks.
  • If not compatible:

    • Call the incompatible() method of the IOIOLooper. From this method the client can report the user of the problem.
  • As soon as the IOIO connection is dropped, as result of a physical disconnection or of exiting the application, call the disconnected() method. The IOIO instance is no longer usable from this method. The framework will also call interrupt() on the thread, which the client can use to abort any non-IOIO blocking operations (as the IOIO blocking operations will throw an exception on disconnection anyway).

For convenience, the BaseIOIOLooper class can be extended, which provides default no-op implementations of all the methods, as well as defines a ioio_ field which will hold the IOIO instance, as soon as setup() is executed.

Note that the IOIO API is completely thread-safe, so the client is not constrained to perform all interaction with the IOIO-derived interfaces through the IOIOLooper. It is perfectly valid to share the ioio_ instance, or any interfaces created from it, with another thread to use.

The setup() and loop() methods are allowed to throw a ConnectionLostException and an InterruptedException (as well as any runtime exceptions). Throwing any exception from that will cause the IOIO connection to drop and a reconnection attempt will be made immediately.

The following sections of this page will describe how to create different kinds of IOIO-based applications on different platforms.

##Creating IOIO-Based Applications on Android

This explanation assumes your development environment is setup for developing Android applications and that you have basic familiarity with Android development tools and techniques. If this is not the case, [http://developer.android.com](the Android developer site) has great tutorials and instructions to get you started.

###Available IOIO Connections On the Android platform, several types of connections to IOIO can be used:

  • ADB over USB. This is the standard connection type, supported on every Android device. It requires you to connect the IOIO board over USB and to have USB debugging enabled on the Android.
  • Bluetooth. This is used for a wireless connection. It requires a compatible dongle to be plugged into the IOIO, Bluetooth pairing to be done and the IOIOLibBT library to be linked against your application. See this page for more information. Note that the framework will try to establish a connection to every paired IOIO. Trying to connect to a non-existing device may interfere with existing connection, so make sure to un-pair any IOIO devices not in use.
  • OpenAccessory. This required an OpenAccessory-capable Android devices, USB debugging to be off and the IOIOLibAccessory to be linked against your application. See this page for more information.

###Available Utility Classes

The IOIO application framework for Android lives in the IOIOLibAndroid package, which is available from the IOIO software bundle or (starting at version 5.05) from the Maven Central repository. The relevant classes and interfaces can be found in the ioio.lib.util.android Java package. The framework provides utility classes for easy creation of IOIO-based Android Activity's and Service's.

To implement a IOIO-based activity, simply extend the IOIOActivity class and implement the createLooper() method with your IOIOLooper logic. Similarly, a IOIOService class exists for IOIO-based services. Make sure to call the super-class methods (e.g. onStart(), onStop()) if you override them. The HelloIOIO, IOIOSimpleApp and HelloIOIOService sample applications demonstrate the usage of these classes.

For advanced use-cases not covered by these utilities (for example if you want your IOIO connection to persist beyond the scope of a single activity, or if you have to have your activity class extend a different super-class), the IOIOAndroidApplicationHelper class provides a lower-level framework. You should instantiate this class and pass in the relevant Android events, and in turn, this class will callback on your createIOIOLooper() and on the looper's methods whenever appropriate. You can study the implementation of IOIOActivity and IOIOService, which use IOIOAndroidApplicationHelper under the hood.

For more details, consult the Javadocs of aforementioned classes.

Note: If you're looking for the old documentation of the now-deprecated AbstractIOIOActivity class, it is [here](Using-AbstractIOIOActivity-(deprecated)). It is recommended that you switch to IOIOActivity - the migration process is close to trivial.

##Creating IOIO-Based Applications on a PC

Controlling the IOIO board from a Java application running on a PC has been introduced with the release of the IOIO-OTG board and its accompanying software libraries. While mainly intended for IOIO-OTG devices, the original IOIO boards can be used with this library over Bluetooth.

###Available IOIO Connections On the PC platform, several types of connections to IOIO can be used:

  • USB device. This is supported only with IOIO-OTG boards. In this mode, the IOIO is connected to the PC as a USB device, using a USB A-to-micro-B cable. This IOIO can be powered either from the host PC or from a separate power supply (required if more than 500mA are used). Proper drivers need to be installed INSERT LINK on the host. The mode selection switch on the IOIO must be set to the A (auto) position.
  • Bluetooth. This is supported both by IOIO-OTG and older boards (running application firmware V3.x or higher). It requires a compatible dongle to be plugged into the IOIO and Bluetooth pairing to be done with the host. See this page for more information. Note that the framework will try to establish a connection to every paired IOIO. Thus, it is recommended to un-pair any IOIO devices not in use. With IOIO-OTG devices, make sure to use a micro-A connector on the IOIO side, or otherwise to force host mode by setting the mode switch to the H (host) position.

Both kinds of connections expose the IOIO to the PC as a serial device. The framework will use the following logic to decide which serial device(s) to use:

  • The user can explicitly set the system property ioio.SerialPorts to a colon-separated list of ports. For example, running the HelloIOIOConsole example from command line, may look like this:
    java -Dioio.SerialPorts=COM6 -jar HelloIOIOConsole.jar
    More than one port is acceptable. In Eclipse, you can set this argument in Run Configurations > Arguments > VM Arguments (and the the -Dioio.SerialPorts=xxx).
  • It is possible to set the property using property files (TODO: add explanation).
  • If the property is not set, the framework will try to open every possible serial port on the system upon start-up. Every port that was able to open will be considered a potential IOIO connection.

###Available Utility Classes

The IOIO application framework for PC lives in the IOIOLibPC package, which is available from the IOIO software bundle or (starting at version 5.05) from the Maven Central repository. The relevant classes and interfaces can be found in the ioio.lib.util.pc Java package. The framework provides utility classes for easy creation of IOIO-based console applications and GUI applications using the Swing library.

If you need a good introduction to Java, Oracle has some great tutorials here, covering everything from learning the language through building and running your applications to advanced topics.

To implement a IOIO-based console application, follow the following steps:

  • Create your main class, extending IOIOConsoleApp.
  • Implement static void main(String[] args) in your class by creating an instance of this class, and calling its void go(String[] args) method.
  • Implement void run(String[] args) with your main thread logic.
  • Implement IOIOLooper createIOIOLooper(String connectionType, Object extra) with code that should run on IOIO-dedicated threads.

For a complete example, see the HelloIOIOConsole example, included in the software bundle.

You can also implement applications with a Graphical User Interface (GUI), using the Java Swing library. If you need a tutorial on developing Swing applications, see the official tutorial. To implement a IOIO-based Swing application, follow the following steps:

  • Create your main class, extending IOIOSwingApp.
  • Implement static void main(String[] args) in your class by creating an instance of this class, and calling its void go(String[] args) method.
  • Implement Window createMainWindow(String args[]) with code to create your main window. For proper cleanup on exit, make sure to set JFrame.DISPOSE_ON_CLOSE as the default close operation of your window.
  • Implement IOIOLooper createIOIOLooper(String connectionType, Object extra) with code that should run on IOIO-dedicated threads.

For a complete example, see the HelloIOIOSwing example, included in the software bundle.

For advanced use-cases not covered by the above utilities (e.g. if you want the IOIO connection to be established only at a certain state of your application), the IOIOPcApplicationHelper class provides a lower-level framework. You should instantiate this class and call its start() and stop() methods when you want the IOIO interaction to begin / end. In turn, this class will callback on your createIOIOLooper() whenever appropriate. You can study the implementation of IOIOConsoleApp and IOIOSwingApp, which use IOIOPcApplicationHelper under the hood.

For more details, consult the Javadocs of the aforementioned classes.