Executing Commands

You can control the things by sending commands from the mobile applications. The commands are processed on the things to achieve various services. See here for the overview.

Executing commands

To send a command, you will first set the parameters for each action that composes the command. Then, you will execute the method for sending the command to Kii Cloud.

Prior to the execution, you need to get a ThingIFAPI instance (api) that is initialized by the steps described in Initializing and Onboarding. You also need the user ID of the user who is going to execute the command.

Here, we will show a sample code block for sending a command based on the example shown in Defining Schema.

// Create an array for actions to be executed as a command.
List<Action> actions = new ArrayList<Action>();

// Create actions.
TurnPower action1 = new TurnPower();
action1.power = true;

SetPresetTemperature action2 = new SetPresetTemperature();
action2.presetTemperature = 25;

SetFanSpeed action3 = new SetFanSpeed();
action3.fanSpeed = 5;

// Add the actions to the array.
actions.add(action1);
actions.add(action2);
actions.add(action3);

try {
  // Execute the command.
  Command command = api.postNewCommand("AirConditioner-Demo", 1, actions);
} catch (ThingIFException e) {
  // Handle the error.
}

This is what is happening in the sample code:

  1. Prepare an array of the actions you want to send

    In this example, we are setting three actions in sequence. TurnPower,SetPresetTemperature, and SetFanSpeed are subclasses of the Action class that are created in the schema definition. You are setting the parameters for these commands.

    The actions created with action1, action2, and action3 are stored in List <Action>. The thing will receive them in the same order as you set them here.

  2. Execute the Command

    We execute the method for sending the command. Here, we set the schema name, schema version, and the command that we've specified in the Initialization and Onboarding as the method argument. The method returns a Command instance.

The following will happen after executing the command.

The API returns control when Thing Interaction Framework receives the command. At this point, the command is not delivered to the thing yet, so the command result in the Command is undefined. Thing Interaction Framework assigns a command ID for each Command execution. This ID can later be used to get the command result when the command is executed on the thing, and its command result is ready.

Thing Interaction Framework will send a request for executing the command to the thing via the MQTT push. The thing will execute the specified three actions accordingly after receiving the request.

Finally, the command result and error codes (if any) are registered to Thing Interaction Framework. Thing Interaction Framework will send a push notification to notify the command ID to the mobile application. The mobile application, using its push notification handler, can get the command result and error codes using the command ID. See Getting Command Result for the details.

Sending a portion of actions

You do not need to use all actions defined in a schema at once. You can send only the required action in a certain situation.

For example, suppose you just want to send TurnPower.power = false (power off). Since you do not need to configure the preset temperature and fan speed, you can send a command in the following way:

// Create an array for actions to be executed as a command.
List<Action> actions = new ArrayList<Action>();

// Create an action.
TurnPower action1 = new TurnPower();
action1.power = false;

// Add the action to the array.
actions.add(action1);

try {
  // Execute the command.
  Command command = api.postNewCommand("AirConditioner-Demo", 1, actions);
} catch (ThingIFException e) {
  // Handle the error.
}

This time, only one action is set in the array. The command sent to the thing, therefore, will have only this action.

Sending with command details

Use the CommandForm class to register the command title or description when you send a command.

// Create an array for actions to be executed as a command.
List<Action> actions = new ArrayList<Action>();

// Create actions.
TurnPower action1 = new TurnPower();
action1.power = true;

SetPresetTemperature action2 = new SetPresetTemperature();
action2.presetTemperature = 25;

SetFanSpeed action3 = new SetFanSpeed();
action3.fanSpeed = 5;

// Add the actions to the array.
actions.add(action1);
actions.add(action2);
actions.add(action3);

// Set metadata to be sent with a command.
JSONObject metadata = new JSONObject("{ \"iconIndex\" : 3, \"issuer\" : \"remoteController\" }");

try {
  // Create a command form from the schema name, schema version, and actions.
  CommandForm form = new CommandForm("AirConditioner-Demo", 1, actions);

  // Set the title, description, and metadata in the command form.
  form.setTitle("Power on");
  form.setDescription("Power on and set to 25 deg C");
  form.setMetadata(metadata);

  // Execute the command with the command form.
  Command command = api.postNewCommand(form);
} catch (ThingIFException e) {
  // Handle the error.
}

The command to execute is the same as the one in the first snippet but the CommandForm class uses the setTitle, the setDescription and the setMetadata methods to set command details. You can use these as you like based on the specifications of your application as described in Command Details. See Command Details also for limits such as the maximum length of the fields.

