Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * mbed Microcontroller Library
00003  * Copyright (c) 2006-2018 ARM Limited
00004  *
00005  * SPDX-License-Identifier: Apache-2.0
00006  *
00007  * Licensed under the Apache License, Version 2.0 (the "License");
00008  * you may not use this file except in compliance with the License.
00009  * You may obtain a copy of the License at
00010  *
00011  *     http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  * Unless required by applicable law or agreed to in writing, software
00014  * distributed under the License is distributed on an "AS IS" BASIS,
00015  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  * See the License for the specific language governing permissions and
00017  * limitations under the License.
00018  */
00019 
00020 #include "mbed.h"
00021 #include "FATFileSystem.h"
00022 #include "LittleFileSystem.h"
00023 #include "simple-mbed-cloud-client.h"
00024 #include "greentea-client/test_env.h"
00025 #include "common_defines_test.h"
00026 
00027 #ifndef MBED_CONF_APP_TESTS_FS_SIZE
00028   #define MBED_CONF_APP_TESTS_FS_SIZE (2*1024*1024)
00029 #endif
00030 
00031 #if !defined(MBED_CONF_APP_NO_LED)
00032 DigitalOut led1(LED1);
00033 DigitalOut led2(LED2);
00034 void led_thread() {
00035     led1 = !led1;
00036     led2 = !led1;
00037 }
00038 #endif
00039 
00040 RawSerial pc(USBTX, USBRX);
00041 
00042 void wait_nb(uint16_t ms) {
00043     wait_ms(ms);
00044 }
00045 
00046 void logger(const char* message, const char* decor) {
00047     wait_nb(10);
00048     pc.printf(message, decor);
00049     wait_nb(10);
00050 }
00051 void logger(const char* message) {
00052     wait_nb(10);
00053     pc.printf(message);
00054     wait_nb(10);
00055 }
00056 void test_failed() {
00057     greentea_send_kv("test_failed", 1);
00058 }
00059 void test_case_start(const char *name, size_t index) {
00060     wait_nb(10);
00061     pc.printf("\r\n>>> Running case #%u: '%s'...\n", index, name);
00062     GREENTEA_TESTCASE_START(name);
00063 }
00064 void test_case_finish(const char *name, size_t passed, size_t failed) {
00065     GREENTEA_TESTCASE_FINISH(name, passed, failed);
00066     wait_nb(10);
00067     pc.printf(">>> '%s': %u passed, %u failed\r\n", name, passed, failed);
00068 }
00069 
00070 static const ConnectorClientEndpointInfo* endpointInfo;
00071 void registered(const ConnectorClientEndpointInfo *endpoint) {
00072     logger("[INFO] Connected to Pelion Device Management. Device ID: %s\n",
00073             endpoint->internal_endpoint_name.c_str());
00074     endpointInfo = endpoint;
00075 }
00076 
00077 void post_test_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
00078     logger("[INFO] POST test callback executed.\r\n");
00079     greentea_send_kv("verify_lwm2m_post_test_result", 0);
00080 }
00081 
00082 void spdmc_testsuite_connect(void) {
00083     int i = 0;
00084     int iteration = 0;
00085     char _key[20] = { };
00086     char _value[128] = { };
00087 
00088     greentea_send_kv("device_ready", true);
00089     while (1) {
00090         greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
00091 
00092         if (strcmp(_key, "iteration") == 0) {
00093             iteration = atoi(_value);
00094             break;
00095         }
00096     }
00097 
00098     // provide manifest to greentea so it can correct show skipped and failed tests
00099     if (iteration == 0) {
00100         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_COUNT, 10);
00101         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Connect to " TEST_NETWORK_TYPE);
00102         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Initialize " TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE);
00103         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Format " TEST_FILESYSTEM_TYPE);
00104         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Initialize Simple PDMC");
00105         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Pelion Bootstrap & Reg.");
00106         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Pelion Directory");
00107         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Pelion Re-register");
00108         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Post-reset Identity");
00109         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Resource LwM2M GET");
00110         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Resource LwM2M SET");
00111         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Resource LwM2M PUT");
00112         greentea_send_kv(GREENTEA_TEST_ENV_TESTCASE_NAME, "Resource LwM2M POST");
00113     }
00114 
00115     // Start network connection test.
00116     test_case_start("Connect to " TEST_NETWORK_TYPE, 1);
00117     logger("[INFO] Attempting to connect to network.\r\n");
00118 
00119     // Connection definition.
00120     NetworkInterface *net = NetworkInterface::get_default_instance();
00121     nsapi_error_t net_status = -1;
00122     for (int tries = 0; tries < 3; tries++) {
00123         net_status = net->connect();
00124         if (net_status == NSAPI_ERROR_OK) {
00125             break;
00126         } else {
00127             logger("[WARN] Unable to connect to network. Retrying...");
00128         }
00129     }
00130 
00131     // Report status to console.
00132     if (net_status != 0) {
00133         logger("[ERROR] Device failed to connect to Network.\r\n");
00134         test_failed();
00135     } else {
00136         logger("[INFO] Connected to network successfully. IP address: %s\n", net->get_ip_address());
00137     }
00138 
00139     test_case_finish("Connect to " TEST_NETWORK_TYPE, iteration + (net_status == 0), (net_status != 0));
00140 
00141     test_case_start("Initialize " TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE, 2);
00142     logger("[INFO] Attempting to initialize storage.\r\n");
00143 
00144     // Default storage definition.
00145     BlockDevice* bd = BlockDevice::get_default_instance();
00146     SlicingBlockDevice sd(bd, 0, MBED_CONF_APP_TESTS_FS_SIZE);
00147 #if TEST_USE_FILESYSTEM == FS_FAT
00148     FATFileSystem fs("fs", &sd);
00149 #else
00150     LittleFileSystem fs("fs", &sd);
00151 #endif
00152 
00153     test_case_finish("Initialize " TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE, iteration + 1, 0);
00154 
00155     if (iteration == 0) {
00156         test_case_start("Format " TEST_FILESYSTEM_TYPE, 3);
00157         logger("[INFO] Resetting storage to a clean state for test.\n");
00158 
00159         int storage_status = fs.reformat(&sd);
00160         if (storage_status != 0) {
00161             storage_status = sd.erase(0, sd.size());
00162             if (storage_status == 0) {
00163                 storage_status = fs.format(&sd);
00164                 if (storage_status != 0) {
00165                     logger("[ERROR] Filesystem init failed\n");
00166                 }
00167             }
00168         }
00169 
00170         // Report status to console.
00171         if (storage_status == 0) {
00172             logger("[INFO] Storage format successful.\r\n");
00173         } else {
00174             logger("[ERROR] Storage format failed.\r\n");
00175             test_failed();
00176         }
00177 
00178         test_case_finish("Format " TEST_FILESYSTEM_TYPE, (storage_status == 0), (storage_status != 0));
00179     }
00180 
00181     // SimpleMbedCloudClient initialization must be successful.
00182     test_case_start("Initialize Simple PDMC", 4);
00183 
00184     SimpleMbedCloudClient client(net, &sd, &fs);
00185     int client_status = client.init();
00186 
00187     // Report status to console.
00188     if (client_status == 0) {
00189         logger("[INFO] Simple PDMC initialization successful.\r\n");
00190     } else {
00191         logger("[ERROR] Simple PDMC failed to initialize.\r\n");
00192         // End the test early, cannot continue without successful cloud client initialization.
00193         test_failed();
00194     }
00195 
00196     test_case_finish("Initialize Simple PDMC", iteration + (client_status == 0), (client_status != 0));
00197 
00198     //Create LwM2M resources
00199     MbedCloudClientResource *res_get_test;
00200     res_get_test = client.create_resource("5000/0/1", "get_resource");
00201     res_get_test->observable(true);
00202     res_get_test->methods(M2MMethod::GET);
00203     res_get_test->set_value("test0");
00204 
00205     MbedCloudClientResource *res_put_test;
00206     res_put_test = client.create_resource("5000/0/2", "put_resource");
00207     res_put_test->methods(M2MMethod::PUT | M2MMethod::GET);
00208     res_put_test->set_value(1);
00209 
00210     MbedCloudClientResource *res_post_test;
00211     res_post_test = client.create_resource("5000/0/3", "post_resource");
00212     res_post_test->methods(M2MMethod::POST);
00213     res_post_test->attach_post_callback(post_test_callback);
00214 
00215     // Register to Pelion Device Management.
00216     if (iteration == 0) {
00217         test_case_start("Pelion Bootstrap & Reg.", 5);
00218     } else {
00219         test_case_start("Pelion Re-register", 7);
00220     }
00221     // Set client callback to report endpoint name.
00222     client.on_registered(&registered);
00223     client.register_and_connect();
00224 
00225     i = 600; // wait 60 seconds
00226     while (i-- > 0 && !client.is_client_registered()) {
00227         wait_ms(100);
00228     }
00229 
00230     // Get registration status.
00231     bool client_registered = client.is_client_registered();
00232     if (client_registered) {
00233         client_status = 0;
00234         wait_nb(100);
00235         logger("[INFO] Device successfully registered to Pelion DM.\r\n");
00236     } else {
00237         client_status = -1;
00238         logger("[ERROR] Device failed to register.\r\n");
00239         test_failed();
00240     }
00241     if (iteration == 0) {
00242         test_case_finish("Pelion Bootstrap & Reg.", (client_status == 0), (client_status != 0));
00243     } else {
00244         test_case_finish("Pelion Re-register", (client_status == 0), (client_status != 0));
00245     }
00246 
00247     if (iteration == 0) {
00248         //Start registration status test
00249         test_case_start("Pelion Directory", 6);
00250         int reg_status;
00251 
00252         logger("[INFO] Wait up to 10 seconds for Device Directory to update after initial registration.\r\n");
00253         i = 100;
00254         while (i-- > 0 and !endpointInfo) {
00255             wait(100);
00256         }
00257 
00258         // Start host tests with device id
00259         logger("[INFO] Starting Pelion verification using Python SDK...\r\n");
00260         greentea_send_kv("verify_registration", endpointInfo->internal_endpoint_name.c_str());
00261         while (1) {
00262             greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
00263 
00264             if (strcmp(_key, "registered") == 0) {
00265                 if (atoi(_value)) {
00266                     reg_status = 0;
00267                     logger("[INFO] Device is registered in the Device Directory.\r\n");
00268                 } else {
00269                     reg_status = -1;
00270                     logger("[ERROR] Device could not be verified as registered in Device Directory.\r\n");
00271                     test_failed();
00272                 }
00273                 break;
00274             }
00275         }
00276 
00277         test_case_finish("Pelion Directory", (reg_status == 0), (reg_status != 0));
00278 
00279         if (reg_status == 0) {
00280             logger("[INFO] Resetting device.\r\n");
00281             greentea_send_kv("test_advance", 0);
00282             while (1) {
00283                 greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
00284 
00285                 if (strcmp(_key, "reset") == 0) {
00286                     system_reset();
00287                     break;
00288                 }
00289             }
00290         }
00291     } else {
00292         //Start consistent identity test.
00293         test_case_start("Post-reset Identity", 8);
00294         int identity_status;
00295 
00296         logger("[INFO] Wait up to 5 seconds for Device Directory to update after reboot.\r\n");
00297         i = 50;
00298         while (i-- > 0 and !endpointInfo) {
00299             wait(100);
00300         }
00301 
00302         // Wait for Host Test to verify consistent device ID (blocking here)
00303         logger("[INFO] Verifying consistent Device ID...\r\n");
00304         greentea_send_kv("verify_identity", endpointInfo->internal_endpoint_name.c_str());
00305         while (1) {
00306             greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
00307 
00308             if (strcmp(_key, "verified") == 0) {
00309                 if (atoi(_value)) {
00310                     identity_status = 0;
00311                     logger("[INFO] Device ID consistent, SOTP and Secure Storage is preserved correctly.\r\n");
00312                 } else {
00313                     identity_status = -1;
00314                     logger("[ERROR] Device ID is inconsistent. SOTP and Secure Storage was not preserved.\r\n");
00315                 }
00316                 break;
00317             }
00318         }
00319 
00320         test_case_finish("Post-reset Identity", (identity_status == 0), (identity_status != 0));
00321 
00322         // LwM2M tests
00323         logger("[INFO] Beginning LwM2M resource tests.\r\n");
00324 
00325         wait_nb(1000);
00326 
00327         // ---------------------------------------------
00328         // GET test
00329         test_case_start("Resource LwM2M GET", 9);
00330         int get_status;
00331         // Read original value of /5000/0/1 and wait for Host Test to verify it read the value and send it back.
00332         greentea_send_kv("verify_lwm2m_get_test", "/5000/0/1");
00333         while (1) {
00334             greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
00335 
00336             if (strcmp(_key, "get_value") == 0) {
00337                 if (strcmp(_value, "test0") == 0) {
00338                     get_status = 0;
00339                     logger("[INFO] Original value of LwM2M resource /5000/0/1 is read correctly\r\n");
00340                 } else {
00341                     get_status = -1;
00342                     logger("[ERROR] Wrong value reported in Pelion DM.\r\n");
00343                 }
00344                 break;
00345             } else if (strcmp(_key, "timeout") == 0) {
00346                 get_status = -1;
00347                 logger("[ERROR] Observation of LwM2M resource /5000/0/1 timed out.\r\n");
00348                 break;
00349             }
00350         }
00351         test_case_finish("Resource LwM2M GET", (get_status == 0), (get_status != 0));
00352 
00353         wait_nb(500);
00354 
00355         // ---------------------------------------------
00356         // SET test
00357         test_case_start("Resource LwM2M SET", 10);
00358         int set_status;
00359         // Update resource /5000/0/1 from client and observe value
00360         res_get_test->set_value("test1");
00361 
00362         greentea_send_kv("verify_lwm2m_set_test", "/5000/0/1");
00363         while (1) {
00364             greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
00365 
00366             if (strcmp(_key, "set_value") == 0) {
00367                 if (strcmp(_value, "test1") == 0) {
00368                     set_status = 0;
00369                     logger("[INFO] Changed value of LwM2M resource /5000/0/1 is observed correctly\r\n");
00370                 } else {
00371                     set_status = -1;
00372                     logger("[ERROR] Wrong value observed in Pelion DM.\r\n");
00373                 }
00374                 break;
00375             } else if (strcmp(_key, "timeout") == 0) {
00376                 set_status = -1;
00377                 logger("[ERROR] Observation of LwM2M resource /5000/0/1 timed out.\r\n");
00378                 break;
00379             }
00380         }
00381         test_case_finish("Resource LwM2M SET", (set_status == 0), (set_status != 0));
00382 
00383         wait_nb(500);
00384 
00385         // ---------------------------------------------
00386         // PUT Test
00387         test_case_start("Resource LwM2M PUT", 11);
00388         int put_status;
00389         int current_res_value;
00390         int updated_res_value;
00391 
00392         // Observe resource /5000/0/2 from cloud, add +5, and confirm value is correct on client
00393         greentea_send_kv("verify_lwm2m_put_test", "/5000/0/2");
00394         while (1) {
00395             greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
00396 
00397             if (strcmp(_key, "res_set") == 0) {
00398                 // Get updated value from host test.
00399                 updated_res_value = atoi(_value);
00400                 // Get current value from resource.
00401                 current_res_value = res_put_test->get_value_int();
00402 
00403                 if (updated_res_value == current_res_value) {
00404                     put_status = 0;
00405                     logger("[INFO] Value of resource /5000/0/2 successfully changed from the cloud using PUT.\r\n");
00406                 } else {
00407                     put_status = -1;
00408                     logger("[ERROR] Wrong value read from device after resource update.\r\n");
00409                 }
00410                 break;
00411             } else if (strcmp(_key, "timeout") == 0) {
00412                 put_status = -1;
00413                 logger("[ERROR] PUT of LwM2M resource /5000/0/2 timed out.\r\n");
00414                 break;
00415             }
00416         }
00417 
00418         test_case_finish("Resource LwM2M PUT", (put_status == 0), (put_status != 0));
00419 
00420         wait_nb(500);
00421 
00422         // ---------------------------------------------
00423         // POST test
00424         test_case_start("Resource LwM2M POST", 12);
00425         int post_status;
00426 
00427         logger("[INFO] Executing POST on /5000/0/3 and waiting for callback function\r\n.");
00428         greentea_send_kv("verify_lwm2m_post_test", "/5000/0/3");
00429         while (1) {
00430             greentea_parse_kv(_key, _value, sizeof(_key), sizeof(_value));
00431 
00432             if (strcmp(_key, "post_test_executed") == 0) {
00433                 int result = atoi(_value);
00434                 if (result == 0) {
00435                     post_status = 0;
00436                     logger("[INFO] Callback on resource /5000/0/3 executed successfully.\r\n");
00437                 } else {
00438                     post_status = -1;
00439                     logger("[ERROR] Callback on resource /5000/0/3 failed.\r\n");
00440                 }
00441                 break;
00442             } else if (strcmp(_key, "timeout") == 0) {
00443                 post_status = -1;
00444                 logger("[ERROR] POST of LwM2M resource /5000/0/3 timed out.\r\n");
00445                 break;
00446             }
00447         }
00448 
00449         test_case_finish("Resource LwM2M POST", (post_status == 0), (post_status != 0));
00450 
00451         GREENTEA_TESTSUITE_RESULT((get_status == 0) && (set_status == 0) && (put_status == 0) && (post_status == 0));
00452 
00453         while (1) {
00454             wait(100);
00455         }
00456     }
00457 }
00458 
00459 int main(void) {
00460     //Create a thread to blink an LED and signal that the device is alive
00461 #if !defined(MBED_CONF_APP_NO_LED)
00462     Ticker t;
00463     t.attach(led_thread, 0.5);
00464 #endif
00465 
00466     greentea_send_kv("device_booted", 1);
00467 
00468     GREENTEA_SETUP(240, "sdk_host_tests");
00469     spdmc_testsuite_connect();
00470 
00471     return 0;
00472 }