Skip to content

Commit 23a2c36

Browse files
implementing cbor message decoder following cloud utils definition
1 parent e63ec02 commit 23a2c36

File tree

2 files changed

+82
-177
lines changed

2 files changed

+82
-177
lines changed

src/cbor/MessageDecoder.cpp

+46-132
Original file line numberDiff line numberDiff line change
@@ -14,61 +14,18 @@
1414

1515
#include <Arduino.h>
1616

17-
#undef max
18-
#undef min
19-
#include <algorithm>
20-
2117
#include "MessageDecoder.h"
2218
#include <AIoTC_Config.h>
2319

2420
/******************************************************************************
2521
PUBLIC MEMBER FUNCTIONS
2622
******************************************************************************/
2723

28-
Decoder::Status CBORMessageDecoder::decode(Message * message, uint8_t const * const payload, size_t& length)
29-
{
30-
CborValue main_iter, array_iter;
31-
CborTag tag;
32-
CborParser parser;
33-
34-
if (cbor_parser_init(payload, length, 0, &parser, &main_iter) != CborNoError)
35-
return Decoder::Status::Error;
36-
37-
if (main_iter.type != CborTagType)
38-
return Decoder::Status::Error;
39-
40-
if (cbor_value_get_tag(&main_iter, &tag) == CborNoError) {
41-
message->id = toCommandId(CBORCommandTag(tag));
42-
}
43-
44-
if (cbor_value_advance(&main_iter) != CborNoError) {
45-
return Decoder::Status::Error;
46-
}
47-
48-
ArrayParserState current_state = ArrayParserState::EnterArray,
49-
next_state = ArrayParserState::Error;
50-
51-
while (current_state != ArrayParserState::Complete) {
52-
switch (current_state) {
53-
case ArrayParserState::EnterArray : next_state = handle_EnterArray(&main_iter, &array_iter); break;
54-
case ArrayParserState::ParseParam : next_state = handle_Param(&array_iter, message); break;
55-
case ArrayParserState::LeaveArray : next_state = handle_LeaveArray(&main_iter, &array_iter); break;
56-
case ArrayParserState::Complete : return Decoder::Status::Complete;
57-
case ArrayParserState::MessageNotSupported : return Decoder::Status::Error;
58-
case ArrayParserState::Error : return Decoder::Status::Error;
59-
}
60-
61-
current_state = next_state;
62-
}
63-
64-
return Decoder::Status::Complete;
65-
}
66-
6724
/******************************************************************************
6825
PRIVATE MEMBER FUNCTIONS
6926
******************************************************************************/
7027

