Skip to content

Commit fd428e2

Browse files
committed
Merge branch 'master' of /home/alex/projects/arduino/tmp/ArduinoCloudThing into integrate-ArduinoCloudThing
2 parents c6723e8 + abb0d0d commit fd428e2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+9689
-0
lines changed

cbor/ArduinoCloudProperty.cpp

+278
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
//
2+
// This file is part of ArduinoCloudThing
3+
//
4+
// Copyright 2019 ARDUINO SA (http://www.arduino.cc/)
5+
//
6+
// This software is released under the GNU General Public License version 3,
7+
// which covers the main part of ArduinoCloudThing.
8+
// The terms of this license can be found at:
9+
// https://www.gnu.org/licenses/gpl-3.0.en.html
10+
//
11+
// You can be released from the requirements of the above licenses by purchasing
12+
// a commercial license. Buying such a license is mandatory if you want to modify or
13+
// otherwise use the software for commercial activities involving the Arduino
14+
// software without disclosing the source code of your own applications. To purchase
15+
// a commercial license, send an email to [email protected].
16+
//
17+
18+
#include "ArduinoCloudProperty.h"
19+
20+
#ifndef ARDUINO_ARCH_SAMD
21+
#pragma message "No RTC available on this architecture - ArduinoIoTCloud will not keep track of local change timestamps ."
22+
#endif
23+
24+
/******************************************************************************
25+
CTOR/DTOR
26+
******************************************************************************/
27+
ArduinoCloudProperty::ArduinoCloudProperty()
28+
: _name(""),
29+
_min_delta_property(0.0f),
30+
_min_time_between_updates_millis(0),
31+
_permission(Permission::Read),
32+
_get_time_func{nullptr},
33+
_update_callback_func(nullptr),
34+
_sync_callback_func(nullptr),
35+
_has_been_updated_once(false),
36+
_has_been_modified_in_callback(false),
37+
_last_updated_millis(0),
38+
_update_interval_millis(0),
39+
_last_local_change_timestamp(0),
40+
_last_cloud_change_timestamp(0),
41+
_map_data_list(nullptr),
42+
_identifier(0),
43+
_attributeIdentifier(0),
44+
_lightPayload(false) {
45+
}
46+
47+
/******************************************************************************
48+
PUBLIC MEMBER FUNCTIONS
49+
******************************************************************************/
50+
void ArduinoCloudProperty::init(String const name, Permission const permission, GetTimeCallbackFunc func) {
51+
_name = name;
52+
_permission = permission;
53+
_get_time_func = func;
54+
}
55+
56+
ArduinoCloudProperty & ArduinoCloudProperty::onUpdate(UpdateCallbackFunc func) {
57+
_update_callback_func = func;
58+
return (*this);
59+
}
60+
61+
ArduinoCloudProperty & ArduinoCloudProperty::onSync(SyncCallbackFunc func) {
62+
_sync_callback_func = func;
63+
return (*this);
64+
}
65+
66+
ArduinoCloudProperty & ArduinoCloudProperty::publishOnChange(float const min_delta_property, unsigned long const min_time_between_updates_millis) {
67+
_update_policy = UpdatePolicy::OnChange;
68+
_min_delta_property = min_delta_property;
69+
_min_time_between_updates_millis = min_time_between_updates_millis;
70+
return (*this);
71+
}
72+
73+
ArduinoCloudProperty & ArduinoCloudProperty::publishEvery(unsigned long const seconds) {
74+
_update_policy = UpdatePolicy::TimeInterval;
75+
_update_interval_millis = (seconds * 1000);
76+
return (*this);
77+
}
78+
79+
bool ArduinoCloudProperty::shouldBeUpdated() {
80+
if (!_has_been_updated_once) {
81+
return true;
82+
}
83+
84+
if (_has_been_modified_in_callback) {
85+
_has_been_modified_in_callback = false;
86+
return true;
87+
}
88+
89+
if (_update_policy == UpdatePolicy::OnChange) {
90+
return (isDifferentFromCloud() && ((millis() - _last_updated_millis) >= (_min_time_between_updates_millis)));
91+
} else if (_update_policy == UpdatePolicy::TimeInterval) {
92+
return ((millis() - _last_updated_millis) >= _update_interval_millis);
93+
} else {
94+
return false;
95+
}
96+
}
97+
98+
void ArduinoCloudProperty::execCallbackOnChange() {
99+
if (_update_callback_func != NULL) {
100+
_update_callback_func();
101+
}
102+
if (!isDifferentFromCloud()) {
103+
_has_been_modified_in_callback = true;
104+
}
105+
}
106+
107+
void ArduinoCloudProperty::execCallbackOnSync() {
108+
if (_sync_callback_func != NULL) {
109+
_sync_callback_func(*this);
110+
}
111+
}
112+
113+
void ArduinoCloudProperty::append(CborEncoder *encoder, bool lightPayload) {
114+
_lightPayload = lightPayload;
115+
_attributeIdentifier = 0;
116+
appendAttributesToCloudReal(encoder);
117+
fromLocalToCloud();
118+
_has_been_updated_once = true;
119+
_last_updated_millis = millis();
120+
}
121+
122+
void ArduinoCloudProperty::appendAttributeReal(bool value, String attributeName, CborEncoder *encoder) {
123+
appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) {
124+
cbor_encode_int(&mapEncoder, static_cast<int>(CborIntegerMapKey::BooleanValue));
125+
cbor_encode_boolean(&mapEncoder, value);
126+
}, encoder);
127+
}
128+
129+
void ArduinoCloudProperty::appendAttributeReal(int value, String attributeName, CborEncoder *encoder) {
130+
appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) {
131+
cbor_encode_int(&mapEncoder, static_cast<int>(CborIntegerMapKey::Value));
132+
cbor_encode_int(&mapEncoder, value);
133+
}, encoder);
134+
}
135+
136+
void ArduinoCloudProperty::appendAttributeReal(float value, String attributeName, CborEncoder *encoder) {
137+
appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) {
138+
cbor_encode_int(&mapEncoder, static_cast<int>(CborIntegerMapKey::Value));
139+
cbor_encode_float(&mapEncoder, value);
140+
}, encoder);
141+
}
142+
143+
void ArduinoCloudProperty::appendAttributeReal(String value, String attributeName, CborEncoder *encoder) {
144+
appendAttributeName(attributeName, [value](CborEncoder & mapEncoder) {
145+
cbor_encode_int(&mapEncoder, static_cast<int>(CborIntegerMapKey::StringValue));
146+
cbor_encode_text_stringz(&mapEncoder, value.c_str());
147+
}, encoder);
148+
}
149+
150+
void ArduinoCloudProperty::appendAttributeName(String attributeName, std::function<void (CborEncoder& mapEncoder)>appendValue, CborEncoder *encoder) {
151+
if (attributeName != "") {
152+
// 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
153+
_attributeIdentifier++;
154+
}
155+
CborEncoder mapEncoder;
156+
cbor_encoder_create_map(encoder, &mapEncoder, 2);
157+
cbor_encode_int(&mapEncoder, static_cast<int>(CborIntegerMapKey::Name));
158+
159+
// if _lightPayload is true, the property and attribute identifiers will be encoded instead of the property name
160+
if (_lightPayload) {
161+
// the most significant byte of the identifier to be encoded represent the property identifier
162+
int completeIdentifier = _attributeIdentifier * 256;
163+
// the least significant byte of the identifier to be encoded represent the attribute identifier
164+
completeIdentifier += _identifier;
165+
cbor_encode_int(&mapEncoder, completeIdentifier);
166+
} else {
167+
String completeName = _name;
168+
if (attributeName != "") {
169+
completeName += ":" + attributeName;
170+
}
171+
cbor_encode_text_stringz(&mapEncoder, completeName.c_str());
172+
}
173+
appendValue(mapEncoder);
174+
cbor_encoder_close_container(encoder, &mapEncoder);
175+
}
176+
177+
void ArduinoCloudProperty::setAttributesFromCloud(LinkedList<CborMapData *> *map_data_list) {
178+
_map_data_list = map_data_list;
179+
_attributeIdentifier = 0;
180+
setAttributesFromCloud();
181+
}
182+
183+
void ArduinoCloudProperty::setAttributeReal(bool& value, String attributeName) {
184+
setAttributeReal(attributeName, [&value](CborMapData * md) {
185+
// Manage the case to have boolean values received as integers 0/1
186+
if (md->bool_val.isSet()) {
187+
value = md->bool_val.get();
188+
} else if (md->val.isSet()) {
189+
if (md->val.get() == 0) {
190+
value = false;
191+
} else if (md->val.get() == 1) {
192+
value = true;
193+
} else {
194+
/* This should not happen. Leave the previous value */
195+
}
196+
}
197+
});
198+
}
199+
200+
void ArduinoCloudProperty::setAttributeReal(int& value, String attributeName) {
201+
setAttributeReal(attributeName, [&value](CborMapData * md) {
202+
value = md->val.get();
203+
});
204+
}
205+
206+
void ArduinoCloudProperty::setAttributeReal(float& value, String attributeName) {
207+
setAttributeReal(attributeName, [&value](CborMapData * md) {
208+
value = md->val.get();
209+
});
210+
}
211+
212+
void ArduinoCloudProperty::setAttributeReal(String& value, String attributeName) {
213+
setAttributeReal(attributeName, [&value](CborMapData * md) {
214+
value = md->str_val.get();
215+
});
216+
}
217+
218+
void ArduinoCloudProperty::setAttributeReal(String attributeName, std::function<void (CborMapData *md)>setValue) {
219+
if (attributeName != "") {
220+
_attributeIdentifier++;
221+
}
222+
for (int i = 0; i < _map_data_list->size(); i++) {
223+
CborMapData *map = _map_data_list->get(i);
224+
if (map != nullptr) {
225+
if (map->light_payload.isSet() && map->light_payload.get()) {
226+
// if a light payload is detected, the attribute identifier is retrieved from the cbor map and the corresponding attribute is updated
227+
int attid = map->attribute_identifier.get();
228+
if (attid == _attributeIdentifier) {
229+
setValue(map);
230+
break;
231+
}
232+
} else {
233+
// if a normal payload is detected, the name of the attribute to be updated is extracted directly from the cbor map
234+
String an = map->attribute_name.get();
235+
if (an == attributeName) {
236+
setValue(map);
237+
break;
238+
}
239+
}
240+
}
241+
}
242+
243+
}
244+
245+
String ArduinoCloudProperty::getAttributeName(String propertyName, char separator) {
246+
int colonPos;
247+
String attributeName = "";
248+
(colonPos = propertyName.indexOf(separator)) != -1 ? attributeName = propertyName.substring(colonPos + 1) : "";
249+
return attributeName;
250+
}
251+
252+
void ArduinoCloudProperty::updateLocalTimestamp() {
253+
if (isReadableByCloud()) {
254+
if (_get_time_func) {
255+
_last_local_change_timestamp = _get_time_func();
256+
}
257+
}
258+
}
259+
260+
void ArduinoCloudProperty::setLastCloudChangeTimestamp(unsigned long cloudChangeEventTime) {
261+
_last_cloud_change_timestamp = cloudChangeEventTime;
262+
}
263+
264+
void ArduinoCloudProperty::setLastLocalChangeTimestamp(unsigned long localChangeTime) {
265+
_last_local_change_timestamp = localChangeTime;
266+
}
267+
268+
unsigned long ArduinoCloudProperty::getLastCloudChangeTimestamp() {
269+
return _last_cloud_change_timestamp;
270+
}
271+
272+
unsigned long ArduinoCloudProperty::getLastLocalChangeTimestamp() {
273+
return _last_local_change_timestamp;
274+
}
275+
276+
void ArduinoCloudProperty::setIdentifier(int identifier) {
277+
_identifier = identifier;
278+
}

0 commit comments

Comments
 (0)