The ThinCloud Embedded C SDK is a header-only library that includes a set of utilities to help embedded devices connect and communicate with ThinCloud. This is especially useful for devices that require a low footprint in disk, memory, and power.
The SDK is based on the AWS IoT Embedded C SDKand depends on json-cto marshal and unmarshal JSON payloads.
This tutorial will show you how to connect to ThinCloud, commission your device, and process command requests using this SDK. The full example and details is available on the SDK’s page.
Connect your device to the cloudFirst configure a MQTT client instance to connect to a ThinCloud MQTT endpoint using your root CA and client public and private key.
AWS_IoT_Client client;
IoT_Error_t rc = tc_init(&client, “xxxxx.us-eas-t-1.amazonaws.com”, “rootCA.pem”, “client.crt”, “client.key”, NULL, NULL);
if (rc != SUCCESS)
{
return rc;
}
Next start the MQTT connection using a unique client ID.
rc = tc_connect(&client, "my-client-id", true);
if (rc != SUCCESS)
{
return rc;
}
With a valid MQTT client initialized and connected, you can start sending and receive messages from ThinCloud.
Commission Your DeviceWe now make a commissioning request. Commissioning registers your device to ThinCloud and assigns a device ID unique to this device. Note that all MQTT requests to ThinCloud follow the JSON-RPC spec.
Note: a device needs to commissioning once during its lifetime or until it resets. Your device will need to keep track of its commissioning status. The device could persist its device ID and check if the device has it on start. In this example we will keep a status flag and the device ID in memory.
Now we define some important values:
- A unique RPC request ID.
- A device type.
- A physical ID.
The physical ID should be unique between devices such as a MAC address.
const char *commissionRequestId = "12345";
const char *deviceType = "lock";
const char *physicalId = "56789";
Using these values, we subscribe to a commissioning response topic. We will be defining the commissioning callback handler later.
rc = subscribe_to_commissioning_response(&client, commissionRequestId, deviceType, physicalId, commissioning_callback_handler, NULL);
Next we define an event loop that can process incoming client events and most importantly call aws_iot_mqtt_yield periodically. The yield function waits on the MQTT client to process subscribe messages and dispatch them to their handlers. More information about the yield function is here.
Within the loop we check if we have sent a commissioning request before and if not we send it now.
while (NETWORK_ATTEMPTING_RECONNECT == rc || NETWORK_RECONNECTED == rc || SUCCESS == rc)
{
rc = aws_iot_mqtt_yield(&client, 100);
if (NETWORK_ATTEMPTING_RECONNECT == rc)
{
continue;
}
if (!isCommissioned && !requestedCommission)
{
rc = send_commissioning_request(&client, commissionRequestId, deviceType, physicalId);
requestedCommission = true;
}
}
Handle Commissioning ResponseNow we define the commissioning callback handler. The client executes this handler when it receives a message on the commissioning response topic we had subscribe to.
Here we unmarshal the commissioning response to extract a device ID. ThinCloud requires this device ID to identify a particular device in consecutive requests. As mentioned before, we want to persist this device ID. In this example, we persist it in memory.
static void commissioning_callback_handler(
AWS_IoT_Client *client,
char *topicName,
uint16_t topicNameLen,
IoT_Publish_Message_Params *params,
void *data)
{
isCommissioned = true;
static uint16_t statusCode = 0;
IoT_Error_t rc = commissioning_response(deviceId, &statusCode, NULL, params->payload, params->payloadLen);
if (rc != SUCCESS)
{
IOT_ERROR("Failed to process commissioning response: rc = %d", rc); return;
}
if (statusCode != 200)
{
IOT_ERROR("Failed to commission device: Status Code = %d", statusCode);
abort();
}
Next we subscribe to device’s command request topic using the newly acquired device ID. ThinCloud will make command requests initiated by clients to this topic.
rc = subscribe_to_command_request(client, deviceId, command_callback_handler, NULL);
if (rc != SUCCESS)
{
IOT_ERROR("Failed to subscribe to command request topic: rc = %d", rc);
return;
}
}
Handle Command RequestsWe now define the command callback handler.
We identify command requests by a method and a command ID which is the same as the RPC request ID. Here we check that we support a method, do some work and then send a response back with the same command ID. ThinCloud requires command ID in the response otherwise the command is not acknowledged in the cloud.
In this example, we support a method called ping and send a pong response.
static void command_callback_handler(
AWS_IoT_Client *client,
char *topicName,
uint16_t topicNameLen,
IoT_Publish_Message_Params *paramsthi,
void *data)
{
char commandId[TC_ID_LENGTH];
char method[16];
json_object *commandParams = json_object_new_array();
IoT_Error_t rc = command_request(commandId, method, &commandParams, params->payload, params->payloadLen);
if (rc != SUCCESS)
{
IOT_ERROR("Failed to process command request: rc = %d", rc); return;
}
if (strcmp(method, "ping") == 0)
{
json_object *body = json_object_new_object();
json_object *data = json_object_new_object();
json_object *pong = json_object_new_string("pong");
json_object_object_add(data, "echo", pong);
json_object_object_add(body, "data", data);
rc = send_command_response(client, deviceId, commandId, 200, false, NULL, body);
if (rc != SUCCESS)
{
IOT_ERROR("Failed to publish command response: rc = %d", rc); return;
}
}
else
{
IOT_WARN("Received a command request with an unsupported method: %s", method);
}
}
ConclusionThis article covered the basics of the ThinCloud Embedded C SDK. It should give you enough information to be able to connect to ThinCloud, commission your device, and start sending and receiving messages. To further explore other capabilities of ThinCloud, see the MQTT API documentation.
Jorge Martinez Hernandez

Comments