Initializing and Onboarding with Gateway

Initialization needs to be done from the mobile app in which the SDKs are incorporated.

This topic explains how to initialize the gateway and end nodes using the gateway feature of Thing Interaction Framework. If you initialize stand-alone things, use the initialization method described in Initializing and Onboarding.

Initialize the gateway first and then initialize end nodes as they are added. The initialization process creates and associates the gateway and multiple end nodes with the user of the mobile app on Kii Cloud as shown in Things on Application.

The username and password of the gateway need to be shared among the gateway, end nodes, and mobile app in order to initialize things. You can make the credentials available on the mobile app by getting them from the sticker on the gateway and entering them to the mobile app manually or by sending them to the mobile app via a short-range wireless communication such as Bluetooth.

Initializing the gateway

Initialize the gateway by following the steps below in both gateway app and end node app.

  1. Initializing the Kii Cloud SDK

  2. Getting the ThingIFAPI

  3. Getting the GatewayAPI and connecting to the gateway

  4. Onboarding

This section describes how to get the ThingIFAPI and GatewayAPI instances for the gateway. These API instances are API classes to operate the gateway itself and described in API Classes in SDKs. Follow the steps explained later for the end node app to get the API class for the end nodes.

See the figure in Onboarding Gateway in the Function Guide while reading the sample code of initialization to understand the entire flow better.

Initializing the Kii Cloud SDK

Execute the following code from the application class. This code will be executed upon the mobile app launch.

Make sure to align the name of the application class with the name you've specified in the AndroidManifest.xml in the steps described in Adding the Thing-IF SDK.

// The MobileApp class should be declared in your mobile app's AndroidManifest.xml.
public class MobileApp extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // Initialize the Kii Cloud SDK. Call this method before any other Kii SDK API calls.
    // This method can be called multiple times.
    Kii.initialize(getApplicationContext(), "___APPID___", "___APPKEY___", Kii.Site.JP, false);
  }
}

Replace the placeholders ___APPID___ and ___APPKEY___ with your application's AppID and an arbitrary value, respectively (See Creating a Kii Application for more information). Also, set the Site (Site.US, Site.JP, Site.CN3, Site.SG, or Site.EU) that corresponds to the server location you've specified on the developer portal.

The fifth argument is set to false to indicate that we are not using the analytics feature of the Kii Cloud SDK. Leave this parameter to false unless you are going to use the analytics feature.

You can safely embed the AppID in your application as long as you apply the correct access control. Please read Security for more information.

Getting the ThingIFAPI

Next, get the ThingIFAPI instance to send requests to Thing Interaction Framework to operate the gateway. This code can be executed anywhere in the mobile app as far as the initialization of the Kii Cloud SDK described in the previous section is completed.

ThingIFAPI apiGateway;

// Instantiate your application on Kii Cloud.
KiiApp app = new KiiApp("___APPID___", "___APPKEY___", Site.JP);

// Instantiate a ThingIFAPIBuilder object.
ThingIFAPIBuilder ib = ThingIFAPIBuilder.newBuilder(getApplicationContext(), app, owner);

// Set a tag for the ThingIFAPIBuilder instance.
ib.setTag("gateway");

// Add a schema to the ThingIFAPIBuilder instance.
ib.addSchema(schema);

// Instantiate a Thing-IF API from the ThingIFAPIBuilder instance.
apiGateway = ib.build();

Specify these items in the source code:

  • Replace the placeholders ___APPID___ and ___APPKEY___ with your application's AppID and an arbitrary value, respectively (See Creating a Kii Application for more information). Also, set the Site (Site.US, Site.JP, Site.CN3, Site.SG, or Site.EU) that corresponds to the server location you've specified on the developer portal (Site of KiiApp and that of Kii.initialize are in different packages).

    You can specify the server hostname such as api.kii.com instead of the Site. See the Javadoc for more information.

  • owner represents a user who will be the owner of the gateway. See Defining Owner with Gateway to learn how to get it.

    There are many ways to specify the user (owner). The method to select the user depends on the design of the mobile app. In this guide, we will present a method with a pseudo user that does not require any explicit user registration and login. If you want to implement the explicit user login, you will need to provide a login screen and initialize the Thing-IF SDK after the login processes are done.

  • schema represents the schema definition. See Defining Schema with Gateway to learn how to set it up.

When initialization is complete, you can get the instance that implements the API. Initialize the SDK by executing the build method of the ThingIFAPIBuilder, and you will get a ThingIFAPI instance. Please preserve the ThingIFAPI instance in somewhere, for example in the class field or Activity class, so that you can call it in the subsequent processes. You can also use the method explained in Saving and Restoring Initialized Information with Gateway to preserve the instance and restore it when the process is relaunched.

