forked from PelionIoT/simple-mbed-cloud-client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
simple-mbed-cloud-client.cpp
397 lines (349 loc) · 13.8 KB
/
simple-mbed-cloud-client.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
// ----------------------------------------------------------------------------
// 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;
}