Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers simple-mbed-cloud-client.cpp Source File

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-cloud-client/MbedCloudClient.h"
00022 #include "m2mdevice.h"
00023 #include "m2mresource.h"
00024 #include "mbed-client/m2minterface.h"
00025 #include "key_config_manager.h"
00026 #include "resource.h"
00027 #include "mbed-client/m2mvector.h"
00028 #include "mbed_cloud_client_resource.h"
00029 #include "factory_configurator_client.h"
00030 #include "update_client_hub.h"
00031 
00032 #ifdef MBED_CLOUD_CLIENT_USER_CONFIG_FILE
00033 #include MBED_CLOUD_CLIENT_USER_CONFIG_FILE
00034 #endif
00035 
00036 #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
00037 #include "update_ui_example.h"
00038 #endif
00039 
00040 #ifdef MBED_HEAP_STATS_ENABLED
00041 #include "memory_tests.h"
00042 #endif
00043 
00044 #ifndef DEFAULT_FIRMWARE_PATH
00045 #define DEFAULT_FIRMWARE_PATH       "/sd/firmware"
00046 #endif
00047 
00048 BlockDevice *arm_uc_blockdevice;
00049 
00050 SimpleMbedCloudClient::SimpleMbedCloudClient(NetworkInterface *net, BlockDevice *bd, FileSystem *fs) :
00051     _registered(false),
00052     _register_called(false),
00053     _register_and_connect_called(false),
00054     _registered_cb(NULL),
00055     _unregistered_cb(NULL),
00056     _net(net),
00057     _bd(bd),
00058     _fs(fs)
00059 {
00060     arm_uc_blockdevice = bd;
00061 }
00062 
00063 SimpleMbedCloudClient::~SimpleMbedCloudClient() {
00064     for (unsigned int i = 0; _resources.size(); i++) {
00065         delete _resources[i];
00066     }
00067 }
00068 
00069 int SimpleMbedCloudClient::init() {
00070     // Requires DAPLink 245+ (https://github.com/ARMmbed/DAPLink/pull/364)
00071     // Older versions: workaround to prevent possible deletion of credentials:
00072     wait(1);
00073 
00074     extern const uint8_t arm_uc_vendor_id[];
00075     extern const uint16_t arm_uc_vendor_id_size;
00076     extern const uint8_t arm_uc_class_id[];
00077     extern const uint16_t arm_uc_class_id_size;
00078 
00079     ARM_UC_SetVendorId(arm_uc_vendor_id, arm_uc_vendor_id_size);
00080     ARM_UC_SetClassId(arm_uc_class_id, arm_uc_class_id_size);
00081 
00082     // Initialize the FCC
00083     fcc_status_e  fcc_status = fcc_init();
00084     if(fcc_status != FCC_STATUS_SUCCESS) {
00085         printf("[Simple Cloud Client] Factory Client Configuration failed with status %d. \n", fcc_status);
00086         return 1;
00087     }
00088 
00089     fcc_status = fcc_verify_device_configured_4mbed_cloud();
00090 
00091     if (fcc_status == FCC_STATUS_KCM_STORAGE_ERROR) {
00092         int mount_result = mount_storage();
00093         if (mount_result != 0) {
00094             printf("[Simple Cloud Client] Failed to mount file system with status %d. \n", mount_result);
00095 #if !defined(MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR) || MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR == 0
00096             return 1;
00097 #endif
00098         } else {
00099             // Retry with mounted filesystem.
00100             fcc_status = fcc_verify_device_configured_4mbed_cloud();
00101         }
00102     }
00103 
00104     // This is designed to simplify user-experience by auto-formatting the
00105     // primary storage if no valid certificates exist.
00106     // This should never be used for any kind of production devices.
00107 #if defined(MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR) && MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR == 1
00108     if (fcc_status != FCC_STATUS_SUCCESS) {
00109         if (reformat_storage() != 0) {
00110             return 1;
00111         }
00112 
00113         reset_storage();
00114     }
00115 #else
00116     if (fcc_status != FCC_STATUS_SUCCESS) {
00117         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");
00118         return 1;
00119     }
00120 #endif
00121 
00122     // Resets storage to an empty state.
00123     // Use this function when you want to clear storage from all the factory-tool generated data and user data.
00124     // After this operation device must be injected again by using factory tool or developer certificate.
00125 #ifdef RESET_STORAGE
00126     reset_storage();
00127 #endif
00128 
00129     // Deletes existing firmware images from storage.
00130     // This deletes any existing firmware images during application startup.
00131     // This compilation flag is currently implemented only for mbed OS.
00132 #ifdef RESET_FIRMWARE
00133     palStatus_t status = PAL_SUCCESS;
00134     status = pal_fsRmFiles(DEFAULT_FIRMWARE_PATH);
00135     if(status == PAL_SUCCESS) {
00136         printf("[Simple Cloud Client] Firmware storage erased.\n");
00137     } else if (status == PAL_ERR_FS_NO_PATH) {
00138         printf("[Simple Cloud Client] Firmware path not found/does not exist.\n");
00139     } else {
00140         printf("[Simple Cloud Client] Firmware storage erasing failed with %" PRId32, status);
00141         return 1;
00142     }
00143 #endif
00144 
00145 #if MBED_CONF_APP_DEVELOPER_MODE == 1
00146     printf("[Simple Cloud Client] Starting developer flow\n");
00147     fcc_status = fcc_developer_flow();
00148     if (fcc_status == FCC_STATUS_KCM_FILE_EXIST_ERROR) {
00149         printf("[Simple Cloud Client] Developer credentials already exist\n");
00150     } else if (fcc_status != FCC_STATUS_SUCCESS) {
00151         printf("[Simple Cloud Client] Failed to load developer credentials - is the storage device active and accessible?\n");
00152         return 1;
00153     }
00154 #endif
00155 
00156     return 0;
00157 }
00158 
00159 bool SimpleMbedCloudClient::call_register() {
00160     // need to unregister first before calling this function again
00161     if (_register_called) return false;
00162 
00163     _cloud_client.on_registered(this, &SimpleMbedCloudClient::client_registered);
00164     _cloud_client.on_unregistered(this, &SimpleMbedCloudClient::client_unregistered);
00165     _cloud_client.on_error(this, &SimpleMbedCloudClient::error);
00166 
00167     bool setup = _cloud_client.setup(_net);
00168     _register_called = true;
00169     if (!setup) {
00170         printf("[Simple Cloud Client] Client setup failed\n");
00171         return false;
00172     }
00173 
00174 #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
00175     /* Set callback functions for authorizing updates and monitoring progress.
00176        Code is implemented in update_ui_example.cpp
00177        Both callbacks are completely optional. If no authorization callback
00178        is set, the update process will procede immediately in each step.
00179     */
00180     update_ui_set_cloud_client(&_cloud_client);
00181     _cloud_client.set_update_authorize_handler(update_authorize);
00182     _cloud_client.set_update_progress_handler(update_progress);
00183 #endif
00184     return true;
00185 }
00186 
00187 void SimpleMbedCloudClient::close() {
00188     _cloud_client.close();
00189 }
00190 
00191 void SimpleMbedCloudClient::register_update() {
00192     _cloud_client.register_update();
00193 }
00194 
00195 void SimpleMbedCloudClient::client_registered() {
00196     _registered = true;
00197     static const ConnectorClientEndpointInfo* endpoint = NULL;
00198     if (endpoint == NULL) {
00199         endpoint = _cloud_client.endpoint_info();
00200         if (endpoint && _registered_cb) {
00201             _registered_cb(endpoint);
00202         }
00203     }
00204 #ifdef MBED_HEAP_STATS_ENABLED
00205     heap_stats();
00206 #endif
00207 }
00208 
00209 void SimpleMbedCloudClient::client_unregistered() {
00210     _registered = false;
00211     _register_called = false;
00212 
00213     if (_unregistered_cb) {
00214         _unregistered_cb();
00215     }
00216 
00217 #ifdef MBED_HEAP_STATS_ENABLED
00218     heap_stats();
00219 #endif
00220 }
00221 
00222 void SimpleMbedCloudClient::error(int error_code) {
00223     const char *error;
00224     switch(error_code) {
00225         case MbedCloudClient::ConnectErrorNone:
00226             error = "MbedCloudClient::ConnectErrorNone";
00227             break;
00228         case MbedCloudClient::ConnectAlreadyExists:
00229             error = "MbedCloudClient::ConnectAlreadyExists";
00230             break;
00231         case MbedCloudClient::ConnectBootstrapFailed:
00232             error = "MbedCloudClient::ConnectBootstrapFailed";
00233             break;
00234         case MbedCloudClient::ConnectInvalidParameters:
00235             error = "MbedCloudClient::ConnectInvalidParameters";
00236             break;
00237         case MbedCloudClient::ConnectNotRegistered:
00238             error = "MbedCloudClient::ConnectNotRegistered";
00239             break;
00240         case MbedCloudClient::ConnectTimeout:
00241             error = "MbedCloudClient::ConnectTimeout";
00242             break;
00243         case MbedCloudClient::ConnectNetworkError:
00244             error = "MbedCloudClient::ConnectNetworkError";
00245             break;
00246         case MbedCloudClient::ConnectResponseParseFailed:
00247             error = "MbedCloudClient::ConnectResponseParseFailed";
00248             break;
00249         case MbedCloudClient::ConnectUnknownError:
00250             error = "MbedCloudClient::ConnectUnknownError";
00251             break;
00252         case MbedCloudClient::ConnectMemoryConnectFail:
00253             error = "MbedCloudClient::ConnectMemoryConnectFail";
00254             break;
00255         case MbedCloudClient::ConnectNotAllowed:
00256             error = "MbedCloudClient::ConnectNotAllowed";
00257             break;
00258         case MbedCloudClient::ConnectSecureConnectionFailed:
00259             error = "MbedCloudClient::ConnectSecureConnectionFailed";
00260             break;
00261         case MbedCloudClient::ConnectDnsResolvingFailed:
00262             error = "MbedCloudClient::ConnectDnsResolvingFailed";
00263             break;
00264 #ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
00265         case MbedCloudClient::UpdateWarningCertificateNotFound:
00266             error = "MbedCloudClient::UpdateWarningCertificateNotFound";
00267             break;
00268         case MbedCloudClient::UpdateWarningIdentityNotFound:
00269             error = "MbedCloudClient::UpdateWarningIdentityNotFound";
00270             break;
00271         case MbedCloudClient::UpdateWarningCertificateInvalid:
00272             error = "MbedCloudClient::UpdateWarningCertificateInvalid";
00273             break;
00274         case MbedCloudClient::UpdateWarningSignatureInvalid:
00275             error = "MbedCloudClient::UpdateWarningSignatureInvalid";
00276             break;
00277         case MbedCloudClient::UpdateWarningVendorMismatch:
00278             error = "MbedCloudClient::UpdateWarningVendorMismatch";
00279             break;
00280         case MbedCloudClient::UpdateWarningClassMismatch:
00281             error = "MbedCloudClient::UpdateWarningClassMismatch";
00282             break;
00283         case MbedCloudClient::UpdateWarningDeviceMismatch:
00284             error = "MbedCloudClient::UpdateWarningDeviceMismatch";
00285             break;
00286         case MbedCloudClient::UpdateWarningURINotFound:
00287             error = "MbedCloudClient::UpdateWarningURINotFound";
00288             break;
00289         case MbedCloudClient::UpdateWarningRollbackProtection:
00290             error = "MbedCloudClient::UpdateWarningRollbackProtection";
00291             break;
00292         case MbedCloudClient::UpdateWarningUnknown:
00293             error = "MbedCloudClient::UpdateWarningUnknown";
00294             break;
00295         case MbedCloudClient::UpdateErrorWriteToStorage:
00296             error = "MbedCloudClient::UpdateErrorWriteToStorage";
00297             break;
00298         case MbedCloudClient::UpdateErrorInvalidHash:
00299             error = "MbedCloudClient::UpdateErrorInvalidHash";
00300             break;
00301 #endif
00302         default:
00303             error = "UNKNOWN";
00304     }
00305 
00306     // @todo: move this into user space
00307     printf("\n[Simple Cloud Client] Error occurred : %s\n", error);
00308     printf("[Simple Cloud Client] Error code : %d\n", error_code);
00309     printf("[Simple Cloud Client] Error details : %s\n",_cloud_client.error_description());
00310 }
00311 
00312 bool SimpleMbedCloudClient::is_client_registered() {
00313     return _registered;
00314 }
00315 
00316 bool SimpleMbedCloudClient::is_register_called() {
00317     return _register_called;
00318 }
00319 
00320 bool SimpleMbedCloudClient::register_and_connect() {
00321     if (_register_and_connect_called) return false;
00322 
00323     mcc_resource_def resourceDef;
00324 
00325     for (int i = 0; i < _resources.size(); i++) {
00326         _resources[i]->get_data(&resourceDef);
00327         M2MResource *res = add_resource(&_obj_list, resourceDef.object_id, resourceDef.instance_id,
00328                     resourceDef.resource_id, resourceDef.name.c_str(), M2MResourceInstance::STRING,
00329                     (M2MBase::Operation)resourceDef.method_mask, resourceDef.value.c_str(), resourceDef.observable,
00330                     resourceDef.put_callback, resourceDef.post_callback, resourceDef.notification_callback);
00331         _resources[i]->set_m2m_resource(res);
00332     }
00333     _cloud_client.add_objects(_obj_list);
00334 
00335     _register_and_connect_called = true;
00336 
00337     // Start registering to the cloud.
00338     bool retval = call_register();
00339 
00340     // Print memory statistics if the MBED_HEAP_STATS_ENABLED is defined.
00341     #ifdef MBED_HEAP_STATS_ENABLED
00342         printf("[Simple Cloud Client] Register being called\r\n");
00343         heap_stats();
00344     #endif
00345 
00346     return retval;
00347 }
00348 
00349 void SimpleMbedCloudClient::on_registered(Callback<void(const ConnectorClientEndpointInfo*)> cb) {
00350     _registered_cb = cb;
00351 }
00352 
00353 void SimpleMbedCloudClient::on_unregistered(Callback<void()> cb) {
00354     _unregistered_cb = cb;
00355 }
00356 
00357 MbedCloudClient& SimpleMbedCloudClient::get_cloud_client() {
00358     return _cloud_client;
00359 }
00360 
00361 MbedCloudClientResource* SimpleMbedCloudClient::create_resource(const char *path, const char *name) {
00362     MbedCloudClientResource *resource = new MbedCloudClientResource(this, path, name);
00363     _resources.push_back(resource);
00364     return resource;
00365 }
00366 
00367 int SimpleMbedCloudClient::reformat_storage()
00368 {
00369     int reformat_result = -1;
00370     printf("[Simple Cloud Client] Autoformatting the storage.\n");
00371     if (_bd) {
00372         reformat_result = _fs->reformat(_bd);
00373         if (reformat_result != 0) {
00374             printf("[Simple Cloud Client] Autoformatting failed with error %d\n", reformat_result);
00375         }
00376     }
00377     return reformat_result;
00378 }
00379 
00380 void SimpleMbedCloudClient::reset_storage()
00381 {
00382     printf("[Simple Cloud Client] Reset storage to an empty state.\n");
00383     fcc_status_e  delete_status = fcc_storage_delete();
00384     if (delete_status != FCC_STATUS_SUCCESS) {
00385         printf("[Simple Cloud Client] Failed to delete storage - %d\n", delete_status);
00386     }
00387 }
00388 
00389 int SimpleMbedCloudClient::mount_storage()
00390 {
00391     int mount_result = -1;
00392     printf("[Simple Cloud Client] Initializing storage.\n");
00393     if (_bd) {
00394         mount_result = _fs->mount(_bd);
00395     }
00396     return mount_result;
00397 }