Set a unique name as a tag in the setTag method of the ib to identify each ThingIFAPI instance. The tag is used to identify the instance when you use the saveInstance and loadFromStoredInstance methods to save and restore it. Set different tag names from "gateway" in the initialization of end nodes. The process will be explained later.

Getting the GatewayAPI and connecting to the gateway

Next, get the GatewayAPI instance. This instance is an object which includes APIs necessary to access the gateway from the mobile app via a local network such as Wi-Fi .

GatewayAPI gatewayLocal;

// Instantiate a gateway API object.
Uri gatewayUri = Uri.parse("___GATEWAY_URL___");
gatewayLocal = GatewayAPIBuilder.newBuilder(getApplicationContext(), app, gatewayUri).build();

try {
  // Authenticate a user to the gateway.
  gatewayLocal.login("___GATEWAY_USERNAME___", "___GATEWAY_PASSWORD___");
} catch (ThingIFException e) {
  // Handle the error.
}
  • Specify the gateway URL, username, and password in the ___GATEWAY_URL___, ___GATEWAY_USERNAME___, and ___GATEWAY_PASSWORD___. The gateway URL is an address such as http://192.168.0.10/, which is accessible from the mobile app via Wi-Fi on a local network. The gateway username and password are the credentials for the gateway agent. Share them with the mobile app in some way.

  • Specify the KiiApp instance, which was used to initialize the ThingIFAPI instance, in the app instance of the newBuilder. The KiiApp instance has information such as the AppID and AppKey.

  • The login method accesses the gateway and gets the gateway user authenticated when it is called.

Onboarding

To control a thing such as a gateway and an end node from the mobile app, you need to bind the mobile app to the thing. This binding process is called Onboarding.

Including the onboarding API, all of the APIs in the Thing-IF SDK are blocking APIs. The user interface stops if the main thread calls any blocking API. Call the APIs of the Thing-IF SDK with any asynchronous technology discussed in Implementation Guidelines or from a worker thread created by yourself.

The onboarding needs to be done for the gateway as below:

try {
  // Instantiate the gateway.
  Gateway gateway = gatewayLocal.onboardGateway();

  // Get the thing ID of the gateway.
  String thingID = gateway.getThingID();

  // Set the gateway password.
  String gatewayPassword = "___GATEWAY_PASSWORD___";

  // Onboard the gateway to Thing Interaction Framework.
  apiGateway.onboard(thingID, gatewayPassword);
} catch (ThingIFException e) {
  // Handle the error.
}

The above sample code processes these tasks:

  1. The onboardGateway sends an onboarding request to the gateway via Wi-Fi. The Gateway instance is returned when the request is successfully processed. You can get the thingID of the gateway from the Gateway instance.

  2. The onboard sends an onboarding request to Thing Interaction Framework. This associates the owner which was specified in onboarding the apiGateway with the gateway which was specified in the thingID.

This is the only supported method to onboard the gateway. For stand-alone things, you can select the method where you onboard things from the mobile app or the method where you onboard things from both the mobile app and things.

The gateway and the mobile app have been associated when the above process is completed. Continue to the subsequent steps with the obtained apiGateway and gatewayLocal.

This completes the necessary initialization on the gateway app. The additional steps required on the end node app are described in the next section.

Initializing end nodes

The end node app initializes end nodes as they are added after the gateway has been initialized.

Initialize end nodes by following the steps below.

  1. Getting a list of pending nodes

  2. Onboarding

  3. Getting the ThingIFAPI

  4. Installing a device

  5. Notifying the gateway

See the figure in Onboarding End Node in the Function Guide while reading the sample code of initialization to understand the entire flow better.

Getting a list of pending nodes

First, by accessing the gateway, get the list of pending end nodes which are yet to be initialized. The gateway maintains the list of end nodes which have been connected to the gateway but not completed onboarding to Thing Interaction Framework. You can get the list through the Gateway API.

Use the gatewayLocal instance of the GatewayAPI to access the gateway. Get the list of pending end nodes and select one of them to initialize.

try {
  // Get a list of pending end nodes.
  List<PendingEndNode> pendingEndNodeList = gatewayLocal.listPendingEndNodes();

  for (PendingEndNode pendingEndNode : pendingEndNodeList) {
    String endnodeVendorThingID = pendingEndNode.getVendorThingID();
    String endnodeThingType = pendingEndNode.getThingType();
    JSONObject endnodeProperties = pendingEndNode.getThingProperties();
    // Select a pending end node to onboard.
  }
} catch (ThingIFException e) {
  // Handle the error.
}

Call the listPendingEndNodes to get the list of end nodes as the List<PendingEndNode>. This list contains end nodes that are yet to be registered to Thing Interaction Framework. The above sample code processes the entries of the list one by one to get detailed information of them.

The mobile app decides one PendingEndNode instance to process. To decide a target, you might let the user select one through the user interface of the mobile app or process all the pending end nodes one by one.

