KPN IoT / senml

Fork of kpn_senml by KPN IoT

Committer:
kpniot
Date:
Sun May 27 14:31:44 2018 +0000
Revision:
2:9b44be6e79ac
Parent:
0:a9259748d982
try to fix repo

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kpniot 0:a9259748d982 1 /* _ __ ____ _ _
kpniot 0:a9259748d982 2 * | |/ / | _ \ | \ | |
kpniot 0:a9259748d982 3 * | ' / | |_) | | \| |
kpniot 0:a9259748d982 4 * | . \ | __/ | |\ |
kpniot 0:a9259748d982 5 * |_|\_\ |_| |_| \_|
kpniot 0:a9259748d982 6 *
kpniot 0:a9259748d982 7 * (c) 2018 KPN
kpniot 0:a9259748d982 8 * License: MIT License.
kpniot 0:a9259748d982 9 * Author: Jan Bogaerts
kpniot 0:a9259748d982 10 *
kpniot 0:a9259748d982 11 * parse cbor header
kpniot 0:a9259748d982 12 */
kpniot 0:a9259748d982 13
kpniot 0:a9259748d982 14 #ifndef SENMLCBORPARSER
kpniot 0:a9259748d982 15 #define SENMLCBORPARSER
kpniot 0:a9259748d982 16
kpniot 0:a9259748d982 17 #include <senml_base_parser.h>
kpniot 0:a9259748d982 18 #include <senml_enums.h>
kpniot 0:a9259748d982 19 #include <senml_logging.h>
kpniot 0:a9259748d982 20 #include <senml_helpers.h>
kpniot 0:a9259748d982 21 #include <cbor.h>
kpniot 0:a9259748d982 22
kpniot 0:a9259748d982 23 enum SenMLCborDataType {};
kpniot 0:a9259748d982 24
kpniot 0:a9259748d982 25 #define SENML_CBOR_KEY 1
kpniot 0:a9259748d982 26 #define SENML_CBOR_VALUE 2
kpniot 0:a9259748d982 27
kpniot 0:a9259748d982 28
kpniot 0:a9259748d982 29 /**
kpniot 0:a9259748d982 30 * Inernal helper class for parsing cbor data.
kpniot 0:a9259748d982 31 */
kpniot 0:a9259748d982 32 class SenMLCborParser: public SenMLBaseParser {
kpniot 0:a9259748d982 33
kpniot 0:a9259748d982 34 public:
kpniot 0:a9259748d982 35 SenMLCborParser(SenMLPack* root, SenMLStreamMethod format): SenMLBaseParser(root), state(0)
kpniot 0:a9259748d982 36 {
kpniot 0:a9259748d982 37 this->ctx.format = format;
kpniot 0:a9259748d982 38 this->ctx.baseValue.baseUint = 0; //init to 0, so we get correct results for first element as well.
kpniot 0:a9259748d982 39 this->ctx.baseSum.baseUint = 0;
kpniot 0:a9259748d982 40 _streamCtx = &this->ctx; //set the global variable so that we don't have to pass it along on the stack all the time (saves mem & codesize)
kpniot 0:a9259748d982 41 };
kpniot 0:a9259748d982 42
kpniot 0:a9259748d982 43 //convert the cbor raw data into senml and actuate the records in the root pack.
kpniot 0:a9259748d982 44 void parse(Stream* source);
kpniot 0:a9259748d982 45
kpniot 0:a9259748d982 46
kpniot 0:a9259748d982 47 void parse(char* source, int length);
kpniot 0:a9259748d982 48
kpniot 0:a9259748d982 49
kpniot 0:a9259748d982 50 private:
kpniot 0:a9259748d982 51 unsigned char state; //keeps track of the current parse state
kpniot 0:a9259748d982 52 int curLabel; //the cbor number that represents the current senml label (unit, value, boolvalue, basename,..). The next item to read has to be the value for the label
kpniot 0:a9259748d982 53 StreamContext ctx;
kpniot 0:a9259748d982 54
kpniot 0:a9259748d982 55 unsigned int parseNext();
kpniot 0:a9259748d982 56
kpniot 0:a9259748d982 57 void setValue(void* value, int length, SenMLDataType type);
kpniot 0:a9259748d982 58 void setBinaryValue(const char* value, int length);
kpniot 0:a9259748d982 59 void processDouble(double value);
kpniot 0:a9259748d982 60
kpniot 0:a9259748d982 61 void internalParse();
kpniot 0:a9259748d982 62
kpniot 0:a9259748d982 63 unsigned int processBytes(SenMLDataType type);
kpniot 0:a9259748d982 64
kpniot 0:a9259748d982 65 unsigned int processArray();
kpniot 0:a9259748d982 66
kpniot 0:a9259748d982 67 inline unsigned int processMap()
kpniot 0:a9259748d982 68 {
kpniot 0:a9259748d982 69 const bool is_indefinite = (peekChar() == (CBOR_MAP | CBOR_VAR_FOLLOWS));
kpniot 0:a9259748d982 70 uint64_t map_length = 0;
kpniot 0:a9259748d982 71 size_t read_bytes;
kpniot 0:a9259748d982 72
kpniot 0:a9259748d982 73 if (is_indefinite){
kpniot 0:a9259748d982 74 log_debug("not supported");
kpniot 0:a9259748d982 75 }
kpniot 0:a9259748d982 76 else
kpniot 0:a9259748d982 77 read_bytes = decode_int(&map_length);
kpniot 0:a9259748d982 78
kpniot 0:a9259748d982 79 unsigned char curState = this->state;
kpniot 0:a9259748d982 80 size_t i = 0;
kpniot 0:a9259748d982 81 while (i < map_length) {
kpniot 0:a9259748d982 82 size_t key_read_bytes, value_read_bytes;
kpniot 0:a9259748d982 83 this->state = SENML_CBOR_KEY;
kpniot 0:a9259748d982 84 key_read_bytes = this->parseNext(); /* key */
kpniot 0:a9259748d982 85 this->state = SENML_CBOR_VALUE;
kpniot 0:a9259748d982 86 value_read_bytes = this->parseNext(); /* value */
kpniot 0:a9259748d982 87 if (key_read_bytes == 0 || value_read_bytes == 0) {
kpniot 0:a9259748d982 88 log_debug("invalid input");
kpniot 0:a9259748d982 89 break;
kpniot 0:a9259748d982 90 }
kpniot 0:a9259748d982 91 read_bytes += key_read_bytes + value_read_bytes;
kpniot 0:a9259748d982 92 ++i;
kpniot 0:a9259748d982 93 }
kpniot 0:a9259748d982 94 this->state = curState; //reset to the original state. was changed inside loop
kpniot 0:a9259748d982 95 this->ctx.baseValue.baseUint = 0; //if there was a base value, reset it for the next run.
kpniot 0:a9259748d982 96 return read_bytes;
kpniot 0:a9259748d982 97 };
kpniot 0:a9259748d982 98
kpniot 0:a9259748d982 99 inline unsigned int processUnsignedInt()
kpniot 0:a9259748d982 100 {
kpniot 0:a9259748d982 101 uint64_t val;
kpniot 0:a9259748d982 102 size_t read_bytes = cbor_deserialize_uint64_t(&val);
kpniot 0:a9259748d982 103 if(this->state == SENML_CBOR_VALUE){
kpniot 0:a9259748d982 104 switch (this->curLabel)
kpniot 0:a9259748d982 105 {
kpniot 0:a9259748d982 106 case SENML_CBOR_BV_LABEL: this->ctx.baseValue.baseUint = val; break;
kpniot 0:a9259748d982 107 case SENML_CBOR_V_LABEL:
kpniot 0:a9259748d982 108 uint64_t calculated = this->ctx.baseValue.baseUint + val;
kpniot 0:a9259748d982 109 this->setValue((void*)&calculated, sizeof(uint64_t), CBOR_TYPE_UINT);
kpniot 0:a9259748d982 110 break;
kpniot 0:a9259748d982 111 }
kpniot 0:a9259748d982 112 }
kpniot 0:a9259748d982 113 else if(this->state == SENML_CBOR_KEY) //store the value type (basename, baseunit, value, stringvalue,...)
kpniot 0:a9259748d982 114 this->curLabel = (int)val;
kpniot 0:a9259748d982 115 return read_bytes;
kpniot 0:a9259748d982 116 };
kpniot 0:a9259748d982 117
kpniot 0:a9259748d982 118 inline unsigned int processInt()
kpniot 0:a9259748d982 119 {
kpniot 0:a9259748d982 120 int64_t val;
kpniot 0:a9259748d982 121 size_t read_bytes = cbor_deserialize_int64_t(&val);
kpniot 0:a9259748d982 122 if(this->state == SENML_CBOR_VALUE){
kpniot 0:a9259748d982 123 switch (this->curLabel)
kpniot 0:a9259748d982 124 {
kpniot 0:a9259748d982 125 case SENML_CBOR_BV_LABEL: this->ctx.baseValue.baseInt = val; break;
kpniot 0:a9259748d982 126 case SENML_CBOR_V_LABEL:
kpniot 0:a9259748d982 127 uint64_t calculated = this->ctx.baseValue.baseInt + val;
kpniot 0:a9259748d982 128 this->setValue((void*)&calculated, sizeof(int64_t), CBOR_TYPE_INT);
kpniot 0:a9259748d982 129 break;
kpniot 0:a9259748d982 130 }
kpniot 0:a9259748d982 131 }
kpniot 0:a9259748d982 132 else if(this->state == SENML_CBOR_KEY) //store the value type (basename, baseunit, value, stringvalue,...)
kpniot 0:a9259748d982 133 this->curLabel = val;
kpniot 0:a9259748d982 134 return read_bytes;
kpniot 0:a9259748d982 135 };
kpniot 0:a9259748d982 136
kpniot 0:a9259748d982 137
kpniot 0:a9259748d982 138 };
kpniot 0:a9259748d982 139
kpniot 0:a9259748d982 140 #endif // SENMLCBORPARSER
kpniot 0:a9259748d982 141
kpniot 0:a9259748d982 142
kpniot 0:a9259748d982 143
kpniot 0:a9259748d982 144
kpniot 0:a9259748d982 145
kpniot 0:a9259748d982 146
kpniot 0:a9259748d982 147