NuMaker Pelion Device Management example

Fork of mbed-os-example-pelion by cc li

Revision:
11:d147172e94b5
Parent:
5:ae686808e015
Child:
16:75a4830fc40a
--- a/main.cpp	Fri May 15 09:27:37 2020 +0800
+++ b/main.cpp	Tue Apr 14 16:01:24 2020 +0800
@@ -1,5 +1,5 @@
 // ----------------------------------------------------------------------------
-// Copyright 2016-2019 ARM Ltd.
+// Copyright 2016-2020 ARM Ltd.
 //
 // SPDX-License-Identifier: Apache-2.0
 //
@@ -21,6 +21,7 @@
 #include "mbed-cloud-client/MbedCloudClient.h" // Required for new MbedCloudClient()
 #include "factory_configurator_client.h"       // Required for fcc_* functions and FCC_* defines
 #include "m2mresource.h"                       // Required for M2MResource
+#include "key_config_manager.h"                // Required for kcm_factory_reset
 
 #include "mbed-trace/mbed_trace.h"             // Required for mbed_trace_*
 
@@ -28,29 +29,44 @@
 static MbedCloudClient *cloud_client;
 static bool cloud_client_running = true;
 static NetworkInterface *network = NULL;
+static int error_count = 0;
 
 // Fake entropy needed for non-TRNG boards. Suitable only for demo devices.
 const uint8_t MBED_CLOUD_DEV_ENTROPY[] = { 0xf6, 0xd6, 0xc0, 0x09, 0x9e, 0x6e, 0xf2, 0x37, 0xdc, 0x29, 0x88, 0xf1, 0x57, 0x32, 0x7d, 0xde, 0xac, 0xb3, 0x99, 0x8c, 0xb9, 0x11, 0x35, 0x18, 0xeb, 0x48, 0x29, 0x03, 0x6a, 0x94, 0x6d, 0xe8, 0x40, 0xc0, 0x28, 0xcc, 0xe4, 0x04, 0xc3, 0x1f, 0x4b, 0xc2, 0xe0, 0x68, 0xa0, 0x93, 0xe6, 0x3a };
+const int MAX_ERROR_COUNT = 5;
 
 static M2MResource* m2m_get_res;
 static M2MResource* m2m_put_res;
 static M2MResource* m2m_post_res;
 static M2MResource* m2m_deregister_res;
+static M2MResource* m2m_factory_reset_res;
+static SocketAddress sa;
+
+EventQueue queue(32 * EVENTS_EVENT_SIZE);
+Thread t;
+Mutex value_increment_mutex;
 
 void print_client_ids(void)
 {
     printf("Account ID: %s\n", cloud_client->endpoint_info()->account_id.c_str());
     printf("Endpoint name: %s\n", cloud_client->endpoint_info()->internal_endpoint_name.c_str());
-    printf("Device Id: %s\n\n", cloud_client->endpoint_info()->endpoint_name.c_str());
+    printf("Device ID: %s\n\n", cloud_client->endpoint_info()->endpoint_name.c_str());
 }
 
-void button_press(void)
+void value_increment(void)
 {
+    value_increment_mutex.lock();
     m2m_get_res->set_value(m2m_get_res->get_value_int() + 1);
     printf("Counter %" PRIu64 "\n", m2m_get_res->get_value_int());
+    value_increment_mutex.unlock();
 }
 
-void put_update(const char* /*object_name*/)
+void get_res_update(const char* /*object_name*/)
+{
+    printf("Counter resource set to %d\n", (int)m2m_get_res->get_value_int());
+}
+
+void put_res_update(const char* /*object_name*/)
 {
     printf("PUT update %d\n", (int)m2m_put_res->get_value_int());
 }
@@ -78,6 +94,13 @@
 {
     printf("Client registered.\n");
     print_client_ids();
+    error_count = 0;
+}
+
+void client_registration_updated(void)
+{
+    printf("Client registration updated.\n");
+    error_count = 0;
 }
 
 void client_unregistered(void)
@@ -87,9 +110,26 @@
     cloud_client_running = false;
 }
 
+void factory_reset(void*)
+{
+    printf("POST factory reset executed\n");
+    m2m_factory_reset_res->send_delayed_post_response();
+
+    kcm_factory_reset();
+}
+
 void client_error(int err)
 {
     printf("client_error(%d) -> %s\n", err, cloud_client->error_description());
+    if (err == MbedCloudClient::ConnectNetworkError ||
+        err == MbedCloudClient::ConnectDnsResolvingFailed ||
+        err == MbedCloudClient::ConnectSecureConnectionFailed) {
+        if(++error_count == MAX_ERROR_COUNT) {
+            printf("Max error count %d reached, rebooting.\n\n", MAX_ERROR_COUNT);
+            ThisThread::sleep_for(1*1000);
+            NVIC_SystemReset();
+	}
+    }
 }
 
 void update_progress(uint32_t progress, uint32_t total)
