Implementation Guidelines

Please note the following points when implementing things with the Thing-IF SDK.

Tasks

When implementing with the Thing-IF SDK, you will need to handle multiple tasks (threads).

For example, you will implement some callback functions in your thing program. These callback functions will be executed from the dedicated tasks managed by the SDK. For some features, like the SDK initialization, the thing program will create a task and invoke the SDK.

The following table summarizes the tasks.

Process Which task executes the process? Description
Initializing,
Onboarding
Any task in your program Any task in your program can execute the SDK initialization. Once the initialization is done, there is no more SDK execution the task needs to make. The task can idle or execute non-Thing Interaction Framework processes.
Executing Action Handler Command reception task The SDK manages a dedicated task for receiving a command. This task will execute the action handler.
Executing State Handler State updating task The task that executes the state handler depends on the upload timing:
  • The dedicated task managed by the SDK will update the thing state at regular intervals.
  • The task that executes the action handler (i.e., the command reception task) will update the thing state when the action execution is done.
These two tasks could execute the state handler simultaneously, so the callback function must be reentrant or need to be serialized with the synchronous process.
Allocating Resource for Parsing JSON Any task requesting to parse JSON (in the SDK and in your program) The thing program can have a callback function to allocate the necessary resources for parsing JSON tokens. This callback function will be executed from the tasks that request the JSON parsing. Multiple JSON parsing requests can come simultaneously, so the callback function must be reentrant or need to be serialized with the synchronous process.

Note these points:

  • In addition to the tasks in this table, the Thing SDK Embedded starts a task which periodically sends MQTT PINGREQ commands. This task prevents the MQTT connection from being disconnected when the connection is idle and does not affect processes executed outside the SDK.

  • All the APIs on the thing are blocking APIs. Once a task calls any API, it freezes until the API completes.

Data types

Many data types are used in the Thing-IF SDK. In the guide, we will introduce them as they appear in the sample code. Here, we present a commonly-used one (kii_bool_t).

kii_bool_t

The following kii_bool_t is the boolean data type commonly used throughout the SDK.

typedef enum kii_bool_t {
    KII_FALSE = 0,
    KII_TRUE
} kii_bool_t;

This data type will be imported automatically when you include kii_thing_if.h. The actual declaration is made in kii_core.h that kii_thing_if.h uses internally.

Please be careful not to confuse the APIs that return this boolean type with the ones that return error codes. Most APIs return kii_bool_t, but some APIs return error codes. If your code skips comparing the returned value, it might become hard to comprehend at a glance. Please check the following example:

/* Initialize the Thing-IF SDK. */
if (init_kii_thing_if(...)) {
  /* The function succeeded and returned kii_bool_t. */
}

/* Parse a JSON string. */
if (kii_json_read_object(...)) {
  /* The function failed and returned kii_json_parse_result_t. */
}

String handling

All strings handled by the Thing-IF SDK's C library are null-terminated UTF-8 strings unless described otherwise.

You should have no problem handling characters in the ASCII range. Should you need to use the characters outside the ASCII range (e.g., in the command parameters), you need to handle them as the UTF-8's multibyte characters.

Memory management

The Thing-IF SDK receives designated memory spaces for particular uses from the user program. Heap memory is not used other than these memory spaces.

Process with designated spaces

The SDK gets designated memory spaces for the following purposes at initialization. The user program reserves these memory spaces with the initialization API during SDK initialization.

  • Space for the command handler
  • Space for receiving MQTT messages
  • Space for updating the state

See the sample code of initialization for how to allocate the memory spaces.

General API process

Be careful with the life cycle of memory spaces for APIs which do not use designated spaces. The SDK does not use heap memory for those APIs. Therefore, specified memory spaces as arguments need to be retained for the period in which API results are used.

See the below pseudo code of a program which uses the Thing-IF SDK. An implementation like this would point to non-existent memory space and could cause unexpected behaviors in subsequent processes.

kii_bool_t myInitialize(kii_thing_if_t* kii_thing_if, ...) {
  /* Assume that the lengths of the AppID, AppKey and site have been checked. */
  char appID[100], charAppKey[100], site[10];
  strcpy(appID, config_getAppID());
  strcpy(charAppKey, config_getAppKey());
  strcpy(site, config_getSite());

  /* The program might crash when the SDK uses kii_thing_if */
  return init_kii_thing_if_with_onboarded_thing(kii_thing_if, appID, appKey, site, ...);
}

