/*! \mainpage Device Library overview
 *
 * <p>The device and enterprise client libraries simplify working with the Oracle IoT
 * Cloud Service. These client libraries are a low-level abstraction over
 * top of messages and REST APIs. Device clients are primarily concerned with 
 * sending data and alert messages to the cloud service, and acting upon requests
 * from the cloud service. Enterprise clients are primarily concerned with 
 * monitor and control of device endpoints.</p>
 * 
 * <p>The Oracle Internet of Things C Client Library is a high level native library 
 * for accessing the Oracle IoT Cloud Service. Basically, Cloud Service supports 
 * only low level REST API and this library provides higher level abstraction on 
 * top of that making development of client applications easier and faster.</p>
 *
 * <h2>Trusted Assets</h2>
 *
 * <p>Trusted assets are defined as material that contribute to the chain of trust
 * between the client and the server. The client library relies on an
 * implementation of a TrustedAssetsManager to securely manage these
 * assets on the client. The client-library has a default implementation of the
 * TrustedAssetsManager which uses a trust-store to secure the trust assets.
 * To create the trust-store for the default TrustedAssetsManager, the user must
 * use the iotcs_tam.h methods.</p>
 *
 * <h2>Device Models</h2>
 *
 * <p>A device model is a predefined specification of the attributes, formats and 
 * resources of a device that can be accessed by the client-library. 
 * The attributes of a device model represent the basic variables that the device supports, 
 * such as temperature, humidity, flow rate, valve position, and so forth. 
 * The formats of a device model define the structure of a message payload. 
 * A format describes the message attributes by specifying the attribute names, types, 
 * optionality, and default values. The resources of a device model define additional, 
 * ad-hoc REST resources which provide richer REST support than what is possible with attributes and formats.</p>
 *
 * <h2>Device Client Quick Start</h2>
 * 
 * <p>Note: C Posix library uses strlen(). Be sure tha you use a single byte chars and null terminated strings.</p>
 * <p>The following steps must be taken to run a device-client application.</p>
 * 
 * <ol>
 * <li>Initialize device client
 * <pre>
//// Initialize the library before any other calls. 
//// Initiate all subsystems like ssl, TAM, request dispatcher, 
//// async message dispatcher, etc which needed for correct library work.
//// Initialization require a path to trusted assets store and
//// a password for trusted assets store.
iotcs_init(trusted_assets_store_path, trusted_assets_store_password);
 * </pre>
 * </li>
 * <li>Activate the device
 * <pre>
//// set supported device models by device
if (!iotcs_is_activated()) {
    iotcs_activate(device_models);
}
 * </pre>
 * </li>
 * <li>Register indirectly-connected devices 
 * <pre>
//// create meta-data with the indirectly-connected device's
//// manufacturer, model, and serial number
const static iotcs_key_value temp_metadata[] = {
    {"manufacturer", "A Manufacturer"},
    {"modelNumber", "MN-xxxx-xxxx"},
    {"serialNumber", "SN-yyyyyyyy"},
    {NULL, NULL}
};
//// add any vendor-specific meta-data to the metaData Map
//// register it
iotcs_register_device(hardware_id, metadata, device_models, output_endpoint_id);
 * </pre>
 * </li>
 * <li>Create a virtual device implementing the device model 
 * <pre>
iotcs_get_device_model_handle(device_model_urn, &device_model_handle);
iotcs_get_virtual_device_handle(endpoint_id, device_model_handle, &device_handle);
 * </pre>
 * </li>
 * <li>Monitor the device through the virtual device 
 * <pre>
//// set a callback for any changes to this virtual object
iotcs_virtual_device_set_on_change(device_handle, on_change_callback);
iotcs_virtual_device_set_on_error(device_handle, on_error_callback);

//// set a callback for any changes to attribute of this virtual object
iotcs_virtual_device_attribute_set_on_change(device_handle, attribute_name, on_change_callback);
iotcs_virtual_device_attribute_set_on_error(device_handle, attribute_name, on_error_callback);

//// set a callback for action
iotcs_virtual_device_set_callback(device_handle, action_name, action_callback);
 * </pre>
 * </li>
 * <li>Control the device through the virtual device  
 * <pre>
//// set a value for a particular attribute in this virtual device
iotcs_virtual_device_set(device_handle, attribute_name, value, length);
iotcs_virtual_device_set_string(device_handle, attribute_name, value);
iotcs_virtual_device_set_integer(device_handle, attribute_name, value);
iotcs_virtual_device_set_float(device_handle, attribute_name, value);
iotcs_virtual_device_set_boolean(device_handle, attribute_name, value);
iotcs_virtual_device_set_date_time(device_handle, attribute_name, value);
 * </pre>
 * </li>
 * <li>Dispose the virtual device and the device model
 * <pre>
iotcs_free_virtual_device_handle(device_handle);
iotcs_free_device_model_handle(device_model_handle);
 * </pre>
 * </li>
 *
 * <h2>Storage Cloud Quick Start</h3>
 *
 * <p>This shows how to use a virtual device attribute to upload content to, or download content from, the Oracle Storage Cloud Service. To upload
 * or download content from a virtual device, there must be an attribute, field, or action in the device model with type URI. For the Oracle Storage
 * Cloud Service, the URI type corresponds to the class oracle.iot.client.StorageObject. When the attribute, field, or action of type URI is set to a
 * StorageObject instance, the content is automatically synchronized with the Storage Cloud Service. </p>
 * 
 * <b>Uploading content</b>
 * <p>An instance of iotcs_storage_object_handle is first needed to upload a file from a device client. The
 * iotcs_storage_object_handle is created using the iotcs_create_storage_object_handle API in "iotcs_storage_object_handle.h". The
 * iotcs_storage_object_handle names the object in storage, and provides the mime-type of the content. To set the input file,
 * the iotcs_storage_object_handle API iotcs_storage_object_set_input_path(file_path) is used. </p>
 * <pre>
iotcs_storage_object_handle storage_object;
iotcs_create_storage_object_handle("mediaSnapshot.jpg", "image/jpg", &storage_object);
iotcs_storage_object_set_input_path(storage_object, "../images/mediaSnapshot.jpg");
iotcs_virtual_device_set_storage_object("snapshot", storage_object);
 * </pre>
 * <p> A iotcs_storage_object_handle may also be set on an Alert field, or as an Action parameter, provided the type in the device model is URI. </p>
 * 
 * <b>Downloading content</b>
 * <p>In the virtualization API, the client is notified through an iotcs_virtual_device_change_event event, or a call callback for an action. The value
 * in the event is a iotcs_storage_object_handle. To download the content, the output path is set on the iotcs_storage_object_handle, and the content is
 * synchronized by calling the iotcs_storage_object_sync() API. </p>
 * 
 * <b>Checking synchronization status</b>
 * <p>A iotcs_storage_object_handle is a reference to some content in the Storage Cloud. The content can be in sync with the storage cloud, not in sync
 * with the storage cloud, or in process of being sync'd with the storage cloud. The synchronization happens on a separate thread, but can be monitored
 * by setting a iotcs_storage_object_sync_callback with iotcs_storage_object_set_callback. </p>
 * <p>For the upload case, set the iotcs_storage_object_set_callback on the storage object before setting the virtual device attribute. For the download
 * case, set the iotcs_storage_object_set_callback on the storage object from within the iotcs_virtual_device_changed_callback callback. </p>
 * <p>This example shows the typical use case from an iotcs_virtual_device_change_event event. </p>
 * <pre>

//// include methods for device client
#include "iotcs.h"
//// include iot cs device model APIs
#include "iotcs_virtual_device.h"
#include "iotcs_device.h"
#include "iotcs_storage_object_handle.h"

static void sync_callback(iotcs_storage_object_sync_event *event) {
    printf("\nOn change callback was called for %s with sync status: %d\n", event->name, iotcs_storage_object_get_sync_status(event->source));
    if (iotcs_storage_object_get_sync_status(event->source) == IOTCS_IN_SYNC) {
    	//// File was uploaded
    } else if (iotcs_storage_object_get_sync_status(event->source) == IOTCS_SYNC_FAILED) {
       //// File was not uploaded, take action!
    }
}

static void changed_callback(iotcs_virtual_device_change_event *event) {
    printf("\nOn change callback was called for %s\n", event->named_value.name);
    iotcs_storage_object_handle hstorage = event->named_value.typed_value.value.storage_object;
    
    iotcs_storage_object_set_output_path(hstorage, "output_file.txt");
    iotcs_storage_object_set_callback(hstorage, sync_callback);
    iotcs_sync_storage_handle(hstorage);
}
...
main() {
	
    iotcs_storage_object_handle hstorage;
//// Create storage object
    iotcs_create_storage_object_handle("image", "application/x-www-form-urlencoded", &hstorage);
    iotcs_storage_object_set_callback(hstorage, sync_callback);
    iotcs_virtual_device_set_on_change(device_handle, changed_callback);
    iotcs_storage_object_set_input_path(hstorage, filename);
//// Set new object
    iotcs_virtual_device_set_storage_object_handle(device_handle, "image", hstorage);
}

 * </pre>
 * <li>Dispose the device client 
 * <pre>iotcs_finalize();</pre>
 * </li>
 * </ol>
 */