Once the command is executed, you can get the set command details by the getTitle, the getDescription, and the getMetadata methods of the Command class. You can also get the Command instances by the way described in Getting a List of Registered Commands below in order to execute these methods.

Getting command result

When the thing uploads the command result, Thing Interaction Framework will send a push notification via FCM to the mobile application.

The command ID is included in the payload of the push notification. The mobile application can get the entire command with this ID and fetch the command result. By checking the status code and error message in the command result, the mobile application will be able to know the command execution result.

The destination of the push notification with the command ID depends on whether the owner is a pseudo user or a normal user. See Implementation tips for more information.

The following sample code processes the push notification reception handler.

You can get the ID of the executed command via FCM with the sample code below:

public class MyFirebaseMessagingService extends FirebaseMessagingService {
  @Override
  public void onMessageReceived(RemoteMessage remoteMessage) {
    // Get the payload of a push message.
    Map<String, String> payload = remoteMessage.getData();

    // Get the command ID from the payload.
    String returnedID = payload.get("commandID");
  }
}

A subclass of FirebaseMessagingService receives push notifications. The onMessageReceived method processes the received message.

Get the payload of the push message with remoteMessage.getData(). commandID contains the ID of the command executed on the thing. If you are using the push notification also for non-IoT SDK purposes, commandID will be a null value when the push notification is not related with the command execution.

If the push notification is not properly delivered...

If the push notification does not arrive after the command is being processed on the thing, check the troubleshooting section of the Kii Cloud SDK push notification feature to resolve the issue. You might also want to try the Kii Cloud SDK tutorial to test if the Kii Cloud SDK push notification feature works fine with the simple program.

Note that using the push notification feature with the Thing-IF SDK is a bit different from using it with the Kii Cloud SDK in the following manners:

  • When using the Thing-IF SDK, the push notification is always delivered to both development and production environments.
  • The API to install a device is different between the Thing-IF SDK and the Kii Cloud SDK. See Installing a device for how to implement it.
  • The Thing-IF SDK will wrap some Kii Cloud push notification features (i.e., topic creation, topic subscription, and message sending). These features will be executed automatically by the Thing-IF SDK when you execute the onboarding and when the corresponding event occurs.

Getting a command with the ID

You can get the details of the command using its command ID. By getting the command, you can reference the command result and take appropriate actions in your application.

try {
  // Get the command.
  Command command = api.getCommand(returnedID);

  // Get each of the action results.
  List<ActionResult> results = command.getActionResults();
  for (ActionResult result : results) {
    String actionName = result.getActionName();
    boolean succeeded = result.succeeded();
    String errorMessage = result.getErrorMessage();
  }
} catch (ThingIFException e) {
  // Handle the error.
}

Here is what is happening in the sample code:

  • Execute the getCommand method of the ThingIFAPI instance (api) with the command ID as an argument to get the entire command from the server.
  • Extract each ActionResult in the command to check the action name, the status, and the error message. The action name will be the name you've set on the ActionResult subclass in the schema.

Getting a list of registered commands

You can get a list of all commands that are registered on the server.

If there are many registered commands, you can use the pagination. If there are 30 registered commands, for example, you can get ten commands per page. In this case, you can get all commands by parsing three pages, ten commands at a time.

The following is the sample code.

try {
  String paginationKey = null;

  do {
    // Get a list of commands.
    Pair<List<Command>, String> results = api.listCommands(0, paginationKey);
    List<Command> commands = results.first;

    for (Command command : commands) {
      // Do something with each command.
    }

    // Get the next pagination key.
    paginationKey = results.second;
  } while (paginationKey != null);
} catch (ThingIFException e) {
  // Handle the error.
}

As shown in the sample code, you can get a list of commands with the listCommands method.

The paginationKey represents the current page status. When you execute the listCommands method with a null value, the first page is returned with the next pagination key being set in the second. You can get the next page by setting this value as the pagination key of the next listCommands execution. When all commands are obtained, a null value will be returned as the pagination key.

The first argument of the listCommands denotes the number of commands to get (i.e., the size of a page). If you set the number to 0 or below, the server will apply the optimal setting. The size of the page set here will be handled in a best-effort manner, so the actual number of commands obtained can be smaller than the specified number. The commands that could not be retrieved can be obtained in the next page.

You can get the commands only in the ascending order. You cannot get them in the descending order.

The list of commands is stored in the results.first.