The above example specifies the AppID and the site for an application as arguments of the init_kii_thing_if_with_onboarded_thing to initialize the kii_thing_if structure. The caller of the myInitialize will use the initialized kii_thing_if.

On the other hand, the API internally implements the below code.

typedef struct kii_thing_if_t {
  char* appID;
  char* appKey;
  char* site;
} kii_thing_if_t;

kii_bool_t init_kii_thing_if_with_onboarded_thing(kii_thing_if* thingIf, char* appID, char* appKey, char* site, ...) {
  thingIf->appID = appID;
  thingIf->appKey = appKey;
  thingIf->site = site;
  return KII_TRUE;
}

The myInitialize calls the API by reserving string buffers on the stack. API does not internally copy the values to heap memory but initialize the kii_thing_if by using the pointers to the spaces of the caller without change. The buffer on the stack will be discarded when the myInitialize process is complete. Therefore, the kii_thing_if will have an invalid reference. This will cause a defect which is very difficult to find.

Such a problem can occur in not only the initialization API but all the Thing-IF APIs. Retain the memory spaces which the API receives from the caller while the API result is used.

Macros for build settings

The Thing-IF SDK provides some rooms for customizing the build conditions with macros. Usually, you do not need to touch these macros. When you need some deep customization and need to dig into the SDK's source code, please use the following information as your reference.

The following table summarizes the available macros. The "default" column in the table shows the default value set in the reference implementation.

Symbol Module using this symbol Default Description
DEBUG KiiThingSDK-Embedded Undefined Set this macro if you want to log debug information. The debug information includes the execution position with the source file name and line number and requests and responses of the REST API. The destination of the logged information is the logger_cb_impl function in the reference implementation.
KII_JSON_FIXED_
TOKEN_NUM
kii_json, KiiThingSDK-Embedded, thing-if-ThingSDK 128 The size of the buffer (i.e., the number of token) to allocate for parsing JSON. Please read here for the details. Consider increasing the value if the action parameter is complex. This macro is mutually exclusive with FLEXIBLE_JSON_TOKEN.
FLEXIBLE_JSON_
TOKEN
kii_json, KiiThingSDK-Embedded, thing-if-ThingSDK Undefined Define this macro to parse JSON strings with dynamically allocated memory. If this macro is defined, kii_json calls a callback function specified with kii_json_t.resource_cb when memory is required. When the callback function allocates memory, kii_json uses it to parse JSON strings. See the comments for resource_cb for the implementation method. This macro is mutually exclusive with KII_JSON_FIXED_TOKEN_NUM.
KII_PUSH_KEEP_ALIVE_
INTERVAL_SECONDS
KiiThingSDK-Embedded, thing-if-ThingSDK 300 Set the number of seconds for the MQTT keep alive timer. This is used as the value of the keep alive timer specified with the CONNECT command and as the interval of sending the PINGREQ command from the client. Kii recommends to set a value which is greater than or equal to 60.
KII_SOCKET_MAX_
BUFF_SIZE
KiiThingSDK-Embedded Undefined The size of buffer (in bytes) to allocate for the socket communication. All HTTP messages will be chunked in this size. The SDK will apply the optimal value (256 bytes) if the symbol is undefined.
KII_THING_IF_NOASSERT thing-if SDK Undefined Define this macro if the system library does not support assert. The reference implementation will automatically define the macro according to the running environment, so you can leave it undefined.
KII_JSON_NOASSERT kii_json Undefined Define this macro if the system library does not support assert. The reference implementation will automatically define the macro according to the running environment, so you can leave it undefined.
JSMN_PARENT_LINKS kii_json, KiiThingSDK-Embedded Undefined The setting for the library the SDK internally uses for parsing JSON. Please leave it undefined.
JSMN_STRICT kii_json, KiiThingSDK-Embedded Undefined The setting for the library the SDK internally uses for parsing JSON. Please leave it undefined.
KII_USE_CUSTOM_
HTTP_CLIENT
KiiThingSDK-Embedded Undefined For the future expansion (aimed to be used for replacing the HTTP/HTTPS client implementation). Please leave it undefined.