NuMaker connection with AWS IoT thru MQTT/HTTPS

Dependencies:   MQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* This example demonstrates connection with AWS IoT through MQTT/HTTPS protocol. 
00002  *
00003  * AWS IoT: Thing Shadow MQTT Topics 
00004  * http://docs.aws.amazon.com/iot/latest/developerguide/thing-shadow-mqtt.html
00005  *
00006  * AWS IoT: Publish to a topic through HTTPS/POST method:
00007  * http://docs.aws.amazon.com/iot/latest/developerguide/protocols.html
00008  *
00009  * AWS IoT: Thing Shadow RESTful API:
00010  * http://docs.aws.amazon.com/iot/latest/developerguide/thing-shadow-rest-api.html
00011  */
00012 
00013 #define AWS_IOT_MQTT_TEST       1
00014 #define AWS_IOT_HTTPS_TEST      0
00015 
00016 #include "mbed.h"
00017 #include "MyTLSSocket.h"
00018 
00019 #if AWS_IOT_MQTT_TEST
00020 /* MQTT-specific header files */
00021 #include "MQTTmbed.h"
00022 #include "MQTTClient.h"
00023 #endif  // End of AWS_IOT_MQTT_TEST
00024 
00025 
00026 namespace {
00027 
00028 /* List of trusted root CA certificates
00029  * currently only GlobalSign, the CA for os.mbed.com
00030  *
00031  * To add more than one root, just concatenate them.
00032  */
00033 const char SSL_CA_CERT_PEM[] = "-----BEGIN CERTIFICATE-----\n"
00034     "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n"
00035     "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n"
00036     "b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n"
00037     "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n"
00038     "b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n"
00039     "ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n"
00040     "9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n"
00041     "IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n"
00042     "VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n"
00043     "93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n"
00044     "jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n"
00045     "AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n"
00046     "A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n"
00047     "U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n"
00048     "N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n"
00049     "o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n"
00050     "5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n"
00051     "rqXRfboQnoZsG4q5WTP468SQvvG5\n"
00052     "-----END CERTIFICATE-----\n";
00053 
00054 /* User certificate which has been activated and attached with specific thing and policy */
00055 const char SSL_USER_CERT_PEM[] = "-----BEGIN CERTIFICATE-----\n"
00056     "MIIDWTCCAkGgAwIBAgIUAzDIpEQWV/yKVo8suGhvjmFY0n4wDQYJKoZIhvcNAQEL\n"
00057     "BQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g\n"
00058     "SW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTE4MDQxNzA5NDMx\n"
00059     "M1oXDTQ5MTIzMTIzNTk1OVowHjEcMBoGA1UEAwwTQVdTIElvVCBDZXJ0aWZpY2F0\n"
00060     "ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKsLlECiw4ud5laejJmL\n"
00061     "bBhafKLdCRx6tkcjBYyEUoAC3Qs2ogqGngQgjU4QJoWpEBO/U1M+e1QtlZ2o/CiL\n"
00062     "MViHA3rYvP86N/TH8pFA3aPKaeEp+WIt5v4OXdfPkVNKTotiRuRCpzRzrY4xKp11\n"
00063     "ouKkVKf3FcNuKIMt/uEhje90KofBbFHQY3HFYe19qIg1m/IBV+npmNlAKElGNSB7\n"
00064     "xHHLzzUuue38s+ceJyzsWuPjFiVYoeyPHF8gDVWf28XJ4KUFs80Deycqe9efroud\n"
00065     "cQY/6aLDWDJXHvhenwoAIbHqUsYRoWoanrg5Cq3id5+pzVkadNV3+x9bGwROhpbQ\n"
00066     "M9ECAwEAAaNgMF4wHwYDVR0jBBgwFoAUVUXg3+Dd1qSnAT9LN413zSdNoE0wHQYD\n"
00067     "VR0OBBYEFIx86SOxw5k/50GtyRjUwlj+9d1gMAwGA1UdEwEB/wQCMAAwDgYDVR0P\n"
00068     "AQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IBAQCI1fqqjvLAFzL2E1nvWMrkaWN2\n"
00069     "EQK44uOcw53ZzgNNH7fJ85BW8T2l1yZx/Blgs10pEp7vmccnRoR7nYbUGO8++9nG\n"
00070     "S7bfZhiaE2syJqqvLwPGdqR6fvDdfEpmhgJ1CqeMCqun9XZvUTsgBn7Sqqz7P99h\n"
00071     "gGmDRKS/CtsPai0Df0ZPNuV/YuUkpHKJSDm+ZTnzevMS3KXkG1cc/sIuc4IwF+aj\n"
00072     "nbyzdC2fN0r+34srQ8/9aXezOTQ0NBWtoJCCkD+LL6PYJJkAgLA2jcbcbuRJUQ7n\n"
00073     "Zsp25kKX40fuyIcgPRsd/7sao3zTVYxwKy8r6/mbgrPiMeHvJZ8y3nwUpsPO\n"
00074     "-----END CERTIFICATE-----\n";
00075 
00076 /* User private key paired with above */
00077 const char SSL_USER_PRIV_KEY_PEM[] = "-----BEGIN RSA PRIVATE KEY-----\n"
00078     "MIIEowIBAAKCAQEAqwuUQKLDi53mVp6MmYtsGFp8ot0JHHq2RyMFjIRSgALdCzai\n"
00079     "CoaeBCCNThAmhakQE79TUz57VC2Vnaj8KIsxWIcDeti8/zo39MfykUDdo8pp4Sn5\n"
00080     "Yi3m/g5d18+RU0pOi2JG5EKnNHOtjjEqnXWi4qRUp/cVw24ogy3+4SGN73Qqh8Fs\n"
00081     "UdBjccVh7X2oiDWb8gFX6emY2UAoSUY1IHvEccvPNS657fyz5x4nLOxa4+MWJVih\n"
00082     "7I8cXyANVZ/bxcngpQWzzQN7Jyp715+ui51xBj/posNYMlce+F6fCgAhsepSxhGh\n"
00083     "ahqeuDkKreJ3n6nNWRp01Xf7H1sbBE6GltAz0QIDAQABAoIBAAzl7KILJA/NMmdp\n"
00084     "wVR6zQXxHODzJhK9ti0bGPoFqGr6zExiLEn66MOK6NzwHteJbirvDIuEdKxeW5/t\n"
00085     "9EXiaTAxzjNfULE2ZK3Svhnx+ES3qNBP5/xdVcPmtXDmuCC9w7qDCLGBzTYJWxcT\n"
00086     "4hDJpCTPG4sm+L8p+Wga+dNkQl3CFyHHINDZ0pKcP0kDDt6inKfiU7uU4lFYbCZy\n"
00087     "PceUgIOTQiNVoPQYtkHgZAtmD9rcwdq2/0GZEbzTkZuSE9S8+WlGxJP5xMGzeVsv\n"
00088     "zZ/scx0LM7fz5Zq0lsvAwSB1mcs04DaaNpU7Z0tXDIS249RTqdtpPkJzmevpAGhF\n"
00089     "VNe30/kCgYEA4rflfqyw/YHWKRxCGJRO+q0gPvlBIes30noz5Hxl0knb/J5Ng4Nx\n"
00090     "xMaIMZgCbwHbw5i01JOPvVKICROKb8wkli4Y2eVzxMPKk2CSpji16RQZ4eOl3YXL\n"
00091     "1Vnn07Ei+GpsGgDNF0HWf/Ur7es/KdAPCWbKJyoSR90+WN29gP2+Zp8CgYEAwSLv\n"
00092     "Kt/vdd6XKnR9xR3IajsW/X2GR/x/m2JffJPOP6VpDTKAbv86hVHDV0oBEDMDc7qy\n"
00093     "023ognyFCPb9Gzol2lq8egjMsisA2bgoB9HqldrSYlaZ0wPe0QJBf1gZ29jPyVJ0\n"
00094     "ciaBbNbSRhwTrwet7Bae9EbpJsyvBxVh00v0f48CgYEAvKQKviXudmCL01UB4fW0\n"
00095     "6XsXs44tlY1juyuW9exTxG9ULZOCJ4U9Kl+OfsVecQL42ny7KY1GMl7zdanerDsN\n"
00096     "zi+42cTDWNsYORxHqSrSoYbqKjwCjJmBCppt/IQM9umF3PUBsPJFCd7zmFj/C0lk\n"
00097     "2Yu/dGrbHxSFheeqgCOhQz0CgYBfZxdHUYji64o2cYay+QxH1Vp86yWKp6KNKeHL\n"
00098     "EuP9soKa/0hMDA1nT8UzeB3gV6Kr5xxwrkj9M+8vR3otmeKa4tlZWsFqfS2VXo9/\n"
00099     "lWTQk1/7LZYckzvceMXL1sQnQgkaBH366SRjlBYYhcP/YMa76Uypk+GVxePrltdU\n"
00100     "3Z8v5wKBgEXL38yc9LqTIWe1U40ZZKvp2A8c86jtstorEEFqXharE8kxcEpL8ZLL\n"
00101     "wjgPKdfNMIuApHSrhG7a7gU1rgJyDy1sOIwSvgTYrWfITPTVu5owvSZEblx4KYOm\n"
00102     "g8hke3Oego4v9cwctkQss3/HZ6rs3PR942oAetuxLy3KPF83IeFm\n"
00103     "-----END RSA PRIVATE KEY-----\n";
00104 
00105 #if AWS_IOT_MQTT_TEST
00106 
00107 #define AWS_IOT_MQTT_SERVER_NAME                "a1fljoeglhtf61-ats.iot.us-east-2.amazonaws.com"
00108 #define AWS_IOT_MQTT_SERVER_PORT                8883
00109 
00110 #define AWS_IOT_MQTT_THINGNAME                  "Nuvoton-Mbed-D001"
00111 
00112 /* Uncomment and assign one unique MQTT client name; otherwise, one random will be assigned. */
00113 //#define AWS_IOT_MQTT_CLIENTNAME                 "Nuvoton Client"
00114 
00115 /* User self-test topic */
00116 const char USER_MQTT_TOPIC[] = "Nuvoton/Mbed/D001";
00117 const char *USER_MQTT_TOPIC_FILTERS[] = {
00118     "Nuvoton/Mbed/+"
00119 };
00120 const char USER_MQTT_TOPIC_PUBLISH_MESSAGE[] = "{ \"message\": \"Hello from Nuvoton Mbed device\" }";
00121 
00122 /* Update thing shadow */
00123 const char UPDATETHINGSHADOW_MQTT_TOPIC[] = "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/update";
00124 const char *UPDATETHINGSHADOW_MQTT_TOPIC_FILTERS[] = {
00125     "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/update/accepted",
00126     "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/update/rejected"
00127 };
00128 const char UPDATETHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE[] = "{ \"state\": { \"reported\": { \"attribute1\": 3, \"attribute2\": \"1\" } } }";
00129 
00130 /* Get thing shadow */
00131 const char GETTHINGSHADOW_MQTT_TOPIC[] = "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/get";
00132 const char *GETTHINGSHADOW_MQTT_TOPIC_FILTERS[] = {
00133     "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/get/accepted",
00134     "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/get/rejected"
00135 };
00136 const char GETTHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE[] = "";
00137 
00138 /* Delete thing shadow */
00139 const char DELETETHINGSHADOW_MQTT_TOPIC[] = "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/delete";
00140 const char *DELETETHINGSHADOW_MQTT_TOPIC_FILTERS[] = {
00141     "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/delete/accepted",
00142     "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/delete/rejected"
00143 };
00144 const char DELETETHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE[] = "";
00145 
00146 /* MQTT user buffer size */
00147 const int MQTT_USER_BUFFER_SIZE = 600;
00148 
00149 /* Configure MAX_MQTT_PACKET_SIZE to meet your application.
00150  * We may meet unknown MQTT error with MAX_MQTT_PACKET_SIZE too small, but 
00151  * MQTT lib doesn't tell enough error message. Try to enlarge it. */
00152 const int MAX_MQTT_PACKET_SIZE = 1000;
00153 
00154 /* Timeout for receiving message with subscribed topic */
00155 const int MQTT_RECEIVE_MESSAGE_WITH_SUBSCRIBED_TOPIC_TIMEOUT_MS = 5000;
00156 
00157 #if !defined(AWS_IOT_MQTT_CLIENTNAME)
00158 #if TARGET_M23_NS
00159 extern "C"
00160 int mbedtls_hardware_poll( void *data, unsigned char *output, size_t len, size_t *olen );
00161 #endif
00162 #endif
00163 
00164 #endif  // End of AWS_IOT_MQTT_TEST
00165 
00166 #if AWS_IOT_HTTPS_TEST
00167 
00168 #define AWS_IOT_HTTPS_SERVER_NAME               "a1fljoeglhtf61-ats.iot.us-east-2.amazonaws.com"
00169 #define AWS_IOT_HTTPS_SERVER_PORT               8443
00170 
00171 #define AWS_IOT_HTTPS_THINGNAME                 "Nuvoton-Mbed-D001"
00172 
00173 /* Publish to user topic through HTTPS/POST 
00174  * HTTP POST https://"endpoint"/topics/"yourTopicHierarchy" */
00175 const char USER_TOPIC_HTTPS_PATH[] = "/topics/Nuvoton/Mbed/D001?qos=1";
00176 const char USER_TOPIC_HTTPS_REQUEST_METHOD[] = "POST";
00177 const char USER_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = "{ \"message\": \"Hello from Nuvoton Mbed device\" }";
00178 
00179 /* Update thing shadow by publishing to UpdateThingShadow topic through HTTPS/POST
00180  * HTTP POST https://"endpoint"/topics/$aws/things/"thingName"/shadow/update */
00181 const char UPDATETHINGSHADOW_TOPIC_HTTPS_PATH[] = "/topics/$aws/things/" AWS_IOT_HTTPS_THINGNAME "/shadow/update?qos=1";
00182 const char UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD[] = "POST";
00183 const char UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = "{ \"state\": { \"reported\": { \"attribute1\": 3, \"attribute2\": \"1\" } } }";
00184 
00185 /* Get thing shadow by publishing to GetThingShadow topic through HTTPS/POST
00186  * HTTP POST https://"endpoint"/topics/$aws/things/"thingName"/shadow/get */
00187 const char GETTHINGSHADOW_TOPIC_HTTPS_PATH[] = "/topics/$aws/things/" AWS_IOT_HTTPS_THINGNAME "/shadow/get?qos=1";
00188 const char GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD[] = "POST";
00189 const char GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = "";
00190 
00191 /* Delete thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST
00192  * HTTP POST https://"endpoint"/topics/$aws/things/"thingName"/shadow/delete */
00193 const char DELETETHINGSHADOW_TOPIC_HTTPS_PATH[] = "/topics/$aws/things/" AWS_IOT_HTTPS_THINGNAME "/shadow/delete?qos=1";
00194 const char DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD[] = "POST";
00195 const char DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = "";
00196 
00197 /* Update thing shadow RESTfully through HTTPS/POST
00198  * HTTP POST https://endpoint/things/thingName/shadow */
00199 const char UPDATETHINGSHADOW_THING_HTTPS_PATH[] = "/things/" AWS_IOT_HTTPS_THINGNAME "/shadow";
00200 const char UPDATETHINGSHADOW_THING_HTTPS_REQUEST_METHOD[] = "POST";
00201 const char UPDATETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY[] = "{ \"state\": { \"desired\": { \"attribute1\": 1, \"attribute2\": \"2\" }, \"reported\": { \"attribute1\": 2, \"attribute2\": \"1\" } } }";
00202 
00203 /* Get thing shadow RESTfully through HTTPS/GET
00204  * HTTP GET https://"endpoint"/things/"thingName"/shadow */
00205 const char GETTHINGSHADOW_THING_HTTPS_PATH[] = "/things/" AWS_IOT_HTTPS_THINGNAME "/shadow";
00206 const char GETTHINGSHADOW_THING_HTTPS_REQUEST_METHOD[] = "GET";
00207 const char GETTHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY[] = "";
00208 
00209 /* Delete thing shadow RESTfully through HTTPS/DELETE
00210  * HTTP DELETE https://endpoint/things/thingName/shadow */
00211 const char DELETETHINGSHADOW_THING_HTTPS_PATH[] = "/things/" AWS_IOT_HTTPS_THINGNAME "/shadow";
00212 const char DELETETHINGSHADOW_THING_HTTPS_REQUEST_METHOD[] = "DELETE";
00213 const char DELETETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY[] = "";
00214 
00215 /* HTTPS user buffer size */
00216 const int HTTPS_USER_BUFFER_SIZE = 600;
00217 
00218 const char *HTTPS_OK_STR = "200 OK";
00219 
00220 #endif  // End of AWS_IOT_HTTPS_TEST
00221 
00222 }
00223 
00224 #if AWS_IOT_MQTT_TEST
00225 
00226 /**
00227  * /brief   AWS_IoT_MQTT_Test implements the logic with AWS IoT User/Thing Shadow topics through MQTT.
00228  */
00229 class AWS_IoT_MQTT_Test {
00230 
00231 public:
00232     /**
00233      * @brief   AWS_IoT_MQTT_Test Constructor
00234      *
00235      * @param[in] domain    Domain name of the MQTT server
00236      * @param[in] port      Port number of the MQTT server
00237      * @param[in] net_iface Network interface
00238      */
00239     AWS_IoT_MQTT_Test(const char * domain, const uint16_t port, NetworkInterface *net_iface) :
00240         _domain(domain), _port(port), _net_iface(net_iface) {
00241         _tlssocket = new MyTLSSocket;
00242         _mqtt_client = new MQTT::Client<MyTLSSocket, Countdown, MAX_MQTT_PACKET_SIZE>(*_tlssocket);
00243     }
00244 
00245     /**
00246      * @brief AWS_IoT_MQTT_Test Destructor
00247      */
00248     ~AWS_IoT_MQTT_Test() {
00249         delete _mqtt_client;
00250         _mqtt_client = NULL;
00251 
00252         _tlssocket->close();
00253         delete _tlssocket;
00254         _tlssocket = NULL;
00255     }
00256     /**
00257      * @brief   Start AWS IoT test through MQTT
00258      */
00259     void start_test() {
00260 
00261         int tls_rc;
00262         int mqtt_rc;
00263 
00264         do {
00265             /* Set host name of the remote host, used for certificate checking */
00266             _tlssocket->set_hostname(_domain);
00267 
00268             /* Set the certification of Root CA */
00269             tls_rc = _tlssocket->set_root_ca_cert(SSL_CA_CERT_PEM);
00270             if (tls_rc != NSAPI_ERROR_OK) {
00271                 printf("TLSSocket::set_root_ca_cert(...) returned %d\n", tls_rc);
00272                 break;
00273             }
00274 
00275             /* Set client certificate and client private key */
00276             tls_rc = _tlssocket->set_client_cert_key(SSL_USER_CERT_PEM, SSL_USER_PRIV_KEY_PEM);
00277             if (tls_rc != NSAPI_ERROR_OK) {
00278                 printf("TLSSocket::set_client_cert_key(...) returned %d\n", tls_rc);
00279                 break;
00280             }
00281 
00282             /* Blocking mode */
00283             _tlssocket->set_blocking(true);
00284 
00285             /* Open a network socket on the network stack of the given network interface */
00286             printf("Opening network socket on network stack\n");
00287             tls_rc = _tlssocket->open(_net_iface);
00288             if (tls_rc != NSAPI_ERROR_OK) {
00289                 printf("Opens network socket on network stack failed: %d\n", tls_rc);
00290                 break;
00291             }
00292             printf("Opens network socket on network stack OK\n");
00293 
00294             /* DNS resolution */
00295             printf("DNS resolution for %s...\n", _domain);
00296             SocketAddress sockaddr;
00297             tls_rc = _net_iface->gethostbyname(_domain, &sockaddr);
00298             if (tls_rc != NSAPI_ERROR_OK) {
00299                 printf("DNS resolution for %s failed with %d\n", _domain, tls_rc);
00300                 break;
00301             }
00302             sockaddr.set_port(_port);
00303             printf("DNS resolution for %s: %s:%d\n", _domain, sockaddr.get_ip_address(), sockaddr.get_port());
00304 
00305             /* Connect to the server */
00306             /* Initialize TLS-related stuff */
00307             printf("Connecting with %s:%d\n", _domain, _port);
00308             tls_rc = _tlssocket->connect(sockaddr);
00309             if (tls_rc != NSAPI_ERROR_OK) {
00310                 printf("Connects with %s:%d failed: %d\n", _domain, _port, tls_rc);
00311                 break;
00312             }
00313             printf("Connects with %s:%d OK\n", _domain, _port);
00314 
00315             /* See the link below for AWS IoT support for MQTT:
00316              * http://docs.aws.amazon.com/iot/latest/developerguide/protocols.html */
00317 
00318             /* MQTT connect */
00319             /* The message broker does not support persistent sessions (connections made with 
00320              * the cleanSession flag set to false. */
00321             MQTTPacket_connectData conn_data = MQTTPacket_connectData_initializer;
00322             /* AWS IoT message broker implementation is based on MQTT version 3.1.1
00323              * 3 = 3.1
00324              * 4 = 3.1.1 */
00325             conn_data.MQTTVersion = 4;
00326             /* Version number of this structure. Must be 0 */
00327             conn_data.struct_version = 0;
00328 
00329             /* The message broker uses the client ID to identify each client. The client ID is passed
00330              * in from the client to the message broker as part of the MQTT payload. Two clients with
00331              * the same client ID are not allowed to be connected concurrently to the message broker.
00332              * When a client connects to the message broker using a client ID that another client is using,
00333              * a CONNACK message will be sent to both clients and the currently connected client will be
00334              * disconnected. */
00335 #if defined(AWS_IOT_MQTT_CLIENTNAME)
00336             conn_data.clientID.cstring = AWS_IOT_MQTT_CLIENTNAME;
00337 #else
00338             char client_id_data[32];
00339 #if TARGET_M23_NS
00340             /* FMC/UID lies in SPE and is inaccessible to NSPE. Use random to generate pseudo-unique instead. */
00341             uint32_t rand_words[3];
00342             size_t olen;
00343             mbedtls_hardware_poll(NULL, (unsigned char *) rand_words, sizeof(rand_words), &olen);
00344             snprintf(client_id_data, sizeof(client_id_data), "%08X-%08X-%08X",
00345                      rand_words[0], rand_words[1], rand_words[2]);
00346 #else
00347             /* Use FMC/UID to generate unique client ID */
00348             SYS_UnlockReg();
00349             FMC_Open();
00350             snprintf(client_id_data, sizeof(client_id_data), "%08X-%08X-%08X",
00351                      FMC_ReadUID(0), FMC_ReadUID(1), FMC_ReadUID(2));
00352             FMC_Close();
00353             SYS_LockReg();
00354 #endif
00355             conn_data.clientID.cstring = client_id_data;
00356 #endif
00357             printf("Resolved MQTT client ID: %s\n", conn_data.clientID.cstring);
00358 
00359             /* The message broker does not support persistent sessions (connections made with 
00360              * the cleanSession flag set to false. The AWS IoT message broker assumes all sessions 
00361              * are clean sessions and messages are not stored across sessions. If an MQTT client 
00362              * attempts to connect to the AWS IoT message broker with the cleanSession set to false, 
00363              * the client will be disconnected. */
00364             conn_data.cleansession = 1;
00365             //conn_data.username.cstring = "USERNAME";
00366             //conn_data.password.cstring = "PASSWORD";
00367 
00368             MQTT::connackData connack_data;
00369 
00370             /* _tlssocket must connect to the network endpoint before calling this. */
00371             printf("MQTT connecting");
00372             if ((mqtt_rc = _mqtt_client->connect(conn_data, connack_data)) != 0) {
00373                 printf("\rMQTT connects failed: %d\n", mqtt_rc);
00374                 break;
00375             }
00376             printf("\rMQTT connects OK\n\n");
00377 
00378             /* Subscribe/publish user topic */
00379             printf("Subscribing/publishing user topic\n");
00380             if (! sub_pub_topic(USER_MQTT_TOPIC, USER_MQTT_TOPIC_FILTERS, sizeof (USER_MQTT_TOPIC_FILTERS) / sizeof (USER_MQTT_TOPIC_FILTERS[0]), USER_MQTT_TOPIC_PUBLISH_MESSAGE)) {
00381                 break;
00382             }
00383             printf("Subscribes/publishes user topic OK\n\n");
00384 
00385             /* Subscribe/publish UpdateThingShadow topic */
00386             printf("Subscribing/publishing UpdateThingShadow topic\n");
00387             if (! sub_pub_topic(UPDATETHINGSHADOW_MQTT_TOPIC, UPDATETHINGSHADOW_MQTT_TOPIC_FILTERS, sizeof (UPDATETHINGSHADOW_MQTT_TOPIC_FILTERS) / sizeof (UPDATETHINGSHADOW_MQTT_TOPIC_FILTERS[0]), UPDATETHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE)) {
00388                 break;
00389             }
00390             printf("Subscribes/publishes UpdateThingShadow topic OK\n\n");
00391 
00392             /* Subscribe/publish GetThingShadow topic */
00393             printf("Subscribing/publishing GetThingShadow topic\n");
00394             if (! sub_pub_topic(GETTHINGSHADOW_MQTT_TOPIC, GETTHINGSHADOW_MQTT_TOPIC_FILTERS, sizeof (GETTHINGSHADOW_MQTT_TOPIC_FILTERS) / sizeof (GETTHINGSHADOW_MQTT_TOPIC_FILTERS[0]), GETTHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE)) {
00395                 break;
00396             }
00397             printf("Subscribes/publishes GetThingShadow topic OK\n\n");
00398 
00399             /* Subscribe/publish DeleteThingShadow topic */
00400             printf("Subscribing/publishing DeleteThingShadow topic\n");
00401             if (! sub_pub_topic(DELETETHINGSHADOW_MQTT_TOPIC, DELETETHINGSHADOW_MQTT_TOPIC_FILTERS, sizeof (DELETETHINGSHADOW_MQTT_TOPIC_FILTERS) / sizeof (DELETETHINGSHADOW_MQTT_TOPIC_FILTERS[0]), DELETETHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE)) {
00402                 break;
00403             }
00404             printf("Subscribes/publishes DeleteThingShadow topic OK\n\n");
00405 
00406         } while (0);
00407 
00408         printf("MQTT disconnecting");
00409         if ((mqtt_rc = _mqtt_client->disconnect()) != 0) {
00410             printf("\rMQTT disconnects failed %d\n\n", mqtt_rc);
00411         }
00412         printf("\rMQTT disconnects OK\n\n");
00413 
00414         _tlssocket->close();
00415     }
00416 
00417 protected:
00418 
00419     /**
00420      * @brief   Subscribe/publish specific topic
00421      */
00422     bool sub_pub_topic(const char *topic, const char **topic_filters, size_t topic_filters_size, const char *publish_message_body) {
00423 
00424         bool ret = false;
00425         int mqtt_rc;
00426 
00427         do {
00428             const char **topic_filter;
00429             const char **topic_filter_end = topic_filters + topic_filters_size;
00430 
00431             for (topic_filter = topic_filters; topic_filter != topic_filter_end; topic_filter ++) {
00432                 /* AWS IoT does not support publishing and subscribing with QoS 2.
00433                  * The AWS IoT message broker does not send a PUBACK or SUBACK when QoS 2 is requested. */
00434                 printf("MQTT subscribing to %s", *topic_filter);
00435                 if ((mqtt_rc = _mqtt_client->subscribe(*topic_filter, MQTT::QOS1, message_arrived)) != 0) {
00436                     printf("\rMQTT subscribes to %s failed: %d\n", *topic_filter, mqtt_rc);
00437                     continue;
00438                 }
00439                 printf("\rMQTT subscribes to %s OK\n", *topic_filter);
00440             }
00441 
00442             /* Clear count of received message with subscribed topic */
00443             clear_message_arrive_count();
00444 
00445             MQTT::Message message;
00446 
00447             int _bpos;
00448 
00449             _bpos = snprintf(_buffer, sizeof (_buffer) - 1, publish_message_body);
00450             if (_bpos < 0 || ((size_t) _bpos) > (sizeof (_buffer) - 1)) {
00451                 printf("snprintf failed: %d\n", _bpos);
00452                 break;
00453             }
00454             _buffer[_bpos] = 0;
00455             /* AWS IoT does not support publishing and subscribing with QoS 2.
00456              * The AWS IoT message broker does not send a PUBACK or SUBACK when QoS 2 is requested. */
00457             message.qos = MQTT::QOS1;
00458             message.retained = false;
00459             message.dup = false;
00460             message.payload = _buffer;
00461             message.payloadlen = strlen(_buffer);
00462             /* Print publish message */
00463             printf("Message to publish:\n");
00464             printf("%s\n", _buffer);
00465             printf("MQTT publishing message to %s", topic);
00466             if ((mqtt_rc = _mqtt_client->publish(topic, message)) != 0) {
00467                 printf("\rMQTT publishes message to %s failed: %d\n", topic, mqtt_rc);
00468                 break;
00469             }
00470             printf("\rMQTT publishes message to %s OK\n", topic);
00471 
00472             /* Receive message with subscribed topic */
00473             printf("MQTT receives message with subscribed %s...\n", topic);
00474             Timer timer;
00475             timer.start();
00476             while (! _message_arrive_count) {
00477                 if (timer.read_ms() >= MQTT_RECEIVE_MESSAGE_WITH_SUBSCRIBED_TOPIC_TIMEOUT_MS) {
00478                     printf("MQTT receives message with subscribed %s TIMEOUT\n", topic);
00479                     break;
00480                 }
00481 
00482                 _mqtt_client->yield(100);
00483             }
00484             if (_message_arrive_count) {
00485                 printf("MQTT receives message with subscribed %s OK\n", topic);
00486             }
00487             printf("\n");
00488 
00489             /* Unsubscribe 
00490              * We meet second unsubscribe failed. This is caused by MQTT lib bug. */
00491             for (topic_filter = topic_filters; topic_filter != topic_filter_end; topic_filter ++) {
00492                 printf("MQTT unsubscribing from %s", *topic_filter);
00493                 if ((mqtt_rc = _mqtt_client->unsubscribe(*topic_filter)) != 0) {
00494                     printf("\rMQTT unsubscribes from %s failed: %d\n", *topic_filter, mqtt_rc);
00495                     continue;
00496                 }
00497                 printf("\rMQTT unsubscribes from %s OK\n", *topic_filter);
00498             }
00499 
00500             ret = true;
00501 
00502         } while (0);
00503 
00504         return ret;
00505     }
00506 
00507 protected:
00508     MyTLSSocket *                                                           _tlssocket;
00509     MQTT::Client<MyTLSSocket, Countdown, MAX_MQTT_PACKET_SIZE> *            _mqtt_client;
00510 
00511     const char *_domain;                    /**< Domain name of the MQTT server */
00512     const uint16_t _port;                   /**< Port number of the MQTT server */
00513     char _buffer[MQTT_USER_BUFFER_SIZE];    /**< User buffer */
00514     NetworkInterface *_net_iface;
00515 
00516 private:
00517     static volatile uint16_t   _message_arrive_count;
00518 
00519     static void message_arrived(MQTT::MessageData& md) {
00520         MQTT::Message &message = md.message;
00521         printf("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
00522         printf("Payload:\n");
00523         printf("%.*s\n", message.payloadlen, (char*)message.payload);
00524         ++ _message_arrive_count;
00525     }
00526 
00527     static void clear_message_arrive_count() {
00528         _message_arrive_count = 0;
00529     }
00530 };
00531 
00532 volatile uint16_t   AWS_IoT_MQTT_Test::_message_arrive_count = 0;
00533 
00534 #endif  // End of AWS_IOT_MQTT_TEST
00535 
00536 
00537 #if AWS_IOT_HTTPS_TEST
00538 
00539 /**
00540  * /brief   AWS_IoT_HTTPS_Test implements the logic with AWS IoT User/Thing Shadow topics (publish-only)
00541  *          and Thing Shadow RESTful API through HTTPS.
00542  */
00543 class AWS_IoT_HTTPS_Test {
00544 
00545 public:
00546     /**
00547      * @brief   AWS_IoT_HTTPS_Test Constructor
00548      *
00549      * @param[in] domain    Domain name of the HTTPS server
00550      * @param[in] port      Port number of the HTTPS server
00551      * @param[in] net_iface Network interface
00552      */
00553     AWS_IoT_HTTPS_Test(const char * domain, const uint16_t port, NetworkInterface *net_iface) :
00554         _domain(domain), _port(port), _net_iface(net_iface) {
00555         _tlssocket = new MyTLSSocket;
00556     }
00557     /**
00558      * @brief AWS_IoT_HTTPS_Test Destructor
00559      */
00560     ~AWS_IoT_HTTPS_Test() {
00561         _tlssocket->close();
00562         delete _tlssocket;
00563         _tlssocket = NULL;
00564     }
00565     /**
00566      * @brief Start AWS IoT test through HTTPS
00567      *
00568      * @param[in] path  The path of the file to fetch from the HTTPS server
00569      */
00570     void start_test() {
00571 
00572         int tls_rc;
00573 
00574         do {
00575             /* Set host name of the remote host, used for certificate checking */
00576             _tlssocket->set_hostname(_domain);
00577 
00578             /* Set the certification of Root CA */
00579             tls_rc = _tlssocket->set_root_ca_cert(SSL_CA_CERT_PEM);
00580             if (tls_rc != NSAPI_ERROR_OK) {
00581                 printf("TLSSocket::set_root_ca_cert(...) returned %d\n", tls_rc);
00582                 break;
00583             }
00584 
00585             /* Set client certificate and client private key */
00586             tls_rc = _tlssocket->set_client_cert_key(SSL_USER_CERT_PEM, SSL_USER_PRIV_KEY_PEM);
00587             if (tls_rc != NSAPI_ERROR_OK) {
00588                 printf("TLSSocket::set_client_cert_key(...) returned %d\n", tls_rc);
00589                 break;
00590             }
00591 
00592             /* Open a network socket on the network stack of the given network interface */
00593             printf("Opening network socket on network stack\n");
00594             tls_rc = _tlssocket->open(_net_iface);
00595             if (tls_rc != NSAPI_ERROR_OK) {
00596                 printf("Opens network socket on network stack failed: %d\n", tls_rc);
00597                 break;
00598             }
00599             printf("Opens network socket on network stack OK\n");
00600 
00601             /* DNS resolution */
00602             printf("DNS resolution for %s...\n", _domain);
00603             SocketAddress sockaddr;
00604             tls_rc = _net_iface->gethostbyname(_domain, &sockaddr);
00605             if (tls_rc != NSAPI_ERROR_OK) {
00606                 printf("DNS resolution for %s failed with %d\n", _domain, tls_rc);
00607                 break;
00608             }
00609             sockaddr.set_port(_port);
00610             printf("DNS resolution for %s: %s:%d\n", _domain, sockaddr.get_ip_address(), sockaddr.get_port());
00611 
00612             /* Connect to the server */
00613             /* Initialize TLS-related stuff */
00614             printf("Connecting with %s:%d\n", _domain, _port);
00615             tls_rc = _tlssocket->connect(sockaddr);
00616             if (tls_rc != NSAPI_ERROR_OK) {
00617                 printf("Connects with %s:%d failed: %d\n", _domain, _port, tls_rc);
00618                 break;
00619             }
00620             printf("Connects with %s:%d OK\n", _domain, _port);
00621 
00622             /* Non-blocking mode
00623              *
00624              * Don't change to non-blocking mode before connect; otherwise, we may meet NSAPI_ERROR_IN_PROGRESS.
00625              */
00626             _tlssocket->set_blocking(false);
00627 
00628             /* Publish to user topic through HTTPS/POST */
00629             printf("Publishing to user topic through HTTPS/POST\n");
00630             if (! run_req_resp(USER_TOPIC_HTTPS_PATH, USER_TOPIC_HTTPS_REQUEST_METHOD, USER_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) {
00631                 break;
00632             }
00633             printf("Publishes to user topic through HTTPS/POST OK\n\n");
00634 
00635             /* Update thing shadow by publishing to UpdateThingShadow topic through HTTPS/POST */
00636             printf("Updating thing shadow by publishing to Update Thing Shadow topic through HTTPS/POST\n");
00637             if (! run_req_resp(UPDATETHINGSHADOW_TOPIC_HTTPS_PATH, UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD, UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) {
00638                 break;
00639             }
00640             printf("Update thing shadow by publishing to Update Thing Shadow topic through HTTPS/POST OK\n\n");
00641 
00642             /* Get thing shadow by publishing to GetThingShadow topic through HTTPS/POST */
00643             printf("Getting thing shadow by publishing to GetThingShadow topic through HTTPS/POST\n");
00644             if (! run_req_resp(GETTHINGSHADOW_TOPIC_HTTPS_PATH, GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD, GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) {
00645                 break;
00646             }
00647             printf("Get thing shadow by publishing to GetThingShadow topic through HTTPS/POST OK\n\n");
00648 
00649             /* Delete thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST */
00650             printf("Deleting thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST\n");
00651             if (! run_req_resp(DELETETHINGSHADOW_TOPIC_HTTPS_PATH, DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD, DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) {
00652                 break;
00653             }
00654             printf("Delete thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST OK\n\n");
00655 
00656             /* Update thing shadow RESTfully through HTTPS/POST */
00657             printf("Updating thing shadow RESTfully through HTTPS/POST\n");
00658             if (! run_req_resp(UPDATETHINGSHADOW_THING_HTTPS_PATH, UPDATETHINGSHADOW_THING_HTTPS_REQUEST_METHOD, UPDATETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY)) {
00659                 break;
00660             }
00661             printf("Update thing shadow RESTfully through HTTPS/POST OK\n\n");
00662 
00663             /* Get thing shadow RESTfully through HTTPS/GET */
00664             printf("Getting thing shadow RESTfully through HTTPS/GET\n");
00665             if (! run_req_resp(GETTHINGSHADOW_THING_HTTPS_PATH, GETTHINGSHADOW_THING_HTTPS_REQUEST_METHOD, GETTHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY)) {
00666                 break;
00667             }
00668             printf("Get thing shadow RESTfully through HTTPS/GET OK\n\n");
00669 
00670             /* Delete thing shadow RESTfully through HTTPS/DELETE */
00671             printf("Deleting thing shadow RESTfully through HTTPS/DELETE\n");
00672             if (! run_req_resp(DELETETHINGSHADOW_THING_HTTPS_PATH, DELETETHINGSHADOW_THING_HTTPS_REQUEST_METHOD, DELETETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY)) {
00673                 break;
00674             }
00675             printf("Delete thing shadow RESTfully through HTTPS/DELETE OK\n\n");
00676             
00677         } while (0);
00678         
00679         /* Close socket */
00680         _tlssocket->close();
00681     }
00682 
00683 protected:
00684 
00685     /**
00686      * @brief   Run request/response through HTTPS
00687      */
00688     bool run_req_resp(const char *https_path, const char *https_request_method, const char *https_request_message_body) {
00689 
00690         bool ret = false;
00691 
00692         do {
00693             int tls_rc;
00694             bool _got200 = false;
00695 
00696             int _bpos;
00697 
00698             /* Fill the request buffer */
00699             _bpos = snprintf(_buffer, sizeof(_buffer) - 1,
00700                             "%s %s HTTP/1.1\r\n" "Host: %s\r\n" "Content-Length: %d\r\n" "\r\n" "%s",
00701                             https_request_method, https_path, AWS_IOT_HTTPS_SERVER_NAME, strlen(https_request_message_body), https_request_message_body);
00702             if (_bpos < 0 || ((size_t) _bpos) > (sizeof (_buffer) - 1)) {
00703                 printf("snprintf failed: %d\n", _bpos);
00704                 break;
00705             }
00706             _buffer[_bpos] = 0;
00707             /* Print request message */
00708             printf("HTTPS: Request message:\n");
00709             printf("%s\n", _buffer);
00710 
00711             int offset = 0;
00712             do {
00713                 tls_rc = _tlssocket->send((const unsigned char *) _buffer + offset, _bpos - offset);
00714                 if (tls_rc > 0) {
00715                     offset += tls_rc;
00716                 }
00717             } while (offset < _bpos && 
00718                     (tls_rc > 0 || tls_rc == NSAPI_ERROR_WOULD_BLOCK));
00719             if (tls_rc < 0 &&
00720                 tls_rc != NSAPI_ERROR_WOULD_BLOCK) {
00721                 print_mbedtls_error("_tlssocket->send", tls_rc);
00722                 break;
00723             }
00724 
00725             /* Read data out of the socket */
00726             offset = 0;
00727             size_t content_length = 0;
00728             size_t offset_end = 0;
00729             char *line_beg = _buffer;
00730             char *line_end = NULL;
00731             do {
00732                 tls_rc = _tlssocket->recv((unsigned char *) _buffer + offset, sizeof(_buffer) - offset - 1);
00733                 if (tls_rc > 0) {
00734                     offset += tls_rc;
00735                 }
00736                 
00737                 /* Make it null-terminated */
00738                 _buffer[offset] = 0;
00739 
00740                 /* Scan response message
00741                  *             
00742                  * 1. A status line which includes the status code and reason message (e.g., HTTP/1.1 200 OK)
00743                  * 2. Response header fields (e.g., Content-Type: text/html)
00744                  * 3. An empty line (\r\n)
00745                  * 4. An optional message body
00746                  */
00747                 if (! offset_end) {
00748                     line_end = strstr(line_beg, "\r\n");
00749                     if (line_end) {
00750                         /* Scan status line */
00751                         if (! _got200) {
00752                             _got200 = strstr(line_beg, HTTPS_OK_STR) != NULL;
00753                         }
00754             
00755                         /* Scan response header fields for Content-Length 
00756                          * 
00757                          * NOTE: Assume chunked transfer (Transfer-Encoding: chunked) is not used
00758                          * NOTE: Assume response field name are in lower case
00759                          */
00760                         if (content_length == 0) {
00761                             sscanf(line_beg, "content-length:%d", &content_length);
00762                         }
00763                     
00764                         /* An empty line indicates end of response header fields */
00765                         if (line_beg == line_end) {
00766                             offset_end = line_end - _buffer + 2 + content_length;
00767                         }
00768                     
00769                         /* Go to next line */
00770                         line_beg = line_end + 2;
00771                         line_end = NULL;
00772                     }
00773                 }
00774             } while ((offset_end == 0 || offset < offset_end) &&
00775                     (tls_rc > 0 || tls_rc == NSAPI_ERROR_WOULD_BLOCK));
00776             if (tls_rc < 0 && 
00777                 tls_rc != NSAPI_ERROR_WOULD_BLOCK) {
00778                 print_mbedtls_error("_tlssocket->read", tls_rc);
00779                 break;
00780             }
00781             _bpos = offset;
00782 
00783             _buffer[_bpos] = 0;
00784 
00785             /* Print status messages */
00786             printf("HTTPS: Received %d chars from server\n", _bpos);
00787             printf("HTTPS: Received 200 OK status ... %s\n", _got200 ? "[OK]" : "[FAIL]");
00788             printf("HTTPS: Received message:\n");
00789             printf("%s\n", _buffer);
00790 
00791             ret = true;
00792 
00793         } while (0);
00794 
00795         return ret;
00796     }
00797 
00798 protected:
00799     MyTLSSocket *     _tlssocket;
00800 
00801     const char *_domain;                    /**< Domain name of the HTTPS server */
00802     const uint16_t _port;                   /**< Port number of the HTTPS server */
00803     char _buffer[HTTPS_USER_BUFFER_SIZE];   /**< User buffer */
00804     NetworkInterface *_net_iface;
00805 };
00806 
00807 #endif  // End of AWS_IOT_HTTPS_TEST
00808 
00809 int main() {
00810 
00811     /* The default 9600 bps is too slow to print full TLS debug info and could
00812      * cause the other party to time out. */
00813 
00814     printf("\nStarting AWS IoT test\n");
00815 
00816 #if defined(MBED_MAJOR_VERSION)
00817     printf("Using Mbed OS %d.%d.%d\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
00818 #else
00819     printf("Using Mbed OS from master.\n");
00820 #endif
00821 
00822     NetworkInterface *net = NetworkInterface::get_default_instance();
00823     if (NULL == net) {
00824         printf("Connecting to the network failed. See serial output.\n");
00825         return 1;
00826     }
00827     nsapi_error_t status = net->connect();
00828     if (status != NSAPI_ERROR_OK) {
00829         printf("Connecting to the network failed %d!\n", status);
00830         return -1;
00831     }
00832     SocketAddress sockaddr;
00833     status = net->get_ip_address(&sockaddr);
00834     if (status != NSAPI_ERROR_OK) {
00835         printf("Network interface get_ip_address(...) failed with %d", status);
00836         return -1;
00837     }
00838     printf("Connected to the network successfully. IP address: %s\n", sockaddr.get_ip_address());
00839 
00840 #if AWS_IOT_MQTT_TEST
00841     AWS_IoT_MQTT_Test *mqtt_test = new AWS_IoT_MQTT_Test(AWS_IOT_MQTT_SERVER_NAME, AWS_IOT_MQTT_SERVER_PORT, net);
00842     mqtt_test->start_test();
00843     delete mqtt_test;
00844 #endif  // End of AWS_IOT_MQTT_TEST
00845 
00846 #if AWS_IOT_HTTPS_TEST
00847     AWS_IoT_HTTPS_Test *https_test = new AWS_IoT_HTTPS_Test(AWS_IOT_HTTPS_SERVER_NAME, AWS_IOT_HTTPS_SERVER_PORT, net);
00848     https_test->start_test();
00849     delete https_test;
00850 #endif  // End of AWS_IOT_HTTPS_TEST
00851 
00852     /* Some cellular modems e.g.: QUECTEL EC2X need graceful exit; otherwise, they will break in next reboot. */
00853     status = net->disconnect();
00854     if (status != NSAPI_ERROR_OK) {
00855         printf("\n\nDisconnect from network interface failed %d\n", status);
00856     }
00857 }