If you let the user select a target end node, the thing type and thing information are available to identify a target end node. You can design these values at your discretion when connecting end nodes to the gateway. For example, you can set a serial number of the product or the product name such as Kii Smart LED E26 [ABC-123] as a field of the endnodeProperties. Let the user decide a PendingEndNode instance to initialize by some way, such as displaying these values on the screen.

Move to the next step once the PendingEndNode instance to initialize is decided.

Onboarding

Next, execute onboarding which associates an end node, the mobile app (the user), and the gateway.

Enter the end node password to the mobile app before onboarding. This task aims to ensure security in handling the end node on Thing Interaction Framework. You can let the user enter it on the user interface or the mobile app generate it internally. Note that the end node password needs to be safely managed because leakage of it could lead to potential unauthorized access and loss of it makes access to the end node impossible.

Onboard the end node by the below API dedicated to end nodes.

EndNode endNode;
try {
  // Set the end node password.
  String endNodePassword = "123ABC";

  // Set the data grouping interval option.
  OnboardEndnodeWithGatewayOptions.Builder builder = new OnboardEndnodeWithGatewayOptions.Builder();
  builder.setDataGroupingInterval(DataGroupingInterval.INTERVAL_15_MINUTES);
  OnboardEndnodeWithGatewayOptions options = builder.build();

  // Onboard the end node.
  endNode = apiGateway.onboardEndnodeWithGateway(pendingEndNode, endNodePassword, options);
} catch (ThingIFException e) {
  // Handle the error.
}

The following values are set in the above sample code.

  • pendingEndNode: The end node which was selected in Get List of Pending Nodes as an initialization target.
  • endNodePassword: The password of the end node to be initialized. Enter it to the mobile app in some way.
  • setDataGroupingInterval(): The grouping interval for storing state history. The history will not be stored if no grouping interval is specified. The available intervals are INTERVAL_1_MINUTE, INTERVAL_15_MINUTES, INTERVAL_30_MINUTES, INTERVAL_1_HOUR, and INTERVAL_12_HOURS. See this page for the details.

Once onboarding is completed, you can get the EndNode instance which represents an onboarded end node. This instance will be used in the next step.

Note that the state history is not available until onboarding from the mobile app completes. The thing can upload state information but it is not stored as history data until the first mobile app gets associated with the thing.

Getting the ThingIFAPI

Get the ThingIFAPI instance to send requests to each end node via Thing Interaction Framework.

The obtained instance in the sample code is named as apiEndNode1 while the actual program would generate as many ThingIFAPI instances as the number of end nodes connected to the gateway. Kii recommends that you manage end nodes in the data structure which can handle multiple nodes such as a map and an array.

ThingIFAPI apiEndNode1;

// Instantiate a ThingIFAPIBuilder object.
ThingIFAPIBuilder ib = ThingIFAPIBuilder.newBuilder(getApplicationContext(), app, owner);

// Specify the end node to associate with a new Thing-IF API.
ib.setTarget(endNode);

// Set a tag for the ThingIFAPIBuilder instance.
ib.setTag("endnode1");

// Add a schema to the ThingIFAPIBuilder instance.
ib.addSchema(schema);

// Instantiate a Thing-IF API from the ThingIFAPIBuilder instance.
apiEndNode1 = ib.build();

Review the considerations below in initializing end nodes while the way to get the ThingIFAPI instance is the same as that for the gateway.

  • Specify the instance used to initialize the gateway in the app. The gateway and end nodes work on the same application from the viewpoint of the end node app.

  • Usually, set the user specified in initializing the gateway and other end nodes in the owner in order to operate things with the same owner's privileges.

  • Use the setTarget method to associate the ThingIFAPI to be initialized with the onboarded EndNode.

  • Tag endnode1 is set in the setTag method of the ib. The tag is used to identify the instance when you use the saveInstance and loadFromStoredInstance methods to save and restore it. Set a unique string which is different from ones for the gateway and other end nodes. See also the code sample in Saving and Restoring Initialized Information with Gateway.

  • Specify the schema definition in the schema. This is the schema definition to be used by the end node which is being onboarded. The schema can be different from those for the gateway and other end nodes. See Defining Schema with Gateway to learn how to set up a schema.

Installing a device

You need to install the device so that it can receive responses from end nodes when the device sends commands to them. This action associates the owner with the FCM device token or JPush registration ID on Kii Cloud.

Installing a device

Use the ThingIFAPI instance obtained when initializing the Thing-IF SDK for each end node to install the device as below. See the implementation examples described later for more information about the parameters.

try {
  // Register the device token for the thing owner to Kii Cloud.
  apiEndNode1.installPush(token, PushBackend.GCM);
} catch (ThingIFException e) {
  // Handle the error.
}

