NuMaker Pelion Device Management example

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2020 ARM Ltd.
00003 //
00004 // SPDX-License-Identifier: Apache-2.0
00005 //
00006 // Licensed under the Apache License, Version 2.0 (the "License");
00007 // you may not use this file except in compliance with the License.
00008 // You may obtain a copy of the License at
00009 //
00010 //     http://www.apache.org/licenses/LICENSE-2.0
00011 //
00012 // Unless required by applicable law or agreed to in writing, software
00013 // distributed under the License is distributed on an "AS IS" BASIS,
00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 // See the License for the specific language governing permissions and
00016 // limitations under the License.
00017 // ----------------------------------------------------------------------------
00018 #ifndef MBED_TEST_MODE
00019 #include "mbed.h"
00020 #include "kv_config.h"
00021 #include "mbed-cloud-client/MbedCloudClient.h" // Required for new MbedCloudClient()
00022 #include "factory_configurator_client.h"       // Required for fcc_* functions and FCC_* defines
00023 #include "m2mresource.h"                       // Required for M2MResource
00024 #include "key_config_manager.h"                // Required for kcm_factory_reset
00025 
00026 #include "mbed-trace/mbed_trace.h"             // Required for mbed_trace_*
00027 
00028 // Pointers to the resources that will be created in main_application().
00029 static MbedCloudClient *cloud_client;
00030 static bool cloud_client_running = true;
00031 static NetworkInterface *network = NULL;
00032 static int error_count = 0;
00033 
00034 // Fake entropy needed for non-TRNG boards. Suitable only for demo devices.
00035 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 };
00036 const int MAX_ERROR_COUNT = 5;
00037 
00038 static M2MResource* m2m_get_res;
00039 static M2MResource* m2m_put_res;
00040 static M2MResource* m2m_post_res;
00041 static M2MResource* m2m_deregister_res;
00042 static M2MResource* m2m_factory_reset_res;
00043 static SocketAddress sa;
00044 
00045 EventQueue queue(32 * EVENTS_EVENT_SIZE);
00046 Thread t;
00047 Mutex value_increment_mutex;
00048 
00049 void print_client_ids(void)
00050 {
00051     printf("Account ID: %s\n", cloud_client->endpoint_info()->account_id.c_str());
00052     printf("Endpoint name: %s\n", cloud_client->endpoint_info()->internal_endpoint_name.c_str());
00053     printf("Device ID: %s\n\n", cloud_client->endpoint_info()->endpoint_name.c_str());
00054 }
00055 
00056 void value_increment(void)
00057 {
00058     value_increment_mutex.lock();
00059     m2m_get_res->set_value(m2m_get_res->get_value_int() + 1);
00060     printf("Counter %" PRIu64 "\n", m2m_get_res->get_value_int());
00061     value_increment_mutex.unlock();
00062 }
00063 
00064 void get_res_update(const char* /*object_name*/)
00065 {
00066     printf("Counter resource set to %d\n", (int)m2m_get_res->get_value_int());
00067 }
00068 
00069 void put_res_update(const char* /*object_name*/)
00070 {
00071     printf("PUT update %d\n", (int)m2m_put_res->get_value_int());
00072 }
00073 
00074 void execute_post(void* /*arguments*/)
00075 {
00076     printf("POST executed\n");
00077 }
00078 
00079 void deregister_client(void)
00080 {
00081     printf("Unregistering and disconnecting from the network.\n");
00082     cloud_client->close();
00083 }
00084 
00085 void deregister(void* /*arguments*/)
00086 {
00087     printf("POST deregister executed\n");
00088     m2m_deregister_res->send_delayed_post_response();
00089 
00090     deregister_client();
00091 }
00092 
00093 void client_registered(void)
00094 {
00095     printf("Client registered.\n");
00096     print_client_ids();
00097     error_count = 0;
00098 }
00099 
00100 void client_registration_updated(void)
00101 {
00102     printf("Client registration updated.\n");
00103     error_count = 0;
00104 }
00105 
00106 void client_unregistered(void)
00107 {
00108     printf("Client unregistered.\n");
00109     (void) network->disconnect();
00110     cloud_client_running = false;
00111 }
00112 
00113 void factory_reset(void*)
00114 {
00115     printf("POST factory reset executed\n");
00116     m2m_factory_reset_res->send_delayed_post_response();
00117 
00118     kcm_factory_reset();
00119 }
00120 
00121 void client_error(int err)
00122 {
00123     printf("client_error(%d) -> %s\n", err, cloud_client->error_description());
00124     if (err == MbedCloudClient::ConnectNetworkError ||
00125         err == MbedCloudClient::ConnectDnsResolvingFailed ||
00126         err == MbedCloudClient::ConnectSecureConnectionFailed) {
00127         if(++error_count == MAX_ERROR_COUNT) {
00128             printf("Max error count %d reached, rebooting.\n\n", MAX_ERROR_COUNT);
00129             ThisThread::sleep_for(1*1000);
00130             NVIC_SystemReset();
00131     }
00132     }
00133 }
00134 
00135 void update_progress(uint32_t progress, uint32_t total)
00136 {
00137     uint8_t percent = (uint8_t)((uint64_t)progress * 100 / total);
00138     printf("Update progress = %" PRIu8 "%%\n", percent);
00139 }
00140 
00141 void flush_stdin_buffer(void)
00142 {
00143     FileHandle *debug_console = mbed::mbed_file_handle(STDIN_FILENO);
00144     while(debug_console->readable()) {
00145         char buffer[1];
00146         debug_console->read(buffer, 1);
00147     }
00148 }
00149 
00150 extern "C" MBED_WEAK void dispatch_host_command(int);
00151 
00152 int main(void)
00153 {
00154     int status;
00155 #ifdef MBED_MAJOR_VERSION
00156     printf("Mbed OS version %d.%d.%d\r\n\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
00157 #endif 
00158     status = mbed_trace_init();
00159     if (status != 0) {
00160         printf("mbed_trace_init() failed with %d\n", status);
00161         return -1;
00162     }
00163 
00164     // Mount default kvstore
00165     printf("Application ready\n");
00166     status = kv_init_storage_config();
00167     if (status != MBED_SUCCESS) {
00168         printf("kv_init_storage_config() - failed, status %d\n", status);
00169         return -1;
00170     }
00171 
00172     // Connect with NetworkInterface
00173     printf("Connect to network\n");
00174     network = NetworkInterface::get_default_instance();
00175     if (network == NULL) {
00176         printf("Failed to get default NetworkInterface\n");
00177         return -1;
00178     }
00179     status = network->connect();
00180     if (status != NSAPI_ERROR_OK) {
00181         printf("NetworkInterface failed to connect with %d\n", status);
00182         return -1;
00183     }
00184     status = network->get_ip_address(&sa);
00185     if (status!=0) {
00186         printf("get_ip_address failed with %d\n", status);
00187         return -2;
00188     }
00189     printf("Network initialized, connected with IP %s\n\n", sa.get_ip_address());
00190 
00191     // Run developer flow
00192     printf("Start developer flow\n");
00193     status = fcc_init();
00194     if (status != FCC_STATUS_SUCCESS) {
00195         printf("fcc_init() failed with %d\n", status);
00196         return -1;
00197     }
00198 
00199     // Inject hardcoded entropy for the device. Suitable only for demo devices.
00200     (void) fcc_entropy_set(MBED_CLOUD_DEV_ENTROPY, sizeof(MBED_CLOUD_DEV_ENTROPY));
00201     status = fcc_developer_flow();
00202     if (status != FCC_STATUS_SUCCESS && status != FCC_STATUS_KCM_FILE_EXIST_ERROR && status != FCC_STATUS_CA_ERROR) {
00203         printf("fcc_developer_flow() failed with %d\n", status);
00204         return -1;
00205     }
00206 
00207 #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
00208     cloud_client = new MbedCloudClient(client_registered, client_unregistered, client_error, NULL, update_progress);
00209 #else
00210     cloud_client = new MbedCloudClient(client_registered, client_unregistered, client_error);
00211 #endif // MBED_CLOUD_CLIENT_SUPPORT_UPDATE
00212 
00213     // Initialize client
00214     cloud_client->init();
00215 
00216     printf("Create resources\n");
00217     M2MObjectList m2m_obj_list;
00218 
00219     // GET resource 3200/0/5501
00220     // PUT also allowed for resetting the resource
00221     m2m_get_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 3200, 0, 5501, M2MResourceInstance::INTEGER, M2MBase::GET_PUT_ALLOWED);
00222     if (m2m_get_res->set_value(0) != true) {
00223         printf("m2m_get_res->set_value() failed\n");
00224         return -1;
00225     }
00226     if (m2m_get_res->set_value_updated_function(get_res_update) != true) {
00227         printf("m2m_get_res->set_value_updated_function() failed\n");
00228         return -1;
00229     }
00230 
00231     // PUT resource 3201/0/5853
00232     m2m_put_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 3201, 0, 5853, M2MResourceInstance::INTEGER, M2MBase::GET_PUT_ALLOWED);
00233     if (m2m_put_res->set_value(0) != true) {
00234         printf("m2m_put_res->set_value() failed\n");
00235         return -1;
00236     }
00237     if (m2m_put_res->set_value_updated_function(put_res_update) != true) {
00238         printf("m2m_put_res->set_value_updated_function() failed\n");
00239         return -1;
00240     }
00241 
00242     // POST resource 3201/0/5850
00243     m2m_post_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 3201, 0, 5850, M2MResourceInstance::INTEGER, M2MBase::POST_ALLOWED);
00244     if (m2m_post_res->set_execute_function(execute_post) != true) {
00245         printf("m2m_post_res->set_execute_function() failed\n");
00246         return -1;
00247     }
00248 
00249     // POST resource 5000/0/1 to trigger deregister.
00250     m2m_deregister_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 5000, 0, 1, M2MResourceInstance::INTEGER, M2MBase::POST_ALLOWED);
00251 
00252     // Use delayed response
00253     m2m_deregister_res->set_delayed_response(true);
00254 
00255     if (m2m_deregister_res->set_execute_function(deregister) != true) {
00256         printf("m2m_post_res->set_execute_function() failed\n");
00257         return -1;
00258     }
00259 
00260     // optional Device resource for running factory reset for the device. Path of this resource will be: 3/0/5.
00261     m2m_factory_reset_res = M2MInterfaceFactory::create_device()->create_resource(M2MDevice::FactoryReset);
00262     if (m2m_factory_reset_res) {
00263         m2m_factory_reset_res->set_execute_function(factory_reset);
00264     }
00265 
00266     printf("Register Pelion Device Management Client\n\n");
00267 
00268     cloud_client->on_registration_updated(client_registration_updated);
00269 
00270     cloud_client->add_objects(m2m_obj_list);
00271     cloud_client->setup(network);
00272 
00273     t.start(callback(&queue, &EventQueue::dispatch_forever));
00274     queue.call_every(5000, value_increment);
00275 
00276     // Flush the stdin buffer before reading from it
00277     flush_stdin_buffer();
00278 
00279     while(cloud_client_running) {
00280         int in_char = getchar();
00281         if (in_char == 'i') {
00282             print_client_ids(); // When 'i' is pressed, print endpoint info
00283             continue;
00284         } else if (in_char == 'r') {
00285             (void) fcc_storage_delete(); // When 'r' is pressed, erase storage and reboot the board.
00286             printf("Storage erased, rebooting the device.\n\n");
00287             ThisThread::sleep_for(1*1000);
00288             NVIC_SystemReset();
00289         } else if (dispatch_host_command && in_char != 0x03) {
00290             /* Intercept other host commands */
00291             dispatch_host_command(in_char);
00292             continue;
00293         } else if (in_char > 0 && in_char != 0x03) { // Ctrl+C is 0x03 in Mbed OS and Linux returns negative number
00294             value_increment(); // Simulate button press
00295             continue;
00296         }
00297         deregister_client();
00298         break;
00299     }
00300     return 0;
00301 }
00302 
00303 #endif /* MBED_TEST_MODE */