# Asynchronous Remote Commands

# Introduction

This chapter describes a way of scheduling remote command execution on the devices connected to the ABB Ability™ Platform either directly or via ABB Ability™ Edge, while not keeping the requesting thread waiting for a response. After your cloud application requested the execution, Ability Platform takes care of request queueing and delivery to the desired device. After the devices has completed the requested task, the requesting application is notified about the result and outputs of the method by means of web hook (HTTP response endpoint hosted by the application).

# Sending a Request

Cloud applications should send remote command execution requests using HTTP POST requests on /objects/{objectId}/models/{modelId}/methods/{name} endpoint:

# Query Parameters

Parameter Mandatory Description Data Type
objectId Yes The Object ID of the device where this method should be executed string
modelId Yes The model definition where this method is defined string
name Yes The name of the method requested string

# Request Headers

  • X-Correlation-Id - used to pass the correlation ID that will synchronize the command across services for tracking and callback purposes. If one is not provided, then one is created automatically.

# Request Body

{
  "callbackUrl": "<string>",
  "timeout": "<int>",
  "input": {}
}
Parameter Mandatory Description Data Type
callbackUrl Yes This property specifies where you want to receive a response once the command is completed. This needs to be a publicly accessible URL string
timeout No This property limits how long you will wait for a method invocation response. If the method invocation does not respond within your timeout period, then a timeout message is sent to your callback URL. This value is in seconds string
input No This property will satisfy the input object in the instance model definition for the method name you passed in the route Object

# Response Codes

  • HTTP 202 - Method Accepted - This response only reflects the fact that the command was received, validated, and dispatched to the Ability™ Platform. This response does not indicate completion of the command to the device.
  • HTTP 400 - BadRequest - Returned when the request body is invalid.
  • HTTP 404 - NotFound - Returned when the object model is not found
  • HTTP 500 - InternalServerError - Returned when there is an error processing the request

# Error response body

{
  "error": [
    {
      "status": "<integer>",
      "code": "<integer>",
      "title": "<string>",
      "detail": "<string>"
    }
  ]
}

# Remote Command Execution Flow

Following is a diagram showing, from a very high level, the sequence of commanding through this endpoint.

Diagram of Commanding

Above you will notice that the command execution request is sent to the Data Access API. That command invokes a method on a device. At the time prior to invocation, a response is returned to the caller. Once the device responds, the command response is sent to the command responder which invokes a POST to the callback URL originally provided by the client. There are two ways in which to receive a response that demand clarity:

Note

Responses are sent once only.

  1. Normal response
    One in which the device responded within the timeout set by the client. In this case, a response is received from the device before the timeout period elapses and is relayed back to the client via the callback URL.

  2. Timeout response
    One in which the timeout period elapsed before the device responded. In this case, a timeout response is sent to the client via the callback URL. If the device responds after the timeout period and a timeout response has already been sent to the client, then the device response will not be sent. This adheres to the rule that a response is sent once and once only.

# Example

The following is an example client request and description.

# Request from the cloud app

POST /api/v1/objects/e6109577-7db4-4cc6-81ce-87064aea09a4/models/abb.ability.device/methods/firmwareDownload
Host: abidasvcxxyyzz.azurewebsites.net
Content-Type: application/json
Accept: application/json
X-Correlation-Id: f4c6551c-f1aa-4483-a92c-d64260d52637

{
  "callbackUrl": "https://commandingcallback.azurewebsites.net/api/HttpTriggerCSharp1",
  "timeout": 10,
  "input": {
    "filePath": "path/subpath/file.bak"
  }
}

In the above request, the client is issuing a command for a device with objectId of e6109577-7db4-4cc6-81ce-87064aea09a4. The command is received and validated, and a response is quickly sent back to the client. In parallel with the response, the command is sent to the async commanding processor in ABB Ability™. The processor picks up the command and invokes the direct method (in this case the firmwareDownload method is invoked). In the body, the client has provided a callback URL, a timeout of 10 seconds, and an input path location where the file can be found. Let's examine each component of this request.​

# ObjectId

The objectId e6109577-7db4-4cc6-81ce-87064aea09a4 needs to exist in the information model database. If it doesn't, the client will get a validation error. If one is testing a directly connected device (as this example assumes) then there must exist in the IotHub a device named e6109577-7db4-4cc6-81ce-87064aea09a4. The object model must also contain this objectId.

# Method Name

The method name must exist in the object model. If it does not, then the client will receive a validation error.

# File Path

The file (identified in the filePath) must exist in the global storage. Therefore, for this example, the client would first upload the file.bak file to the global storage with the path of path/subpath.

# Device implementation

In order for this example to work, one must have a sample device up and running and a direct method listening. The direct method name must be firmwareDownload. An example using .NET is provided below. The example assumes x509 security.

using Microsoft.Azure.Devices.Client;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

static void Main(string[] args)
{
    var cert = new X509Certificate2(@"SomePathToCert\e6109577-7db4-4cc6-81ce-87064aea09a4.pfx", "certpassword");
    var auth = new DeviceAuthenticationWithX509Certificate("e6109577-7db4-4cc6-81ce-87064aea09a4", cert);
    _client = DeviceClient.Create("AbiGtwyIthca5cUswTst.azure-devices.net", auth, TransportType.Mqtt);
    _client.SetMethodHandlerAsync("firmwareDownload", Download, null).Wait();
}

private static Task<MethodResponse> Download(MethodRequest methodRequest, object userContext){
    var cloudMessage = methodRequest.DataAsJson;return Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(methodRequest.DataAsJson), 200));
}

For the above described components, the testing scenario would be as follows:

  1. You have a device client running and listening on the firmwareDownload method.
  2. You have a publicly available callback URL. For development testing, we simply just set up a new Http Triggered Azure function. The above example request body shows a callback URL of https://commandingcallback.azurewebsites.net/api/HttpTriggerCSharp1 which is simply an HTTP-triggered Azure Function named commandingcallback. Be sure to set the authorization to anonymous (this can be done in the function.json file).
  3. Once steps 1 and 2 are set up, the client can issue commands, as described above, using POSTMAN. Monitor the feedback through the http triggered Azure function.
Last updated: 9/6/2021, 1:25:50 PM
Feedback