71-
bool copyCBORStringToArray(CborValue * param, char * dest, size_t dest_size) {
28+
static bool copyCBORStringToArray(CborValue * param, char * dest, size_t dest_size) {
7229
if (cbor_value_is_text_string(param)) {
7330
// NOTE: keep in mind that _cbor_value_copy_string tries to put a \0 at the end of the string
7431
if(_cbor_value_copy_string(param, dest, &dest_size, NULL) == CborNoError) {
@@ -81,7 +38,7 @@ bool copyCBORStringToArray(CborValue * param, char * dest, size_t dest_size) {
8138

8239
// FIXME dest_size should be also returned, the copied byte array can have a different size from the starting one
8340
// for the time being we need this on SHA256 only
84-
bool copyCBORByteToArray(CborValue * param, uint8_t * dest, size_t dest_size) {
41+
static bool copyCBORByteToArray(CborValue * param, uint8_t * dest, size_t dest_size) {
8542
if (cbor_value_is_byte_string(param)) {
8643
// NOTE: keep in mind that _cbor_value_copy_string tries to put a \0 at the end of the string
8744
if(_cbor_value_copy_string(param, dest, &dest_size, NULL) == CborNoError) {
@@ -92,153 +49,110 @@ bool copyCBORByteToArray(CborValue * param, uint8_t * dest, size_t dest_size) {
9249
return false;
9350
}
9451

95-
CBORMessageDecoder::ArrayParserState CBORMessageDecoder::handle_EnterArray(CborValue * main_iter, CborValue * array_iter) {
96-
ArrayParserState next_state = ArrayParserState::Error;
97-
if (cbor_value_get_type(main_iter) == CborArrayType) {
98-
if (cbor_value_enter_container(main_iter, array_iter) == CborNoError) {
99-
next_state = ArrayParserState::ParseParam;
100-
}
101-
}
102-
103-
return next_state;
104-
}
105-
106-
CBORMessageDecoder::ArrayParserState CBORMessageDecoder::handle_LeaveArray(CborValue * main_iter, CborValue * array_iter) {
107-
// Advance to the next parameter (the last one in the array)
108-
if (cbor_value_advance(array_iter) == CborNoError) {
109-
// Leave the array
110-
if (cbor_value_leave_container(main_iter, array_iter) == CborNoError) {
111-
return ArrayParserState::Complete;
112-
}
113-
}
114-
115-
return ArrayParserState::Error;
116-
}
117-
11852
/******************************************************************************
11953
MESSAGE DECODE FUNCTIONS
12054
******************************************************************************/
12155

122-
CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeThingUpdateCmd(CborValue * param, Message * message) {
123-
ThingUpdateCmd * thingCommand = (ThingUpdateCmd *) message;
56+
Decoder::Status ThingUpdateCommandDecoder::decode(CborValue* iter, Message *msg) {
57+
ThingUpdateCmd * thingCommand = (ThingUpdateCmd *) msg;
12458

12559
// Message is composed of a single parameter, a string (thing_id)
126-
if (!copyCBORStringToArray(param, thingCommand->params.thing_id, sizeof(thingCommand->params.thing_id))) {
127-
return ArrayParserState::Error;
60+
if (!copyCBORStringToArray(iter, thingCommand->params.thing_id, sizeof(thingCommand->params.thing_id))) {
61+
return Decoder::Status::Error;
12862
}
12963

130-
return ArrayParserState::LeaveArray;
64+
return Decoder::Status::Complete;
13165
}
13266

133-
CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeThingDetachCmd(CborValue * param, Message * message) {
134-
ThingDetachCmd * thingCommand = (ThingDetachCmd *) message;
67+
Decoder::Status ThingDetachCommandDecoder::decode(CborValue* iter, Message *msg) {
68+
ThingDetachCmd * thingCommand = (ThingDetachCmd *) msg;
13569

13670
// Message is composed of a single parameter, a string (thing_id)
137-
if (!copyCBORStringToArray(param, thingCommand->params.thing_id, sizeof(thingCommand->params.thing_id))) {
138-
return ArrayParserState::Error;
71+
if (!copyCBORStringToArray(iter, thingCommand->params.thing_id, sizeof(thingCommand->params.thing_id))) {
72+
return Decoder::Status::Error;
13973
}
14074

141-
return ArrayParserState::LeaveArray;
75+
return Decoder::Status::Complete;
14276
}
14377

144-
CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeTimezoneCommandDown(CborValue * param, Message * message) {
145-
TimezoneCommandDown * setTz = (TimezoneCommandDown *) message;
78+
Decoder::Status TimezoneCommandDownDecoder::decode(CborValue* iter, Message *msg) {
79+
TimezoneCommandDown * setTz = (TimezoneCommandDown *) msg;
14680

14781
// Message is composed of 2 parameters, offset 32-bit signed integer and until 32-bit unsigned integer
14882
// Get offset
149-
if (cbor_value_is_integer(param)) {
83+
if (cbor_value_is_integer(iter)) {
15084
int64_t val = 0;
151-
if (cbor_value_get_int64(param, &val) == CborNoError) {
85+
if (cbor_value_get_int64(iter, &val) == CborNoError) {
15286
setTz->params.offset = static_cast<int32_t>(val);
15387
}
15488
}
15589

15690
// Next
157-
if (cbor_value_advance(param) != CborNoError) {
158-
return ArrayParserState::Error;
91+
if (cbor_value_advance(iter) != CborNoError) {
92+
return Decoder::Status::Error;
15993
}
16094

16195
// Get until
162-
if (cbor_value_is_integer(param)) {
96+
if (cbor_value_is_integer(iter)) {
16397
uint64_t val = 0;
164-
if (cbor_value_get_uint64(param, &val) == CborNoError) {
98+
if (cbor_value_get_uint64(iter, &val) == CborNoError) {
16599
setTz->params.until = static_cast<uint32_t>(val);
166100
}
167101
}
168102

169-
return ArrayParserState::LeaveArray;
103+
return Decoder::Status::Complete;
170104
}
171105

172-
CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeLastValuesUpdateCmd(CborValue * param, Message * message) {
173-
LastValuesUpdateCmd * setLv = (LastValuesUpdateCmd *) message;
106+
Decoder::Status LastValuesUpdateCommandDecoder::decode(CborValue* iter, Message *msg) {
107+
LastValuesUpdateCmd * setLv = (LastValuesUpdateCmd *) msg;
174108

175109
// Message is composed by a single parameter, a variable length byte array.
176-
if (cbor_value_is_byte_string(param)) {
110+
if (cbor_value_is_byte_string(iter)) {
177111
// Cortex M0 is not able to assign a value to pointed memory that is not 32bit aligned
178112
// we use a support variable to cope with that
179113
size_t s;
180-
if (cbor_value_dup_byte_string(param, &setLv->params.last_values, &s, NULL) != CborNoError) {
181-
return ArrayParserState::Error;
114+
if (cbor_value_dup_byte_string(iter, &setLv->params.last_values, &s, NULL) != CborNoError) {
115+
return Decoder::Status::Error;
182116
}
183117

184118
setLv->params.length = s;
185119
}
186120

187-
return ArrayParserState::LeaveArray;
121+
return Decoder::Status::Complete;
188122
}
189123

190-
CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeOtaUpdateCmdDown(CborValue * param, Message * message) {
124+
Decoder::Status OtaUpdateCommandDecoder::decode(CborValue* iter, Message *msg) {
191125
CborError error = CborNoError;
192-
OtaUpdateCmdDown * ota = (OtaUpdateCmdDown *) message;
126+
OtaUpdateCmdDown * ota = (OtaUpdateCmdDown *) msg;
193127

194128
// Message is composed 4 parameters: id, url, initialSha, finalSha
195-
if (!copyCBORByteToArray(param, ota->params.id, sizeof(ota->params.id))) {
196-
return ArrayParserState::Error;
129+
if (!copyCBORByteToArray(iter, ota->params.id, sizeof(ota->params.id))) {
130+
return Decoder::Status::Error;
197131
}
198132

199-
error = cbor_value_advance(param);
133+
error = cbor_value_advance(iter);
200134

201-
if ((error != CborNoError) || !copyCBORStringToArray(param, ota->params.url, sizeof(ota->params.url))) {
202-
return ArrayParserState::Error;
135+
if ((error != CborNoError) || !copyCBORStringToArray(iter, ota->params.url, sizeof(ota->params.url))) {
136+
return Decoder::Status::Error;
203137
}
204138

205-
error = cbor_value_advance(param);
139+
error = cbor_value_advance(iter);
206140

207-
if ((error != CborNoError) || !copyCBORByteToArray(param, ota->params.initialSha256, sizeof(ota->params.initialSha256))) {
208-
return ArrayParserState::Error;
141+
if ((error != CborNoError) || !copyCBORByteToArray(iter, ota->params.initialSha256, sizeof(ota->params.initialSha256))) {
142+
return Decoder::Status::Error;
209143
}
210144

211-
error = cbor_value_advance(param);
145+
error = cbor_value_advance(iter);
212146

213-
if ((error != CborNoError) || !copyCBORByteToArray(param, ota->params.finalSha256, sizeof(ota->params.finalSha256))) {
214-
return ArrayParserState::Error;
147+
if ((error != CborNoError) || !copyCBORByteToArray(iter, ota->params.finalSha256, sizeof(ota->params.finalSha256))) {
148+
return Decoder::Status::Error;
215149
}
216150

217-
return ArrayParserState::LeaveArray;
151+
return Decoder::Status::Complete;
218152
}
219153

220-
CBORMessageDecoder::ArrayParserState CBORMessageDecoder::handle_Param(CborValue * param, Message * message) {
221-
222-
switch (message->id)
223-
{
224-
case CommandId::ThingUpdateCmdId:
225-
return CBORMessageDecoder::decodeThingUpdateCmd(param, message);
226-
227-
case CommandId::ThingDetachCmdId:
228-
return CBORMessageDecoder::decodeThingDetachCmd(param, message);
229-
230-
case CommandId::TimezoneCommandDownId:
231-
return CBORMessageDecoder::decodeTimezoneCommandDown(param, message);
232-
233-
case CommandId::LastValuesUpdateCmdId:
234-
return CBORMessageDecoder::decodeLastValuesUpdateCmd(param, message);
235-
236-
case CommandId::OtaUpdateCmdDownId:
237-
return CBORMessageDecoder::decodeOtaUpdateCmdDown(param, message);
238-
239-
default:
240-
return ArrayParserState::MessageNotSupported;
241-
}
242-
243-
return ArrayParserState::LeaveArray;
244-
}
154+
static OtaUpdateCommandDecoder otaUpdateCommandDecoder;
155+
static ThingUpdateCommandDecoder thingUpdateCommandDecoder;
156+
static ThingDetachCommandDecoder thingDetachCommandDecoder;
157+
static LastValuesUpdateCommandDecoder lastValuesUpdateCommandDecoder;
158+
static TimezoneCommandDownDecoder timezoneCommandDownDecoder;

src/cbor/MessageDecoder.h

+36-45
Original file line numberDiff line numberDiff line change
@@ -15,61 +15,52 @@
1515
INCLUDE
1616
******************************************************************************/
1717

18-
#include <Arduino.h>
19-
20-
#undef max
21-
#undef min
22-
#include <list>
23-
24-
#include "CBOR.h"
25-
#include "../interfaces/Decoder.h"
26-
#include <Arduino_TinyCBOR.h>
18+
#include "./CBOR.h"
19+
#include <cbor/CborDecoder.h>
20+
#include "message/Commands.h"
2721

2822
/******************************************************************************
2923
CLASS DECLARATION
3024
******************************************************************************/
3125

32-
class CBORMessageDecoder: public Decoder
33-
{
26+
class OtaUpdateCommandDecoder: public CBORMessageDecoderInterface {
3427
public:
35-
CBORMessageDecoder() { }
36-
CBORMessageDecoder(CBORMessageDecoder const &) { }
37-
38-
/* decode a CBOR payload received from the cloud */
39-
Decoder::Status decode(Message * msg, uint8_t const * const payload, size_t& length);
40-
41-
private:
42-
43-
enum class DecoderState {
44-
Success,
45-
MessageNotSupported,
46-
MalformedMessage,
47-
Error
48-
};
49-
50-
enum class ArrayParserState {
51-
EnterArray,
52-
ParseParam,
53-
LeaveArray,
54-
Complete,
55-
Error,
56-
MessageNotSupported
57-
};
28+
OtaUpdateCommandDecoder()
29+
: CBORMessageDecoderInterface(CBOROtaUpdateCmdDown, OtaUpdateCmdDownId) {}
30+
protected:
31+
Decoder::Status decode(CborValue* iter, Message *msg) override;
32+
};
5833

59-
ArrayParserState handle_EnterArray(CborValue * main_iter, CborValue * array_iter);
60-
ArrayParserState handle_Param(CborValue * param, Message * message);
61-
ArrayParserState handle_LeaveArray(CborValue * main_iter, CborValue * array_iter);
34+
class ThingUpdateCommandDecoder: public CBORMessageDecoderInterface {
35+
public:
36+
ThingUpdateCommandDecoder()
37+
: CBORMessageDecoderInterface(CBORThingUpdateCmd, ThingUpdateCmdId) {}
38+
protected:
39+
Decoder::Status decode(CborValue* iter, Message *msg) override;
40+
};
6241

63-
bool ifNumericConvertToDouble(CborValue * value_iter, double * numeric_val);
64-
double convertCborHalfFloatToDouble(uint16_t const half_val);
42+
class ThingDetachCommandDecoder: public CBORMessageDecoderInterface {
43+
public:
44+
ThingDetachCommandDecoder()
45+
: CBORMessageDecoderInterface(CBORThingDetachCmd, ThingDetachCmdId) {}
46+
protected:
47+
Decoder::Status decode(CborValue* iter, Message *msg) override;
48+
};
6549

66-
// Message specific decoders
67-
ArrayParserState decodeThingUpdateCmd(CborValue * param, Message * message);
68-
ArrayParserState decodeThingDetachCmd(CborValue * param, Message * message);
69-
ArrayParserState decodeTimezoneCommandDown(CborValue * param, Message * message);
70-
ArrayParserState decodeLastValuesUpdateCmd(CborValue * param, Message * message);
71-
ArrayParserState decodeOtaUpdateCmdDown(CborValue * param, Message * message);
50+
class LastValuesUpdateCommandDecoder: public CBORMessageDecoderInterface {
51+
public:
52+
LastValuesUpdateCommandDecoder()
53+
: CBORMessageDecoderInterface(CBORLastValuesUpdate, LastValuesUpdateCmdId) {}
54+
protected:
55+
Decoder::Status decode(CborValue* iter, Message *msg) override;
56+
};
7257

58+
class TimezoneCommandDownDecoder: public CBORMessageDecoderInterface {
59+
public:
60+
TimezoneCommandDownDecoder()
61+
: CBORMessageDecoderInterface(CBORTimezoneCommandDown, TimezoneCommandDownId) {}
62+
protected:
63+
Decoder::Status decode(CborValue* iter, Message *msg) override;
7364
};
7465

7566
#endif /* ARDUINO_CBOR_MESSAGE_DECODER_H_ */

0 commit comments

Comments
 (0)