Show Contents

# Receive data from Remote Manager

You can use Cloud Connector to receive data from Remote Manager, also known as receiving Device Requests. Transfers are initiated from a Web Services client connected to Remote Manager, which hosts the device. This transfer is used to send data to the device or trigger actions in the device. The device may also return a response.

Device Requests are composed of:

- Target: A unique name which specifies which part of the application is in charge of attending this request.
- Data: Arbitrary data sent to the device.

On the device, when Cloud Connector receives the request, it looks into the user-registered targets. If a match is found, then it is automatically accepted and the appropriate handlers called. If no match is found, Cloud Connector returns a standard error response to Remote Manager.

Follow these steps to receive data from Remote Manager:

1. Register a target

2. Define receive callbacks

3. Use the API Explorer to send Device Requests

For a list of possible errors receiving device request from Remote Manager, see Description of errors.

Digi Embedded Yocto includes a sample application demonstrating how to receive device requests from Remote Manager.

## 1. Register a target

In order to make your application aware of Device Requests sent to the device, you must register a handler for each new target. The ccapi_receive_add_target() function allows you to register specific targets.

    ccapi_receive_error_t ccapi_receive_add_target(char const * const target, ccapi_receive_data_cb_t const data_cb,
           ccapi_receive_status_cb_t const status_cb, size_t const max_request_size)

Parameter | Description
--- | ---
target | Name of the target to register. It must be unique.
data_cb | Callback called when new data for target is received. This function performs the request and optionally returns a response to Remote Manager.
status_cb | Callback called when the receive process has completed. This function checks status and free resources. This may be NULL if no status callback is required.
max_request_size | Maximum length of the data to be received in a request from Remote Manager for this target. If the data received exceeds this value, data_cb will not be called, only status_cb.

The following subset of ccapi_receive_error_t errors can be returned by ccapi_receive_add_target():

- CCAPI_RECEIVE_ERROR_NONE
- CCAPI_RECEIVE_ERROR_CCAPI_NOT_RUNNING
- CCAPI_RECEIVE_ERROR_NO_RECEIVE_SUPPORT
- CCAPI_RECEIVE_ERROR_INSUFFICIENT_MEMORY
- CCAPI_RECEIVE_ERROR_INVALID_TARGET
- CCAPI_RECEIVE_ERROR_TARGET_ALREADY_ADDED
- CCAPI_RECEIVE_ERROR_INVALID_DATA_CB
- CCAPI_RECEIVE_ERROR_LOCK_FAILED

See Description of errors for more information.

If you want to stop listening for any specific Device Request, you can remove the target with ccapi_receive_remove_target() function.

    ccapi_receive_error_t ccapi_receive_remove_target(char const * const target);

Parameter | Description
--- | ---
target | Name of the target to remove. It must be unique.

    Registering a target

    int main (void)
    {
        [...]

        init_error = init_cloud_connection(NULL);

        [...]
        receive_error = ccapi_receive_add_target("increment_counter", increment_counter_cb,
                                                 increment_counter_status_cb, DESIRED_MAX_REQUEST_SIZE);
        if (receive_error != CCAPI_RECEIVE_ERROR_NONE) {
            log_error("Cannot register target 'increment_counter', error %d", receive_error);
        }

        [...]

        start_error = start_cloud_connection();

        [...]
    }

The following subset of ccapi_receive_error_t errors can be returned by ccapi_receive_remove_target():

- CCAPI_RECEIVE_ERROR_NONE
- CCAPI_RECEIVE_ERROR_CCAPI_NOT_RUNNING
- CCAPI_RECEIVE_ERROR_NO_RECEIVE_SUPPORT
- CCAPI_RECEIVE_ERROR_INSUFFICIENT_MEMORY
- CCAPI_RECEIVE_ERROR_INVALID_TARGET
- CCAPI_RECEIVE_ERROR_TARGET_NOT_ADDED
- CCAPI_RECEIVE_ERROR_LOCK_FAILED

See Description of errors for more information.

## 2. Define receive callbacks

Custom receive callbacks are required when registering a new target with ccapi_receive_add_target() : a data callback to perform the requested operation, and an optional status callback to check the status of the process. In the example above, increment_counter_cb and increment_counter_status_cb callbacks are those custom callbacks:

### Data callback

Input and output callback where the application performs the necessary operations to attend the request and optionally creates and returns a response to Remote Manager.

The callback typically follows this scheme:

1. Analyze the input data from the request.
2. Perform any necessary operations on the device.
3. Provide a response to Remote Manager. The callback cannot return a response if Remote Manager made the request without requesting a response.

>     typedef void (*ccapi_receive_data_cb_t)(char const * const target, ccapi_transport_t const transport,
>                                             ccapi_buffer_info_t const * const request_buffer_info,
>                                             ccapi_buffer_info_t * const response_buffer_info)

Parameter | Description
--- | ---
target | Name of the received target.
transport | The transport used to received the request. Always CCAPI_TRANSPORT_TCP.
request_buffer_info | Data sent from Remote Manager to the device. It may be empty if no data is required to process the target.
response_buffer_info | Device response to Remote Manager after processing the request.

### Status callback

Cloud Connector calls status user callback (if provided) when the receive process is complete.

This callback provides overall error status. Users should check status and free all possible resources allocated during the receive process, including the memory allocated to provide a response within the data callback.

    typedef void (*ccapi_receive_status_cb_t)(char const * const target, ccapi_transport_t const transport,
                                              ccapi_buffer_info_t * const response_buffer_info, ccapi_receive_error_t receive_error)

