Server Code Triggers

To execute server code automatically, set the information about the server code and the condition in the trigger.

When the server code execution is finished, you can get the execution result (i.e., the returned value and error).

Registering state condition triggers

Before you register a trigger, set the target server code. Refer to Server Extension Programming Guide to learn how you can set the server code.

When you are done with setting the server code, set the endpoint you want to execute by the trigger.

The next example is setting a trigger to execute the alertTemperature endpoint of the server code with the parameter {"caller":"trigger"} when the room temperature goes over 30 degrees.

// Specify an end point of server code.
let accessToken = KiiUser.currentUser().accessToken
let param : Dictionary = ["caller": "trigger"]
let serverCode = ServerCode(endpoint: "alertTemperature", executorAccessToken: accessToken, targetAppID: nil, parameters: param)

// Create a predicate.
// Execute the server code when the temperature is greater than or equal to 30 deg C.
let condition = Condition(clause:RangeClause(field: "currentTemperature", lowerLimit: 30, lowerIncluded: true))
let predicate = StatePredicate(condition: condition, triggersWhen: TriggersWhen.CONDITION_FALSE_TO_TRUE)

// Send a trigger.
api.postNewTrigger(serverCode, predicate: predicate, completionHandler: { (trigger: Trigger?, error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }
})

In the sample code, we create ServerCode and StatePredicate instances and register a trigger with the postNewTrigger method.

The ServerCode instance is used to set the condition for the server code. We are setting the following parameters in the ServerCode constructor.

  • The first argument: the name of the server code endpoint (i.e., the name of JavaScript function) to execute.
  • The second argument: the access token to be used for executing the server code. We are setting the access token of the owner user in this example. In the server code, you can use the context.getAccessToken() to get the access token of the caller and execute the server code with the privilege of this caller. When you execute the server code with a trigger, the token specified in the argument will be used as the caller token.
  • The third argument: the AppID of the Kii Cloud application that is hosting the server code. If you want to run the server code that is hosted by other application, please specify the AppID of the application here. If the server code is hosted by the same application (i.e., the application specified when you initialize api), you can specify a nil value. Please note that the application needs to be in the same server location.
  • The fourth argument: the parameter to be passed to the endpoint. The actual parameter is sent to the server code as a JSON, but we will set it with the Dictionary in Swift. You can set nil if there is no parameter.

The way to initialize the StatePredicate is the same as that of when you initialize it for the trigger to execute a command.

When the trigger is registered, you will get a Trigger instance as an argument of the completionHandler.

Getting execution results of server code

After setting a trigger, the specified server code will be executed every time when the designated state condition is satisfied. The results are stored in Thing Interaction Framework, and you can check these results via the API.

You can use the pagination if there are many results. If there are 30 results stored in Thing Interaction Framework, for example, you can get 10 results per request (i.e., 10 results per page) and get all results in three requests.

The following is the sample code:

// Get a list of server code results.
api.listTriggeredServerCodeResults(trigger!.triggerID, bestEffortLimit: nil, paginationKey: nil) { (results: [TriggeredServerCodeResult]?, paginationKey: String?, error: ThingIFError?) -> Void in
  if error != nil {
    // Handle the error.
    return
  }

  // Check if the server code succeeded or not and process each result.
  for serverCodeResult in results! {
    if serverCodeResult.succeeded {
      let returnedValue = serverCodeResult.getReturnedValueAsString();
      let executedAt = serverCodeResult.executedAt;
    } else {
      let errorMessage = serverCodeResult.error!.errorMessage;
      let executedAt = serverCodeResult.executedAt;
    }
  }

  // If the next page exists
  if paginationKey != nil {
    // Get the next page of the list.
    api.listTriggeredServerCodeResults(trigger!.triggerID, bestEffortLimit: nil, paginationKey: paginationKey) { (results: [TriggeredServerCodeResult]?, paginationKey: String?, error: ThingIFError?) -> Void in
    if error != nil {
      // Handle the error.
      return
    }

    // Check if the server code succeeded or not and process each result.
  }
}

We are getting the results stored in the server with the listTriggeredServerCodeResults method. As shown in the sample code, we need to set the trigger ID of the target trigger instance. This trigger instance has been returned when you register the trigger to Thing Interaction Framework.

The paginationKey represents the current page status. When you execute the listTriggeredServerCodeResults method with nil, 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 listTriggeredServerCodeResults execution. When all results are obtained, nil will be returned as the pagination key.

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

The list of results is stored in the argument results of the handler. As shown in the sample code, you can check the time when the server code was executed and if the execution was a success. If the execution succeeded, you can get the returned value. If the execution failed, you can get an error message. We are getting the returned value as a string in the sample code. You can, of course, code your application to get the returned value in other formats, like integer and JSON.