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

CM-386 / Reduce payload size #6

Merged
merged 64 commits into from
Feb 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
235d7f6
Reducing the overall payload size by replacing the string key with a …
aentinger Nov 15, 2018
12319f6
Squashing multiple commits concerning the refactoring of the test code
aentinger Nov 15, 2018
1a9f941
Of course the conversion from cbor half float also needs to be fixed …
aentinger Nov 16, 2018
a817934
Squashing multiple commits concerning the refactoring of the test code
aentinger Nov 16, 2018
7ea0fd2
Implementing first draft of state machine based CBOR decoding
aentinger Dec 12, 2018
89f63fe
More simplification of the CBOR parser - but not guaranteed to work i…
aentinger Dec 12, 2018
ae5379a
Adding C++ Unit Testing Library 'catch'
aentinger Dec 18, 2018
18316a7
Creating CMakeLists.txt and main for writing unit test code with 'catch'
aentinger Dec 18, 2018
8ff87ec
Porting 1st test case for testing the encoding of the status property
aentinger Dec 18, 2018
66568b1
Adding first draft of how we could test the different protocol versions
aentinger Dec 18, 2018
fd28f6c
Adding minimal 'Arduino.h' file which stubs the required methods in o…
aentinger Dec 18, 2018
87b4dca
Creating include/src subfolders and moving header and source files in…
aentinger Dec 18, 2018
ec2882d
Support for CloudProtocol::V1/V2 implemented for boolean values
aentinger Dec 18, 2018
bdc12cc
Adding 'encode' test for int property
aentinger Dec 18, 2018
0883a9c
Implementing test and production code for encoding float properties f…
aentinger Dec 18, 2018
325e7bc
Porting encode tests for string - however, there is still some work t…
aentinger Dec 19, 2018
0f84000
Porting test cases for 'encode' for protocol versions V1/V2
aentinger Dec 19, 2018
786d936
Extracting test code for method ArduinoCloudThing::encode to file tes…
aentinger Dec 19, 2018
918f158
Fixing wrong comment
aentinger Dec 19, 2018
7515194
Implementation of first draft of encode complete
aentinger Jan 7, 2019
d6f5a8a
Since we do have a definite 'end' state of the do while loop we can s…
aentinger Jan 7, 2019
a2a8d1f
Adding test code for testing decoding of CBOR messages
aentinger Jan 7, 2019
a512922
Adding test code for testing a read-only property
aentinger Jan 7, 2019
5b447b1
Adding test code for testing write only paramter
aentinger Jan 7, 2019
9019ad9
Adding test to check if the callbacks registered via onUpdate are act…
aentinger Jan 8, 2019
b79cdf8
Adding test code for testing function publishEvery
aentinger Jan 8, 2019
077e93e
Adding test code for testing function publishOnChange with delta
aentinger Jan 8, 2019
fd6a07c
Fixing bug in test case - test was not sufficiently expressive
aentinger Jan 8, 2019
f1a3314
Adding test code for testing publish on change policy with limited rate
aentinger Jan 22, 2019
2e8f0fe
Wrapping std::string with a small wrapper class in order to prevent a…
aentinger Jan 22, 2019
3bad3b5
Ignoring build folder
aentinger Jan 22, 2019
c99608a
Supporting both encoding protocols for String
aentinger Jan 22, 2019
a846a57
Adding test code for testing when multiple properties are encoded
aentinger Jan 22, 2019
4c48d95
Adding test code for decoding a string property
aentinger Jan 22, 2019
d74db55
Removing ArduinoCloudThing_test.ino test sketch file since all tests …
aentinger Jan 22, 2019
f9be01e
Fixing bug when decoding multiple strings
aentinger Jan 23, 2019
c09429c
Changing test strategy be emulating the progress of time for reliably…
aentinger Jan 23, 2019
9f5aa99
Adding method 'getInitialMinDeltaPropertyValue' which provides the in…
aentinger Jan 23, 2019
d3e1084
Adding test method for evaluating the decoding of multiple properties…
aentinger Jan 23, 2019
600bbf3
Adding test for checking if decoding multiple strings works
aentinger Jan 23, 2019
2d41d74
Improving test description
aentinger Jan 23, 2019
40ef034
Adding decoding implementation for CloudProtocol::V2
aentinger Jan 24, 2019
f029640
Changing author name to copyright notice
aentinger Jan 24, 2019
3b9c844
Reducing the overall payload size by replacing the string key with a …
aentinger Nov 15, 2018
da1d172
Merge branch 'cm-386/reduce-payload-size' of https://github.com/bcmi-…
aentinger Jan 24, 2019
1ab9c3b
Adding test logic for testing if callbacks are called when using Clou…
aentinger Jan 24, 2019
3e6b109
Rewriting test for publishOnChange for better expressitivity and addi…
aentinger Jan 24, 2019
f0682b6
Adding Travis CI configuration file for CI build of source
aentinger Jan 24, 2019
dfe331d
Adding implementation and test code for decoding a base tag property
aentinger Feb 4, 2019
3f3fa83
Adding test skeleton code for testing parsing of base time / time
aentinger Feb 4, 2019
cdd395f
Adding implementation and test code for decoding a base time map entry
aentinger Feb 4, 2019
bc45ddb
Adding implementation and test code for decoding a time map entry
aentinger Feb 4, 2019
c1fbe6f
Adding test code for decoding a CBOR stream containing a BaseTime, Ba…
aentinger Feb 4, 2019
95fadde
Refactoring state machine for better readability
aentinger Feb 4, 2019
93bbc8c
Extracting all state code into dedicated functions for better readabi…
aentinger Feb 5, 2019
c72bbda
Rearranging function ordering for better readability
aentinger Feb 5, 2019
d1294d4
Addding code to automatically execute unit test as post build step
aentinger Feb 5, 2019
058cfe8
Rewriting parser in such way that the order of the map entries is no …
aentinger Feb 5, 2019
0910b95
In case of a unkown map key we now just advance to the next map key i…
aentinger Feb 5, 2019
0a3dc7b
Implementing parsing for base version
aentinger Feb 5, 2019
02c43a0
Making sure the map data is reset when entering a new map
aentinger Feb 5, 2019
da6f439
Bugfix: Parsing BaseTime regardless if its a double or an int
aentinger Feb 5, 2019
8308bff
Bugfix - taking into account that the CBOR library might collapse any…
aentinger Feb 5, 2019
8fd1d03
Bugfix - All numeric data types are excepted for BaseTime and Time
aentinger Feb 5, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*.bin
*.elf
build
*~

