/*! \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 CPP 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>The following steps must be taken to run a device-client application.</p>
 * 
 * <ol>
 * <li>Initialize device
 * <pre>
//// Create the device
//// Constructor requires a path to trusted assets store and
//// a password for trusted assets store.
GatewayDevice gwd("trusted_assets_store", "changeit");
//// or
DirectlyConnectedDevice dcd("trusted_assets_store", "changeit");
 * </pre>
 * </li>
 * <li>Activate the device
 * <pre>
//// set supported device models by device
if (!gwd.isActivated()) {
    const std::vector<std::string> deviceModels = {temperatureSensorUrn,
                                                   humiditySensorUrn};
    gwd.activate(deviceModels);
}
 * </pre>
 * </li>
 * <li>Register indirectly-connected devices 
 * <pre>
//// create meta-data with the indirectly-connected device's
//// manufacturer, model, and serial number
const std::map<std::string, std::string> temperatureMeta = {
    {"manufacturer", "A Manufacturer"},
    {"modelNumber", "MN-xxxx-xxxx"},
    {"serialNumber", "SN-yyyyyyyy"}
};
//// add any vendor-specific meta-data to the metaData Map
//// register it
const std::string output_endpoint_id = gwd.registerDevice(false, hardware_id, metadata, humiditySensorUrn);
 * </pre>
 * </li>
 * <li>Create a virtual device implementing the device model 
 * <pre>
deviceModel = gwd.getDeviceModel(device_model_urn);
virtualDevice = gwd.createVirtualDevice(endpointID, deviceModel);
 * </pre>
 * </li>
 * <li>Monitor the device through the virtual device 
 * <pre>
//// set a callback for any changes to this virtual object
virtualDevice.setOnChange(deviceOnChange);
virtualDevice.setOnError(deviceOnError);

//// set a callback for any changes to attribute of this virtual object
virtualDevice.setOnChange(attributeName, deviceOnChange);
virtualDevice.setOnError(attributeName, deviceOnError);

//// set a callback for action
virtualDevice.setOnAction(actionName, deviceOnError);
 * </pre>
 * </li>
 * <li>Control the device through the virtual device  
 * <pre>
//// set a value for a particular attribute in this virtual device
virtualDevice.update()
             .set(attributeName1, attributeValue1)
             .set(attributeName2, attributeValue2)
             .set(attributeName3, attributeValue3)
             .set(attributeName4, attributeValue4)
             .set(attributeName5, attributeValue5)
             .finish();
 * </pre>
 * </li>
 * </ol>
 */