Skip to content

MetaWearBoard Class

Metawear edited this page Aug 5, 2015 · 4 revisions

The MetaWearBoard class is the central class for communicating with your MetaWear board. It is similar to the old MetaWear class from previous APIs but has some key differences that we will highlight on this page.

To retrieve a MetaWearBoard object, you will need a reference to the MetaWearBleService.LocalBinder class and the BluetoothDevice object that corresponds to the MetaWear board you are using. You can create a BluetoothDevice object with BluetoothAdapter.getRemoteDevice if you know the MAC address or initiate a Bluetooth LE scan to find your board.

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
///< Other required imports

public class ExampleActivity extends Activity implements ServiceConnection {
    private final String MW_MAC_ADDRESS= "EC:2C:09:81:22:AC";
    private MetaWearBoard mwBoard;

    public void retrieveBoard() {
        final BluetoothManager btManager= 
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        final BluetoothDevice remoteDevice= 
                btManager.getAdapter().getRemoteDevice(MW_MAC_ADDRESS);

        ///< Create a MetaWear board object for the Bluetooth Device
        mwBoard= binder.getMetaWearBoard(remoteDevice);
    }
}

Connection State

The device's connection state is controlled with the connect and disconnect functions. You can also receive notifications about the connection state, by registering a ConnectionStateHandler via a call to setConnectionStateHandler.

import android.util.Log;
import static com.mbientlab.metawear.MetaWearBoard.ConnectionStateHandler;

public class ExampleActivity extends Activity implements ServiceConnection {
    public void connectBoard() {
        mwBoard.setConnectionStateHandler(new ConnectionStateHandler() {
            @Override
            public void connected() {
                Toast.makeText(ExampleActivity.this, "Connected", 
                                Toast.LENGTH_LONG).show();
            }

            @Override
            public void disconnected() {
                Toast.makeText(ExampleActivity.this, "Connection Lost", 
                                Toast.LENGTH_LONG).show();
            }

            @Override
            public void failure(int status, Throwable error) {
                Toast.makeText(ExampleActivity.this, "Error Connecting", 
                                Toast.LENGTH_LONG).show();
                Log.e("ExampleActivity", "Error connecting", error);
            }
        });
        mwBoard.connect();
    }
}

Asynchronous Operations

Instead of registering callback functions to asynchronously receive responses from MetaWear or Bluetooth LE requests, asynchronous operations are encapsulated in the AsyncOperation object. This class acts as an observer of the task, notifying the user asynchronously when the task is complete.

To see this class in action, lets call MetaWearBoard.readRssi. This returns an AsyncOperation which holds an integer result.

AsyncOperation <Integer> result= mwBoard.readRssi();

With our AsyncOperation object in hand, we now register a handler to listen for the result of this request. If the request has already been completed when the handler is registered, it will immediately be executed and discarded. Otherwise, it will be queued and executed later, when the task has finished.

The CompletionHandler class has two methods: success and failure. The former is called if the request was successful and passes the result to the caller and the latter is called if the operation or success callback function failed, and passes the error to the user instead.

import com.mbientlab.metawear.AsyncResult;
import com.mbientlab.metawear.MetaWearBoard.DeviceInformation;

public class ExampleActivity extends Activity implements ServiceConnection {
    public void updateRssi() {
        AsyncResult<Integer> result= mwBoard.readRssi();
        result.onComplete(new AsyncResult.CompletionHandler<Integer>() {
            @Override
            public void success(final Integer result) {
                Toast.makeText(ExampleActivity.this, String.format("Rssi (%d dBm)", result), 
                        Toast.LENGTH_LONG).show();
            }

            @Override
            public void failure(Throwable error) {
                Log.e("AsyncResult Example", "Error reading RSSI value", 
                        error);
            }
        });
    }
}

Interacting with Modules

To interact with the underlying MetaWear modules, you will first need to establish a connection with the board. Once a successful connection has been established, you can then call MetaWearBoard.getModule. If the board does not support the requested module, an UnsupportedModuleException will be thrown. This is a checked exception, meaning user must handle the exception.

import com.mbientlab.metawear.module.Led;
import com.mbientlab.metawear.UnsupportedModuleException;

public class ExampleActivity extends Activity implements ServiceConnection {
    ///< Only run this function once a connection to the board has been made
    public void turnOnLed() {
        try {
            ///< Do not need to type cast result to Led class
            Led ledCtrllr= mwBoard.getModuleController(Led.class);
            ledCtrllr.writeChannelAttributes(Led.ColorChannel.BLUE)
                    .withRiseTime((short) 0).withPulseDuration((short) 1000)
                    .withRepeatCount((byte) -1).withHighTime((short) 500)
                    .withHighIntensity((byte) 16).withLowIntensity((byte) 16)
                    .commit();
            ledCtrllr.playLed(false);
        } catch (UnsupportedModuleException e) {
            Toast.makeText(this, "Led module not supported on this board / firmware", 
                Toast.LENGTH_LONG).show();
            Log.e("ExampleActivity", "No Led on the board", e);
        }
    }
}

Routing Sensor Data

API v2.0.0 replaces the callback scheme from the earlier APIs with a Java DSL. This language expresses what to do with the sensor data, controlling where the data goes and how it is manipulated. The following code demonstrates how to stream button activity to your device:

import com.mbientlab.metawear.module.Switch;
import com.mbientlab.metawear.AsyncOperation.CompletionHandler;
import com.mbientlab.metawear.Message ;
import com.mbientlab.metawear.RouteManager;
import com.mbientlab.metawear.RouteManager.MessageHandler;

public class ExampleActivity extends Activity implements ServiceConnection {
    private static String SWITCH_STREAM_KEY= "switch_stream";

    public void setupSwitchNotify() {
        try {
            Switch switchModule= mwBoard.getModuleController(Switch.class);
            switchModule.routeData().fromSensor().stream(SWITCH_STREAM_KEY).commit()
                .onComplete(new CompletionHandler<RouteManager>() {
                    @Override
                    public void success(RouteManager result) {
                        result.subscribe(SWITCH_STREAM_KEY, new MessageHandler() {
                            @Override
                            public void process(Message msg) {
                                Log.i("ExampleActivity", String.format("Switch %s" , 
                                  msg.getData(Boolean.class) ? "Pressed" : "Released"));
                            }
                        });
                    }
                });
        } catch (UnsupportedModuleException e) {
            Toast.makeText(this, "A mechanical switch not supported on this board / firmware", 
                Toast.LENGTH_LONG).show();
            Log.e("ExampleActivity", "No switch on board", e);
        }
    }
}

The ins and outs of data routes are further elaborated on the date route [wiki page](Data Route Basics).