Nabto Edge Service Invocation

Nabto Edge Service Invocation enables embedded devices to invoke a webservice through the Nabto Edge Basestation. This means the embedded device does not need a full HTTP/TLS/TCP stack to e.g. send notifications or process data in a 3rd party big data solution. Instead, the device application can just use the Nabto Embedded SDK’s already established connection to the Nabto Basestation - this connection requires only basic UDP.

The Nabto Basestation acts as a bridge towards the target webservice: It forwards the request from the vendor’s device to the vendor configured webservice and passes the response back:

Note that the Nabto Basestation must be trusted in this scenario as the request and response from/to the device exist in cleartext when being passed to/from the configured webservice. The device can apply application level encryption to ensure end-to-end encryption between the device and the external vendor webservice if this is required.

Invoking a Service with a Message

When invoking a configured service, the vendor’s application on the device specifies a message to send. The message is a buffer with arbitrary data and a length.

The Nabto Basestation base64 encodes the message and passes it on to the target webservice in a JSON envelope. The envelope also contains information about the calling device (product and device IDs).

Treating the message as binary means that the device can send JSON documents without worrying about the hassle of escaping JSON. It does, however, add some complexity in the configured target webservice that must then handle decoding the input message and encoding the response.

Request sent to webservice by basestation

JSON document passed on from Nabto Basestation to vendor webservice:

{
  "productId": "pr-abcdefgh",
  "deviceId": "de-ijklmnop",
  "message": "aGksIHdlYnNlcnZpY2UhCg=="
}

The message is specified as raw binary data by the device application when passing it to the Nabto Embedded SDK. The Nabto basestation base64 encodes the message when creating the JSON document passed on to the vendor webservice.

Response from webservice to basestation

The vendor webservice in turn provides a JSON document as response (content type application/json). The document always has a single field, message - the value must be base64 encoded by the webservice:

{
  "message": "aGksIGRldmljZSEK"
}

The basestation decodes the base64 message and provides a binary message to the service invocation application on the embedded device. The device receives the webservice HTTP status code along with the decoded message.

To make Nabto Edge Service Invocation compatible with standard webservice error handling, the basestation also accepts responses with content type text/plain and text/html. In this case, the contents of the HTTP response body is used unaltered as the message returned to the device application. Finally, the basestation also accepts an empty HTTP response body. In this case, only the HTTP status code is returned to the device.

When receiving a service invocation response in the device application, a Message Format is available to show which HTTP response format was received. This can help the device application determine how to interpret the message.

Register Webservice in Console

In the Nabto Cloud Console a Service must be created. In the Service, the URL of the external vendor webservice to invoke must be configured. In addition to the URL, a basic auth username and password can be configured. If configured, the basestation will add the proper basic auth Authorization header to the HTTP request.

On creation, the Service is assigned a Service ID which the device uses to reference which service the Basestation should invoke on its behalf.

To only allow devices within specific Products to invoke the webservice, the Service must be added to the Products for which devices should have access to the webservice. This is done from the Product Settings page.

Invoke a Service from the Device

In the device, services are invoked through the Nabto Embedded Device SDK. Invoking services requires a Device Context. Once the device is started and the device is hence connected to the basestation (attached), use the Nabto Embedded SDK service invocation functions as seen in the following example:

// "device" has been allocated and started prior to this point
// "serviceId" matches the configuration in the Nabto Cloud Console

const char* message = "hello-world";
NabtoDeviceServiceInvocation* invocation = nabto_device_service_invocation_new(device);
nabto_device_service_invocation_set_service_id(invocation, serviceId);
nabto_device_service_invocation_set_message(invocation, (const uint8_t*)message, strlen(message));

NabtoDeviceFuture* future = nabto_device_future_new(device);
nabto_device_service_invocation_execute(invocation, future);
NabtoDeviceError ec = nabto_device_future_wait(future);

if (ec != NABTO_DEVICE_EC_OK) {
    printf("Service invocation failed %s\n", nabto_device_error_get_message(ec));
} else {
    uint16_t statusCode = nabto_device_service_invocation_get_response_status_code(invocation);
    const uint8_t* msg = nabto_device_service_invocation_get_response_message_data(invocation);
    NabtoDeviceServiceInvokeMessageFormat fmt =
        nabto_device_service_invocation_get_response_message_format(invocation);
    size_t len = nabto_device_service_invocation_get_response_message_size(invocation);
    printf("Service invocation ok. Status: %d, MessageLength: %d, MessageFormat: %d, Message %.*s\n",
            statusCode, (int)len, (int)fmt, (int)len, (const char*)msg);
}

Note: The embedded device application specifies raw binary data with a length indication - the basestation is responsible for base64 encoding the data before passing on to the vendor webservice in a JSON document.

Full Example

The Nabto Embedded SDK provides a full example implementation for Service Invocation. The Service Invocation Example section shows how to use the example implementation to invoke a generic online webhook service.