LoWPAN

The Android Things LoWPAN APIs enable apps to interact with local devices connected over a wireless personal area network. Using LoWPAN user drivers, your apps can extend this framework and add new LoWPAN interfaces connected over Peripheral I/O.

Interface hardware connected through a LoWPAN user driver must implement a Network Control Processor (NCP) that supports the Spinel protocol. This is the standard communications protocol used by OpenThread devices.

Adding the required permission

Add the required permission for the user driver to your app's manifest file:

<uses-permission android:name="com.google.android.things.permission.MANAGE_LOWPAN_INTERFACES" />

Implementing the driver

To define a new LoWPAN interface, extend the LowpanDriver class and override the methods to manage the hardware connection:

import com.google.android.things.userdriver.lowpan.LowpanDriver;
import com.google.android.things.userdriver.lowpan.LowpanDriverCallback;
...

public class NcpLowpanDriver extends LowpanDriver {

    ...

    @Override
    public void start(LowpanDriverCallback lowpanDriverCallback) {
        /* Open connection to interface hardware */
    }

    @Override
    public void stop() {
        /* Close connection to interface hardware */
    }

    @Override
    public void reset() {
        /* Send a reset command or power cycle the radio interface */
    }

    @Override
    public void sendFrame(byte[] bytes) {
        /* Transmit a data frame to the radio interface */
    }
}

Managing the device connection

When the framework registers your new driver, it passes a LowpanDriverCallback instance in the start() method. Use this callback to report asynchronous events from the hardware back to the framework service.

Once your driver has opened a connection to your interface hardware, report to the framework that initialization is complete by calling onStarted() callback method. Report any errors that occur communicating with the interface hardware via the onError() callback method.

import com.google.android.things.userdriver.lowpan.LowpanDriver;
import com.google.android.things.userdriver.lowpan.LowpanDriverCallback;
...

public class NcpLowpanDriver extends LowpanDriver {

    private LowpanDriverCallback mCallback;

    ...

    @Override
    public void start(LowpanDriverCallback lowpanDriverCallback) {
        mCallback = lowpanDriverCallback;

        try {
            /* Open connection to interface hardware */

            // Report completion to the framework
            mCallback.onStarted();
        } catch (IOException e) {
            // Report error to the framework
            mCallback.onError(HAL_ERROR_IOFAIL);
        }
    }
}

Your driver should also monitor the interface hardware for reset events. If the hardware is reset for any reason, report this to the framework via LowpanDriverCallback.onReset().

Transferring data

The framework delivers data frames to the driver using the sendFrame() method. Pass each frame onto the interface hardware, and report any incoming frames from the hardware via onReceiveFrame().

import com.google.android.things.userdriver.lowpan.LowpanDriver;
import com.google.android.things.userdriver.lowpan.LowpanDriverCallback;
...

public class NcpLowpanDriver extends LowpanDriver {

    private LowpanDriverCallback mCallback;

    ...

    @Override
    public void sendFrame(byte[] bytes) {
        try {
            /* Transmit a data frame to the radio interface */
        } catch (IOException e) {
            // Report error to the framework
            mCallback.onError(HAL_ERROR_IOFAIL);
        }
    }

    /* Interface hardware generated a new data frame */
    private void onDataReceived(byte[] data) {
        // Report data to the framework
        mCallback.onReceiveFrame(data);
    }
}

Registering the interface

Connect your new radio interface to the framework by registering it with the UserDriverManager:

import com.google.android.things.userdriver.UserDriverManager;
...

public class LowpanDriverService extends Service {

    NcpLowpanDriver mDriver;

    @Override
    public void onCreate() {
        super.onCreate();
        ...
        UserDriverManager manager = UserDriverManager.getInstance();

        mDriver = new NcpLowpanDriver();
        // Register the new driver with the framework
        manager.registerLowpanDriver(mDriver);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        ...
        UserDriverManager manager = UserDriverManager.getInstance();
        // Unregister the driver when finished
        manager.unregisterLowpanDriver(mDriver);
    }
}

With the driver properly registered, apps can form or join local networks and communicate with connected devices using the Android LoWPAN API.