@@ -98,6 +138,15 @@
     printf("Update progress = %" PRIu8 "%%\n", percent);
 }
 
+void flush_stdin_buffer(void)
+{
+    FileHandle *debug_console = mbed::mbed_file_handle(STDIN_FILENO);
+    while(debug_console->readable()) {
+        char buffer[1];
+        debug_console->read(buffer, 1);
+    }
+}
+
 extern "C" MBED_WEAK void dispatch_host_command(int);
 
 int main(void)
@@ -130,8 +179,12 @@
         printf("NetworkInterface failed to connect with %d\n", status);
         return -1;
     }
-
-    printf("Network initialized, connected with IP %s\n\n", network->get_ip_address());
+    status = network->get_ip_address(&sa);
+    if (status!=0) {
+        printf("get_ip_address failed with %d\n", status);
+        return -2;
+    }
+    printf("Network initialized, connected with IP %s\n\n", sa.get_ip_address());
 
     // Run developer flow
     printf("Start developer flow\n");
@@ -149,23 +202,37 @@
         return -1;
     }
 
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+    cloud_client = new MbedCloudClient(client_registered, client_unregistered, client_error, NULL, update_progress);
+#else
+    cloud_client = new MbedCloudClient(client_registered, client_unregistered, client_error);
+#endif // MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+
+    // Initialize client
+    cloud_client->init();
+
     printf("Create resources\n");
     M2MObjectList m2m_obj_list;
 
     // GET resource 3200/0/5501
-    m2m_get_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 3200, 0, 5501, M2MResourceInstance::INTEGER, M2MBase::GET_ALLOWED);
+    // PUT also allowed for resetting the resource
+    m2m_get_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 3200, 0, 5501, M2MResourceInstance::INTEGER, M2MBase::GET_PUT_ALLOWED);
     if (m2m_get_res->set_value(0) != true) {
         printf("m2m_get_res->set_value() failed\n");
         return -1;
     }
+    if (m2m_get_res->set_value_updated_function(get_res_update) != true) {
+        printf("m2m_get_res->set_value_updated_function() failed\n");
+        return -1;
+    }
 
     // PUT resource 3201/0/5853
     m2m_put_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 3201, 0, 5853, M2MResourceInstance::INTEGER, M2MBase::GET_PUT_ALLOWED);
     if (m2m_put_res->set_value(0) != true) {
-        printf("m2m_led_res->set_value() failed\n");
+        printf("m2m_put_res->set_value() failed\n");
         return -1;
     }
-    if (m2m_put_res->set_value_updated_function(put_update) != true) {
+    if (m2m_put_res->set_value_updated_function(put_res_update) != true) {
         printf("m2m_put_res->set_value_updated_function() failed\n");
         return -1;
     }
@@ -188,10 +255,24 @@
         return -1;
     }
 
+    // optional Device resource for running factory reset for the device. Path of this resource will be: 3/0/5.
+    m2m_factory_reset_res = M2MInterfaceFactory::create_device()->create_resource(M2MDevice::FactoryReset);
+    if (m2m_factory_reset_res) {
+        m2m_factory_reset_res->set_execute_function(factory_reset);
+    }
+
     printf("Register Pelion Device Management Client\n\n");
-    cloud_client = new MbedCloudClient(client_registered, client_unregistered, client_error, NULL, update_progress);
+
+    cloud_client->on_registration_updated(client_registration_updated);
+
     cloud_client->add_objects(m2m_obj_list);
-    cloud_client->setup(network); // cloud_client->setup(NULL); -- https://jira.arm.com/browse/IOTCLT-3114
+    cloud_client->setup(network);
+
+    t.start(callback(&queue, &EventQueue::dispatch_forever));
+    queue.call_every(5000, value_increment);
+
+    // Flush the stdin buffer before reading from it
+    flush_stdin_buffer();
 
     while(cloud_client_running) {
         int in_char = getchar();
@@ -201,14 +282,14 @@
         } else if (in_char == 'r') {
             (void) fcc_storage_delete(); // When 'r' is pressed, erase storage and reboot the board.
             printf("Storage erased, rebooting the device.\n\n");
-            wait(1);
+            ThisThread::sleep_for(1*1000);
             NVIC_SystemReset();
         } else if (dispatch_host_command && in_char != 0x03) {
             /* Intercept other host commands */
             dispatch_host_command(in_char);
             continue;
         } else if (in_char > 0 && in_char != 0x03) { // Ctrl+C is 0x03 in Mbed OS and Linux returns negative number
-            button_press(); // Simulate button press
+            value_increment(); // Simulate button press
             continue;
         }
         deregister_client();