Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
simple-mbed-cloud-client.cpp
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2018 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 00019 #include <stdio.h> 00020 #include "simple-mbed-cloud-client.h" 00021 #include "mbed-trace-helper.h" 00022 #include "resource-helper.h" 00023 00024 #ifdef MBED_CLOUD_DEV_UPDATE_ID 00025 #include "update_client_hub.h" 00026 #endif 00027 00028 #define TRACE_GROUP "SMCC" 00029 00030 #ifdef MBED_CLOUD_CLIENT_USER_CONFIG_FILE 00031 #include MBED_CLOUD_CLIENT_USER_CONFIG_FILE 00032 #endif 00033 00034 #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE 00035 #include "update-helper/update-helper.h" 00036 #endif 00037 00038 #ifdef MBED_HEAP_STATS_ENABLED 00039 #include "memory_tests.h" 00040 #endif 00041 00042 #ifndef DEFAULT_FIRMWARE_PATH 00043 #define DEFAULT_FIRMWARE_PATH "/fs/firmware" 00044 #endif 00045 00046 SimpleMbedCloudClient::SimpleMbedCloudClient(NetworkInterface *net, BlockDevice *bd, FileSystem *fs) : 00047 _registered(false), 00048 _register_called(false), 00049 _register_and_connect_called(false), 00050 _registered_cb(NULL), 00051 _unregistered_cb(NULL), 00052 _error_cb(NULL), 00053 _net(net), 00054 _bd(bd), 00055 _fs(fs), 00056 _storage(bd, fs) 00057 { 00058 } 00059 00060 SimpleMbedCloudClient::~SimpleMbedCloudClient() { 00061 for (unsigned int i = 0; _resources.size(); i++) { 00062 delete _resources[i]; 00063 } 00064 } 00065 00066 int SimpleMbedCloudClient::init(bool format) { 00067 // Requires DAPLink 245+ (https://github.com/ARMmbed/DAPLink/pull/364) 00068 // Older versions: workaround to prevent possible deletion of credentials: 00069 wait(1); 00070 00071 #ifdef MBED_CLOUD_DEV_UPDATE_ID 00072 00073 extern const uint8_t arm_uc_vendor_id[]; 00074 extern const uint16_t arm_uc_vendor_id_size; 00075 extern const uint8_t arm_uc_class_id[]; 00076 extern const uint16_t arm_uc_class_id_size; 00077 00078 ARM_UC_SetVendorId(arm_uc_vendor_id, arm_uc_vendor_id_size); 00079 ARM_UC_SetClassId(arm_uc_class_id, arm_uc_class_id_size); 00080 00081 #endif 00082 00083 // Initialize Mbed Trace for debugging 00084 // Create mutex for tracing to avoid broken lines in logs 00085 if(!mbed_trace_helper_create_mutex()) { 00086 printf("[SMCC] ERROR - Mutex creation for mbed_trace failed!\n"); 00087 return 1; 00088 } 00089 00090 // Initialize mbed trace 00091 mbed_trace_init(); 00092 mbed_trace_helper_create_mutex(); 00093 mbed_trace_mutex_wait_function_set(mbed_trace_helper_mutex_wait); 00094 mbed_trace_mutex_release_function_set(mbed_trace_helper_mutex_release); 00095 00096 // Initialize the FCC 00097 int status = fcc_init(); 00098 if (status != FCC_STATUS_SUCCESS && status != FCC_STATUS_ENTROPY_ERROR && status != FCC_STATUS_ROT_ERROR) { 00099 tr_error("Factory Client Configuration failed with status %d", status); 00100 return 1; 00101 } 00102 00103 status = _storage.init(); 00104 if (status != FCC_STATUS_SUCCESS) { 00105 tr_error("Failed to initialize storage layer (%d)", status); 00106 return 1; 00107 } 00108 00109 status = _storage.sotp_init(); 00110 if (status != FCC_STATUS_SUCCESS) { 00111 tr_error("Could not initialize SOTP (%d)", status); 00112 fcc_finalize(); 00113 return 1; 00114 } 00115 00116 #if RESET_STORAGE 00117 status = reset_storage(); 00118 if (status != FCC_STATUS_SUCCESS) { 00119 tr_error("reset_storage (triggered by RESET_STORAGE macro) failed (%d)", status); 00120 return 1; 00121 } 00122 // Reinitialize SOTP 00123 status = _storage.sotp_init(); 00124 if (status != FCC_STATUS_SUCCESS) { 00125 tr_error("Could not initialize SOTP (%d)", status); 00126 return 1; 00127 } 00128 #endif 00129 00130 status = verify_cloud_configuration(format); 00131 00132 if (status != 0) { 00133 // This is designed to simplify user-experience by auto-formatting the 00134 // primary storage if no valid certificates exist. 00135 // This should never be used for any kind of production devices. 00136 #if MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR == 1 00137 tr_info("Could not load certificate (e.g. no certificates or RoT might have changed), resetting storage..."); 00138 status = reset_storage(); 00139 if (status != FCC_STATUS_SUCCESS) { 00140 return status; 00141 } 00142 status = _storage.sotp_init(); 00143 if (status != FCC_STATUS_SUCCESS) { 00144 return status; 00145 } 00146 status = verify_cloud_configuration(format); 00147 if (status != 0) { 00148 return status; 00149 } 00150 #else 00151 return 1; 00152 #endif 00153 } 00154 00155 // Deletes existing firmware images from storage. 00156 // This deletes any existing firmware images during application startup. 00157 // This compilation flag is currently implemented only for mbed OS. 00158 #ifdef RESET_FIRMWARE 00159 palStatus_t status = PAL_SUCCESS; 00160 status = pal_fsRmFiles(DEFAULT_FIRMWARE_PATH); 00161 if(status == PAL_SUCCESS) { 00162 printf("[SMCC] Firmware storage erased\n"); 00163 } else if (status == PAL_ERR_FS_NO_PATH) { 00164 tr_info("Firmware path not found/does not exist"); 00165 } else { 00166 tr_error("Firmware storage erasing failed with %" PRId32, status); 00167 return 1; 00168 } 00169 #endif 00170 00171 return 0; 00172 } 00173 00174 bool SimpleMbedCloudClient::call_register() { 00175 // need to unregister first before calling this function again 00176 if (_register_called) return false; 00177 00178 _cloud_client.on_registered(this, &SimpleMbedCloudClient::client_registered); 00179 _cloud_client.on_unregistered(this, &SimpleMbedCloudClient::client_unregistered); 00180 _cloud_client.on_error(this, &SimpleMbedCloudClient::error); 00181 00182 bool setup = _cloud_client.setup(_net); 00183 _register_called = true; 00184 if (!setup) { 00185 tr_error("Client setup failed"); 00186 return false; 00187 } 00188 00189 #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE 00190 /* Set callback functions for authorizing updates and monitoring progress. 00191 Code is implemented in update_ui_example.cpp 00192 Both callbacks are completely optional. If no authorization callback 00193 is set, the update process will procede immediately in each step. 00194 */ 00195 update_helper_set_cloud_client(&_cloud_client); 00196 _cloud_client.set_update_authorize_handler(update_authorize); 00197 _cloud_client.set_update_progress_handler(update_progress); 00198 #endif 00199 return true; 00200 } 00201 00202 void SimpleMbedCloudClient::close() { 00203 _cloud_client.close(); 00204 } 00205 00206 void SimpleMbedCloudClient::register_update() { 00207 _cloud_client.register_update(); 00208 } 00209 00210 void SimpleMbedCloudClient::client_registered() { 00211 _registered = true; 00212 static const ConnectorClientEndpointInfo* endpoint = NULL; 00213 if (endpoint == NULL) { 00214 endpoint = _cloud_client.endpoint_info(); 00215 if (endpoint && _registered_cb) { 00216 _registered_cb(endpoint); 00217 } 00218 } 00219 #ifdef MBED_HEAP_STATS_ENABLED 00220 heap_stats(); 00221 #endif 00222 } 00223 00224 void SimpleMbedCloudClient::client_unregistered() { 00225 _registered = false; 00226 _register_called = false; 00227 00228 if (_unregistered_cb) { 00229 _unregistered_cb(); 00230 } 00231 00232 #ifdef MBED_HEAP_STATS_ENABLED 00233 heap_stats(); 00234 #endif 00235 } 00236 00237 void SimpleMbedCloudClient::error(int error_code) { 00238 const char *error; 00239 switch(error_code) { 00240 case MbedCloudClient::ConnectErrorNone: 00241 error = "MbedCloudClient::ConnectErrorNone"; 00242 break; 00243 case MbedCloudClient::ConnectAlreadyExists: 00244 error = "MbedCloudClient::ConnectAlreadyExists"; 00245 break; 00246 case MbedCloudClient::ConnectBootstrapFailed: 00247 error = "MbedCloudClient::ConnectBootstrapFailed"; 00248 break; 00249 case MbedCloudClient::ConnectInvalidParameters: 00250 error = "MbedCloudClient::ConnectInvalidParameters"; 00251 break; 00252 case MbedCloudClient::ConnectNotRegistered: 00253 error = "MbedCloudClient::ConnectNotRegistered"; 00254 break; 00255 case MbedCloudClient::ConnectTimeout: 00256 error = "MbedCloudClient::ConnectTimeout"; 00257 break; 00258 case MbedCloudClient::ConnectNetworkError: 00259 error = "MbedCloudClient::ConnectNetworkError"; 00260 break; 00261 case MbedCloudClient::ConnectResponseParseFailed: 00262 error = "MbedCloudClient::ConnectResponseParseFailed"; 00263 break; 00264 case MbedCloudClient::ConnectUnknownError: 00265 error = "MbedCloudClient::ConnectUnknownError"; 00266 break; 00267 case MbedCloudClient::ConnectMemoryConnectFail: 00268 error = "MbedCloudClient::ConnectMemoryConnectFail"; 00269 break; 00270 case MbedCloudClient::ConnectNotAllowed: 00271 error = "MbedCloudClient::ConnectNotAllowed"; 00272 break; 00273 case MbedCloudClient::ConnectSecureConnectionFailed: 00274 error = "MbedCloudClient::ConnectSecureConnectionFailed"; 00275 break; 00276 case MbedCloudClient::ConnectDnsResolvingFailed: 00277 error = "MbedCloudClient::ConnectDnsResolvingFailed"; 00278 break; 00279 #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE 00280 case MbedCloudClient::UpdateWarningCertificateNotFound: 00281 error = "MbedCloudClient::UpdateWarningCertificateNotFound"; 00282 break; 00283 case MbedCloudClient::UpdateWarningIdentityNotFound: 00284 error = "MbedCloudClient::UpdateWarningIdentityNotFound"; 00285 break; 00286 case MbedCloudClient::UpdateWarningCertificateInvalid: 00287 error = "MbedCloudClient::UpdateWarningCertificateInvalid"; 00288 break; 00289 case MbedCloudClient::UpdateWarningSignatureInvalid: 00290 error = "MbedCloudClient::UpdateWarningSignatureInvalid"; 00291 break; 00292 case MbedCloudClient::UpdateWarningVendorMismatch: 00293 error = "MbedCloudClient::UpdateWarningVendorMismatch"; 00294 break; 00295 case MbedCloudClient::UpdateWarningClassMismatch: 00296 error = "MbedCloudClient::UpdateWarningClassMismatch"; 00297 break; 00298 case MbedCloudClient::UpdateWarningDeviceMismatch: 00299 error = "MbedCloudClient::UpdateWarningDeviceMismatch"; 00300 break; 00301 case MbedCloudClient::UpdateWarningURINotFound: 00302 error = "MbedCloudClient::UpdateWarningURINotFound"; 00303 break; 00304 case MbedCloudClient::UpdateWarningRollbackProtection: 00305 error = "MbedCloudClient::UpdateWarningRollbackProtection"; 00306 break; 00307 case MbedCloudClient::UpdateWarningUnknown: 00308 error = "MbedCloudClient::UpdateWarningUnknown"; 00309 break; 00310 case MbedCloudClient::UpdateErrorWriteToStorage: 00311 error = "MbedCloudClient::UpdateErrorWriteToStorage"; 00312 break; 00313 case MbedCloudClient::UpdateErrorInvalidHash: 00314 error = "MbedCloudClient::UpdateErrorInvalidHash"; 00315 break; 00316 #endif 00317 default: 00318 error = "UNKNOWN"; 00319 } 00320 00321 if (_error_cb) { 00322 _error_cb(error_code, error); 00323 return; 00324 } 00325 00326 printf("\n[SMCC] Error occurred : %s\n", error); 00327 printf("[SMCC] Error code : %d\n", error_code); 00328 printf("[SMCC] Error details : %s\n",_cloud_client.error_description()); 00329 } 00330 00331 bool SimpleMbedCloudClient::is_client_registered() { 00332 return _registered; 00333 } 00334 00335 bool SimpleMbedCloudClient::is_register_called() { 00336 return _register_called; 00337 } 00338 00339 bool SimpleMbedCloudClient::register_and_connect() { 00340 if (_register_and_connect_called) return false; 00341 00342 mcc_resource_def resourceDef; 00343 00344 for (int i = 0; i < _resources.size(); i++) { 00345 _resources[i]->get_data(&resourceDef); 00346 M2MResource *res = add_resource(&_obj_list, resourceDef.object_id, resourceDef.instance_id, 00347 resourceDef.resource_id, resourceDef.name.c_str(), M2MResourceInstance::STRING, 00348 (M2MBase::Operation)resourceDef.method_mask, resourceDef.value.c_str(), resourceDef.observable, 00349 resourceDef.put_callback, resourceDef.post_callback, resourceDef.notification_callback); 00350 _resources[i]->set_m2m_resource(res); 00351 } 00352 _cloud_client.add_objects(_obj_list); 00353 00354 _register_and_connect_called = true; 00355 00356 // Start registering to the cloud. 00357 bool retval = call_register(); 00358 00359 // Print memory statistics if the MBED_HEAP_STATS_ENABLED is defined. 00360 #ifdef MBED_HEAP_STATS_ENABLED 00361 tr_info("Register being called"); 00362 heap_stats(); 00363 #endif 00364 00365 return retval; 00366 } 00367 00368 void SimpleMbedCloudClient::on_registered(Callback<void(const ConnectorClientEndpointInfo*)> cb) { 00369 _registered_cb = cb; 00370 } 00371 00372 void SimpleMbedCloudClient::on_unregistered(Callback<void()> cb) { 00373 _unregistered_cb = cb; 00374 } 00375 00376 void SimpleMbedCloudClient::on_update_authorized(void (*cb)(int32_t request)) { 00377 _cloud_client.set_update_authorize_handler(cb); 00378 } 00379 00380 void SimpleMbedCloudClient::on_update_progress(void (*cb)(uint32_t progress, uint32_t total)) { 00381 _cloud_client.set_update_progress_handler(cb); 00382 } 00383 00384 void SimpleMbedCloudClient::on_error_cb(Callback<void(int, const char*)> cb) { 00385 _error_cb = cb; 00386 } 00387 00388 int SimpleMbedCloudClient::reformat_storage() { 00389 return _storage.reformat_storage(); 00390 } 00391 00392 MbedCloudClient *SimpleMbedCloudClient::get_cloud_client() { 00393 return &_cloud_client; 00394 } 00395 00396 MbedCloudClientResource* SimpleMbedCloudClient::create_resource(const char *path, const char *name) { 00397 MbedCloudClientResource *resource = new MbedCloudClientResource(this, path, name); 00398 _resources.push_back(resource); 00399 return resource; 00400 } 00401 00402 int SimpleMbedCloudClient::reset_storage() { 00403 tr_info("Resetting storage to an empty state..."); 00404 int status = fcc_storage_delete(); 00405 if (status != FCC_STATUS_SUCCESS) { 00406 tr_debug("Failed to delete FCC storage (%d), formatting...", status); 00407 00408 status = _storage.reformat_storage(); 00409 if (status == 0) { 00410 tr_debug("Storage reformatted, resetting storage again..."); 00411 // Try to reset storage again after format. 00412 // It is required to run fcc_storage_delete() after format. 00413 status = fcc_storage_delete(); 00414 if (status != FCC_STATUS_SUCCESS) { 00415 tr_warn("Failed to delete FCC storage (again) (%d)", status); 00416 } 00417 else { 00418 tr_debug("Deleted FCC storage"); 00419 } 00420 } 00421 } 00422 00423 if (status == FCC_STATUS_SUCCESS) { 00424 tr_info("OK - Reset storage to an empty state..."); 00425 } 00426 00427 return status; 00428 } 00429 00430 int SimpleMbedCloudClient::verify_cloud_configuration(bool format) { 00431 int status; 00432 00433 #if MBED_CONF_DEVICE_MANAGEMENT_DEVELOPER_MODE == 1 00434 tr_debug("Starting developer flow"); 00435 if( format ) { 00436 status = reset_storage(); 00437 if (status != FCC_STATUS_SUCCESS) { 00438 tr_debug("Failed to reset storage"); 00439 return status; 00440 } 00441 } 00442 status = fcc_developer_flow(); 00443 if (status == FCC_STATUS_KCM_FILE_EXIST_ERROR) { 00444 tr_debug("Developer credentials already exist on storage layer, verifying credentials..."); 00445 } else if (status != FCC_STATUS_SUCCESS) { 00446 tr_debug("No developer credentials on storage layer yet"); 00447 return status; 00448 } 00449 #endif 00450 status = fcc_verify_device_configured_4mbed_cloud(); 00451 return status; 00452 }
Generated on Tue Jul 12 2022 20:21:02 by
