Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit ed362dd

Browse files
aentingermattiabertorello
authored andcommitted
Refactoring code in order to reduce code duplication
adding method 'ifNumericConvertToDouble' in order to deal with the fact that CBOR might collapse any numeric value from its original type to a 'smaller' type if it reduces the data necessary for transmission. E.g. a double without any digits after the decimal point might be collapsed into a integer. This function extract the value from the cbor stream and is converted to double from where it can be converted to the desired type without any loss of precision
1 parent c869a88 commit ed362dd

File tree

2 files changed

+108
-138
lines changed

2 files changed

+108
-138
lines changed

src/ArduinoCloudThing.cpp

Lines changed: 79 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -84,35 +84,32 @@ void ArduinoCloudThing::begin() {
8484

8585
int ArduinoCloudThing::encode(uint8_t * data, size_t const size) {
8686

87-
// check if backing storage and cloud has diverged
88-
// time interval may be elapsed or property may be changed
8987
int const num_changed_properties = _property_cont.getNumOfChangedProperties();
9088

91-
if (num_changed_properties > 0) {
92-
CborError err;
93-
CborEncoder encoder, arrayEncoder;
89+
if(num_changed_properties > 0) {
90+
CborEncoder encoder, arrayEncoder;
9491

95-
cbor_encoder_init(&encoder, data, size, 0);
96-
// create a cbor array containing the property that should be updated.
97-
err = cbor_encoder_create_array(&encoder, &arrayEncoder, num_changed_properties);
98-
if (err) {
99-
//Serial.println(cbor_error_string(err));
100-
return -1;
101-
}
92+
cbor_encoder_init(&encoder, data, size, 0);
10293

103-
_property_cont.appendChangedProperties(&arrayEncoder, _cloud_protocol);
94+
if(cbor_encoder_create_array(&encoder, &arrayEncoder, num_changed_properties) != CborNoError) {
95+
return -1;
96+
}
10497

105-
err = cbor_encoder_close_container(&encoder, &arrayEncoder);
98+
_property_cont.appendChangedProperties(&arrayEncoder, _cloud_protocol);
10699

107-
// return the number of byte of the CBOR encoded array
108-
return cbor_encoder_get_buffer_size(&encoder, data);
109-
}
100+
if(cbor_encoder_close_container(&encoder, &arrayEncoder) != CborNoError) {
101+
return -1;
102+
}
110103

111104
#if defined(DEBUG_MEMORY) && defined(ARDUINO_ARCH_SAMD)
112-
PrintFreeRam();
105+
PrintFreeRam();
113106
#endif
114-
// If nothing has to be sent, return diff, that is 0 in this case
115-
return num_changed_properties;
107+
int const bytes_encoded = cbor_encoder_get_buffer_size(&encoder, data);
108+
return bytes_encoded;
109+
}
110+
else {
111+
return num_changed_properties;
112+
}
116113
}
117114

118115
ArduinoCloudProperty<bool> & ArduinoCloudThing::addPropertyReal(bool & property, String const & name, Permission const permission) {
@@ -175,7 +172,7 @@ void ArduinoCloudThing::decode(uint8_t const * const payload, size_t const lengt
175172
if(cbor_value_enter_container(&array_iter, &map_iter) != CborNoError)
176173
return;
177174

178-
MapData map_data;
175+
CborMapData map_data;
179176
MapParserState current_state = MapParserState::EnterMap,
180177
next_state;
181178

@@ -206,12 +203,12 @@ void ArduinoCloudThing::decode(uint8_t const * const payload, size_t const lengt
206203
* PRIVATE MEMBER FUNCTIONS
207204
******************************************************************************/
208205

209-
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_EnterMap(CborValue * map_iter, CborValue * value_iter, MapData * map_data) {
206+
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_EnterMap(CborValue * map_iter, CborValue * value_iter, CborMapData * map_data) {
210207
MapParserState next_state = MapParserState::Error;
211208

212209
if(cbor_value_get_type(map_iter) == CborMapType) {
213210
if(cbor_value_enter_container(map_iter, value_iter) == CborNoError) {
214-
resetMapData(map_data);
211+
map_data->reset();
215212
next_state = MapParserState::MapKey;
216213
}
217214
}
@@ -278,13 +275,14 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_UndefinedKey(CborVal
278275
return next_state;
279276
}
280277

281-
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BaseVersion(CborValue * value_iter, MapData * map_data) {
278+
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BaseVersion(CborValue * value_iter, CborMapData * map_data) {
282279
MapParserState next_state = MapParserState::Error;
283280

284281
if(cbor_value_is_integer(value_iter)) {
285282
int val = 0;
286283
if(cbor_value_get_int(value_iter, &val) == CborNoError) {
287284
map_data->base_version.set(val);
285+
288286
if(cbor_value_advance(value_iter) == CborNoError) {
289287
next_state = MapParserState::MapKey;
290288
}
@@ -294,7 +292,7 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BaseVersion(CborValu
294292
return next_state;
295293
}
296294

297-
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BaseName(CborValue * value_iter, MapData * map_data) {
295+
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BaseName(CborValue * value_iter, CborMapData * map_data) {
298296
MapParserState next_state = MapParserState::Error;
299297

300298
if(cbor_value_is_text_string(value_iter)) {
@@ -310,45 +308,21 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BaseName(CborValue *
310308
return next_state;
311309
}
312310

313-
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BaseTime(CborValue * value_iter, MapData * map_data) {
311+
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BaseTime(CborValue * value_iter, CborMapData * map_data) {
314312
MapParserState next_state = MapParserState::Error;
315313

316-
if(cbor_value_is_integer(value_iter)) {
317-
int val = 0;
318-
if(cbor_value_get_int(value_iter, &val) == CborNoError) {
319-
map_data->base_time.set(static_cast<double>(val));
320-
}
321-
}
322-
323-
if(cbor_value_is_double(value_iter)) {
324-
double val = 0.0;
325-
if(cbor_value_get_double(value_iter, &val) == CborNoError) {
326-
map_data->base_time.set(val);
327-
}
328-
}
329-
330-
if(cbor_value_is_float(value_iter)) {
331-
float val = 0.0;
332-
if(cbor_value_get_float(value_iter, &val) == CborNoError) {
333-
map_data->base_time.set(static_cast<double>(val));
334-
}
335-
}
314+
double val = 0.0;
315+
if(ifNumericConvertToDouble(value_iter, &val)) {
316+
map_data->base_time.set(val);
336317

337-
if(cbor_value_is_half_float(value_iter)) {
338-
uint16_t val = 0;
339-
if(cbor_value_get_half_float(value_iter, &val) == CborNoError) {
340-
map_data->base_time.set(static_cast<double>(convertCborHalfFloatToDouble(val)));
318+
if(cbor_value_advance(value_iter) == CborNoError) {
319+
next_state = MapParserState::MapKey;
341320
}
342321
}
343-
344-
if(cbor_value_advance(value_iter) == CborNoError) {
345-
next_state = MapParserState::MapKey;
346-
}
347-
348322
return next_state;
349323
}
350324

351-
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * value_iter, MapData * map_data) {
325+
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * value_iter, CborMapData * map_data) {
352326
MapParserState next_state = MapParserState::Error;
353327

354328
if(cbor_value_is_text_string(value_iter)) {
@@ -364,42 +338,22 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * val
364338
return next_state;
365339
}
366340

367-
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Value(CborValue * value_iter, MapData * map_data) {
341+
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Value(CborValue * value_iter, CborMapData * map_data) {
368342
MapParserState next_state = MapParserState::Error;
369343

370-
if(value_iter->type == CborIntegerType) {
371-
int val = 0;
372-
if(cbor_value_get_int(value_iter, &val) == CborNoError) {
373-
map_data->val.set(static_cast<float>(val));
374-
}
375-
}
376-
else if(value_iter->type == CborDoubleType) {
377-
double val = 0.0;
378-
if(cbor_value_get_double(value_iter, &val) == CborNoError) {
379-
map_data->val.set(static_cast<float>(val));
380-
}
381-
}
382-
else if(value_iter->type == CborFloatType) {
383-
float val = 0.0f;
384-
if(cbor_value_get_float(value_iter, &val) == CborNoError) {
385-
map_data->val.set(val);
386-
}
387-
}
388-
else if(value_iter->type == CborHalfFloatType) {
389-
uint16_t val = 0;
390-
if(cbor_value_get_half_float(value_iter, &val) == CborNoError) {
391-
map_data->val.set(static_cast<float>(convertCborHalfFloatToDouble(val)));
392-
}
393-
}
344+
double val = 0.0;
345+
if(ifNumericConvertToDouble(value_iter, &val)) {
346+
map_data->val.set(val);
394347

395-
if(cbor_value_advance(value_iter) == CborNoError) {
396-
next_state = MapParserState::MapKey;
348+
if(cbor_value_advance(value_iter) == CborNoError) {
349+
next_state = MapParserState::MapKey;
350+
}
397351
}
398352

399353
return next_state;
400354
}
401355

402-
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_StringValue(CborValue * value_iter, MapData * map_data) {
356+
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_StringValue(CborValue * value_iter, CborMapData * map_data) {
403357
MapParserState next_state = MapParserState::Error;
404358

405359
if(cbor_value_is_text_string(value_iter)) {
@@ -415,12 +369,13 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_StringValue(CborValu
415369
return next_state;
416370
}
417371

418-
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BooleanValue(CborValue * value_iter, MapData * map_data) {
372+
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BooleanValue(CborValue * value_iter, CborMapData * map_data) {
419373
MapParserState next_state = MapParserState::Error;
420374

421375
bool val = false;
422376
if(cbor_value_get_boolean(value_iter, &val) == CborNoError) {
423377
map_data->bool_val.set(val);
378+
424379
if(cbor_value_advance(value_iter) == CborNoError) {
425380
next_state = MapParserState::MapKey;
426381
}
@@ -429,45 +384,22 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_BooleanValue(CborVal
429384
return next_state;
430385
}
431386

432-
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Time(CborValue * value_iter, MapData * map_data) {
387+
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Time(CborValue * value_iter, CborMapData * map_data) {
433388
MapParserState next_state = MapParserState::Error;
434389

435-
if(cbor_value_is_integer(value_iter)) {
436-
int val = 0;
437-
if(cbor_value_get_int(value_iter, &val) == CborNoError) {
438-
map_data->time.set(static_cast<double>(val));
439-
}
440-
}
441-
442-
if(cbor_value_is_double(value_iter)) {
443-
double val = 0.0;
444-
if(cbor_value_get_double(value_iter, &val) == CborNoError) {
445-
map_data->time.set(val);
446-
}
447-
}
448-
449-
if(cbor_value_is_float(value_iter)) {
450-
float val = 0.0;
451-
if(cbor_value_get_float(value_iter, &val) == CborNoError) {
452-
map_data->time.set(static_cast<double>(val));
453-
}
454-
}
390+
double val = 0.0;
391+
if(ifNumericConvertToDouble(value_iter, &val)) {
392+
map_data->time.set(val);
455393

456-
if(cbor_value_is_half_float(value_iter)) {
457-
uint16_t val = 0;
458-
if(cbor_value_get_half_float(value_iter, &val) == CborNoError) {
459-
map_data->time.set(static_cast<double>(convertCborHalfFloatToDouble(val)));
394+
if(cbor_value_advance(value_iter) == CborNoError) {
395+
next_state = MapParserState::MapKey;
460396
}
461397
}
462398

463-
if(cbor_value_advance(value_iter) == CborNoError) {
464-
next_state = MapParserState::MapKey;
465-
}
466-
467399
return next_state;
468400
}
469401

470-
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_LeaveMap(CborValue * map_iter, CborValue * value_iter, MapData const * const map_data) {
402+
ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_LeaveMap(CborValue * map_iter, CborValue * value_iter, CborMapData const * const map_data) {
471403
MapParserState next_state = MapParserState::Error;
472404

473405
/* Update the property containers depending on the parsed data */
@@ -523,15 +455,38 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_LeaveMap(CborValue *
523455
return next_state;
524456
}
525457

526-
void ArduinoCloudThing::resetMapData(MapData * map_data) {
527-
map_data->base_version.reset();
528-
map_data->base_name.reset ();
529-
map_data->base_time.reset ();
530-
map_data->name.reset ();
531-
map_data->val.reset ();
532-
map_data->str_val.reset ();
533-
map_data->bool_val.reset ();
534-
map_data->time.reset ();
458+
bool ArduinoCloudThing::ifNumericConvertToDouble(CborValue * value_iter, double * numeric_val) {
459+
460+
if(cbor_value_is_integer(value_iter)) {
461+
int val = 0;
462+
if(cbor_value_get_int(value_iter, &val) == CborNoError) {
463+
*numeric_val = static_cast<double>(val);
464+
return true;
465+
}
466+
}
467+
else if(cbor_value_is_double(value_iter)) {
468+
double val = 0.0;
469+
if(cbor_value_get_double(value_iter, &val) == CborNoError) {
470+
*numeric_val = val;
471+
return true;
472+
}
473+
}
474+
else if(cbor_value_is_float(value_iter)) {
475+
float val = 0.0;
476+
if(cbor_value_get_float(value_iter, &val) == CborNoError) {
477+
*numeric_val = static_cast<double>(val);
478+
return true;
479+
}
480+
}
481+
else if(cbor_value_is_half_float(value_iter)) {
482+
uint16_t val = 0;
483+
if(cbor_value_get_half_float(value_iter, &val) == CborNoError) {
484+
*numeric_val = static_cast<double>(convertCborHalfFloatToDouble(val));
485+
return true;
486+
}
487+
}
488+
489+
return false;
535490
}
536491

537492
/* Source Idea from https://tools.ietf.org/html/rfc7049 : Page: 50 */

src/ArduinoCloudThing.h

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ static long const DAYS = 86400;
4747
class ArduinoCloudThing {
4848

4949
public:
50+
5051
ArduinoCloudThing(CloudProtocol const cloud_protocol = CloudProtocol::V1);
5152

5253
void begin();
@@ -105,7 +106,21 @@ class ArduinoCloudThing {
105106

106107
};
107108

108-
typedef struct {
109+
class CborMapData {
110+
111+
public:
112+
113+
void reset() {
114+
base_version.reset();
115+
base_name.reset ();
116+
base_time.reset ();
117+
name.reset ();
118+
val.reset ();
119+
str_val.reset ();
120+
bool_val.reset ();
121+
time.reset ();
122+
}
123+
109124
MapEntry<int> base_version;
110125
MapEntry<String> base_name;
111126
MapEntry<double> base_time;
@@ -114,22 +129,22 @@ class ArduinoCloudThing {
114129
MapEntry<String> str_val;
115130
MapEntry<bool> bool_val;
116131
MapEntry<double> time;
117-
} MapData;
132+
};
118133

119-
MapParserState handle_EnterMap (CborValue * map_iter, CborValue * value_iter, MapData * map_data);
134+
MapParserState handle_EnterMap (CborValue * map_iter, CborValue * value_iter, CborMapData * map_data);
120135
MapParserState handle_MapKey (CborValue * value_iter);
121136
MapParserState handle_UndefinedKey (CborValue * value_iter);
122-
MapParserState handle_BaseVersion (CborValue * value_iter, MapData * map_data);
123-
MapParserState handle_BaseName (CborValue * value_iter, MapData * map_data);
124-
MapParserState handle_BaseTime (CborValue * value_iter, MapData * map_data);
125-
MapParserState handle_Name (CborValue * value_iter, MapData * map_data);
126-
MapParserState handle_Value (CborValue * value_iter, MapData * map_data);
127-
MapParserState handle_StringValue (CborValue * value_iter, MapData * map_data);
128-
MapParserState handle_BooleanValue (CborValue * value_iter, MapData * map_data);
129-
MapParserState handle_Time (CborValue * value_iter, MapData * map_data);
130-
MapParserState handle_LeaveMap (CborValue * map_iter, CborValue * value_iter, MapData const * const map_data);
131-
132-
static void resetMapData (MapData * map_data);
137+
MapParserState handle_BaseVersion (CborValue * value_iter, CborMapData * map_data);
138+
MapParserState handle_BaseName (CborValue * value_iter, CborMapData * map_data);
139+
MapParserState handle_BaseTime (CborValue * value_iter, CborMapData * map_data);
140+
MapParserState handle_Name (CborValue * value_iter, CborMapData * map_data);
141+
MapParserState handle_Value (CborValue * value_iter, CborMapData * map_data);
142+
MapParserState handle_StringValue (CborValue * value_iter, CborMapData * map_data);
143+
MapParserState handle_BooleanValue (CborValue * value_iter, CborMapData * map_data);
144+
MapParserState handle_Time (CborValue * value_iter, CborMapData * map_data);
145+
MapParserState handle_LeaveMap (CborValue * map_iter, CborValue * value_iter, CborMapData const * const map_data);
146+
147+
static bool ifNumericConvertToDouble (CborValue * value_iter, double * numeric_val);
133148
static double convertCborHalfFloatToDouble(uint16_t const half_val);
134149

135150
};

0 commit comments

Comments
 (0)