Skip to content

Commit b389995

Browse files
mirkokurtaentinger
authored andcommitted
LoRa support (#48)
1 parent c221d09 commit b389995

5 files changed

+131
-25
lines changed

ArduinoCloudProperty.cpp

+48-10
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ ArduinoCloudProperty::ArduinoCloudProperty()
4747
_update_interval_millis(0),
4848
_last_local_change_timestamp(0),
4949
_last_cloud_change_timestamp(0),
50-
_map_data_list(nullptr) {
50+
_map_data_list(nullptr),
51+
_identifier(0),
52+
_attributeIdentifier(0),
53+
_lightPayload(false) {
5154
}
5255

5356
/******************************************************************************
@@ -115,7 +118,9 @@ void ArduinoCloudProperty::execCallbackOnSync() {
115118
}
116119
}
117120

118-
void ArduinoCloudProperty::append(CborEncoder *encoder) {
121+
void ArduinoCloudProperty::append(CborEncoder *encoder, bool lightPayload) {
122+
_lightPayload = lightPayload;
123+
_attributeIdentifier = 0;
119124
appendAttributesToCloudReal(encoder);
120125
fromLocalToCloud();
121126
_has_been_updated_once = true;
@@ -151,20 +156,35 @@ void ArduinoCloudProperty::appendAttributeReal(String value, String attributeNam
151156
}
152157

153158
void ArduinoCloudProperty::appendAttributeName(String attributeName, std::function<void (CborEncoder& mapEncoder)>appendValue, CborEncoder *encoder) {
159+
if (attributeName != "") {
160+
// when the attribute name string is not empty, the attribute identifier is incremented in order to be encoded in the message if the _lightPayload flag is set
161+
_attributeIdentifier++;
162+
}
154163
CborEncoder mapEncoder;
155164
cbor_encoder_create_map(encoder, &mapEncoder, 2);
156165
cbor_encode_int(&mapEncoder, static_cast<int>(CborIntegerMapKey::Name));
157-
String completeName = _name;
158-
if (attributeName != "") {
159-
completeName += ":" + attributeName;
166+
167+
// if _lightPayload is true, the property and attribute identifiers will be encoded instead of the property name
168+
if (_lightPayload) {
169+
// the most significant byte of the identifier to be encoded represent the property identifier
170+
int completeIdentifier = _attributeIdentifier * 256;
171+
// the least significant byte of the identifier to be encoded represent the attribute identifier
172+
completeIdentifier += _identifier;
173+
cbor_encode_int(&mapEncoder, completeIdentifier);
174+
} else {
175+
String completeName = _name;
176+
if (attributeName != "") {
177+
completeName += ":" + attributeName;
178+
}
179+
cbor_encode_text_stringz(&mapEncoder, completeName.c_str());
160180
}
161-
cbor_encode_text_stringz(&mapEncoder, completeName.c_str());
162181
appendValue(mapEncoder);
163182
cbor_encoder_close_container(encoder, &mapEncoder);
164183
}
165184

166185
void ArduinoCloudProperty::setAttributesFromCloud(LinkedList<CborMapData *> *map_data_list) {
167186
_map_data_list = map_data_list;
187+
_attributeIdentifier = 0;
168188
setAttributesFromCloud();
169189
}
170190

@@ -204,16 +224,30 @@ void ArduinoCloudProperty::setAttributeReal(String& value, String attributeName)
204224
}
205225

206226
void ArduinoCloudProperty::setAttributeReal(String attributeName, std::function<void (CborMapData *md)>setValue) {
227+
if (attributeName != "") {
228+
_attributeIdentifier++;
229+
}
207230
for (int i = 0; i < _map_data_list->size(); i++) {
208231
CborMapData *map = _map_data_list->get(i);
209232
if (map != nullptr) {
210-
String an = map->attribute_name.get();
211-
if (an == attributeName) {
212-
setValue(map);
213-
break;
233+
if (map->light_payload.isSet() && map->light_payload.get()) {
234+
// if a light payload is detected, the attribute identifier is retrieved from the cbor map and the corresponding attribute is updated
235+
int attid = map->attribute_identifier.get();
236+
if (attid == _attributeIdentifier) {
237+
setValue(map);
238+
break;
239+
}
240+
} else {
241+
// if a normal payload is detected, the name of the attribute to be updated is extracted directly from the cbor map
242+
String an = map->attribute_name.get();
243+
if (an == attributeName) {
244+
setValue(map);
245+
break;
246+
}
214247
}
215248
}
216249
}
250+
217251
}
218252

219253
String ArduinoCloudProperty::getAttributeName(String propertyName, char separator) {
@@ -244,3 +278,7 @@ unsigned long ArduinoCloudProperty::getLastCloudChangeTimestamp() {
244278
unsigned long ArduinoCloudProperty::getLastLocalChangeTimestamp() {
245279
return _last_local_change_timestamp;
246280
}
281+
282+
void ArduinoCloudProperty::setIdentifier(int identifier) {
283+
_identifier = identifier;
284+
}

ArduinoCloudProperty.h

+14-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,11 @@ class CborMapData {
9898
MapEntry<String> base_name;
9999
MapEntry<double> base_time;
100100
MapEntry<String> name;
101+
MapEntry<int> name_identifier;
102+
MapEntry<bool> light_payload;
101103
MapEntry<String> attribute_name;
104+
MapEntry<int> attribute_identifier;
105+
MapEntry<int> property_identifier;
102106
MapEntry<float> val;
103107
MapEntry<String> str_val;
104108
MapEntry<bool> bool_val;
@@ -138,6 +142,9 @@ class ArduinoCloudProperty {
138142
inline String name() const {
139143
return _name;
140144
}
145+
inline int identifier() const {
146+
return _identifier;
147+
}
141148
inline bool isReadableByCloud() const {
142149
return (_permission == Permission::Read) || (_permission == Permission::ReadWrite);
143150
}
@@ -152,9 +159,10 @@ class ArduinoCloudProperty {
152159
void setLastLocalChangeTimestamp(unsigned long localChangeTime);
153160
unsigned long getLastCloudChangeTimestamp();
154161
unsigned long getLastLocalChangeTimestamp();
162+
void setIdentifier(int identifier);
155163

156164
void updateLocalTimestamp();
157-
void append(CborEncoder * encoder);
165+
void append(CborEncoder * encoder, bool lightPayload);
158166
void appendAttributeReal(bool value, String attributeName = "", CborEncoder *encoder = nullptr);
159167
void appendAttributeReal(int value, String attributeName = "", CborEncoder *encoder = nullptr);
160168
void appendAttributeReal(float value, String attributeName = "", CborEncoder *encoder = nullptr);
@@ -197,6 +205,11 @@ class ArduinoCloudProperty {
197205
unsigned long _last_local_change_timestamp;
198206
unsigned long _last_cloud_change_timestamp;
199207
LinkedList<CborMapData *> * _map_data_list;
208+
/* Store the identifier of the property in the array list */
209+
int _identifier;
210+
int _attributeIdentifier;
211+
/* Indicates if the property shall be encoded using the identifier instead of the name */
212+
bool _lightPayload;
200213
};
201214

202215
/******************************************************************************

ArduinoCloudThing.cpp

+53-7
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ void PrintFreeRam(void) {
4545

4646
ArduinoCloudThing::ArduinoCloudThing() :
4747
_numPrimitivesProperties(0),
48+
_numProperties(0),
4849
_isSyncMessage(false),
4950
_currentPropertyName(""),
5051
_currentPropertyBaseTime(0),
@@ -58,7 +59,8 @@ ArduinoCloudThing::ArduinoCloudThing() :
5859
void ArduinoCloudThing::begin() {
5960
}
6061

61-
int ArduinoCloudThing::encode(uint8_t * data, size_t const size) {
62+
int ArduinoCloudThing::encode(uint8_t * data, size_t const size, bool lightPayload) {
63+
6264
// check if backing storage and cloud has diverged
6365
// time interval may be elapsed or property may be changed
6466
CborEncoder encoder, arrayEncoder;
@@ -69,7 +71,7 @@ int ArduinoCloudThing::encode(uint8_t * data, size_t const size) {
6971
return -1;
7072
}
7173

72-
if (appendChangedProperties(&arrayEncoder) < 1) {
74+
if (appendChangedProperties(&arrayEncoder, lightPayload) < 1) {
7375
return -1;
7476
}
7577

@@ -84,17 +86,19 @@ int ArduinoCloudThing::encode(uint8_t * data, size_t const size) {
8486
return bytes_encoded;
8587
}
8688

87-
ArduinoCloudProperty& ArduinoCloudThing::addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission) {
89+
ArduinoCloudProperty& ArduinoCloudThing::addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission, int propertyIdentifier) {
8890
property.init(name, permission);
8991
if (isPropertyInContainer(name)) {
9092
return (*getProperty(name));
9193
} else {
9294
if (property.isPrimitive()) {
9395
_numPrimitivesProperties++;
9496
}
95-
addProperty(&property);
97+
_numProperties++;
98+
addProperty(&property, propertyIdentifier);
9699
return (property);
97100
}
101+
98102
}
99103

100104
void ArduinoCloudThing::decode(uint8_t const * const payload, size_t const length, bool isSyncMessage) {
@@ -158,18 +162,19 @@ bool ArduinoCloudThing::isPropertyInContainer(String const & name) {
158162
return false;
159163
}
160164

161-
int ArduinoCloudThing::appendChangedProperties(CborEncoder * arrayEncoder) {
165+
int ArduinoCloudThing::appendChangedProperties(CborEncoder * arrayEncoder, bool lightPayload) {
162166
int appendedProperties = 0;
163167
for (int i = 0; i < _property_list.size(); i++) {
164168
ArduinoCloudProperty * p = _property_list.get(i);
165169
if (p->shouldBeUpdated() && p->isReadableByCloud()) {
166-
p->append(arrayEncoder);
170+
p->append(arrayEncoder, lightPayload);
167171
appendedProperties++;
168172
}
169173
}
170174
return appendedProperties;
171175
}
172176

177+
//retrieve property by name
173178
ArduinoCloudProperty * ArduinoCloudThing::getProperty(String const & name) {
174179
for (int i = 0; i < _property_list.size(); i++) {
175180
ArduinoCloudProperty * p = _property_list.get(i);
@@ -180,6 +185,17 @@ ArduinoCloudProperty * ArduinoCloudThing::getProperty(String const & name) {
180185
return NULL;
181186
}
182187

188+
//retrieve property by identifier
189+
ArduinoCloudProperty * ArduinoCloudThing::getProperty(int const & pos) {
190+
for (int i = 0; i < _property_list.size(); i++) {
191+
ArduinoCloudProperty * p = _property_list.get(i);
192+
if (p->identifier() == pos) {
193+
return p;
194+
}
195+
}
196+
return NULL;
197+
}
198+
183199
// this function updates the timestamps on the primitive properties that have been modified locally since last cloud synchronization
184200
void ArduinoCloudThing::updateTimestampOnLocallyChangedProperties() {
185201
if (_numPrimitivesProperties == 0) {
@@ -312,6 +328,7 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * val
312328
MapParserState next_state = MapParserState::Error;
313329

314330
if (cbor_value_is_text_string(value_iter)) {
331+
// if the value in the cbor message is a string, it corresponds to the name of the property to be updated (int the form [property_name]:[attribute_name])
315332
char * val = nullptr;
316333
size_t val_size = 0;
317334
if (cbor_value_dup_text_string(value_iter, &val, &val_size, value_iter) == CborNoError) {
@@ -326,8 +343,26 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_Name(CborValue * val
326343
map_data->attribute_name.set(attribute_name);
327344
next_state = MapParserState::MapKey;
328345
}
346+
} else if (cbor_value_is_integer(value_iter)) {
347+
// if the value in the cbor message is an integer, a light payload has been used and an integer identifier should be decode in order to retrieve the corresponding property and attribute name to be updated
348+
int val = 0;
349+
if (cbor_value_get_int(value_iter, &val) == CborNoError) {
350+
map_data->light_payload.set(true);
351+
map_data->name_identifier.set(val & 255);
352+
map_data->attribute_identifier.set(val >> 8);
353+
map_data->light_payload.set(true);
354+
String name = getPropertyNameByIdentifier(val);
355+
map_data->name.set(name);
356+
357+
358+
if (cbor_value_advance(value_iter) == CborNoError) {
359+
next_state = MapParserState::MapKey;
360+
}
361+
}
329362
}
330363

364+
365+
331366
return next_state;
332367
}
333368

@@ -404,7 +439,6 @@ ArduinoCloudThing::MapParserState ArduinoCloudThing::handle_LeaveMap(CborValue *
404439
}
405440

406441
if (_currentPropertyName != "" && propertyName != _currentPropertyName) {
407-
408442
/* Update the property containers depending on the parsed data */
409443
updateProperty(_currentPropertyName, _currentPropertyBaseTime + _currentPropertyTime);
410444
/* Reset current property data */
@@ -461,6 +495,18 @@ void ArduinoCloudThing::updateProperty(String propertyName, unsigned long cloudC
461495
}
462496
}
463497
}
498+
499+
// retrieve the property name by the identifier
500+
String ArduinoCloudThing::getPropertyNameByIdentifier(int propertyIdentifier) {
501+
ArduinoCloudProperty* property;
502+
if (propertyIdentifier > 255) {
503+
property = getProperty(propertyIdentifier & 255);
504+
} else {
505+
property = getProperty(propertyIdentifier);
506+
}
507+
return property->name();
508+
}
509+
464510
bool ArduinoCloudThing::ifNumericConvertToDouble(CborValue * value_iter, double * numeric_val) {
465511

466512
if (cbor_value_is_integer(value_iter)) {

ArduinoCloudThing.h

+16-6
Original file line numberDiff line numberDiff line change
@@ -77,23 +77,26 @@ class ArduinoCloudThing {
7777
ArduinoCloudThing();
7878

7979
void begin();
80-
81-
ArduinoCloudProperty & addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission);
80+
//if propertyIdentifier is different from -1, an integer identifier is associated to the added property to be use instead of the property name when the parameter lightPayload is true in the encode method
81+
ArduinoCloudProperty & addPropertyReal(ArduinoCloudProperty & property, String const & name, Permission const permission, int propertyIdentifier = -1);
8282

8383
/* encode return > 0 if a property has changed and encodes the changed properties in CBOR format into the provided buffer */
84-
int encode(uint8_t * data, size_t const size);
84+
/* if lightPayload is true the integer identifier of the property will be encoded in the message instead of the property name in order to reduce the size of the message payload*/
85+
int encode(uint8_t * data, size_t const size, bool lightPayload = false);
8586
/* decode a CBOR payload received from the cloud */
8687
void decode(uint8_t const * const payload, size_t const length, bool isSyncMessage = false);
8788

8889
bool isPropertyInContainer(String const & name);
89-
int appendChangedProperties(CborEncoder * arrayEncoder);
90+
int appendChangedProperties(CborEncoder * arrayEncoder, bool lightPayload);
9091
void updateTimestampOnLocallyChangedProperties();
9192
void updateProperty(String propertyName, unsigned long cloudChangeEventTime);
93+
String getPropertyNameByIdentifier(int propertyIdentifier);
9294

9395
private:
9496
LinkedList<ArduinoCloudProperty *> _property_list;
9597
/* Keep track of the number of primitive properties in the Thing. If 0 it allows the early exit in updateTimestampOnLocallyChangedProperties() */
9698
int _numPrimitivesProperties;
99+
int _numProperties;
97100
/* Indicates the if the message received to be decoded is a response to the getLastValues inquiry */
98101
bool _isSyncMessage;
99102
/* List of map data that will hold all the attributes of a property */
@@ -135,11 +138,18 @@ class ArduinoCloudThing {
135138

136139
static bool ifNumericConvertToDouble(CborValue * value_iter, double * numeric_val);
137140
static double convertCborHalfFloatToDouble(uint16_t const half_val);
138-
void freeMapDataList(LinkedList<CborMapData *> *map_data_list);
139-
inline void addProperty(ArduinoCloudProperty * property_obj) {
141+
void freeMapDataList(LinkedList<CborMapData *> * map_data_list);
142+
inline void addProperty(ArduinoCloudProperty * property_obj, int propertyIdentifier) {
143+
if (propertyIdentifier != -1) {
144+
property_obj->setIdentifier(propertyIdentifier);
145+
} else {
146+
// if property identifier is -1, an incremental value will be assigned as identifier.
147+
property_obj->setIdentifier(_numProperties);
148+
}
140149
_property_list.add(property_obj);
141150
}
142151
ArduinoCloudProperty * getProperty(String const & name);
152+
ArduinoCloudProperty * getProperty(int const & identifier);
143153

144154
};
145155

types/CloudLocation.h

-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ class CloudLocation : public ArduinoCloudProperty {
8383
return _value;
8484
}
8585

86-
8786
virtual void fromCloudToLocal() {
8887
_value = _cloud_value;
8988
}

0 commit comments

Comments
 (0)