NuMaker connection with AWS IoT thru MQTT/HTTPS

Dependencies:   MQTT

Committer:
ccli8
Date:
Thu Sep 02 11:34:22 2021 +0800
Revision:
45:7d315fb1ba3e
Parent:
44:2f9dc54e7f95
Fix MQTT client ID collision

If not assigned, generate unique MQTT client ID:
1. For non-TZ targets, use FMC/UID.
2. For TZ targets (NS), FMC/UID is inaccessible. Use random instead.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ccli8 1:5ffad9f24d63 1 /* This example demonstrates connection with AWS IoT through MQTT/HTTPS protocol.
ccli8 1:5ffad9f24d63 2 *
ccli8 1:5ffad9f24d63 3 * AWS IoT: Thing Shadow MQTT Topics
ccli8 1:5ffad9f24d63 4 * http://docs.aws.amazon.com/iot/latest/developerguide/thing-shadow-mqtt.html
ccli8 1:5ffad9f24d63 5 *
ccli8 1:5ffad9f24d63 6 * AWS IoT: Publish to a topic through HTTPS/POST method:
ccli8 1:5ffad9f24d63 7 * http://docs.aws.amazon.com/iot/latest/developerguide/protocols.html
ccli8 1:5ffad9f24d63 8 *
ccli8 1:5ffad9f24d63 9 * AWS IoT: Thing Shadow RESTful API:
ccli8 1:5ffad9f24d63 10 * http://docs.aws.amazon.com/iot/latest/developerguide/thing-shadow-rest-api.html
ccli8 1:5ffad9f24d63 11 */
ccli8 1:5ffad9f24d63 12
ccli8 1:5ffad9f24d63 13 #define AWS_IOT_MQTT_TEST 1
ccli8 1:5ffad9f24d63 14 #define AWS_IOT_HTTPS_TEST 0
ccli8 1:5ffad9f24d63 15
ccli8 1:5ffad9f24d63 16 #include "mbed.h"
ccli8 17:6f0ff065cd76 17 #include "MyTLSSocket.h"
ccli8 1:5ffad9f24d63 18
ccli8 1:5ffad9f24d63 19 #if AWS_IOT_MQTT_TEST
ccli8 1:5ffad9f24d63 20 /* MQTT-specific header files */
ccli8 1:5ffad9f24d63 21 #include "MQTTmbed.h"
ccli8 1:5ffad9f24d63 22 #include "MQTTClient.h"
ccli8 1:5ffad9f24d63 23 #endif // End of AWS_IOT_MQTT_TEST
ccli8 1:5ffad9f24d63 24
ccli8 1:5ffad9f24d63 25
ccli8 1:5ffad9f24d63 26 namespace {
ccli8 1:5ffad9f24d63 27
ccli8 1:5ffad9f24d63 28 /* List of trusted root CA certificates
ccli8 1:5ffad9f24d63 29 * currently only GlobalSign, the CA for os.mbed.com
ccli8 1:5ffad9f24d63 30 *
ccli8 1:5ffad9f24d63 31 * To add more than one root, just concatenate them.
ccli8 1:5ffad9f24d63 32 */
ccli8 1:5ffad9f24d63 33 const char SSL_CA_CERT_PEM[] = "-----BEGIN CERTIFICATE-----\n"
ccli8 44:2f9dc54e7f95 34 "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n"
ccli8 44:2f9dc54e7f95 35 "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n"
ccli8 44:2f9dc54e7f95 36 "b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n"
ccli8 44:2f9dc54e7f95 37 "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n"
ccli8 44:2f9dc54e7f95 38 "b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n"
ccli8 44:2f9dc54e7f95 39 "ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n"
ccli8 44:2f9dc54e7f95 40 "9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n"
ccli8 44:2f9dc54e7f95 41 "IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n"
ccli8 44:2f9dc54e7f95 42 "VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n"
ccli8 44:2f9dc54e7f95 43 "93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n"
ccli8 44:2f9dc54e7f95 44 "jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n"
ccli8 44:2f9dc54e7f95 45 "AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n"
ccli8 44:2f9dc54e7f95 46 "A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n"
ccli8 44:2f9dc54e7f95 47 "U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n"
ccli8 44:2f9dc54e7f95 48 "N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n"
ccli8 44:2f9dc54e7f95 49 "o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n"
ccli8 44:2f9dc54e7f95 50 "5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n"
ccli8 44:2f9dc54e7f95 51 "rqXRfboQnoZsG4q5WTP468SQvvG5\n"
ccli8 1:5ffad9f24d63 52 "-----END CERTIFICATE-----\n";
ccli8 1:5ffad9f24d63 53
ccli8 1:5ffad9f24d63 54 /* User certificate which has been activated and attached with specific thing and policy */
ccli8 1:5ffad9f24d63 55 const char SSL_USER_CERT_PEM[] = "-----BEGIN CERTIFICATE-----\n"
ccli8 8:d5ea623ffc1f 56 "MIIDWTCCAkGgAwIBAgIUAzDIpEQWV/yKVo8suGhvjmFY0n4wDQYJKoZIhvcNAQEL\n"
ccli8 8:d5ea623ffc1f 57 "BQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g\n"
ccli8 8:d5ea623ffc1f 58 "SW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTE4MDQxNzA5NDMx\n"
ccli8 8:d5ea623ffc1f 59 "M1oXDTQ5MTIzMTIzNTk1OVowHjEcMBoGA1UEAwwTQVdTIElvVCBDZXJ0aWZpY2F0\n"
ccli8 8:d5ea623ffc1f 60 "ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKsLlECiw4ud5laejJmL\n"
ccli8 8:d5ea623ffc1f 61 "bBhafKLdCRx6tkcjBYyEUoAC3Qs2ogqGngQgjU4QJoWpEBO/U1M+e1QtlZ2o/CiL\n"
ccli8 8:d5ea623ffc1f 62 "MViHA3rYvP86N/TH8pFA3aPKaeEp+WIt5v4OXdfPkVNKTotiRuRCpzRzrY4xKp11\n"
ccli8 8:d5ea623ffc1f 63 "ouKkVKf3FcNuKIMt/uEhje90KofBbFHQY3HFYe19qIg1m/IBV+npmNlAKElGNSB7\n"
ccli8 8:d5ea623ffc1f 64 "xHHLzzUuue38s+ceJyzsWuPjFiVYoeyPHF8gDVWf28XJ4KUFs80Deycqe9efroud\n"
ccli8 8:d5ea623ffc1f 65 "cQY/6aLDWDJXHvhenwoAIbHqUsYRoWoanrg5Cq3id5+pzVkadNV3+x9bGwROhpbQ\n"
ccli8 8:d5ea623ffc1f 66 "M9ECAwEAAaNgMF4wHwYDVR0jBBgwFoAUVUXg3+Dd1qSnAT9LN413zSdNoE0wHQYD\n"
ccli8 8:d5ea623ffc1f 67 "VR0OBBYEFIx86SOxw5k/50GtyRjUwlj+9d1gMAwGA1UdEwEB/wQCMAAwDgYDVR0P\n"
ccli8 8:d5ea623ffc1f 68 "AQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IBAQCI1fqqjvLAFzL2E1nvWMrkaWN2\n"
ccli8 8:d5ea623ffc1f 69 "EQK44uOcw53ZzgNNH7fJ85BW8T2l1yZx/Blgs10pEp7vmccnRoR7nYbUGO8++9nG\n"
ccli8 8:d5ea623ffc1f 70 "S7bfZhiaE2syJqqvLwPGdqR6fvDdfEpmhgJ1CqeMCqun9XZvUTsgBn7Sqqz7P99h\n"
ccli8 8:d5ea623ffc1f 71 "gGmDRKS/CtsPai0Df0ZPNuV/YuUkpHKJSDm+ZTnzevMS3KXkG1cc/sIuc4IwF+aj\n"
ccli8 8:d5ea623ffc1f 72 "nbyzdC2fN0r+34srQ8/9aXezOTQ0NBWtoJCCkD+LL6PYJJkAgLA2jcbcbuRJUQ7n\n"
ccli8 8:d5ea623ffc1f 73 "Zsp25kKX40fuyIcgPRsd/7sao3zTVYxwKy8r6/mbgrPiMeHvJZ8y3nwUpsPO\n"
ccli8 1:5ffad9f24d63 74 "-----END CERTIFICATE-----\n";
ccli8 1:5ffad9f24d63 75
ccli8 1:5ffad9f24d63 76 /* User private key paired with above */
ccli8 1:5ffad9f24d63 77 const char SSL_USER_PRIV_KEY_PEM[] = "-----BEGIN RSA PRIVATE KEY-----\n"
ccli8 8:d5ea623ffc1f 78 "MIIEowIBAAKCAQEAqwuUQKLDi53mVp6MmYtsGFp8ot0JHHq2RyMFjIRSgALdCzai\n"
ccli8 8:d5ea623ffc1f 79 "CoaeBCCNThAmhakQE79TUz57VC2Vnaj8KIsxWIcDeti8/zo39MfykUDdo8pp4Sn5\n"
ccli8 8:d5ea623ffc1f 80 "Yi3m/g5d18+RU0pOi2JG5EKnNHOtjjEqnXWi4qRUp/cVw24ogy3+4SGN73Qqh8Fs\n"
ccli8 8:d5ea623ffc1f 81 "UdBjccVh7X2oiDWb8gFX6emY2UAoSUY1IHvEccvPNS657fyz5x4nLOxa4+MWJVih\n"
ccli8 8:d5ea623ffc1f 82 "7I8cXyANVZ/bxcngpQWzzQN7Jyp715+ui51xBj/posNYMlce+F6fCgAhsepSxhGh\n"
ccli8 8:d5ea623ffc1f 83 "ahqeuDkKreJ3n6nNWRp01Xf7H1sbBE6GltAz0QIDAQABAoIBAAzl7KILJA/NMmdp\n"
ccli8 8:d5ea623ffc1f 84 "wVR6zQXxHODzJhK9ti0bGPoFqGr6zExiLEn66MOK6NzwHteJbirvDIuEdKxeW5/t\n"
ccli8 8:d5ea623ffc1f 85 "9EXiaTAxzjNfULE2ZK3Svhnx+ES3qNBP5/xdVcPmtXDmuCC9w7qDCLGBzTYJWxcT\n"
ccli8 8:d5ea623ffc1f 86 "4hDJpCTPG4sm+L8p+Wga+dNkQl3CFyHHINDZ0pKcP0kDDt6inKfiU7uU4lFYbCZy\n"
ccli8 8:d5ea623ffc1f 87 "PceUgIOTQiNVoPQYtkHgZAtmD9rcwdq2/0GZEbzTkZuSE9S8+WlGxJP5xMGzeVsv\n"
ccli8 8:d5ea623ffc1f 88 "zZ/scx0LM7fz5Zq0lsvAwSB1mcs04DaaNpU7Z0tXDIS249RTqdtpPkJzmevpAGhF\n"
ccli8 8:d5ea623ffc1f 89 "VNe30/kCgYEA4rflfqyw/YHWKRxCGJRO+q0gPvlBIes30noz5Hxl0knb/J5Ng4Nx\n"
ccli8 8:d5ea623ffc1f 90 "xMaIMZgCbwHbw5i01JOPvVKICROKb8wkli4Y2eVzxMPKk2CSpji16RQZ4eOl3YXL\n"
ccli8 8:d5ea623ffc1f 91 "1Vnn07Ei+GpsGgDNF0HWf/Ur7es/KdAPCWbKJyoSR90+WN29gP2+Zp8CgYEAwSLv\n"
ccli8 8:d5ea623ffc1f 92 "Kt/vdd6XKnR9xR3IajsW/X2GR/x/m2JffJPOP6VpDTKAbv86hVHDV0oBEDMDc7qy\n"
ccli8 8:d5ea623ffc1f 93 "023ognyFCPb9Gzol2lq8egjMsisA2bgoB9HqldrSYlaZ0wPe0QJBf1gZ29jPyVJ0\n"
ccli8 8:d5ea623ffc1f 94 "ciaBbNbSRhwTrwet7Bae9EbpJsyvBxVh00v0f48CgYEAvKQKviXudmCL01UB4fW0\n"
ccli8 8:d5ea623ffc1f 95 "6XsXs44tlY1juyuW9exTxG9ULZOCJ4U9Kl+OfsVecQL42ny7KY1GMl7zdanerDsN\n"
ccli8 8:d5ea623ffc1f 96 "zi+42cTDWNsYORxHqSrSoYbqKjwCjJmBCppt/IQM9umF3PUBsPJFCd7zmFj/C0lk\n"
ccli8 8:d5ea623ffc1f 97 "2Yu/dGrbHxSFheeqgCOhQz0CgYBfZxdHUYji64o2cYay+QxH1Vp86yWKp6KNKeHL\n"
ccli8 8:d5ea623ffc1f 98 "EuP9soKa/0hMDA1nT8UzeB3gV6Kr5xxwrkj9M+8vR3otmeKa4tlZWsFqfS2VXo9/\n"
ccli8 8:d5ea623ffc1f 99 "lWTQk1/7LZYckzvceMXL1sQnQgkaBH366SRjlBYYhcP/YMa76Uypk+GVxePrltdU\n"
ccli8 8:d5ea623ffc1f 100 "3Z8v5wKBgEXL38yc9LqTIWe1U40ZZKvp2A8c86jtstorEEFqXharE8kxcEpL8ZLL\n"
ccli8 8:d5ea623ffc1f 101 "wjgPKdfNMIuApHSrhG7a7gU1rgJyDy1sOIwSvgTYrWfITPTVu5owvSZEblx4KYOm\n"
ccli8 8:d5ea623ffc1f 102 "g8hke3Oego4v9cwctkQss3/HZ6rs3PR942oAetuxLy3KPF83IeFm\n"
ccli8 1:5ffad9f24d63 103 "-----END RSA PRIVATE KEY-----\n";
ccli8 1:5ffad9f24d63 104
ccli8 1:5ffad9f24d63 105 #if AWS_IOT_MQTT_TEST
ccli8 1:5ffad9f24d63 106
ccli8 44:2f9dc54e7f95 107 #define AWS_IOT_MQTT_SERVER_NAME "a1fljoeglhtf61-ats.iot.us-east-2.amazonaws.com"
ccli8 1:5ffad9f24d63 108 #define AWS_IOT_MQTT_SERVER_PORT 8883
ccli8 1:5ffad9f24d63 109
ccli8 1:5ffad9f24d63 110 #define AWS_IOT_MQTT_THINGNAME "Nuvoton-Mbed-D001"
ccli8 45:7d315fb1ba3e 111
ccli8 45:7d315fb1ba3e 112 /* Uncomment and assign one unique MQTT client name; otherwise, one random will be assigned. */
ccli8 45:7d315fb1ba3e 113 //#define AWS_IOT_MQTT_CLIENTNAME "Nuvoton Client"
ccli8 1:5ffad9f24d63 114
ccli8 1:5ffad9f24d63 115 /* User self-test topic */
ccli8 1:5ffad9f24d63 116 const char USER_MQTT_TOPIC[] = "Nuvoton/Mbed/D001";
ccli8 1:5ffad9f24d63 117 const char *USER_MQTT_TOPIC_FILTERS[] = {
ccli8 1:5ffad9f24d63 118 "Nuvoton/Mbed/+"
ccli8 1:5ffad9f24d63 119 };
ccli8 1:5ffad9f24d63 120 const char USER_MQTT_TOPIC_PUBLISH_MESSAGE[] = "{ \"message\": \"Hello from Nuvoton Mbed device\" }";
ccli8 1:5ffad9f24d63 121
ccli8 1:5ffad9f24d63 122 /* Update thing shadow */
ccli8 1:5ffad9f24d63 123 const char UPDATETHINGSHADOW_MQTT_TOPIC[] = "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/update";
ccli8 1:5ffad9f24d63 124 const char *UPDATETHINGSHADOW_MQTT_TOPIC_FILTERS[] = {
ccli8 1:5ffad9f24d63 125 "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/update/accepted",
ccli8 1:5ffad9f24d63 126 "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/update/rejected"
ccli8 1:5ffad9f24d63 127 };
ccli8 1:5ffad9f24d63 128 const char UPDATETHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE[] = "{ \"state\": { \"reported\": { \"attribute1\": 3, \"attribute2\": \"1\" } } }";
ccli8 1:5ffad9f24d63 129
ccli8 1:5ffad9f24d63 130 /* Get thing shadow */
ccli8 1:5ffad9f24d63 131 const char GETTHINGSHADOW_MQTT_TOPIC[] = "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/get";
ccli8 1:5ffad9f24d63 132 const char *GETTHINGSHADOW_MQTT_TOPIC_FILTERS[] = {
ccli8 1:5ffad9f24d63 133 "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/get/accepted",
ccli8 1:5ffad9f24d63 134 "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/get/rejected"
ccli8 1:5ffad9f24d63 135 };
ccli8 1:5ffad9f24d63 136 const char GETTHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE[] = "";
ccli8 1:5ffad9f24d63 137
ccli8 1:5ffad9f24d63 138 /* Delete thing shadow */
ccli8 1:5ffad9f24d63 139 const char DELETETHINGSHADOW_MQTT_TOPIC[] = "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/delete";
ccli8 1:5ffad9f24d63 140 const char *DELETETHINGSHADOW_MQTT_TOPIC_FILTERS[] = {
ccli8 1:5ffad9f24d63 141 "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/delete/accepted",
ccli8 1:5ffad9f24d63 142 "$aws/things/" AWS_IOT_MQTT_THINGNAME "/shadow/delete/rejected"
ccli8 1:5ffad9f24d63 143 };
ccli8 1:5ffad9f24d63 144 const char DELETETHINGSHADOW_MQTT_TOPIC_PUBLISH_MESSAGE[] = "";
ccli8 1:5ffad9f24d63 145
ccli8 1:5ffad9f24d63 146 /* MQTT user buffer size */
ccli8 1:5ffad9f24d63 147 const int MQTT_USER_BUFFER_SIZE = 600;
ccli8 1:5ffad9f24d63 148
ccli8 1:5ffad9f24d63 149 /* Configure MAX_MQTT_PACKET_SIZE to meet your application.
ccli8 1:5ffad9f24d63 150 * We may meet unknown MQTT error with MAX_MQTT_PACKET_SIZE too small, but
ccli8 1:5ffad9f24d63 151 * MQTT lib doesn't tell enough error message. Try to enlarge it. */
ccli8 1:5ffad9f24d63 152 const int MAX_MQTT_PACKET_SIZE = 1000;
ccli8 1:5ffad9f24d63 153
ccli8 35:36578356ed8a 154 /* Timeout for receiving message with subscribed topic */
ccli8 35:36578356ed8a 155 const int MQTT_RECEIVE_MESSAGE_WITH_SUBSCRIBED_TOPIC_TIMEOUT_MS = 5000;
ccli8 35:36578356ed8a 156
ccli8 45:7d315fb1ba3e 157 #if !defined(AWS_IOT_MQTT_CLIENTNAME)
ccli8 45:7d315fb1ba3e 158 #if TARGET_M23_NS
ccli8 45:7d315fb1ba3e 159 extern "C"
ccli8 45:7d315fb1ba3e 160 int mbedtls_hardware_poll( void *data, unsigned char *output, size_t len, size_t *olen );
ccli8 45:7d315fb1ba3e 161 #endif
ccli8 45:7d315fb1ba3e 162 #endif
ccli8 45:7d315fb1ba3e 163
ccli8 1:5ffad9f24d63 164 #endif // End of AWS_IOT_MQTT_TEST
ccli8 1:5ffad9f24d63 165
ccli8 1:5ffad9f24d63 166 #if AWS_IOT_HTTPS_TEST
ccli8 1:5ffad9f24d63 167
ccli8 44:2f9dc54e7f95 168 #define AWS_IOT_HTTPS_SERVER_NAME "a1fljoeglhtf61-ats.iot.us-east-2.amazonaws.com"
ccli8 1:5ffad9f24d63 169 #define AWS_IOT_HTTPS_SERVER_PORT 8443
ccli8 1:5ffad9f24d63 170
ccli8 1:5ffad9f24d63 171 #define AWS_IOT_HTTPS_THINGNAME "Nuvoton-Mbed-D001"
ccli8 1:5ffad9f24d63 172
ccli8 1:5ffad9f24d63 173 /* Publish to user topic through HTTPS/POST
ccli8 1:5ffad9f24d63 174 * HTTP POST https://"endpoint"/topics/"yourTopicHierarchy" */
ccli8 1:5ffad9f24d63 175 const char USER_TOPIC_HTTPS_PATH[] = "/topics/Nuvoton/Mbed/D001?qos=1";
ccli8 1:5ffad9f24d63 176 const char USER_TOPIC_HTTPS_REQUEST_METHOD[] = "POST";
ccli8 1:5ffad9f24d63 177 const char USER_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = "{ \"message\": \"Hello from Nuvoton Mbed device\" }";
ccli8 1:5ffad9f24d63 178
ccli8 1:5ffad9f24d63 179 /* Update thing shadow by publishing to UpdateThingShadow topic through HTTPS/POST
ccli8 1:5ffad9f24d63 180 * HTTP POST https://"endpoint"/topics/$aws/things/"thingName"/shadow/update */
ccli8 1:5ffad9f24d63 181 const char UPDATETHINGSHADOW_TOPIC_HTTPS_PATH[] = "/topics/$aws/things/" AWS_IOT_HTTPS_THINGNAME "/shadow/update?qos=1";
ccli8 1:5ffad9f24d63 182 const char UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD[] = "POST";
ccli8 1:5ffad9f24d63 183 const char UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = "{ \"state\": { \"reported\": { \"attribute1\": 3, \"attribute2\": \"1\" } } }";
ccli8 1:5ffad9f24d63 184
ccli8 1:5ffad9f24d63 185 /* Get thing shadow by publishing to GetThingShadow topic through HTTPS/POST
ccli8 1:5ffad9f24d63 186 * HTTP POST https://"endpoint"/topics/$aws/things/"thingName"/shadow/get */
ccli8 1:5ffad9f24d63 187 const char GETTHINGSHADOW_TOPIC_HTTPS_PATH[] = "/topics/$aws/things/" AWS_IOT_HTTPS_THINGNAME "/shadow/get?qos=1";
ccli8 1:5ffad9f24d63 188 const char GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD[] = "POST";
ccli8 1:5ffad9f24d63 189 const char GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = "";
ccli8 1:5ffad9f24d63 190
ccli8 1:5ffad9f24d63 191 /* Delete thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST
ccli8 1:5ffad9f24d63 192 * HTTP POST https://"endpoint"/topics/$aws/things/"thingName"/shadow/delete */
ccli8 1:5ffad9f24d63 193 const char DELETETHINGSHADOW_TOPIC_HTTPS_PATH[] = "/topics/$aws/things/" AWS_IOT_HTTPS_THINGNAME "/shadow/delete?qos=1";
ccli8 1:5ffad9f24d63 194 const char DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD[] = "POST";
ccli8 1:5ffad9f24d63 195 const char DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY[] = "";
ccli8 1:5ffad9f24d63 196
ccli8 1:5ffad9f24d63 197 /* Update thing shadow RESTfully through HTTPS/POST
ccli8 1:5ffad9f24d63 198 * HTTP POST https://endpoint/things/thingName/shadow */
ccli8 1:5ffad9f24d63 199 const char UPDATETHINGSHADOW_THING_HTTPS_PATH[] = "/things/" AWS_IOT_HTTPS_THINGNAME "/shadow";
ccli8 1:5ffad9f24d63 200 const char UPDATETHINGSHADOW_THING_HTTPS_REQUEST_METHOD[] = "POST";
ccli8 1:5ffad9f24d63 201 const char UPDATETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY[] = "{ \"state\": { \"desired\": { \"attribute1\": 1, \"attribute2\": \"2\" }, \"reported\": { \"attribute1\": 2, \"attribute2\": \"1\" } } }";
ccli8 1:5ffad9f24d63 202
ccli8 1:5ffad9f24d63 203 /* Get thing shadow RESTfully through HTTPS/GET
ccli8 1:5ffad9f24d63 204 * HTTP GET https://"endpoint"/things/"thingName"/shadow */
ccli8 1:5ffad9f24d63 205 const char GETTHINGSHADOW_THING_HTTPS_PATH[] = "/things/" AWS_IOT_HTTPS_THINGNAME "/shadow";
ccli8 1:5ffad9f24d63 206 const char GETTHINGSHADOW_THING_HTTPS_REQUEST_METHOD[] = "GET";
ccli8 1:5ffad9f24d63 207 const char GETTHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY[] = "";
ccli8 1:5ffad9f24d63 208
ccli8 1:5ffad9f24d63 209 /* Delete thing shadow RESTfully through HTTPS/DELETE
ccli8 1:5ffad9f24d63 210 * HTTP DELETE https://endpoint/things/thingName/shadow */
ccli8 1:5ffad9f24d63 211 const char DELETETHINGSHADOW_THING_HTTPS_PATH[] = "/things/" AWS_IOT_HTTPS_THINGNAME "/shadow";
ccli8 1:5ffad9f24d63 212 const char DELETETHINGSHADOW_THING_HTTPS_REQUEST_METHOD[] = "DELETE";
ccli8 1:5ffad9f24d63 213 const char DELETETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY[] = "";
ccli8 1:5ffad9f24d63 214
ccli8 1:5ffad9f24d63 215 /* HTTPS user buffer size */
ccli8 1:5ffad9f24d63 216 const int HTTPS_USER_BUFFER_SIZE = 600;
ccli8 1:5ffad9f24d63 217
ccli8 1:5ffad9f24d63 218 const char *HTTPS_OK_STR = "200 OK";
ccli8 1:5ffad9f24d63 219
ccli8 1:5ffad9f24d63 220 #endif // End of AWS_IOT_HTTPS_TEST
ccli8 1:5ffad9f24d63 221
ccli8 1:5ffad9f24d63 222 }
ccli8 1:5ffad9f24d63 223
ccli8 1:5ffad9f24d63 224 #if AWS_IOT_MQTT_TEST
ccli8 1:5ffad9f24d63 225
ccli8 1:5ffad9f24d63 226 /**
ccli8 1:5ffad9f24d63 227 * /brief AWS_IoT_MQTT_Test implements the logic with AWS IoT User/Thing Shadow topics through MQTT.
ccli8 1:5ffad9f24d63 228 */
ccli8 1:5ffad9f24d63 229 class AWS_IoT_MQTT_Test {
ccli8 1:5ffad9f24d63 230
ccli8 1:5ffad9f24d63 231 public:
ccli8 1:5ffad9f24d63 232 /**
ccli8 1:5ffad9f24d63 233 * @brief AWS_IoT_MQTT_Test Constructor
ccli8 1:5ffad9f24d63 234 *
ccli8 1:5ffad9f24d63 235 * @param[in] domain Domain name of the MQTT server
ccli8 1:5ffad9f24d63 236 * @param[in] port Port number of the MQTT server
ccli8 1:5ffad9f24d63 237 * @param[in] net_iface Network interface
ccli8 1:5ffad9f24d63 238 */
ccli8 1:5ffad9f24d63 239 AWS_IoT_MQTT_Test(const char * domain, const uint16_t port, NetworkInterface *net_iface) :
ccli8 41:b878d7cd7035 240 _domain(domain), _port(port), _net_iface(net_iface) {
ccli8 41:b878d7cd7035 241 _tlssocket = new MyTLSSocket;
ccli8 17:6f0ff065cd76 242 _mqtt_client = new MQTT::Client<MyTLSSocket, Countdown, MAX_MQTT_PACKET_SIZE>(*_tlssocket);
ccli8 1:5ffad9f24d63 243 }
ccli8 1:5ffad9f24d63 244
ccli8 1:5ffad9f24d63 245 /**
ccli8 1:5ffad9f24d63 246 * @brief AWS_IoT_MQTT_Test Destructor
ccli8 1:5ffad9f24d63 247 */
ccli8 1:5ffad9f24d63 248 ~AWS_IoT_MQTT_Test() {
ccli8 1:5ffad9f24d63 249 delete _mqtt_client;
ccli8 1:5ffad9f24d63 250 _mqtt_client = NULL;
ccli8 1:5ffad9f24d63 251
ccli8 1:5ffad9f24d63 252 _tlssocket->close();
ccli8 1:5ffad9f24d63 253 delete _tlssocket;
ccli8 1:5ffad9f24d63 254 _tlssocket = NULL;
ccli8 1:5ffad9f24d63 255 }
ccli8 1:5ffad9f24d63 256 /**
ccli8 1:5ffad9f24d63 257 * @brief Start AWS IoT test through MQTT
ccli8 1:5ffad9f24d63 258 */
ccli8 1:5ffad9f24d63 259 void start_test() {
ccli8 1:5ffad9f24d63 260
ccli8 1:5ffad9f24d63 261 int tls_rc;
ccli8 1:5ffad9f24d63 262 int mqtt_rc;
ccli8 41:b878d7cd7035 263
ccli8 1:5ffad9f24d63 264 do {
ccli8 41:b878d7cd7035 265 /* Set host name of the remote host, used for certificate checking */
ccli8 41:b878d7cd7035 266 _tlssocket->set_hostname(_domain);
ccli8 41:b878d7cd7035 267
ccli8 41:b878d7cd7035 268 /* Set the certification of Root CA */
ccli8 41:b878d7cd7035 269 tls_rc = _tlssocket->set_root_ca_cert(SSL_CA_CERT_PEM);
ccli8 41:b878d7cd7035 270 if (tls_rc != NSAPI_ERROR_OK) {
ccli8 41:b878d7cd7035 271 printf("TLSSocket::set_root_ca_cert(...) returned %d\n", tls_rc);
ccli8 41:b878d7cd7035 272 break;
ccli8 41:b878d7cd7035 273 }
ccli8 41:b878d7cd7035 274
ccli8 41:b878d7cd7035 275 /* Set client certificate and client private key */
ccli8 41:b878d7cd7035 276 tls_rc = _tlssocket->set_client_cert_key(SSL_USER_CERT_PEM, SSL_USER_PRIV_KEY_PEM);
ccli8 41:b878d7cd7035 277 if (tls_rc != NSAPI_ERROR_OK) {
ccli8 41:b878d7cd7035 278 printf("TLSSocket::set_client_cert_key(...) returned %d\n", tls_rc);
ccli8 41:b878d7cd7035 279 break;
ccli8 41:b878d7cd7035 280 }
ccli8 41:b878d7cd7035 281
ccli8 41:b878d7cd7035 282 /* Blocking mode */
ccli8 41:b878d7cd7035 283 _tlssocket->set_blocking(true);
ccli8 41:b878d7cd7035 284
ccli8 41:b878d7cd7035 285 /* Open a network socket on the network stack of the given network interface */
ccli8 41:b878d7cd7035 286 printf("Opening network socket on network stack\n");
ccli8 41:b878d7cd7035 287 tls_rc = _tlssocket->open(_net_iface);
ccli8 41:b878d7cd7035 288 if (tls_rc != NSAPI_ERROR_OK) {
ccli8 41:b878d7cd7035 289 printf("Opens network socket on network stack failed: %d\n", tls_rc);
ccli8 41:b878d7cd7035 290 break;
ccli8 41:b878d7cd7035 291 }
ccli8 41:b878d7cd7035 292 printf("Opens network socket on network stack OK\n");
ccli8 41:b878d7cd7035 293
ccli8 41:b878d7cd7035 294 /* DNS resolution */
ccli8 41:b878d7cd7035 295 printf("DNS resolution for %s...\n", _domain);
ccli8 41:b878d7cd7035 296 SocketAddress sockaddr;
ccli8 41:b878d7cd7035 297 tls_rc = _net_iface->gethostbyname(_domain, &sockaddr);
ccli8 41:b878d7cd7035 298 if (tls_rc != NSAPI_ERROR_OK) {
ccli8 41:b878d7cd7035 299 printf("DNS resolution for %s failed with %d\n", _domain, tls_rc);
ccli8 41:b878d7cd7035 300 break;
ccli8 41:b878d7cd7035 301 }
ccli8 41:b878d7cd7035 302 sockaddr.set_port(_port);
ccli8 41:b878d7cd7035 303 printf("DNS resolution for %s: %s:%d\n", _domain, sockaddr.get_ip_address(), sockaddr.get_port());
ccli8 41:b878d7cd7035 304
ccli8 1:5ffad9f24d63 305 /* Connect to the server */
ccli8 1:5ffad9f24d63 306 /* Initialize TLS-related stuff */
ccli8 1:5ffad9f24d63 307 printf("Connecting with %s:%d\n", _domain, _port);
ccli8 41:b878d7cd7035 308 tls_rc = _tlssocket->connect(sockaddr);
ccli8 1:5ffad9f24d63 309 if (tls_rc != NSAPI_ERROR_OK) {
ccli8 3:4c8cccd32e34 310 printf("Connects with %s:%d failed: %d\n", _domain, _port, tls_rc);
ccli8 1:5ffad9f24d63 311 break;
ccli8 1:5ffad9f24d63 312 }
ccli8 1:5ffad9f24d63 313 printf("Connects with %s:%d OK\n", _domain, _port);
ccli8 41:b878d7cd7035 314
ccli8 1:5ffad9f24d63 315 /* See the link below for AWS IoT support for MQTT:
ccli8 1:5ffad9f24d63 316 * http://docs.aws.amazon.com/iot/latest/developerguide/protocols.html */
ccli8 41:b878d7cd7035 317
ccli8 1:5ffad9f24d63 318 /* MQTT connect */
ccli8 1:5ffad9f24d63 319 /* The message broker does not support persistent sessions (connections made with
ccli8 1:5ffad9f24d63 320 * the cleanSession flag set to false. */
ccli8 1:5ffad9f24d63 321 MQTTPacket_connectData conn_data = MQTTPacket_connectData_initializer;
ccli8 1:5ffad9f24d63 322 /* AWS IoT message broker implementation is based on MQTT version 3.1.1
ccli8 1:5ffad9f24d63 323 * 3 = 3.1
ccli8 1:5ffad9f24d63 324 * 4 = 3.1.1 */
ccli8 1:5ffad9f24d63 325 conn_data.MQTTVersion = 4;
ccli8 1:5ffad9f24d63 326 /* Version number of this structure. Must be 0 */
ccli8 1:5ffad9f24d63 327 conn_data.struct_version = 0;
ccli8 45:7d315fb1ba3e 328
ccli8 1:5ffad9f24d63 329 /* The message broker uses the client ID to identify each client. The client ID is passed
ccli8 1:5ffad9f24d63 330 * in from the client to the message broker as part of the MQTT payload. Two clients with
ccli8 1:5ffad9f24d63 331 * the same client ID are not allowed to be connected concurrently to the message broker.
ccli8 1:5ffad9f24d63 332 * When a client connects to the message broker using a client ID that another client is using,
ccli8 1:5ffad9f24d63 333 * a CONNACK message will be sent to both clients and the currently connected client will be
ccli8 1:5ffad9f24d63 334 * disconnected. */
ccli8 45:7d315fb1ba3e 335 #if defined(AWS_IOT_MQTT_CLIENTNAME)
ccli8 1:5ffad9f24d63 336 conn_data.clientID.cstring = AWS_IOT_MQTT_CLIENTNAME;
ccli8 45:7d315fb1ba3e 337 #else
ccli8 45:7d315fb1ba3e 338 char client_id_data[32];
ccli8 45:7d315fb1ba3e 339 #if TARGET_M23_NS
ccli8 45:7d315fb1ba3e 340 /* FMC/UID lies in SPE and is inaccessible to NSPE. Use random to generate pseudo-unique instead. */
ccli8 45:7d315fb1ba3e 341 uint32_t rand_words[3];
ccli8 45:7d315fb1ba3e 342 size_t olen;
ccli8 45:7d315fb1ba3e 343 mbedtls_hardware_poll(NULL, (unsigned char *) rand_words, sizeof(rand_words), &olen);
ccli8 45:7d315fb1ba3e 344 snprintf(client_id_data, sizeof(client_id_data), "%08X-%08X-%08X",
ccli8 45:7d315fb1ba3e 345 rand_words[0], rand_words[1], rand_words[2]);
ccli8 45:7d315fb1ba3e 346 #else
ccli8 45:7d315fb1ba3e 347 /* Use FMC/UID to generate unique client ID */
ccli8 45:7d315fb1ba3e 348 SYS_UnlockReg();
ccli8 45:7d315fb1ba3e 349 FMC_Open();
ccli8 45:7d315fb1ba3e 350 snprintf(client_id_data, sizeof(client_id_data), "%08X-%08X-%08X",
ccli8 45:7d315fb1ba3e 351 FMC_ReadUID(0), FMC_ReadUID(1), FMC_ReadUID(2));
ccli8 45:7d315fb1ba3e 352 FMC_Close();
ccli8 45:7d315fb1ba3e 353 SYS_LockReg();
ccli8 45:7d315fb1ba3e 354 #endif
ccli8 45:7d315fb1ba3e 355 conn_data.clientID.cstring = client_id_data;
ccli8 45:7d315fb1ba3e 356 #endif
ccli8 45:7d315fb1ba3e 357 printf("Resolved MQTT client ID: %s\n", conn_data.clientID.cstring);
ccli8 45:7d315fb1ba3e 358
ccli8 1:5ffad9f24d63 359 /* The message broker does not support persistent sessions (connections made with
ccli8 1:5ffad9f24d63 360 * the cleanSession flag set to false. The AWS IoT message broker assumes all sessions
ccli8 1:5ffad9f24d63 361 * are clean sessions and messages are not stored across sessions. If an MQTT client
ccli8 1:5ffad9f24d63 362 * attempts to connect to the AWS IoT message broker with the cleanSession set to false,
ccli8 1:5ffad9f24d63 363 * the client will be disconnected. */
ccli8 1:5ffad9f24d63 364 conn_data.cleansession = 1;
ccli8 1:5ffad9f24d63 365 //conn_data.username.cstring = "USERNAME";
ccli8 1:5ffad9f24d63 366 //conn_data.password.cstring = "PASSWORD";
ccli8 41:b878d7cd7035 367
ccli8 1:5ffad9f24d63 368 MQTT::connackData connack_data;
ccli8 41:b878d7cd7035 369
ccli8 1:5ffad9f24d63 370 /* _tlssocket must connect to the network endpoint before calling this. */
ccli8 1:5ffad9f24d63 371 printf("MQTT connecting");
ccli8 1:5ffad9f24d63 372 if ((mqtt_rc = _mqtt_client->connect(conn_data, connack_data)) != 0) {
ccli8 1:5ffad9f24d63 373 printf("\rMQTT connects failed: %d\n", mqtt_rc);
ccli8 1:5ffad9f24d63 374 break;
ccli8 1:5ffad9f24d63 375 }
ccli8 1:5ffad9f24d63 376 printf("\rMQTT connects OK\n\n");
ccli8 41:b878d7cd7035 377
ccli8 1:5ffad9f24d63 378 /* Subscribe/publish user topic */
ccli8 1:5ffad9f24d63 379 printf("Subscribing/publishing user topic\n");
ccli8 1:5ffad9f24d63 380 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)) {
ccli8 1:5ffad9f24d63 381 break;
ccli8 1:5ffad9f24d63 382 }
ccli8 1:5ffad9f24d63 383 printf("Subscribes/publishes user topic OK\n\n");
ccli8 41:b878d7cd7035 384
ccli8 1:5ffad9f24d63 385 /* Subscribe/publish UpdateThingShadow topic */
ccli8 1:5ffad9f24d63 386 printf("Subscribing/publishing UpdateThingShadow topic\n");
ccli8 1:5ffad9f24d63 387 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)) {
ccli8 1:5ffad9f24d63 388 break;
ccli8 1:5ffad9f24d63 389 }
ccli8 1:5ffad9f24d63 390 printf("Subscribes/publishes UpdateThingShadow topic OK\n\n");
ccli8 41:b878d7cd7035 391
ccli8 1:5ffad9f24d63 392 /* Subscribe/publish GetThingShadow topic */
ccli8 1:5ffad9f24d63 393 printf("Subscribing/publishing GetThingShadow topic\n");
ccli8 1:5ffad9f24d63 394 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)) {
ccli8 1:5ffad9f24d63 395 break;
ccli8 1:5ffad9f24d63 396 }
ccli8 1:5ffad9f24d63 397 printf("Subscribes/publishes GetThingShadow topic OK\n\n");
ccli8 41:b878d7cd7035 398
ccli8 1:5ffad9f24d63 399 /* Subscribe/publish DeleteThingShadow topic */
ccli8 1:5ffad9f24d63 400 printf("Subscribing/publishing DeleteThingShadow topic\n");
ccli8 1:5ffad9f24d63 401 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)) {
ccli8 1:5ffad9f24d63 402 break;
ccli8 1:5ffad9f24d63 403 }
ccli8 1:5ffad9f24d63 404 printf("Subscribes/publishes DeleteThingShadow topic OK\n\n");
ccli8 41:b878d7cd7035 405
ccli8 1:5ffad9f24d63 406 } while (0);
ccli8 41:b878d7cd7035 407
ccli8 1:5ffad9f24d63 408 printf("MQTT disconnecting");
ccli8 1:5ffad9f24d63 409 if ((mqtt_rc = _mqtt_client->disconnect()) != 0) {
ccli8 23:5111e398e651 410 printf("\rMQTT disconnects failed %d\n\n", mqtt_rc);
ccli8 1:5ffad9f24d63 411 }
ccli8 23:5111e398e651 412 printf("\rMQTT disconnects OK\n\n");
ccli8 41:b878d7cd7035 413
ccli8 1:5ffad9f24d63 414 _tlssocket->close();
ccli8 1:5ffad9f24d63 415 }
ccli8 1:5ffad9f24d63 416
ccli8 1:5ffad9f24d63 417 protected:
ccli8 1:5ffad9f24d63 418
ccli8 1:5ffad9f24d63 419 /**
ccli8 1:5ffad9f24d63 420 * @brief Subscribe/publish specific topic
ccli8 1:5ffad9f24d63 421 */
ccli8 1:5ffad9f24d63 422 bool sub_pub_topic(const char *topic, const char **topic_filters, size_t topic_filters_size, const char *publish_message_body) {
ccli8 41:b878d7cd7035 423
ccli8 1:5ffad9f24d63 424 bool ret = false;
ccli8 1:5ffad9f24d63 425 int mqtt_rc;
ccli8 41:b878d7cd7035 426
ccli8 1:5ffad9f24d63 427 do {
ccli8 1:5ffad9f24d63 428 const char **topic_filter;
ccli8 1:5ffad9f24d63 429 const char **topic_filter_end = topic_filters + topic_filters_size;
ccli8 1:5ffad9f24d63 430
ccli8 1:5ffad9f24d63 431 for (topic_filter = topic_filters; topic_filter != topic_filter_end; topic_filter ++) {
ccli8 1:5ffad9f24d63 432 /* AWS IoT does not support publishing and subscribing with QoS 2.
ccli8 1:5ffad9f24d63 433 * The AWS IoT message broker does not send a PUBACK or SUBACK when QoS 2 is requested. */
ccli8 1:5ffad9f24d63 434 printf("MQTT subscribing to %s", *topic_filter);
ccli8 1:5ffad9f24d63 435 if ((mqtt_rc = _mqtt_client->subscribe(*topic_filter, MQTT::QOS1, message_arrived)) != 0) {
ccli8 1:5ffad9f24d63 436 printf("\rMQTT subscribes to %s failed: %d\n", *topic_filter, mqtt_rc);
ccli8 1:5ffad9f24d63 437 continue;
ccli8 1:5ffad9f24d63 438 }
ccli8 1:5ffad9f24d63 439 printf("\rMQTT subscribes to %s OK\n", *topic_filter);
ccli8 1:5ffad9f24d63 440 }
ccli8 1:5ffad9f24d63 441
ccli8 35:36578356ed8a 442 /* Clear count of received message with subscribed topic */
ccli8 35:36578356ed8a 443 clear_message_arrive_count();
ccli8 35:36578356ed8a 444
ccli8 1:5ffad9f24d63 445 MQTT::Message message;
ccli8 1:5ffad9f24d63 446
ccli8 1:5ffad9f24d63 447 int _bpos;
ccli8 41:b878d7cd7035 448
ccli8 1:5ffad9f24d63 449 _bpos = snprintf(_buffer, sizeof (_buffer) - 1, publish_message_body);
ccli8 1:5ffad9f24d63 450 if (_bpos < 0 || ((size_t) _bpos) > (sizeof (_buffer) - 1)) {
ccli8 1:5ffad9f24d63 451 printf("snprintf failed: %d\n", _bpos);
ccli8 1:5ffad9f24d63 452 break;
ccli8 1:5ffad9f24d63 453 }
ccli8 1:5ffad9f24d63 454 _buffer[_bpos] = 0;
ccli8 1:5ffad9f24d63 455 /* AWS IoT does not support publishing and subscribing with QoS 2.
ccli8 1:5ffad9f24d63 456 * The AWS IoT message broker does not send a PUBACK or SUBACK when QoS 2 is requested. */
ccli8 1:5ffad9f24d63 457 message.qos = MQTT::QOS1;
ccli8 1:5ffad9f24d63 458 message.retained = false;
ccli8 1:5ffad9f24d63 459 message.dup = false;
ccli8 1:5ffad9f24d63 460 message.payload = _buffer;
ccli8 1:5ffad9f24d63 461 message.payloadlen = strlen(_buffer);
ccli8 1:5ffad9f24d63 462 /* Print publish message */
ccli8 1:5ffad9f24d63 463 printf("Message to publish:\n");
ccli8 1:5ffad9f24d63 464 printf("%s\n", _buffer);
ccli8 1:5ffad9f24d63 465 printf("MQTT publishing message to %s", topic);
ccli8 1:5ffad9f24d63 466 if ((mqtt_rc = _mqtt_client->publish(topic, message)) != 0) {
ccli8 1:5ffad9f24d63 467 printf("\rMQTT publishes message to %s failed: %d\n", topic, mqtt_rc);
ccli8 1:5ffad9f24d63 468 break;
ccli8 1:5ffad9f24d63 469 }
ccli8 1:5ffad9f24d63 470 printf("\rMQTT publishes message to %s OK\n", topic);
ccli8 41:b878d7cd7035 471
ccli8 1:5ffad9f24d63 472 /* Receive message with subscribed topic */
ccli8 35:36578356ed8a 473 printf("MQTT receives message with subscribed %s...\n", topic);
ccli8 35:36578356ed8a 474 Timer timer;
ccli8 35:36578356ed8a 475 timer.start();
ccli8 1:5ffad9f24d63 476 while (! _message_arrive_count) {
ccli8 35:36578356ed8a 477 if (timer.read_ms() >= MQTT_RECEIVE_MESSAGE_WITH_SUBSCRIBED_TOPIC_TIMEOUT_MS) {
ccli8 35:36578356ed8a 478 printf("MQTT receives message with subscribed %s TIMEOUT\n", topic);
ccli8 35:36578356ed8a 479 break;
ccli8 35:36578356ed8a 480 }
ccli8 35:36578356ed8a 481
ccli8 1:5ffad9f24d63 482 _mqtt_client->yield(100);
ccli8 1:5ffad9f24d63 483 }
ccli8 35:36578356ed8a 484 if (_message_arrive_count) {
ccli8 35:36578356ed8a 485 printf("MQTT receives message with subscribed %s OK\n", topic);
ccli8 35:36578356ed8a 486 }
ccli8 1:5ffad9f24d63 487 printf("\n");
ccli8 1:5ffad9f24d63 488
ccli8 1:5ffad9f24d63 489 /* Unsubscribe
ccli8 1:5ffad9f24d63 490 * We meet second unsubscribe failed. This is caused by MQTT lib bug. */
ccli8 1:5ffad9f24d63 491 for (topic_filter = topic_filters; topic_filter != topic_filter_end; topic_filter ++) {
ccli8 1:5ffad9f24d63 492 printf("MQTT unsubscribing from %s", *topic_filter);
ccli8 1:5ffad9f24d63 493 if ((mqtt_rc = _mqtt_client->unsubscribe(*topic_filter)) != 0) {
ccli8 1:5ffad9f24d63 494 printf("\rMQTT unsubscribes from %s failed: %d\n", *topic_filter, mqtt_rc);
ccli8 1:5ffad9f24d63 495 continue;
ccli8 1:5ffad9f24d63 496 }
ccli8 1:5ffad9f24d63 497 printf("\rMQTT unsubscribes from %s OK\n", *topic_filter);
ccli8 1:5ffad9f24d63 498 }
ccli8 1:5ffad9f24d63 499
ccli8 1:5ffad9f24d63 500 ret = true;
ccli8 41:b878d7cd7035 501
ccli8 1:5ffad9f24d63 502 } while (0);
ccli8 41:b878d7cd7035 503
ccli8 1:5ffad9f24d63 504 return ret;
ccli8 1:5ffad9f24d63 505 }
ccli8 41:b878d7cd7035 506
ccli8 1:5ffad9f24d63 507 protected:
ccli8 17:6f0ff065cd76 508 MyTLSSocket * _tlssocket;
ccli8 17:6f0ff065cd76 509 MQTT::Client<MyTLSSocket, Countdown, MAX_MQTT_PACKET_SIZE> * _mqtt_client;
ccli8 1:5ffad9f24d63 510
ccli8 1:5ffad9f24d63 511 const char *_domain; /**< Domain name of the MQTT server */
ccli8 1:5ffad9f24d63 512 const uint16_t _port; /**< Port number of the MQTT server */
ccli8 1:5ffad9f24d63 513 char _buffer[MQTT_USER_BUFFER_SIZE]; /**< User buffer */
ccli8 41:b878d7cd7035 514 NetworkInterface *_net_iface;
ccli8 41:b878d7cd7035 515
ccli8 1:5ffad9f24d63 516 private:
ccli8 1:5ffad9f24d63 517 static volatile uint16_t _message_arrive_count;
ccli8 1:5ffad9f24d63 518
ccli8 1:5ffad9f24d63 519 static void message_arrived(MQTT::MessageData& md) {
ccli8 1:5ffad9f24d63 520 MQTT::Message &message = md.message;
ccli8 1:5ffad9f24d63 521 printf("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
ccli8 1:5ffad9f24d63 522 printf("Payload:\n");
ccli8 1:5ffad9f24d63 523 printf("%.*s\n", message.payloadlen, (char*)message.payload);
ccli8 1:5ffad9f24d63 524 ++ _message_arrive_count;
ccli8 1:5ffad9f24d63 525 }
ccli8 41:b878d7cd7035 526
ccli8 1:5ffad9f24d63 527 static void clear_message_arrive_count() {
ccli8 1:5ffad9f24d63 528 _message_arrive_count = 0;
ccli8 1:5ffad9f24d63 529 }
ccli8 1:5ffad9f24d63 530 };
ccli8 1:5ffad9f24d63 531
ccli8 1:5ffad9f24d63 532 volatile uint16_t AWS_IoT_MQTT_Test::_message_arrive_count = 0;
ccli8 1:5ffad9f24d63 533
ccli8 1:5ffad9f24d63 534 #endif // End of AWS_IOT_MQTT_TEST
ccli8 1:5ffad9f24d63 535
ccli8 1:5ffad9f24d63 536
ccli8 1:5ffad9f24d63 537 #if AWS_IOT_HTTPS_TEST
ccli8 1:5ffad9f24d63 538
ccli8 1:5ffad9f24d63 539 /**
ccli8 1:5ffad9f24d63 540 * /brief AWS_IoT_HTTPS_Test implements the logic with AWS IoT User/Thing Shadow topics (publish-only)
ccli8 1:5ffad9f24d63 541 * and Thing Shadow RESTful API through HTTPS.
ccli8 1:5ffad9f24d63 542 */
ccli8 1:5ffad9f24d63 543 class AWS_IoT_HTTPS_Test {
ccli8 1:5ffad9f24d63 544
ccli8 1:5ffad9f24d63 545 public:
ccli8 1:5ffad9f24d63 546 /**
ccli8 1:5ffad9f24d63 547 * @brief AWS_IoT_HTTPS_Test Constructor
ccli8 1:5ffad9f24d63 548 *
ccli8 1:5ffad9f24d63 549 * @param[in] domain Domain name of the HTTPS server
ccli8 1:5ffad9f24d63 550 * @param[in] port Port number of the HTTPS server
ccli8 1:5ffad9f24d63 551 * @param[in] net_iface Network interface
ccli8 1:5ffad9f24d63 552 */
ccli8 1:5ffad9f24d63 553 AWS_IoT_HTTPS_Test(const char * domain, const uint16_t port, NetworkInterface *net_iface) :
ccli8 41:b878d7cd7035 554 _domain(domain), _port(port), _net_iface(net_iface) {
ccli8 41:b878d7cd7035 555 _tlssocket = new MyTLSSocket;
ccli8 1:5ffad9f24d63 556 }
ccli8 1:5ffad9f24d63 557 /**
ccli8 1:5ffad9f24d63 558 * @brief AWS_IoT_HTTPS_Test Destructor
ccli8 1:5ffad9f24d63 559 */
ccli8 1:5ffad9f24d63 560 ~AWS_IoT_HTTPS_Test() {
ccli8 1:5ffad9f24d63 561 _tlssocket->close();
ccli8 1:5ffad9f24d63 562 delete _tlssocket;
ccli8 1:5ffad9f24d63 563 _tlssocket = NULL;
ccli8 1:5ffad9f24d63 564 }
ccli8 1:5ffad9f24d63 565 /**
ccli8 1:5ffad9f24d63 566 * @brief Start AWS IoT test through HTTPS
ccli8 1:5ffad9f24d63 567 *
ccli8 1:5ffad9f24d63 568 * @param[in] path The path of the file to fetch from the HTTPS server
ccli8 1:5ffad9f24d63 569 */
ccli8 1:5ffad9f24d63 570 void start_test() {
ccli8 41:b878d7cd7035 571
ccli8 1:5ffad9f24d63 572 int tls_rc;
ccli8 41:b878d7cd7035 573
ccli8 1:5ffad9f24d63 574 do {
ccli8 41:b878d7cd7035 575 /* Set host name of the remote host, used for certificate checking */
ccli8 41:b878d7cd7035 576 _tlssocket->set_hostname(_domain);
ccli8 41:b878d7cd7035 577
ccli8 41:b878d7cd7035 578 /* Set the certification of Root CA */
ccli8 41:b878d7cd7035 579 tls_rc = _tlssocket->set_root_ca_cert(SSL_CA_CERT_PEM);
ccli8 41:b878d7cd7035 580 if (tls_rc != NSAPI_ERROR_OK) {
ccli8 41:b878d7cd7035 581 printf("TLSSocket::set_root_ca_cert(...) returned %d\n", tls_rc);
ccli8 41:b878d7cd7035 582 break;
ccli8 41:b878d7cd7035 583 }
ccli8 41:b878d7cd7035 584
ccli8 41:b878d7cd7035 585 /* Set client certificate and client private key */
ccli8 41:b878d7cd7035 586 tls_rc = _tlssocket->set_client_cert_key(SSL_USER_CERT_PEM, SSL_USER_PRIV_KEY_PEM);
ccli8 41:b878d7cd7035 587 if (tls_rc != NSAPI_ERROR_OK) {
ccli8 41:b878d7cd7035 588 printf("TLSSocket::set_client_cert_key(...) returned %d\n", tls_rc);
ccli8 41:b878d7cd7035 589 break;
ccli8 41:b878d7cd7035 590 }
ccli8 41:b878d7cd7035 591
ccli8 41:b878d7cd7035 592 /* Open a network socket on the network stack of the given network interface */
ccli8 41:b878d7cd7035 593 printf("Opening network socket on network stack\n");
ccli8 41:b878d7cd7035 594 tls_rc = _tlssocket->open(_net_iface);
ccli8 41:b878d7cd7035 595 if (tls_rc != NSAPI_ERROR_OK) {
ccli8 41:b878d7cd7035 596 printf("Opens network socket on network stack failed: %d\n", tls_rc);
ccli8 41:b878d7cd7035 597 break;
ccli8 41:b878d7cd7035 598 }
ccli8 41:b878d7cd7035 599 printf("Opens network socket on network stack OK\n");
ccli8 41:b878d7cd7035 600
ccli8 41:b878d7cd7035 601 /* DNS resolution */
ccli8 41:b878d7cd7035 602 printf("DNS resolution for %s...\n", _domain);
ccli8 41:b878d7cd7035 603 SocketAddress sockaddr;
ccli8 41:b878d7cd7035 604 tls_rc = _net_iface->gethostbyname(_domain, &sockaddr);
ccli8 41:b878d7cd7035 605 if (tls_rc != NSAPI_ERROR_OK) {
ccli8 41:b878d7cd7035 606 printf("DNS resolution for %s failed with %d\n", _domain, tls_rc);
ccli8 41:b878d7cd7035 607 break;
ccli8 41:b878d7cd7035 608 }
ccli8 41:b878d7cd7035 609 sockaddr.set_port(_port);
ccli8 41:b878d7cd7035 610 printf("DNS resolution for %s: %s:%d\n", _domain, sockaddr.get_ip_address(), sockaddr.get_port());
ccli8 41:b878d7cd7035 611
ccli8 1:5ffad9f24d63 612 /* Connect to the server */
ccli8 1:5ffad9f24d63 613 /* Initialize TLS-related stuff */
ccli8 1:5ffad9f24d63 614 printf("Connecting with %s:%d\n", _domain, _port);
ccli8 41:b878d7cd7035 615 tls_rc = _tlssocket->connect(sockaddr);
ccli8 1:5ffad9f24d63 616 if (tls_rc != NSAPI_ERROR_OK) {
ccli8 3:4c8cccd32e34 617 printf("Connects with %s:%d failed: %d\n", _domain, _port, tls_rc);
ccli8 1:5ffad9f24d63 618 break;
ccli8 1:5ffad9f24d63 619 }
ccli8 41:b878d7cd7035 620 printf("Connects with %s:%d OK\n", _domain, _port);
ccli8 41:b878d7cd7035 621
ccli8 41:b878d7cd7035 622 /* Non-blocking mode
ccli8 41:b878d7cd7035 623 *
ccli8 41:b878d7cd7035 624 * Don't change to non-blocking mode before connect; otherwise, we may meet NSAPI_ERROR_IN_PROGRESS.
ccli8 41:b878d7cd7035 625 */
ccli8 41:b878d7cd7035 626 _tlssocket->set_blocking(false);
ccli8 1:5ffad9f24d63 627
ccli8 1:5ffad9f24d63 628 /* Publish to user topic through HTTPS/POST */
ccli8 1:5ffad9f24d63 629 printf("Publishing to user topic through HTTPS/POST\n");
ccli8 1:5ffad9f24d63 630 if (! run_req_resp(USER_TOPIC_HTTPS_PATH, USER_TOPIC_HTTPS_REQUEST_METHOD, USER_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) {
ccli8 1:5ffad9f24d63 631 break;
ccli8 1:5ffad9f24d63 632 }
ccli8 1:5ffad9f24d63 633 printf("Publishes to user topic through HTTPS/POST OK\n\n");
ccli8 41:b878d7cd7035 634
ccli8 1:5ffad9f24d63 635 /* Update thing shadow by publishing to UpdateThingShadow topic through HTTPS/POST */
ccli8 1:5ffad9f24d63 636 printf("Updating thing shadow by publishing to Update Thing Shadow topic through HTTPS/POST\n");
ccli8 1:5ffad9f24d63 637 if (! run_req_resp(UPDATETHINGSHADOW_TOPIC_HTTPS_PATH, UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD, UPDATETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) {
ccli8 1:5ffad9f24d63 638 break;
ccli8 1:5ffad9f24d63 639 }
ccli8 1:5ffad9f24d63 640 printf("Update thing shadow by publishing to Update Thing Shadow topic through HTTPS/POST OK\n\n");
ccli8 41:b878d7cd7035 641
ccli8 1:5ffad9f24d63 642 /* Get thing shadow by publishing to GetThingShadow topic through HTTPS/POST */
ccli8 1:5ffad9f24d63 643 printf("Getting thing shadow by publishing to GetThingShadow topic through HTTPS/POST\n");
ccli8 1:5ffad9f24d63 644 if (! run_req_resp(GETTHINGSHADOW_TOPIC_HTTPS_PATH, GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD, GETTHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) {
ccli8 1:5ffad9f24d63 645 break;
ccli8 1:5ffad9f24d63 646 }
ccli8 1:5ffad9f24d63 647 printf("Get thing shadow by publishing to GetThingShadow topic through HTTPS/POST OK\n\n");
ccli8 41:b878d7cd7035 648
ccli8 1:5ffad9f24d63 649 /* Delete thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST */
ccli8 1:5ffad9f24d63 650 printf("Deleting thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST\n");
ccli8 1:5ffad9f24d63 651 if (! run_req_resp(DELETETHINGSHADOW_TOPIC_HTTPS_PATH, DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_METHOD, DELETETHINGSHADOW_TOPIC_HTTPS_REQUEST_MESSAGE_BODY)) {
ccli8 1:5ffad9f24d63 652 break;
ccli8 1:5ffad9f24d63 653 }
ccli8 1:5ffad9f24d63 654 printf("Delete thing shadow by publishing to DeleteThingShadow topic through HTTPS/POST OK\n\n");
ccli8 41:b878d7cd7035 655
ccli8 1:5ffad9f24d63 656 /* Update thing shadow RESTfully through HTTPS/POST */
ccli8 1:5ffad9f24d63 657 printf("Updating thing shadow RESTfully through HTTPS/POST\n");
ccli8 1:5ffad9f24d63 658 if (! run_req_resp(UPDATETHINGSHADOW_THING_HTTPS_PATH, UPDATETHINGSHADOW_THING_HTTPS_REQUEST_METHOD, UPDATETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY)) {
ccli8 1:5ffad9f24d63 659 break;
ccli8 1:5ffad9f24d63 660 }
ccli8 1:5ffad9f24d63 661 printf("Update thing shadow RESTfully through HTTPS/POST OK\n\n");
ccli8 41:b878d7cd7035 662
ccli8 1:5ffad9f24d63 663 /* Get thing shadow RESTfully through HTTPS/GET */
ccli8 1:5ffad9f24d63 664 printf("Getting thing shadow RESTfully through HTTPS/GET\n");
ccli8 1:5ffad9f24d63 665 if (! run_req_resp(GETTHINGSHADOW_THING_HTTPS_PATH, GETTHINGSHADOW_THING_HTTPS_REQUEST_METHOD, GETTHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY)) {
ccli8 1:5ffad9f24d63 666 break;
ccli8 1:5ffad9f24d63 667 }
ccli8 1:5ffad9f24d63 668 printf("Get thing shadow RESTfully through HTTPS/GET OK\n\n");
ccli8 41:b878d7cd7035 669
ccli8 1:5ffad9f24d63 670 /* Delete thing shadow RESTfully through HTTPS/DELETE */
ccli8 1:5ffad9f24d63 671 printf("Deleting thing shadow RESTfully through HTTPS/DELETE\n");
ccli8 1:5ffad9f24d63 672 if (! run_req_resp(DELETETHINGSHADOW_THING_HTTPS_PATH, DELETETHINGSHADOW_THING_HTTPS_REQUEST_METHOD, DELETETHINGSHADOW_THING_HTTPS_REQUEST_MESSAGE_BODY)) {
ccli8 1:5ffad9f24d63 673 break;
ccli8 1:5ffad9f24d63 674 }
ccli8 1:5ffad9f24d63 675 printf("Delete thing shadow RESTfully through HTTPS/DELETE OK\n\n");
ccli8 1:5ffad9f24d63 676
ccli8 1:5ffad9f24d63 677 } while (0);
ccli8 1:5ffad9f24d63 678
ccli8 1:5ffad9f24d63 679 /* Close socket */
ccli8 1:5ffad9f24d63 680 _tlssocket->close();
ccli8 1:5ffad9f24d63 681 }
ccli8 1:5ffad9f24d63 682
ccli8 1:5ffad9f24d63 683 protected:
ccli8 1:5ffad9f24d63 684
ccli8 1:5ffad9f24d63 685 /**
ccli8 1:5ffad9f24d63 686 * @brief Run request/response through HTTPS
ccli8 1:5ffad9f24d63 687 */
ccli8 1:5ffad9f24d63 688 bool run_req_resp(const char *https_path, const char *https_request_method, const char *https_request_message_body) {
ccli8 41:b878d7cd7035 689
ccli8 1:5ffad9f24d63 690 bool ret = false;
ccli8 41:b878d7cd7035 691
ccli8 1:5ffad9f24d63 692 do {
ccli8 1:5ffad9f24d63 693 int tls_rc;
ccli8 1:5ffad9f24d63 694 bool _got200 = false;
ccli8 1:5ffad9f24d63 695
ccli8 1:5ffad9f24d63 696 int _bpos;
ccli8 1:5ffad9f24d63 697
ccli8 1:5ffad9f24d63 698 /* Fill the request buffer */
ccli8 1:5ffad9f24d63 699 _bpos = snprintf(_buffer, sizeof(_buffer) - 1,
ccli8 1:5ffad9f24d63 700 "%s %s HTTP/1.1\r\n" "Host: %s\r\n" "Content-Length: %d\r\n" "\r\n" "%s",
ccli8 1:5ffad9f24d63 701 https_request_method, https_path, AWS_IOT_HTTPS_SERVER_NAME, strlen(https_request_message_body), https_request_message_body);
ccli8 1:5ffad9f24d63 702 if (_bpos < 0 || ((size_t) _bpos) > (sizeof (_buffer) - 1)) {
ccli8 1:5ffad9f24d63 703 printf("snprintf failed: %d\n", _bpos);
ccli8 1:5ffad9f24d63 704 break;
ccli8 1:5ffad9f24d63 705 }
ccli8 1:5ffad9f24d63 706 _buffer[_bpos] = 0;
ccli8 1:5ffad9f24d63 707 /* Print request message */
ccli8 1:5ffad9f24d63 708 printf("HTTPS: Request message:\n");
ccli8 1:5ffad9f24d63 709 printf("%s\n", _buffer);
ccli8 41:b878d7cd7035 710
ccli8 1:5ffad9f24d63 711 int offset = 0;
ccli8 1:5ffad9f24d63 712 do {
ccli8 1:5ffad9f24d63 713 tls_rc = _tlssocket->send((const unsigned char *) _buffer + offset, _bpos - offset);
ccli8 1:5ffad9f24d63 714 if (tls_rc > 0) {
ccli8 1:5ffad9f24d63 715 offset += tls_rc;
ccli8 1:5ffad9f24d63 716 }
ccli8 1:5ffad9f24d63 717 } while (offset < _bpos &&
ccli8 41:b878d7cd7035 718 (tls_rc > 0 || tls_rc == NSAPI_ERROR_WOULD_BLOCK));
ccli8 41:b878d7cd7035 719 if (tls_rc < 0 &&
ccli8 41:b878d7cd7035 720 tls_rc != NSAPI_ERROR_WOULD_BLOCK) {
ccli8 1:5ffad9f24d63 721 print_mbedtls_error("_tlssocket->send", tls_rc);
ccli8 1:5ffad9f24d63 722 break;
ccli8 1:5ffad9f24d63 723 }
ccli8 1:5ffad9f24d63 724
ccli8 1:5ffad9f24d63 725 /* Read data out of the socket */
ccli8 1:5ffad9f24d63 726 offset = 0;
ccli8 1:5ffad9f24d63 727 size_t content_length = 0;
ccli8 1:5ffad9f24d63 728 size_t offset_end = 0;
ccli8 1:5ffad9f24d63 729 char *line_beg = _buffer;
ccli8 1:5ffad9f24d63 730 char *line_end = NULL;
ccli8 1:5ffad9f24d63 731 do {
ccli8 1:5ffad9f24d63 732 tls_rc = _tlssocket->recv((unsigned char *) _buffer + offset, sizeof(_buffer) - offset - 1);
ccli8 1:5ffad9f24d63 733 if (tls_rc > 0) {
ccli8 1:5ffad9f24d63 734 offset += tls_rc;
ccli8 1:5ffad9f24d63 735 }
ccli8 1:5ffad9f24d63 736
ccli8 1:5ffad9f24d63 737 /* Make it null-terminated */
ccli8 1:5ffad9f24d63 738 _buffer[offset] = 0;
ccli8 1:5ffad9f24d63 739
ccli8 1:5ffad9f24d63 740 /* Scan response message
ccli8 1:5ffad9f24d63 741 *
ccli8 1:5ffad9f24d63 742 * 1. A status line which includes the status code and reason message (e.g., HTTP/1.1 200 OK)
ccli8 1:5ffad9f24d63 743 * 2. Response header fields (e.g., Content-Type: text/html)
ccli8 1:5ffad9f24d63 744 * 3. An empty line (\r\n)
ccli8 1:5ffad9f24d63 745 * 4. An optional message body
ccli8 1:5ffad9f24d63 746 */
ccli8 1:5ffad9f24d63 747 if (! offset_end) {
ccli8 1:5ffad9f24d63 748 line_end = strstr(line_beg, "\r\n");
ccli8 1:5ffad9f24d63 749 if (line_end) {
ccli8 1:5ffad9f24d63 750 /* Scan status line */
ccli8 1:5ffad9f24d63 751 if (! _got200) {
ccli8 1:5ffad9f24d63 752 _got200 = strstr(line_beg, HTTPS_OK_STR) != NULL;
ccli8 1:5ffad9f24d63 753 }
ccli8 1:5ffad9f24d63 754
ccli8 1:5ffad9f24d63 755 /* Scan response header fields for Content-Length
ccli8 1:5ffad9f24d63 756 *
ccli8 1:5ffad9f24d63 757 * NOTE: Assume chunked transfer (Transfer-Encoding: chunked) is not used
ccli8 1:5ffad9f24d63 758 * NOTE: Assume response field name are in lower case
ccli8 1:5ffad9f24d63 759 */
ccli8 1:5ffad9f24d63 760 if (content_length == 0) {
ccli8 1:5ffad9f24d63 761 sscanf(line_beg, "content-length:%d", &content_length);
ccli8 1:5ffad9f24d63 762 }
ccli8 1:5ffad9f24d63 763
ccli8 1:5ffad9f24d63 764 /* An empty line indicates end of response header fields */
ccli8 1:5ffad9f24d63 765 if (line_beg == line_end) {
ccli8 1:5ffad9f24d63 766 offset_end = line_end - _buffer + 2 + content_length;
ccli8 1:5ffad9f24d63 767 }
ccli8 1:5ffad9f24d63 768
ccli8 1:5ffad9f24d63 769 /* Go to next line */
ccli8 1:5ffad9f24d63 770 line_beg = line_end + 2;
ccli8 1:5ffad9f24d63 771 line_end = NULL;
ccli8 1:5ffad9f24d63 772 }
ccli8 1:5ffad9f24d63 773 }
ccli8 1:5ffad9f24d63 774 } while ((offset_end == 0 || offset < offset_end) &&
ccli8 41:b878d7cd7035 775 (tls_rc > 0 || tls_rc == NSAPI_ERROR_WOULD_BLOCK));
ccli8 1:5ffad9f24d63 776 if (tls_rc < 0 &&
ccli8 41:b878d7cd7035 777 tls_rc != NSAPI_ERROR_WOULD_BLOCK) {
ccli8 1:5ffad9f24d63 778 print_mbedtls_error("_tlssocket->read", tls_rc);
ccli8 1:5ffad9f24d63 779 break;
ccli8 1:5ffad9f24d63 780 }
ccli8 1:5ffad9f24d63 781 _bpos = offset;
ccli8 1:5ffad9f24d63 782
ccli8 1:5ffad9f24d63 783 _buffer[_bpos] = 0;
ccli8 1:5ffad9f24d63 784
ccli8 1:5ffad9f24d63 785 /* Print status messages */
ccli8 1:5ffad9f24d63 786 printf("HTTPS: Received %d chars from server\n", _bpos);
ccli8 1:5ffad9f24d63 787 printf("HTTPS: Received 200 OK status ... %s\n", _got200 ? "[OK]" : "[FAIL]");
ccli8 1:5ffad9f24d63 788 printf("HTTPS: Received message:\n");
ccli8 1:5ffad9f24d63 789 printf("%s\n", _buffer);
ccli8 41:b878d7cd7035 790
ccli8 1:5ffad9f24d63 791 ret = true;
ccli8 41:b878d7cd7035 792
ccli8 1:5ffad9f24d63 793 } while (0);
ccli8 41:b878d7cd7035 794
ccli8 1:5ffad9f24d63 795 return ret;
ccli8 1:5ffad9f24d63 796 }
ccli8 41:b878d7cd7035 797
ccli8 1:5ffad9f24d63 798 protected:
ccli8 17:6f0ff065cd76 799 MyTLSSocket * _tlssocket;
ccli8 1:5ffad9f24d63 800
ccli8 1:5ffad9f24d63 801 const char *_domain; /**< Domain name of the HTTPS server */
ccli8 1:5ffad9f24d63 802 const uint16_t _port; /**< Port number of the HTTPS server */
ccli8 1:5ffad9f24d63 803 char _buffer[HTTPS_USER_BUFFER_SIZE]; /**< User buffer */
ccli8 41:b878d7cd7035 804 NetworkInterface *_net_iface;
ccli8 1:5ffad9f24d63 805 };
ccli8 1:5ffad9f24d63 806
ccli8 1:5ffad9f24d63 807 #endif // End of AWS_IOT_HTTPS_TEST
ccli8 1:5ffad9f24d63 808
ccli8 1:5ffad9f24d63 809 int main() {
ccli8 41:b878d7cd7035 810
ccli8 1:5ffad9f24d63 811 /* The default 9600 bps is too slow to print full TLS debug info and could
ccli8 1:5ffad9f24d63 812 * cause the other party to time out. */
ccli8 1:5ffad9f24d63 813
ccli8 1:5ffad9f24d63 814 printf("\nStarting AWS IoT test\n");
ccli8 1:5ffad9f24d63 815
ccli8 1:5ffad9f24d63 816 #if defined(MBED_MAJOR_VERSION)
ccli8 1:5ffad9f24d63 817 printf("Using Mbed OS %d.%d.%d\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
ccli8 1:5ffad9f24d63 818 #else
ccli8 1:5ffad9f24d63 819 printf("Using Mbed OS from master.\n");
ccli8 1:5ffad9f24d63 820 #endif
ccli8 1:5ffad9f24d63 821
ccli8 12:97762a6f55e9 822 NetworkInterface *net = NetworkInterface::get_default_instance();
ccli8 12:97762a6f55e9 823 if (NULL == net) {
ccli8 1:5ffad9f24d63 824 printf("Connecting to the network failed. See serial output.\n");
ccli8 1:5ffad9f24d63 825 return 1;
ccli8 1:5ffad9f24d63 826 }
ccli8 12:97762a6f55e9 827 nsapi_error_t status = net->connect();
ccli8 12:97762a6f55e9 828 if (status != NSAPI_ERROR_OK) {
ccli8 12:97762a6f55e9 829 printf("Connecting to the network failed %d!\n", status);
ccli8 12:97762a6f55e9 830 return -1;
ccli8 12:97762a6f55e9 831 }
ccli8 41:b878d7cd7035 832 SocketAddress sockaddr;
ccli8 41:b878d7cd7035 833 status = net->get_ip_address(&sockaddr);
ccli8 41:b878d7cd7035 834 if (status != NSAPI_ERROR_OK) {
ccli8 41:b878d7cd7035 835 printf("Network interface get_ip_address(...) failed with %d", status);
ccli8 41:b878d7cd7035 836 return -1;
ccli8 41:b878d7cd7035 837 }
ccli8 41:b878d7cd7035 838 printf("Connected to the network successfully. IP address: %s\n", sockaddr.get_ip_address());
ccli8 41:b878d7cd7035 839
ccli8 1:5ffad9f24d63 840 #if AWS_IOT_MQTT_TEST
ccli8 12:97762a6f55e9 841 AWS_IoT_MQTT_Test *mqtt_test = new AWS_IoT_MQTT_Test(AWS_IOT_MQTT_SERVER_NAME, AWS_IOT_MQTT_SERVER_PORT, net);
ccli8 1:5ffad9f24d63 842 mqtt_test->start_test();
ccli8 1:5ffad9f24d63 843 delete mqtt_test;
ccli8 1:5ffad9f24d63 844 #endif // End of AWS_IOT_MQTT_TEST
ccli8 41:b878d7cd7035 845
ccli8 1:5ffad9f24d63 846 #if AWS_IOT_HTTPS_TEST
ccli8 12:97762a6f55e9 847 AWS_IoT_HTTPS_Test *https_test = new AWS_IoT_HTTPS_Test(AWS_IOT_HTTPS_SERVER_NAME, AWS_IOT_HTTPS_SERVER_PORT, net);
ccli8 1:5ffad9f24d63 848 https_test->start_test();
ccli8 1:5ffad9f24d63 849 delete https_test;
ccli8 1:5ffad9f24d63 850 #endif // End of AWS_IOT_HTTPS_TEST
ccli8 36:1bec082ad582 851
ccli8 36:1bec082ad582 852 /* Some cellular modems e.g.: QUECTEL EC2X need graceful exit; otherwise, they will break in next reboot. */
ccli8 36:1bec082ad582 853 status = net->disconnect();
ccli8 36:1bec082ad582 854 if (status != NSAPI_ERROR_OK) {
ccli8 36:1bec082ad582 855 printf("\n\nDisconnect from network interface failed %d\n", status);
ccli8 36:1bec082ad582 856 }
ccli8 1:5ffad9f24d63 857 }