The KPN SenML library helps you create and parse senml documents in both json and cbor format. The library can be used for sending sensor data and receiving actuator commands.

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