Example of AWS IoT connection and Web Dashboard thru STM32 Nucleo evaluation board and mbed OS.
Dependencies: X_NUCLEO_IKS01A1 mbed FP MQTTPacket DnsQuery ATParser
main.cpp
00001 /* SpwfInterface NetworkSocketAPI Example Program 00002 * Copyright (c) 2015 ARM Limited 00003 * Copyright (c) 2017 KLIKA TECH, LLC 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 00017 Contributors: 00018 * Klika Tech - completely adopted to Amazon AWS IoT service 00019 00020 */ 00021 00022 #include "mbed.h" 00023 #include "SpwfInterface.h" 00024 #include "TCPSocket.h" 00025 #include "MQTTClient.h" 00026 #include "MQTTWiFi.h" 00027 #include <ctype.h> 00028 #include "x_nucleo_iks01a1.h" 00029 00030 //------------------------------------ 00031 // Hyperterminal default configuration 00032 // 9600 bauds, 8-bit data, no parity 00033 //------------------------------------ 00034 Serial pc(SERIAL_TX, SERIAL_RX); 00035 DigitalOut myled(LED2); 00036 DigitalOut butled(LED3); 00037 InterruptIn mybutton(USER_BUTTON); 00038 00039 bool myButtonPressed = false; 00040 00041 #define MQTT_MAX_PACKET_SIZE 350 00042 #define MQTT_MAX_PAYLOAD_SIZE 300 00043 00044 #define AWS_IOT_MQTT_HOST "a3t8vwpkw3sltg.iot.us-east-2.amazonaws.com" //Use your own host. 00045 #define AWS_IOT_MQTT_PORT 8883 00046 #define AWS_IOT_MQTT_CLIENT_ID "Nucleo" //Should be kept if you are using same device clent. 00047 #define AWS_IOT_MY_THING_NAME "Nucleo" //Should be kept if you are using same device thing name. 00048 #define AWS_IOT_MQTT_TOPIC_TEST "Nucleo/test" 00049 #define AWS_IOT_MQTT_TOPIC_DATA "Nucleo/data" 00050 #define AWS_IOT_MQTT_TOPIC_SHADOW "$aws/things/Nucleo/shadow/update" 00051 #define AWS_IOT_ID "" 00052 #define AWS_IOT_AUTH_TOKEN "" 00053 00054 // WiFi network credential 00055 #define SSID "" // Network must be visible otherwise it can't connect 00056 #define PASSW "" 00057 #error "Wifi SSID & password empty" 00058 00059 #include "stdint.h" 00060 00061 00062 /********************************************************************************************** 00063 *********************************************************************************************** 00064 Root CA certificate: Never modify 00065 *********************************************************************************************** 00066 ***********************************************************************************************/ 00067 00068 //This root CA can be used. 00069 const uint8_t rootCA[] = "\ 00070 -----BEGIN CERTIFICATE-----\n\ 00071 MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB\ 00072 yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\ 00073 ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp\ 00074 U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW\ 00075 ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0\ 00076 aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL\ 00077 MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW\ 00078 ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln\ 00079 biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp\ 00080 U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y\ 00081 aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1\ 00082 nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex\ 00083 t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz\ 00084 SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG\ 00085 BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+\ 00086 rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/\ 00087 NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E\ 00088 BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH\ 00089 BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy\ 00090 aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv\ 00091 MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE\ 00092 p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y\ 00093 5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK\ 00094 WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ\ 00095 4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N\ 00096 hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao8WNq\n\ 00097 -----END CERTIFICATE-----\n"; 00098 00099 /********************************************************************************************** 00100 *********************************************************************************************** 00101 Device Identity Certificates: Modify for your AWS IoT Thing 00102 *********************************************************************************************** 00103 ***********************************************************************************************/ 00104 00105 /**************************************** 00106 (somecode)-certificate.pem.crt - Amazon signed PEM sertificate. 00107 *****************************************/ 00108 00109 //This Client cert is example. Use own instead. 00110 const uint8_t clientCRT[] = "\ 00111 -----BEGIN CERTIFICATE-----\n\ 00112 MIIC8jCCAdqgAwIBAgIVAJrIfpHLnCshC2j/Tp0dBJlSgaFnMA0GCSqGSIb3DQEB\ 00113 CwUAME0xSzBJBgNVBAsMQkFtYXpvbiBXZWIgU2VydmljZXMgTz1BbWF6b24uY29t\ 00114 IEluYy4gTD1TZWF0dGxlIFNUPVdhc2hpbmd0b24gQz1VUzAeFw0xNzA5MTUxMjQ3\ 00115 NDBaFw00OTEyMzEyMzU5NTlaMIGAMQswCQYDVQQGEwJERTENMAsGA1UECBMERGVt\ 00116 bzENMAsGA1UEBxMERGVtbzENMAsGA1UEChMERGVtbzENMAsGA1UECxMERGVtbzEN\ 00117 MAsGA1UEAxMERGVtbzEmMCQGCSqGSIb3DQEJARYXcHNhdnloaW5Aa2xpa2EtdGVj\ 00118 aC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT5IihA21BQZFW0vSdVxNuD\ 00119 VKXAN7rI3Op3/MiWOlXqHEGHZeYs5ug8qEYkDZDkafhO87LNC0xhNSnGsNnNmyPI\ 00120 o2AwXjAfBgNVHSMEGDAWgBRF1n2grhwmYjwSZmF74bVqm/enfjAdBgNVHQ4EFgQU\ 00121 qSNNYMI1XGRMnnLenZlU1h/WNAkwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMC\ 00122 B4AwDQYJKoZIhvcNAQELBQADggEBADTAhidWjd+MD6sLqr8+ZTdIcka0kT0tnMGy\ 00123 Chz5ixaDpNI/OS9fi+SfOAd1Dd+/panpNtvJ5OfN0wkYJRd+lhBaN8M5lWsIF7EM\ 00124 FvFtc+UV2cvGyYmSW47fFaV3DOv8vL068cmpNkd/HF8q9r0QNd0h2o97G99Xkk9k\ 00125 90DIOgzu0C3sSTy5xDankCvfWIM2ibh5Laz3NmIqVW9jnnkMpQ00xViR8IdnfR4g\ 00126 ke1C33ZQh1yTGNEE94nVGRMB2cPY62ChrM/ffgmUo4De0M45tX8ucFVL+ZwaCc3E\ 00127 pmjMxFza6yZU50a74zZESmWGR5HYp0PSovglr9Xc5jvktqSugKM=\ 00128 \n\ 00129 -----END CERTIFICATE-----\n"; 00130 00131 00132 00133 /********************************************************************************************** 00134 *********************************************************************************************** 00135 Private Key: Modify for your AWS IoT Thing 00136 *********************************************************************************************** 00137 ***********************************************************************************************/ 00138 00139 /********************************************************************8**************************************** 00140 nucleo.key.pem - client key generated according to readme. 00141 **************************************************************************************************************/ 00142 00143 //This Client Key is example. Use own instead. 00144 const uint8_t clientKey[] ="\ 00145 -----BEGIN EC PARAMETERS-----\n\ 00146 BggqhkjOPQMBBw==\ 00147 -----END EC PARAMETERS-----\n\ 00148 -----BEGIN EC PRIVATE KEY-----\n\ 00149 MHcCAQEEIByuPtqukIClJ35+FA0gdvlMs7FmSFiOJGpaYsyQs4wwoAoGCCqGSM49\ 00150 AwEHoUQDQgAE+SIoQNtQUGRVtL0nVcTbg1SlwDe6yNzqd/zIljpV6hxBh2XmLObo\ 00151 PKhGJA2Q5Gn4TvOyzQtMYTUpxrDZzZsjyA==\ 00152 -----END EC PRIVATE KEY-----\n"; 00153 00154 int connack_rc = 0; // MQTT connack return code 00155 int connectTimeout = 1000; 00156 int retryAttempt = 0; 00157 00158 PressureSensor *pressure_sensor; 00159 HumiditySensor *humidity_sensor; 00160 TempSensor *temp_sensor1; 00161 MagneticSensor *magnetic_sensor; 00162 GyroSensor *gyro_sensor; 00163 MotionSensor *accel_sensor; 00164 00165 MQTT::Message message; 00166 MQTTString TopicName= { AWS_IOT_MQTT_TOPIC_TEST }; 00167 MQTT::MessageData MsgData(TopicName, message); 00168 00169 void subscribe_cb(MQTT::MessageData & msgMQTT) { 00170 char msg[MQTT_MAX_PAYLOAD_SIZE]; 00171 msg[0]='\0'; 00172 strncat (msg, (char*)msgMQTT.message.payload, msgMQTT.message.payloadlen); 00173 printf ("--->>> subscribe_cb msg: %s\n\r", msg); 00174 } 00175 00176 int subscribe(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack) 00177 { 00178 char* pubTopic = AWS_IOT_MQTT_TOPIC_TEST; 00179 return client->subscribe(pubTopic, MQTT::QOS0, subscribe_cb); 00180 } 00181 00182 int connect(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack) 00183 { 00184 SpwfSAInterface& WiFi = ipstack->getWiFi(); 00185 00186 // Network debug statements 00187 LOG("=====================================\n\r"); 00188 LOG("Connecting WiFi.\n\r"); 00189 LOG("Nucleo IP ADDRESS: %s\n\r", WiFi.get_ip_address()); 00190 LOG("Nucleo MAC ADDRESS: %s\n\r", WiFi.get_mac_address()); 00191 LOG("Server Hostname: %s port: %d\n\r", AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT); 00192 LOG("Client ID: %s\n\r", AWS_IOT_MQTT_CLIENT_ID); 00193 //LOG("Topic: %s\n\r", AWS_IOT_MQTT_TOPIC_TEST); 00194 //LOG("Subscription URL: %s\n\r", subscription_url); 00195 LOG("=====================================\n\r"); 00196 00197 ipstack->open(&ipstack->getWiFi()); 00198 00199 int rc=ipstack->getNTPtime(); 00200 00201 if (rc != 0) 00202 { 00203 WARN("Get NTP time error: %d\n", rc); 00204 return rc; 00205 } 00206 00207 rc = WiFi.setSocketClientSecurity((uint8_t *)"m", (uint8_t *)rootCA, (uint8_t *)clientCRT, (uint8_t *)clientKey, (uint8_t *)AWS_IOT_MQTT_HOST, ipstack->getTime()); 00208 00209 if (rc != 0) 00210 { 00211 WARN("Set security params error: %d\n", rc); 00212 return rc; 00213 } 00214 00215 rc = ipstack->connect(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, connectTimeout); 00216 00217 if (rc != 0) 00218 { 00219 WARN("IP Stack connect returned: %d\n\r", rc); 00220 return rc; 00221 } 00222 00223 printf ("--->TCP Connected\n\r"); 00224 00225 // MQTT Connect 00226 MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 00227 data.MQTTVersion = 4; 00228 data.struct_version=0; 00229 data.clientID.cstring = AWS_IOT_MQTT_CLIENT_ID; 00230 //data.username.cstring = "use-token-auth"; 00231 //data.password.cstring = AWS_IOT_AUTH_TOKEN; 00232 00233 if ((rc = client->connect(data)) == 0) 00234 { 00235 printf ("--->MQTT Connected\n\r"); 00236 00237 if (!subscribe(client, ipstack)) printf ("--->>>MQTT subscribed to: %s\n\r",AWS_IOT_MQTT_TOPIC_TEST); 00238 } 00239 else 00240 { 00241 WARN("MQTT connect returned %d\n", rc); 00242 } 00243 if (rc >= 0) 00244 connack_rc = rc; 00245 return rc; 00246 } 00247 00248 int getConnTimeout(int attemptNumber) 00249 { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute 00250 // after 20 attempts, retry every 10 minutes 00251 return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600; 00252 } 00253 00254 void attemptConnect(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack) 00255 { 00256 while (connect(client, ipstack) != MQTT_CONNECTION_ACCEPTED) 00257 { 00258 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) 00259 { 00260 printf ("File: %s, Line: %d Error: %d\n\r",__FILE__,__LINE__, connack_rc); 00261 return; // don't reattempt to connect if credentials are wrong 00262 } 00263 00264 int timeout = getConnTimeout(++retryAttempt); 00265 WARN("Retry attempt number %d waiting %d\n\r", retryAttempt, timeout); 00266 00267 // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed 00268 // or maybe just add the proper members to do this disconnect and call attemptConnect(...) 00269 // this works - reset the system when the retry count gets to a threshold 00270 if (retryAttempt == 2) 00271 { 00272 ipstack->getWiFi().reset_chip(); 00273 NVIC_SystemReset(); 00274 } 00275 else 00276 wait(timeout); 00277 } 00278 } 00279 00280 int publish(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack) 00281 { 00282 MQTT::Message message; 00283 char* pubTopic = AWS_IOT_MQTT_TOPIC_SHADOW; 00284 00285 char buf[MQTT_MAX_PAYLOAD_SIZE]; 00286 float temp, press, hum; 00287 int32_t magnet[3]; 00288 int32_t gyro[3]; 00289 int32_t accel[3]; 00290 00291 temp_sensor1->GetTemperature(&temp); 00292 pressure_sensor->GetPressure(&press); 00293 humidity_sensor->GetHumidity(&hum); 00294 magnetic_sensor->Get_M_Axes(magnet); 00295 gyro_sensor->Get_G_Axes(gyro); 00296 accel_sensor->Get_X_Axes(accel); 00297 00298 if (!myButtonPressed) 00299 { 00300 butled = 1; 00301 sprintf(buf, "{\"state\": {\"reported\": {\"temperature\": %f, \"humidity\": %f, \"pressure\": %f, \"accelerometer\": [%f, %f, %f], \"gyroscope\": [%f, %f, %f], \"magnetometer\": [%f, %f, %f]}}}", 00302 temp, hum, press, accel[0]/1000.0, accel[1]/1000.0, accel[2]/1000.0, gyro[0]/1000.0, gyro[1]/1000.0, gyro[2]/1000.0, magnet[0]/10.0, magnet[1]/10.0, magnet[2]/10.0); 00303 } 00304 else 00305 { 00306 myButtonPressed = false; // reset state 00307 butled = 0; 00308 00309 sprintf(buf, "{\"temperature\": %f, \"humidity\": %f, \"pressure\": %f, \"accelerometer\": [%f, %f, %f], \"gyroscope\": [%f, %f, %f], \"magnetometer\": [%f, %f, %f], \"marker\": true}", 00310 temp, hum, press, accel[0]/1000.0, accel[1]/1000.0, accel[2]/1000.0, gyro[0]/1000.0, gyro[1]/1000.0, gyro[2]/1000.0, magnet[0]/10.0, magnet[1]/10.0, magnet[2]/10.0); 00311 pubTopic = AWS_IOT_MQTT_TOPIC_DATA; 00312 } 00313 00314 message.qos = MQTT::QOS0; 00315 message.retained = false; 00316 message.dup = false; 00317 message.payload = (void*)buf; 00318 message.payloadlen = strlen(buf); 00319 00320 printf("Length - %d, Publishing %s\n\r", strlen(buf), buf); 00321 00322 return client->publish(pubTopic, message); 00323 } 00324 00325 void pressed() 00326 { 00327 myButtonPressed = true; 00328 } 00329 00330 int main() 00331 { 00332 const char * ssid = SSID; // Network must be visible otherwise it can't connect 00333 const char * seckey = PASSW; 00334 00335 pc.baud(115200); 00336 00337 SpwfSAInterface spwf(D8, D2, true); 00338 00339 myled=0; 00340 DevI2C *i2c = new DevI2C(I2C_SDA, I2C_SCL); 00341 i2c->frequency(400000); 00342 00343 mybutton.fall(&pressed); 00344 00345 X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(i2c); 00346 pressure_sensor = mems_expansion_board->pt_sensor; 00347 temp_sensor1 = mems_expansion_board->ht_sensor; 00348 humidity_sensor = mems_expansion_board->ht_sensor; 00349 magnetic_sensor = mems_expansion_board->magnetometer; 00350 gyro_sensor = mems_expansion_board->GetGyroscope(); 00351 accel_sensor = mems_expansion_board->GetAccelerometer(); 00352 00353 // Due to bug in mbed this workaround is needed to avoid Nucleo hang up when lsm6ds3 is absent 00354 if (mems_expansion_board->gyro_lsm6ds3 == NULL) 00355 { 00356 NVIC_DisableIRQ(EXTI4_IRQn); 00357 NVIC_ClearPendingIRQ(EXTI4_IRQn); 00358 } 00359 00360 pc.printf("\r\nX-NUCLEO-IDW01M1 mbed Application\r\n"); 00361 pc.printf("\r\nconnecting to AP\r\n"); 00362 00363 MQTTWiFi ipstack(spwf, ssid, seckey, NSAPI_SECURITY_WPA2); 00364 00365 LOG("Connected to WiFI.\r\n"); 00366 00367 spwf.set_debug(false); 00368 00369 MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack, 5000); 00370 00371 attemptConnect(&client, &ipstack); 00372 00373 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) 00374 { 00375 while (true) 00376 wait(1.0); // Permanent failures - don't retry 00377 } 00378 00379 myled=1; 00380 00381 int count = 0; 00382 00383 while (true) 00384 { 00385 if (++count == 1) 00386 { 00387 myled = 0; 00388 // Publish a message every second 00389 if (publish(&client, &ipstack) != 0) 00390 { 00391 myled=0; 00392 ipstack.getWiFi().reset_chip(); 00393 NVIC_SystemReset(); 00394 attemptConnect(&client, &ipstack); // if we have lost the connection 00395 } 00396 else myled=1; 00397 00398 count = 0; 00399 } 00400 00401 client.yield(1000); // allow the MQTT client to receive messages 00402 } 00403 }
Generated on Wed Jul 13 2022 20:28:49 by 1.7.2