.project
.cproject
15 changes: 15 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
language: cpp
sudo: enabled

before_script:
- cd test && mkdir build && cd build

script:
- cmake ..
- make
- ./testArduinoCloudThing

after_script:
- cd ..
- rm -rf build

54 changes: 52 additions & 2 deletions src/ArduinoCloudProperty.hpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
#ifndef ARDUINO_CLOUD_PROPERTY_HPP_
#define ARDUINO_CLOUD_PROPERTY_HPP_

/******************************************************************************
* INCLUDE
******************************************************************************/

#include <Arduino.h>

#include "lib/tinycbor/cbor-lib.h"

/******************************************************************************
* TYPEDEF
******************************************************************************/

/******************************************************************************
* TYPEDEF
******************************************************************************/

enum class CloudProtocol {
V1, /* [{"n": "test", "vb": true}] */
V2 /* [{0: "test", 4: true}] */
};

enum class Permission {
Read, Write, ReadWrite
};
Expand All @@ -17,8 +34,31 @@ enum class UpdatePolicy {
OnChange, TimeInterval
};

/* Source: https://tools.ietf.org/html/rfc8428#section-6 */
enum class CborIntegerMapKey : int
{
BaseVersion = -1, /* bver */
BaseName = -2, /* bn */
BaseTime = -3, /* bt */
BaseUnit = -4, /* bu */
BaseValue = -5, /* bv */
BaseSum = -6, /* bs */
Name = 0, /* n */
Unit = 1, /* u */
Value = 2, /* v */
StringValue = 3, /* vs */
BooleanValue = 4, /* vb */
Sum = 5, /* s */
Time = 6, /* t */
UpdateTime = 7, /* ut */
DataValue = 8 /* vd */
};