Specify PushBackend.GCM for FCM and PushBackend.JPUSH for JPush.

When the device is installed, the owner specified upon creating the ThingIFAPI will be associated with the device token and registered to Thing Interaction Framework. The installation process overwrites the previous device token if any and push notifications to the previous owner will not be sent to this device any longer.

Implementation Example with FCM

This example is a modified version of the sample code in the Android (FCM) Push Notification Tutorial for Thing-IF. The device is asynchronously installed with JDeferred because the sample code in the push notification tutorial installs the device in the main thread of MainActivity.

You can call installPush in a worker thread without JDeferred if you create a worker thread to call the API as in the Hello Thing-IF Tutorial.

Create a method to call the API using a promise with JDeferred.

private Promise<Void, Throwable, Void> installFCMPush(final ThingIFAPI api, final String token) {
  return mAdm.when(new DeferredAsyncTask<Void, Void, Void>() {
    @Override
    protected Void doInBackgroundSafe(final Void... params) throws Exception {
      // Register the device token for the thing owner to Kii Cloud.
      api.installPush(token, PushBackend.GCM);
      return null;
    }
  });
}

Include the method in MainActivity.

private AndroidDeferredManager mAdm = new AndroidDeferredManager();

@Override
protected void onCreate(Bundle savedInstanceState) {
  ......

  // Get a FCM token.
  String fcmToken = FirebaseInstanceId.getInstance().getToken();
  if (fcmToken == null) {
    Toast.makeText(MainActivity.this, "Error FCM is not ready", Toast.LENGTH_LONG).show();
    return;
  }

  // Register the device token for the thing owner to Kii Cloud.
  mAdm.when(installFCMPush(apiEndNode1, fcmToken)
  ).then(new DoneCallback<Void>() {
    @Override
    public void onDone(Void param) {
      Toast.makeText(MainActivity.this, "Succeeded push registration", Toast.LENGTH_LONG).show();
    }
  }).fail(new FailCallback<Throwable>() {
    @Override
    public void onFail(final Throwable tr) {
      Toast.makeText(MainActivity.this, "Error push registration:" + tr.getLocalizedMessage(), Toast.LENGTH_LONG).show();
    }
  });
  ......
}

Implementation Example with JPush

This example is a modified version of the sample code in the Android (JPush) Push Notification Tutorial for Thing-IF. Execute a process equivalent to the below sample code from a worker thread. See Implementation Guidelines for more information about the implementation of asynchronous processing.

try {
  // Register the registration ID for the thing owner to Kii Cloud.
  apiEndNode1.installPush(regId, PushBackend.JPUSH);

  // Save the registration ID in the preference.
  JPushPreference.setRegistrationId(MainActivity.this.getApplicationContext(), regId);
} catch (ThingIFException e) {
  // Handle the error.
}

Uninstalling a device

Execute the following code to uninstall the device.

The uninstalled device will not receive push notifications any longer from all of the end nodes after the uninstallation is done against one of the end nodes. Uninstall the device in the situation like you remove the last end node.

try {
  // Unregister the push notification for the thing owner.
  apiEndNode1.uninstallPush(apiEndNode1.getInstallationID());
} catch (ThingIFException e) {
  // Handle the error.
}

This code assumes that the device has been installed. Otherwise, the GetInstallationID method will return a null value.

The device will not receive push notifications any longer after successful uninstallation.

Notifying the gateway

Finally, notify the gateway of the completion of onboarding.

try {
  // Notify the gateway of the completion of onboarding.
  gatewayLocal.notifyOnboardingCompletion(endNode);
} catch (ThingIFException e) {
  // Handle the error.
}

Specify the EndNode instance obtained as a result of onboarding in the endNode.

Executing functions

The above steps complete the initialization of the gateway and each end node. The instances below are available when initialization is done.

  • ThingIFAPI instance of the gateway

    This instance is represented as apiGateway in this topic. It is used to access the gateway via Thing Interaction Framework and to manage end nodes and the gateway itself. In the current version of Kii Cloud, this instance is necessary to initialize new end nodes.

  • GatewayAPI instance of the gateway

    This instance is represented as gatewayLocal in this topic. It is used to directly access the gateway via Wi-Fi and to manage end nodes and the gateway itself. In the current version of Kii Cloud, this instance is necessary to initialize new end nodes.

  • ThingIFAPI instance of end nodes

    This instance is represented as apiEndNode1 in this topic. Multiple instances will be available if multiple end nodes are connected.

    Use this instance to send commands to end nodes and check the states of end nodes. For example, when you want to send a command to the apiEndNode1, Thing Interaction Framework sends the command to the connected gateway, which will relay it to the end node.

    See Executing Commands, Browsing States, and Triggers to learn how to send commands and receive the states. Replace api in each sample code with apiEndNode1, which is the target end node to operate.