@@ -47,53 +47,59 @@ void ArduinoCloudThing::begin() {
47
47
addPropertyReal (status, " status" ).readOnly ();
48
48
}
49
49
50
- int ArduinoCloudThing::publish (CborArray& object, uint8_t * data, size_t size) {
51
-
52
- ssize_t len = object.encode (data, size);
53
-
54
- #ifdef TESTING_PROTOCOL
55
- decode (data, len);
56
- #endif
57
-
58
- for (int i = 0 ; i < list.size (); i++) {
59
- ArduinoCloudPropertyGeneric *p = list.get (i);
60
- p->updateShadow ();
61
- }
62
-
63
- return len;
64
- }
65
-
66
50
int ArduinoCloudThing::poll (uint8_t * data, size_t size) {
67
51
68
52
// check if backing storage and cloud has diverged
69
53
int diff = 0 ;
70
54
71
55
diff = checkNewData ();
72
56
if (diff > 0 ) {
73
- CborBuffer buffer (1024 );
74
- CborArray object = CborArray (buffer);
75
- compress (object, buffer);
76
- diff = publish (object, data, size);
57
+ CborError err;
58
+ CborEncoder encoder, arrayEncoder;
59
+ cbor_encoder_init (&encoder, data, size, 0 );
60
+ // create a cbor array containing the property that should be updated.
61
+ err = cbor_encoder_create_array (&encoder, &arrayEncoder, CborIndefiniteLength);
62
+ if (err) {
63
+ Serial.println (cbor_error_string (err));
64
+ return -1 ;
65
+ }
66
+ for (int i = 0 ; i < list.size (); i++) {
67
+ ArduinoCloudPropertyGeneric *p = list.get (i);
68
+ // If a property should be updated and has read permission from the Cloud point of view
69
+ if (p->shouldBeUpdated () && p->canRead ()) {
70
+ // create a cbor object for the property and automatically add it into array
71
+ p->append (&arrayEncoder);
72
+ }
73
+ }
74
+
75
+ err = cbor_encoder_close_container (&encoder, &arrayEncoder);
76
+ // update properties shadow values, in order to check if variable has changed since last publish
77
+
78
+ for (int i = 0 ; i < list.size (); i++) {
79
+ ArduinoCloudPropertyGeneric *p = list.get (i);
80
+ p->updateShadow ();
81
+ }
82
+ // return the number of byte of the CBOR encoded array
83
+ return cbor_encoder_get_buffer_size (&encoder, data);
77
84
}
78
85
79
86
#if defined(DEBUG_MEMORY) && defined(ARDUINO_ARCH_SAMD)
80
87
PrintFreeRam ();
81
88
#endif
82
-
89
+ // If nothing has to be sent, return diff, that is 0 in this case
83
90
return diff;
84
91
}
85
92
86
- void ArduinoCloudThing::compress (CborArray& object, CborBuffer& buffer) {
87
-
93
+ // It return the index of the property, inside the local array, with the name passed as parameter. (-1 if it does not exist.)
94
+ int ArduinoCloudThing::findPropertyByName (String &name) {
88
95
for (int i = 0 ; i < list.size (); i++) {
89
96
ArduinoCloudPropertyGeneric *p = list.get (i);
90
- if (p->shouldBeUpdated () && p->canRead ()) {
91
- CborObject child = CborObject (buffer);
92
- p->append (child);
93
- CborVariant variant = CborVariant (buffer, child);
94
- object.add (variant);
97
+ // Check the property existance just comparing its name with existent ones
98
+ if (p->getName () == name) {
99
+ return i;
95
100
}
96
101
}
102
+ return -1 ;
97
103
}
98
104
99
105
int ArduinoCloudThing::checkNewData () {
@@ -144,88 +150,113 @@ ArduinoCloudPropertyGeneric& ArduinoCloudThing::addPropertyReal(float& property,
144
150
return *(reinterpret_cast <ArduinoCloudPropertyGeneric*>(thing));
145
151
}
146
152
147
- void ArduinoCloudThing::decode (uint8_t * payload, size_t length) {
148
- CborBuffer buffer (200 );
149
- CborVariant total = buffer.decode (payload, length);
153
+ ArduinoCloudPropertyGeneric& ArduinoCloudThing::addPropertyReal (String& property, String name) {
154
+ if (ArduinoCloudPropertyGeneric* p = exists (name)) {
155
+ return *p;
156
+ }
157
+ ArduinoCloudProperty<String> *thing = new ArduinoCloudProperty<String>(property, name);
158
+ list.add (thing);
159
+ return *(reinterpret_cast <ArduinoCloudPropertyGeneric*>(thing));
160
+ }
150
161
151
- CborArray array = total.asArray ();
162
+ void ArduinoCloudThing::decode (uint8_t * payload, size_t length) {
163
+ CborError err;
164
+ CborParser parser;
165
+ CborValue recursedMap, propValue, dataArray;
166
+ int propId; String propType, propName;
167
+
168
+ err = cbor_parser_init (payload, length, 0 , &parser, &dataArray);
169
+ if (err) {
170
+ return ;
171
+ }
152
172
153
- for (int i=0 ; ;i++) {
154
- CborVariant variant = array.get (i);
173
+ // parse cbor data only if a cbor array is received.
174
+ if (dataArray.type != CborArrayType)
175
+ return ;
176
+
177
+ // main loop through the cbor array elements
178
+ while (!cbor_value_at_end (&dataArray)) {
179
+ // parse cbor object
180
+ cbor_value_enter_container (&dataArray, &recursedMap);
181
+ CborType type = cbor_value_get_type (&recursedMap);
182
+ if (type != CborMapType) {
183
+ // stop the decode when 1st item thai is not a cbor map is found.
184
+ cbor_value_advance (&dataArray);
185
+ continue ;
186
+ } else {
187
+
188
+ while (!cbor_value_at_end (&recursedMap)) {
189
+ // if the current element is not a cbor object as expected, skip it and go ahead.
190
+ if (cbor_value_get_type (&recursedMap) != CborMapType) {
191
+ cbor_value_advance (&recursedMap);
192
+ continue ;
193
+ }
155
194
156
- if (!variant.isValid ()) {
157
- break ;
158
- }
195
+ CborValue name;
196
+ // chechk for the if the a property has a name, if yes Cbor value name will properly updated
197
+ cbor_value_map_find_value (&recursedMap, " n" , &name);
198
+ // check if a property has a name, of string type, if not do nothin and skip curtrent property
199
+ if (name.type != CborTextStringType) {
200
+ cbor_value_advance (&recursedMap);
201
+ continue ;
202
+ }
159
203
204
+ // get the property name from cbor map as char* string
205
+ char *nameVal; size_t nameValSize;
206
+ err = cbor_value_dup_text_string (&name, &nameVal, &nameValSize, NULL );
207
+ if (err) {
208
+ break ; // couldn't get the value of the field
209
+ }
210
+ // get the name of the received property as String object
211
+ propName = String (nameVal);
212
+ // used to avoid memory leaks (cbor_value_dup_text_string automatically perform a malloc)
213
+ free (nameVal);
214
+ // Search for the index of the device property with that name
215
+ propId = findPropertyByName (propName);
216
+ // If property does not exist, skip it and do nothing.
217
+ if (propId < 0 ) {
218
+ cbor_value_advance (&recursedMap);
219
+ continue ;
220
+ }
160
221
161
- CborObject object = variant.asObject ();
222
+ ArduinoCloudPropertyGeneric* property = list.get (propId);
223
+ // Check for the property type, write method internally check for the permission
162
224
163
- String name = " " ;
164
- if (object.get (" n" ).isValid ()) {
165
- name = object.get (" n" ).asString ();
166
- // search for the property with the same name
167
- for (int idx = 0 ; idx < list.size (); idx++) {
168
- ArduinoCloudPropertyGeneric *p = list.get (idx);
169
- if (p->getName () == name) {
170
- currentListIndex = idx;
171
- break ;
225
+ if (propValue.type == CborDoubleType) {
226
+ double val;
227
+ // get the value of the property as a double
228
+ cbor_value_get_double (&propValue, &val);
229
+ reinterpret_cast <ArduinoCloudProperty<float >*>(property)->write ((float )val);
172
230
}
173
- if (idx == list.size ()) {
174
- currentListIndex = -1 ;
231
+ // if no key proper key was found, do nothing
232
+ if (propValue.type == CborIntegerType) {
233
+ int val;
234
+ cbor_value_get_int (&propValue, &val);
235
+ reinterpret_cast <ArduinoCloudProperty<int >*>(property)->write (val);
175
236
}
176
- }
177
- }
178
-
179
- if (object.get (" t" ).isValid ()) {
180
- int tag = object.get (" t" ).asInteger ();
181
- if (name != " " ) {
182
- list.get (currentListIndex)->setTag (tag);
183
- } else {
184
- for (int idx = 0 ; idx < list.size (); idx++) {
185
- ArduinoCloudPropertyGeneric *p = list.get (idx);
186
- if (p->getTag () == tag) {
187
- // if name == "" associate name and tag, otherwise set current list index
188
- currentListIndex = idx;
189
- break ;
190
- }
191
- if (idx == list.size ()) {
192
- Serial.println (" Property not found, skipping" );
193
- currentListIndex = -1 ;
237
+ if (propValue.type == CborBooleanType) {
238
+ bool val;
239
+ cbor_value_get_boolean (&propValue, &val);
240
+ reinterpret_cast <ArduinoCloudProperty<bool >*>(property)->write (val);
241
+ }
242
+ if (propValue.type == CborTextStringType) {
243
+ char *val; size_t valSize;
244
+ err = cbor_value_dup_text_string (&propValue, &val, &valSize, &propValue);
245
+ // Char* string transformed into array
246
+ reinterpret_cast <ArduinoCloudProperty<String>*>(property)->write (String ((char *)val));
247
+ free (val);
248
+ }
249
+ // If the property has been changed call its callback
250
+ if (property->newData ()) {
251
+ if (property->callback != NULL ) {
252
+ property->callback ();
194
253
}
195
254
}
255
+ // Continue to scan the cbor map
256
+ cbor_value_advance (&recursedMap);
196
257
}
197
258
}
198
-
199
- if (object.get (" i" ).isValid ()) {
200
- int value_i = object.get (" i" ).asInteger ();
201
- reinterpret_cast <ArduinoCloudProperty<int >*>(list.get (currentListIndex))->write (value_i);
202
- }
203
-
204
- if (object.get (" b" ).isValid ()) {
205
- bool value_b = object.get (" b" ).asInteger ();
206
- reinterpret_cast <ArduinoCloudProperty<bool >*>(list.get (currentListIndex))->write (value_b);
207
- }
208
- /*
209
- if (object.get("f").isValid()) {
210
- float value_f = object.get("f").asFloat();
211
- reinterpret_cast<ArduinoCloudProperty<bool>*>(list.get(currentListIndex))->write(value_f);
212
- }
213
- */
214
- if (object.get (" s" ).isValid ()) {
215
- String value_s = object.get (" s" ).asString ();
216
- reinterpret_cast <ArduinoCloudProperty<String>*>(list.get (currentListIndex))->write (value_s);
217
- }
218
-
219
- if (object.get (" p" ).isValid ()) {
220
- permissionType value_p = (permissionType)object.get (" p" ).asInteger ();
221
- list.get (currentListIndex)->setPermission (value_p);
222
- }
223
-
224
- if (list.get (currentListIndex)->newData ()) {
225
- // call onUpdate()
226
- if (list.get (currentListIndex)->callback != NULL ) {
227
- list.get (currentListIndex)->callback ();
228
- }
229
- }
259
+ // Leave the current cbor object, and advance to the next one
260
+ err = cbor_value_leave_container (&dataArray, &recursedMap);
230
261
}
231
262
}
0 commit comments