Parameter | Description
--- | ---
target | Name of the received target.
transport | The transport used to received the request. Always CCAPI_TRANSPORT_TCP.
response_buffer_info | Device response to Remote Manager after processing the request.
receive_error | Error code after completing the response process to Remote Manager.

This callback has a receive_error argument indicating the final error status. Following subset of ccapi_receive_error_t errors can arrive to this callback:

- CCAPI_RECEIVE_ERROR_NONE
- CCAPI_RECEIVE_ERROR_INSUFFICIENT_MEMORY>
- CCAPI_RECEIVE_ERROR_INVALID_DATA_CB
- CCAPI_RECEIVE_ERROR_USER_REFUSED_TARGET
- CCAPI_RECEIVE_ERROR_REQUEST_TOO_BIG
- CCAPI_RECEIVE_ERROR_STATUS_CANCEL
- CCAPI_RECEIVE_ERROR_STATUS_TIMEOUT
- CCAPI_RECEIVE_ERROR_STATUS_SESSION_ERROR

See Description of errors for more information.

    Data and status callbacks

    int counter = 0;

    void increment_counter_cb(char const *const target, ccapi_transport_t const transport,
                              ccapi_buffer_info_t const *const request_buffer_info, ccapi_buffer_info_t *const response_buffer_info)
    {
        char *request = NULL;
        int increment = 0;

        log_info("Increment counter request!");
        /*
         * Request info is available at request_buffer_info->buffer
         * and is request_buffer_info->length bytes long.
         *
         * Handle the request here. Write response to response_buffer_info
         */

         request = calloc(1, sizeof (char) * (request_buffer_info->length + 1));
         strncpy(request, request_buffer_info->buffer, request_buffer_info->length + 1);

         increment = atoi(request);

         counter = counter + increment;

         response_buffer_info->buffer = calloc(1, sizeof (char) * DESIRED_MAX_RESPONSE_SIZE);
         response_buffer_info->length = sprintf(response_buffer_info->buffer, "Current value: %d", counter);
    }

    void increment_counter_status_cb(char const *const target, ccapi_transport_t const transport,
                                     ccapi_buffer_info_t *const response_buffer_info, ccapi_receive_error_t receive_error)
    {
        log_info("increment_counter_status_cb(): error code='%d'", receive_error);

        /* Free the response buffer */
        free(response_buffer_info->buffer);
    }

Note You can register different targets using the same callback. Use the target parameter in the callback function to distinguish between them.

## 3. Use the API Explorer to send Device Requests

A Device Request can be sent via Web Services within the Remote Manager platform. If you have implemented a Device Request listener and you want to test it, follow these steps:

1. Log in to your Remote Manager account (https://remotemanager.digi.com).

2. Go to Documentation > API Explorer.
3. Select Examples > SCI > Data Service > Send Request.
   Remote Manager automatically creates the necessary code.
4. Replace the "device id" value with the ID of your device.
5. Enter your target name and data for the device request.

    Remote Manager - API Explorer

    <sci_request version="1.0">
      <data_service>
        <targets>
          <device id="XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX"/>
        </targets>
        <requests>
          <device_request target_name="increment_counter">5</device_request>
        </requests>
      </data_service>
    </sci_request>

1. Click Send.

## Description of errors

Error | Description
--- | ---
CCAPI_RECEIVE_ERROR_NONE | Operation completed successfully. No error found.
CCAPI_RECEIVE_ERROR_CCAPI_NOT_RUNNING | You missed calling initialize_cloud_connection() function or it failed.
CCAPI_RECEIVE_ERROR_NO_RECEIVE_SUPPORT | Receive service is not available. It probably has not been started.
CCAPI_RECEIVE_ERROR_INSUFFICIENT_MEMORY | Cloud Connector encountered problems allocating memory to perform receive operations. Your system may have run out of resources.
CCAPI_RECEIVE_ERROR_INVALID_TARGET | The target argument in ccapi_receive_add_target() or ccapi_receive_remove_target() is invalid.
CCAPI_RECEIVE_TARGET_NOT_ADDED | The ccapi_receive_remove_target() is trying to remove a target that was not previously added.
CCAPI_RECEIVE_TARGET_ALREADY_ADDED | The ccapi_receive_add_target() is trying to add a target that is already added.
CCAPI_RECEIVE_ERROR_INVALID_DATA_CB | The ccapi_receive_add_target() was called with data_cb argument set to NULL.
CCAPI_RECEIVE_ERROR_LOCK_FAILED | Cloud Connector encountered problems using synchronization mechanisms. Your system may have run out of resources.
CCAPI_RECEIVE_ERROR_REQUEST_TOO_BIG | Received request is bigger that the limit established by the user through the maximum_request_size argument in the ccapi_receive_add_target() function.
CCAPI_RECEIVE_ERROR_STATUS_TIMEOUT | Session timed out.
CCAPI_RECEIVE_ERROR_STATUS_SESSION_ERROR | Error from lower communication layer. You can check the specific error on the logging output.

## Device Request example

The Device Request listener example demonstrates the usage of the Cloud Connector receive data API. In this example, a target to retrieve the system time is registered.

This example is included in Digi Embedded Yocto. Go to GitHub to look at the application source code.

© 2018 Digi International Inc. All rights reserved.
Receive data from Remote Manager updated on 22 January 2018 02:43:38 PM