Jim Carver
/
mbed-cloud-workshop-connect
Fork for workshops
simple-mbed-cloud-client/simple-mbed-cloud-client.cpp
- Committer:
- JimCarver
- Date:
- 2018-10-12
- Revision:
- 0:6b753f761943
File content as of revision 0:6b753f761943:
// ---------------------------------------------------------------------------- // Copyright 2016-2018 ARM Ltd. // // SPDX-License-Identifier: Apache-2.0 // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ---------------------------------------------------------------------------- #include <stdio.h> #include "simple-mbed-cloud-client.h" #include "mbed-cloud-client/MbedCloudClient.h" #include "m2mdevice.h" #include "m2mresource.h" #include "mbed-client/m2minterface.h" #include "key_config_manager.h" #include "resource.h" #include "mbed-client/m2mvector.h" #include "mbed_cloud_client_resource.h" #include "factory_configurator_client.h" #include "update_client_hub.h" #ifdef MBED_CLOUD_CLIENT_USER_CONFIG_FILE #include MBED_CLOUD_CLIENT_USER_CONFIG_FILE #endif #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE #include "update_ui_example.h" #endif #ifdef MBED_HEAP_STATS_ENABLED #include "memory_tests.h" #endif #ifndef DEFAULT_FIRMWARE_PATH #define DEFAULT_FIRMWARE_PATH "/sd/firmware" #endif BlockDevice *arm_uc_blockdevice; SimpleMbedCloudClient::SimpleMbedCloudClient(NetworkInterface *net, BlockDevice *bd, FileSystem *fs) : _registered(false), _register_called(false), _register_and_connect_called(false), _registered_cb(NULL), _unregistered_cb(NULL), _net(net), _bd(bd), _fs(fs) { arm_uc_blockdevice = bd; } SimpleMbedCloudClient::~SimpleMbedCloudClient() { for (unsigned int i = 0; _resources.size(); i++) { delete _resources[i]; } } int SimpleMbedCloudClient::init() { // Requires DAPLink 245+ (https://github.com/ARMmbed/DAPLink/pull/364) // Older versions: workaround to prevent possible deletion of credentials: wait(1); extern const uint8_t arm_uc_vendor_id[]; extern const uint16_t arm_uc_vendor_id_size; extern const uint8_t arm_uc_class_id[]; extern const uint16_t arm_uc_class_id_size; ARM_UC_SetVendorId(arm_uc_vendor_id, arm_uc_vendor_id_size); ARM_UC_SetClassId(arm_uc_class_id, arm_uc_class_id_size); // Initialize the FCC fcc_status_e fcc_status = fcc_init(); if(fcc_status != FCC_STATUS_SUCCESS) { printf("[Simple Cloud Client] Factory Client Configuration failed with status %d. \n", fcc_status); return 1; } fcc_status = fcc_verify_device_configured_4mbed_cloud(); if (fcc_status == FCC_STATUS_KCM_STORAGE_ERROR) { int mount_result = mount_storage(); if (mount_result != 0) { printf("[Simple Cloud Client] Failed to mount file system with status %d. \n", mount_result); #if !defined(MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR) || MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR == 0 return 1; #endif } else { // Retry with mounted filesystem. fcc_status = fcc_verify_device_configured_4mbed_cloud(); } } // This is designed to simplify user-experience by auto-formatting the // primary storage if no valid certificates exist. // This should never be used for any kind of production devices. #if defined(MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR) && MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR == 1 if (fcc_status != FCC_STATUS_SUCCESS) { if (reformat_storage() != 0) { return 1; } reset_storage(); } #else if (fcc_status != FCC_STATUS_SUCCESS) { printf("[Simple Cloud Client] Device not configured for mbed Cloud - try re-formatting your storage device or set MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR to 1\n"); return 1; } #endif // Resets storage to an empty state. // Use this function when you want to clear storage from all the factory-tool generated data and user data. // After this operation device must be injected again by using factory tool or developer certificate. #ifdef RESET_STORAGE reset_storage(); #endif // Deletes existing firmware images from storage. // This deletes any existing firmware images during application startup. // This compilation flag is currently implemented only for mbed OS. #ifdef RESET_FIRMWARE palStatus_t status = PAL_SUCCESS; status = pal_fsRmFiles(DEFAULT_FIRMWARE_PATH); if(status == PAL_SUCCESS) { printf("[Simple Cloud Client] Firmware storage erased.\n"); } else if (status == PAL_ERR_FS_NO_PATH) { printf("[Simple Cloud Client] Firmware path not found/does not exist.\n"); } else { printf("[Simple Cloud Client] Firmware storage erasing failed with %" PRId32, status); return 1; } #endif #if MBED_CONF_APP_DEVELOPER_MODE == 1 printf("[Simple Cloud Client] Starting developer flow\n"); fcc_status = fcc_developer_flow(); if (fcc_status == FCC_STATUS_KCM_FILE_EXIST_ERROR) { printf("[Simple Cloud Client] Developer credentials already exist\n"); } else if (fcc_status != FCC_STATUS_SUCCESS) { printf("[Simple Cloud Client] Failed to load developer credentials - is the storage device active and accessible?\n"); return 1; } #endif return 0; } bool SimpleMbedCloudClient::call_register() { // need to unregister first before calling this function again if (_register_called) return false; _cloud_client.on_registered(this, &SimpleMbedCloudClient::client_registered); _cloud_client.on_unregistered(this, &SimpleMbedCloudClient::client_unregistered); _cloud_client.on_error(this, &SimpleMbedCloudClient::error); bool setup = _cloud_client.setup(_net); _register_called = true; if (!setup) { printf("[Simple Cloud Client] Client setup failed\n"); return false; } #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE /* Set callback functions for authorizing updates and monitoring progress. Code is implemented in update_ui_example.cpp Both callbacks are completely optional. If no authorization callback is set, the update process will procede immediately in each step. */ update_ui_set_cloud_client(&_cloud_client); _cloud_client.set_update_authorize_handler(update_authorize); _cloud_client.set_update_progress_handler(update_progress); #endif return true; } void SimpleMbedCloudClient::close() { _cloud_client.close(); } void SimpleMbedCloudClient::register_update() { _cloud_client.register_update(); } void SimpleMbedCloudClient::client_registered() { _registered = true; static const ConnectorClientEndpointInfo* endpoint = NULL; if (endpoint == NULL) { endpoint = _cloud_client.endpoint_info(); if (endpoint && _registered_cb) { _registered_cb(endpoint); } } #ifdef MBED_HEAP_STATS_ENABLED heap_stats(); #endif } void SimpleMbedCloudClient::client_unregistered() { _registered = false; _register_called = false; if (_unregistered_cb) { _unregistered_cb(); } #ifdef MBED_HEAP_STATS_ENABLED heap_stats(); #endif } void SimpleMbedCloudClient::error(int error_code) { const char *error; switch(error_code) { case MbedCloudClient::ConnectErrorNone: error = "MbedCloudClient::ConnectErrorNone"; break; case MbedCloudClient::ConnectAlreadyExists: error = "MbedCloudClient::ConnectAlreadyExists"; break; case MbedCloudClient::ConnectBootstrapFailed: error = "MbedCloudClient::ConnectBootstrapFailed"; break; case MbedCloudClient::ConnectInvalidParameters: error = "MbedCloudClient::ConnectInvalidParameters"; break; case MbedCloudClient::ConnectNotRegistered: error = "MbedCloudClient::ConnectNotRegistered"; break; case MbedCloudClient::ConnectTimeout: error = "MbedCloudClient::ConnectTimeout"; break; case MbedCloudClient::ConnectNetworkError: error = "MbedCloudClient::ConnectNetworkError"; break; case MbedCloudClient::ConnectResponseParseFailed: error = "MbedCloudClient::ConnectResponseParseFailed"; break; case MbedCloudClient::ConnectUnknownError: error = "MbedCloudClient::ConnectUnknownError"; break; case MbedCloudClient::ConnectMemoryConnectFail: error = "MbedCloudClient::ConnectMemoryConnectFail"; break; case MbedCloudClient::ConnectNotAllowed: error = "MbedCloudClient::ConnectNotAllowed"; break; case MbedCloudClient::ConnectSecureConnectionFailed: error = "MbedCloudClient::ConnectSecureConnectionFailed"; break; case MbedCloudClient::ConnectDnsResolvingFailed: error = "MbedCloudClient::ConnectDnsResolvingFailed"; break; #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE case MbedCloudClient::UpdateWarningCertificateNotFound: error = "MbedCloudClient::UpdateWarningCertificateNotFound"; break; case MbedCloudClient::UpdateWarningIdentityNotFound: error = "MbedCloudClient::UpdateWarningIdentityNotFound"; break; case MbedCloudClient::UpdateWarningCertificateInvalid: error = "MbedCloudClient::UpdateWarningCertificateInvalid"; break; case MbedCloudClient::UpdateWarningSignatureInvalid: error = "MbedCloudClient::UpdateWarningSignatureInvalid"; break; case MbedCloudClient::UpdateWarningVendorMismatch: error = "MbedCloudClient::UpdateWarningVendorMismatch"; break; case MbedCloudClient::UpdateWarningClassMismatch: error = "MbedCloudClient::UpdateWarningClassMismatch"; break; case MbedCloudClient::UpdateWarningDeviceMismatch: error = "MbedCloudClient::UpdateWarningDeviceMismatch"; break; case MbedCloudClient::UpdateWarningURINotFound: error = "MbedCloudClient::UpdateWarningURINotFound"; break; case MbedCloudClient::UpdateWarningRollbackProtection: error = "MbedCloudClient::UpdateWarningRollbackProtection"; break; case MbedCloudClient::UpdateWarningUnknown: error = "MbedCloudClient::UpdateWarningUnknown"; break; case MbedCloudClient::UpdateErrorWriteToStorage: error = "MbedCloudClient::UpdateErrorWriteToStorage"; break; case MbedCloudClient::UpdateErrorInvalidHash: error = "MbedCloudClient::UpdateErrorInvalidHash"; break; #endif default: error = "UNKNOWN"; } // @todo: move this into user space printf("\n[Simple Cloud Client] Error occurred : %s\n", error); printf("[Simple Cloud Client] Error code : %d\n", error_code); printf("[Simple Cloud Client] Error details : %s\n",_cloud_client.error_description()); } bool SimpleMbedCloudClient::is_client_registered() { return _registered; } bool SimpleMbedCloudClient::is_register_called() { return _register_called; } bool SimpleMbedCloudClient::register_and_connect() { if (_register_and_connect_called) return false; mcc_resource_def resourceDef; for (int i = 0; i < _resources.size(); i++) { _resources[i]->get_data(&resourceDef); M2MResource *res = add_resource(&_obj_list, resourceDef.object_id, resourceDef.instance_id, resourceDef.resource_id, resourceDef.name.c_str(), M2MResourceInstance::STRING, (M2MBase::Operation)resourceDef.method_mask, resourceDef.value.c_str(), resourceDef.observable, resourceDef.put_callback, resourceDef.post_callback, resourceDef.notification_callback); _resources[i]->set_m2m_resource(res); } _cloud_client.add_objects(_obj_list); _register_and_connect_called = true; // Start registering to the cloud. bool retval = call_register(); // Print memory statistics if the MBED_HEAP_STATS_ENABLED is defined. #ifdef MBED_HEAP_STATS_ENABLED printf("[Simple Cloud Client] Register being called\r\n"); heap_stats(); #endif return retval; } void SimpleMbedCloudClient::on_registered(Callback<void(const ConnectorClientEndpointInfo*)> cb) { _registered_cb = cb; } void SimpleMbedCloudClient::on_unregistered(Callback<void()> cb) { _unregistered_cb = cb; } MbedCloudClient& SimpleMbedCloudClient::get_cloud_client() { return _cloud_client; } MbedCloudClientResource* SimpleMbedCloudClient::create_resource(const char *path, const char *name) { MbedCloudClientResource *resource = new MbedCloudClientResource(this, path, name); _resources.push_back(resource); return resource; } int SimpleMbedCloudClient::reformat_storage() { int reformat_result = -1; printf("[Simple Cloud Client] Autoformatting the storage.\n"); if (_bd) { reformat_result = _fs->reformat(_bd); if (reformat_result != 0) { printf("[Simple Cloud Client] Autoformatting failed with error %d\n", reformat_result); } } return reformat_result; } void SimpleMbedCloudClient::reset_storage() { printf("[Simple Cloud Client] Reset storage to an empty state.\n"); fcc_status_e delete_status = fcc_storage_delete(); if (delete_status != FCC_STATUS_SUCCESS) { printf("[Simple Cloud Client] Failed to delete storage - %d\n", delete_status); } } int SimpleMbedCloudClient::mount_storage() { int mount_result = -1; printf("[Simple Cloud Client] Initializing storage.\n"); if (_bd) { mount_result = _fs->mount(_bd); } return mount_result; }