typedef void(*UpdateCallbackFunc)(void);

/******************************************************************************
* CLASS DECLARATION
******************************************************************************/

template <typename T>
class ArduinoCloudProperty {
Expand All @@ -40,7 +80,7 @@ class ArduinoCloudProperty {
bool shouldBeUpdated () const;
void execCallbackOnChange ();

void append (CborEncoder * encoder);
void append (CborEncoder * encoder, CloudProtocol const cloud_protocol);

private:

Expand All @@ -59,14 +99,24 @@ class ArduinoCloudProperty {
unsigned long _last_updated_millis,
_update_interval_millis;

void appendValue(CborEncoder * mapEncoder) const;
void appendValue(CborEncoder * mapEncoder, CloudProtocol const cloud_protocol) const;
bool isValueDifferent(T const lhs, T const rhs) const;

T getInitialMinDeltaPropertyValue() const;

};

/******************************************************************************
* PROTOTYPE FREE FUNCTIONs
******************************************************************************/

template <typename T>
inline bool operator == (ArduinoCloudProperty<T> const & lhs, ArduinoCloudProperty<T> const & rhs) { return (lhs.name() == rhs.name()); }

/******************************************************************************
* TEMPLATE IMPLEMENTATION
******************************************************************************/

#include "ArduinoCloudProperty.ipp"

#endif /* ARDUINO_CLOUD_PROPERTY_HPP_ */
61 changes: 49 additions & 12 deletions src/ArduinoCloudProperty.ipp
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/******************************************************************************
* CTOR/DTOR
******************************************************************************/

template <typename T>
ArduinoCloudProperty<T>::ArduinoCloudProperty(T & property, String const & name, Permission const permission)
Expand All @@ -8,13 +11,17 @@ ArduinoCloudProperty<T>::ArduinoCloudProperty(T & property, String const & name,
_update_callback_func(NULL),
_update_policy(UpdatePolicy::OnChange),
_has_been_updated_once(false),
_min_delta_property(T(0)),
_min_delta_property(getInitialMinDeltaPropertyValue()),
_min_time_between_updates_millis(0),
_last_updated_millis(0),
_update_interval_millis(0)
{
}

/******************************************************************************
* PUBLIC MEMBER FUNCTIONS
******************************************************************************/

template <typename T>
void ArduinoCloudProperty<T>::writeByCloud(T const val) {
if(isWriteableByCloud()) {
Expand Down Expand Up @@ -69,14 +76,16 @@ void ArduinoCloudProperty<T>::execCallbackOnChange() {
}

template <typename T>
void ArduinoCloudProperty<T>::append(CborEncoder * encoder) {
void ArduinoCloudProperty<T>::append(CborEncoder * encoder, CloudProtocol const cloud_protocol) {
if (isReadableByCloud()) {
CborEncoder mapEncoder;

cbor_encoder_create_map(encoder, &mapEncoder, CborIndefiniteLength);
cbor_encode_text_stringz(&mapEncoder, "n");

if (cloud_protocol == CloudProtocol::V1) cbor_encode_text_stringz(&mapEncoder, "n");
else if(cloud_protocol == CloudProtocol::V2) cbor_encode_int (&mapEncoder, static_cast<int>(CborIntegerMapKey::Name));
cbor_encode_text_stringz(&mapEncoder, _name.c_str());
appendValue(&mapEncoder);
appendValue(&mapEncoder, cloud_protocol);
cbor_encoder_close_container(encoder, &mapEncoder);

_shadow_property = _property;
Expand All @@ -85,27 +94,35 @@ void ArduinoCloudProperty<T>::append(CborEncoder * encoder) {
}
}

/******************************************************************************
* PRIVATE MEMBER FUNCTIONS
******************************************************************************/

template <>
inline void ArduinoCloudProperty<bool>::appendValue(CborEncoder * mapEncoder) const {
cbor_encode_text_stringz(mapEncoder, "vb");
inline void ArduinoCloudProperty<bool>::appendValue(CborEncoder * mapEncoder, CloudProtocol const cloud_protocol) const {
if (cloud_protocol == CloudProtocol::V1) cbor_encode_text_stringz(mapEncoder, "vb");
else if(cloud_protocol == CloudProtocol::V2) cbor_encode_int (mapEncoder, static_cast<int>(CborIntegerMapKey::BooleanValue));
cbor_encode_boolean(mapEncoder, _property);
}

template <>
inline void ArduinoCloudProperty<int>::appendValue(CborEncoder * mapEncoder) const {
cbor_encode_text_stringz(mapEncoder, "v");
inline void ArduinoCloudProperty<int>::appendValue(CborEncoder * mapEncoder, CloudProtocol const cloud_protocol) const {
if (cloud_protocol == CloudProtocol::V1) cbor_encode_text_stringz(mapEncoder, "v");
else if(cloud_protocol == CloudProtocol::V2) cbor_encode_int (mapEncoder, static_cast<int>(CborIntegerMapKey::Value));
cbor_encode_int(mapEncoder, _property);
}

template <>
inline void ArduinoCloudProperty<float>::appendValue(CborEncoder * mapEncoder) const {
cbor_encode_text_stringz(mapEncoder, "v");
inline void ArduinoCloudProperty<float>::appendValue(CborEncoder * mapEncoder, CloudProtocol const cloud_protocol) const {
if (cloud_protocol == CloudProtocol::V1) cbor_encode_text_stringz(mapEncoder, "v");
else if(cloud_protocol == CloudProtocol::V2) cbor_encode_int (mapEncoder, static_cast<int>(CborIntegerMapKey::Value));
cbor_encode_float(mapEncoder, _property);
}

template <>
inline void ArduinoCloudProperty<String>::appendValue(CborEncoder * mapEncoder) const {
cbor_encode_text_stringz(mapEncoder, "vs");
inline void ArduinoCloudProperty<String>::appendValue(CborEncoder * mapEncoder, CloudProtocol const cloud_protocol) const {
if (cloud_protocol == CloudProtocol::V1) cbor_encode_text_stringz(mapEncoder, "vs");
else if(cloud_protocol == CloudProtocol::V2) cbor_encode_int (mapEncoder, static_cast<int>(CborIntegerMapKey::StringValue));
cbor_encode_text_stringz(mapEncoder, _property.c_str());
}

Expand All @@ -128,3 +145,23 @@ template <>
inline bool ArduinoCloudProperty<String>::isValueDifferent(String const lhs, String const rhs) const {
return (lhs != rhs);
}

template <>
inline bool ArduinoCloudProperty<bool>::getInitialMinDeltaPropertyValue() const {
return false;
}

template <>
inline int ArduinoCloudProperty<int>::getInitialMinDeltaPropertyValue() const {
return 0;
}

template <>
inline float ArduinoCloudProperty<float>::getInitialMinDeltaPropertyValue() const {
return 0.0f;
}

template <>
inline String ArduinoCloudProperty<String>::getInitialMinDeltaPropertyValue() const {
return String("");
}
18 changes: 13 additions & 5 deletions src/ArduinoCloudPropertyContainer.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
/******************************************************************************
* INCLUDE
******************************************************************************/

#include "ArduinoCloudPropertyContainer.hpp"

/******************************************************************************
* PUBLIC MEMBER FUNCTIONS
******************************************************************************/

bool ArduinoCloudPropertyContainer::isPropertyInContainer(Type const type, String const & name) {
if (type == Type::Bool ) return isPropertyInList(_bool_property_list, name);
else if (type == Type::Int ) return isPropertyInList(_int_property_list, name);
Expand All @@ -19,9 +27,9 @@ int ArduinoCloudPropertyContainer::getNumOfChangedProperties() {
return num_changes_properties;
}

void ArduinoCloudPropertyContainer::appendChangedProperties(CborEncoder * arrayEncoder) {
appendChangedProperties<bool> (_bool_property_list, arrayEncoder);
appendChangedProperties<int> (_int_property_list, arrayEncoder);
appendChangedProperties<float> (_float_property_list, arrayEncoder);
appendChangedProperties<String>(_string_property_list, arrayEncoder);
void ArduinoCloudPropertyContainer::appendChangedProperties(CborEncoder * arrayEncoder, CloudProtocol const cloud_protocol) {
appendChangedProperties<bool> (_bool_property_list, arrayEncoder, cloud_protocol);
appendChangedProperties<int> (_int_property_list, arrayEncoder, cloud_protocol);
appendChangedProperties<float> (_float_property_list, arrayEncoder, cloud_protocol);
appendChangedProperties<String>(_string_property_list, arrayEncoder, cloud_protocol);
}
16 changes: 14 additions & 2 deletions src/ArduinoCloudPropertyContainer.hpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
#ifndef ARDUINO_CLOUD_PROPERTY_CONTAINER_NEW_H_
#define ARDUINO_CLOUD_PROPERTY_CONTAINER_NEW_H_

/******************************************************************************
* INCLUDE
******************************************************************************/

#include "ArduinoCloudProperty.hpp"

#include "lib/tinycbor/cbor-lib.h"
#include "lib/LinkedList/LinkedList.h"

/******************************************************************************
* CLASS DECLARATION
******************************************************************************/

class ArduinoCloudPropertyContainer {
public:

bool isPropertyInContainer (Type const type, String const & name);
int getNumOfChangedProperties();
void appendChangedProperties (CborEncoder * arrayEncoder);
void appendChangedProperties (CborEncoder * arrayEncoder, CloudProtocol const cloud_protocol);

inline ArduinoCloudProperty<bool> * getPropertyBool (String const & name) { return getProperty(_bool_property_list, name); }
inline ArduinoCloudProperty<int> * getPropertyInt (String const & name) { return getProperty(_int_property_list, name); }
Expand Down Expand Up @@ -40,10 +48,14 @@ class ArduinoCloudPropertyContainer {
int getNumOfChangedProperties(LinkedList<ArduinoCloudProperty<T> *> & list);

template <typename T>
void appendChangedProperties(LinkedList<ArduinoCloudProperty<T> *> & list, CborEncoder * arrayEncoder);
void appendChangedProperties(LinkedList<ArduinoCloudProperty<T> *> & list, CborEncoder * arrayEncoder, CloudProtocol const cloud_protocol);

};

/******************************************************************************
* TEMPLATE IMPLEMENTATION
******************************************************************************/

#include "ArduinoCloudPropertyContainer.ipp"

#endif /* ARDUINO_CLOUD_PROPERTY_CONTAINER_NEW_H_ */
7 changes: 5 additions & 2 deletions src/ArduinoCloudPropertyContainer.ipp
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/******************************************************************************
* PRIVATE MEMBER FUNCTIONS
******************************************************************************/

template <typename T>
bool ArduinoCloudPropertyContainer::isPropertyInList(LinkedList<ArduinoCloudProperty<T> *> & list, String const & name) {
Expand Down Expand Up @@ -32,11 +35,11 @@ int ArduinoCloudPropertyContainer::getNumOfChangedProperties(LinkedList<ArduinoC
}

template <typename T>
void ArduinoCloudPropertyContainer::appendChangedProperties(LinkedList<ArduinoCloudProperty<T> *> & list, CborEncoder * arrayEncoder) {
void ArduinoCloudPropertyContainer::appendChangedProperties(LinkedList<ArduinoCloudProperty<T> *> & list, CborEncoder * arrayEncoder, CloudProtocol const cloud_protocol) {
for (int i = 0; i < list.size(); i++) {
ArduinoCloudProperty<T> * p = list.get(i);
if (p->shouldBeUpdated() && p->isReadableByCloud()) {
p->append(arrayEncoder);
p->append(arrayEncoder, cloud_protocol);
}
}
}
Loading