Connecting to the Cloud in C++
· Overview
In this example, we will create a stand-alone MQTT client in C++ that implements Everyware™ Cloud Communication Data Model. The client will simulate an actual device, publishing data to the platform using the MQTT transport protocol, and subscribing to certain topics. This will give us a test framework to more readily test all aspects of data transfer throughout the Everyware Cloud.
In this section you will learn how to:
This example assumes that you have a working knowledge of writing C++ code and working with a ‘C’ compiler. Instructions are given here for compiling and running the ‘C’ Client project in Linux using the ‘gcc’ compiler, but you could also use a compiler of your choice, such as Visual Studio (2005 or higher).
The Everyware Cloud example code is available on the GitHub repository at https://github.com/eurotech/edc-examples/. Browse to the Eurotech “edc-examples” GitHub repository, and click on the “ZIP” icon to download the sample Cloud applications as a Zip file.
Extract the contents of the Zip file to put the source code into a working location for your development. See the edc-c-client/readme file for more details on the project.
Change directory to the edc-c-client/edctest directory of the source code. Edit the file edctest.cpp. Toward the top of this file, there are several variables noted with comments, which are specific to your Cloud user account. These variables need to be modified according to your Cloud account credentials, so the ‘C’ client can connect properly. See the section Accessing your Cloud Account to set up an account in Everyware Cloud.
In the edctest.cpp file, set the following variables with the proper settings of your Cloud broker account, and save changes:
// >>>>>> Set these variables according to your Cloud user account #define TEST_ACCOUNT_NAME "myEdcAccount" // Your Account name in Cloud #define TEST_BROKER_URL "tcp://broker-sandbox.everyware-cloud.com:1883/" // URL address of broker #define TEST_CLIENT_ID "001122DDEEFF" // Unique Client ID of this client device #define TEST_ASSET_ID "334455AABBCC" // Unique Asset ID of this client device #define TEST_USERNAME "myEdcUserName_broker" // Username in account, to use for publishing #define TEST_PASSWORD "myEdcPassword3#" // Password associated with Username // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
To compile the project in Linux, change to the ‘edc-c-client’ directory, then issue the following commands:
chmod u+x build.sh
./build.sh
The edc-c-client package folder includes a Visual Studio 2005 solution file (ESD.sln) in order to easily build the project on a Windows PC. The rest of this section gives detailed steps about building the edc-c-client solution using Visual C++ 2010 Express IDE that can be downloaded for free from the Microsoft web site.
· Download the Visual C++ 2010 Express web installer from http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express.
· Run the installer application keeping the default install options to install the Visual C++ 2010 Express IDE on your PC.
· Run Visual C++ 2010 Express, select File | Open | Project/Solution… and browse to the ‘EDC.sln’ file in the edc-c-client folder
The IDE will run the Visual Studio Conversion Wizard:
Click the Next button and follow the wizard instruction keeping the default options.
· Once the conversion has completed select the desired build configuration (the default one is Debug) from the menu:
· Right click on the edctest project and select Build:
· Once the build has completed successfully you should see the following in the IDE Output window:
The following sections describe the ‘C’ Client application.
After the code has been compiled:
· Under Linux:change to the edc-c-client/edctest directory, and execute the run.sh script.
· Under Windows: browse to the edc-c-client\release or the edc-c-client\debug directory, according to the build configuration you selected, and execute edctest.exe
This C++ code example starts in the main() method by creating an instance of the EDCConfiguration and sets up its identity as a device which will be connecting to the Everyware Cloud. Then it starts a session, which makes an IP connection to the cloud.
//Create client configuration, and set its properties EdcConfiguration conf; conf.setAccountName(TEST_ACCOUNT_NAME); conf.setBrokerUrl(TEST_BROKER_URL); conf.setClientId(TEST_CLIENT_ID); conf.setDefaultAssetId(TEST_ASSET_ID); conf.setUsername(TEST_USERNAME); conf.setPassword(TEST_PASSWORD); //Create device profile and set its properties EdcDeviceProfile prof; prof.setDisplayName(TEST_ASSET_ID); prof.setModelName("Native EDC Client");
|
The EdcClientFactory is instantiated, using this C++ client as a callback.
//Create cloud client instance edcCloudClient = EdcCloudClient(&conf, &prof, EdcCloudClientMessageArrived, EdcCloudClientMessageDelivered, //Don't pass a connection lost callback //so the client will reconnect automatically 0);
|
If you have the proper credentials and have entered them correctly in the code, you should see the debug statements in stdout that indicate you have made a successful connection and are publishing and receiving subscribed data.
EDC test start
Start session...
If not configured correctly, there will be an error in stdout, such as:
startSession failed with error code -1
MQTTclient, generic operation failure
Next, the application issues a few subscription requests to the cloud (for data topics, and control topics such as birth certificates), so that we can receive back a copy of the messages that we will later publish. See Introduction to MQTT Protocol for more information on subscription topics.
string accountSemanticTopics = "#"; string accountControlTopics = "#"; //subscribe to all data topics int qoss = 1; rc = edcCloudClient.subscribe(accountSemanticTopics, qoss); //subscribe to all control topics rc = edcCloudClient.controlSubscribe(accountControlTopics, qoss); |
Because the application has subscribed to the topic “#”, you automatically receive back all messages that your client (or any other client on this account) publishes to the Cloud.
Then a series of messages is published by the application. The createPayload() method creates an EdcPayload() structure and populates it with various sample metrics of different data types, including an incrementing counter value (Metric: “counter”) and a GPS position that varies randomly.
EdcPayload * payload = createPayload(); rc = edcCloudClient.publish(pubTSemanticTopic, payload, qoss, false, PUBLISH_TIMEOUT); //call createPayload() each time
|
Publish #1 succeeded, semantic topic=nativeclient/data
timestamp: 1340336705
position latitude: 846930931.869079
position longitude: 1804289395.576729
position altitude: 296.000000
position precision: 10.000000
position heading: 2.000000
position speed: 60.000000
position timestamp: 1340336705
position satellites: 3
position status: 1
metric #0 name: counter
metric #0 type: 3
metric #0 int_value: 1
metric #1 name: str
metric #1 type: 5
metric #1 string_value: this is a string
metric #2 name: int
metric #2 type: 3
metric #2 int_value: 1
metric #3 name: flt
metric #3 type: 1
metric #3 float_value: 2.718282
metric #4 name: dbl
metric #4 type: 0
metric #4 double_value: 0.841471
metric #5 name: long
metric #5 type: 2
metric #5 long_value: 100000
metric #6 name: bool
metric #6 type: 4
metric #6 bool_value: 0
metric #7 name: arr
metric #7 type: 6
metric #7 bytes_value: 0x31 0x32 0x33
Because of the subscriptions created earlier, we receive back into our client the same messages that we just published. The EdcCloudClientMessageArrived() callback displays the contents of the messages received as a result of a subscription.
//callback for message arrived int EdcCloudClientMessageArrived(string topic, EdcPayload * payload){ static int rxMsgCount = 0; rxMsgCount ++; printf("Message #%d arrived: topic=%s\r\n", rxMsgCount, topic.c_str()); #ifdef DISPLAY_RX_MSG_PAYLOAD if (payload != 0){ displayPayload(payload); } #endif return 0; }
|
The displayPayload() parses through each Metric in the EDC message payload and displays the contents.
Message #1 arrived: topic=myEdcAccount/334455AABBCC/nativeclient/data
timestamp: 1340336705
position latitude: 846930931.869079
position longitude: 1804289395.576729
position altitude: 296.000000
position precision: 10.000000
position heading: 2.000000
position speed: 60.000000
position timestamp: 1340336705
position satellites: 3
position status: 1
metric #0 name: counter
metric #0 type: 3
metric #0 int_value: 1
metric #1 name: str
metric #1 type: 5
metric #1 string_value: this is a string
metric #2 name: int
metric #2 type: 3
metric #2 int_value: 1
metric #3 name: flt
metric #3 type: 1
metric #3 float_value: 2.718282
metric #4 name: dbl
metric #4 type: 0
metric #4 double_value: 0.841471
metric #5 name: long
metric #5 type: 2
metric #5 long_value: 100000
metric #6 name: bool
metric #6 type: 4
metric #6 bool_value: 0
metric #7 name: arr
metric #7 type: 6
metric #7 bytes_value: 0x31 0x32 0x33
Finally, the application sleeps for several seconds to keep the connection alive and to receive any last subscribed messages that might be received, and then the cloud client session is terminated.
rc = edcCloudClient.stopSession(); edcCloudClient.terminate();
|
EDC test completed
This is the end of this example code. See the section on Viewing Device Data to verify that the data being published from this ‘C’ client is arriving in the Cloud broker.