KPN IoT / senml

Fork of kpn_senml by KPN IoT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers senml_cbor_parser.cpp Source File

senml_cbor_parser.cpp

00001 /*  _  __  ____    _   _ 
00002  * | |/ / |  _ \  | \ | |
00003  * | ' /  | |_) | |  \| |
00004  * | . \  |  __/  | |\  |
00005  * |_|\_\ |_|     |_| \_|
00006  * 
00007  * (c) 2018 KPN
00008  * License: MIT License.
00009  * Author: Jan Bogaerts
00010  * 
00011  * parse cbor
00012  */
00013 
00014 
00015 #include <senml_cbor_parser.h>
00016 #include <senml_helpers.h>
00017 #include <senml_binary_actuator.h>
00018 
00019 void SenMLCborParser::parse(Stream* source)
00020 {
00021     this->ctx.data.stream = source;
00022     this->ctx.dataAsBlob = false;
00023     this->internalParse();
00024 }
00025 
00026 
00027 void SenMLCborParser::parse(char* source, int length)
00028 {
00029     this->ctx.data.blob.data = source;
00030     this->ctx.data.blob.curPos = 0;
00031     this->ctx.data.blob.length = length;
00032     this->ctx.dataAsBlob = true;
00033     this->internalParse();
00034 }
00035 
00036 void SenMLCborParser::internalParse()
00037 {
00038     unsigned int read_bytes = this->processArray();         //the root element of senml input is always an array. We do this cause the readable() function on mbed doesn't work as expected, so we can't read until there is no more data, we need to read until we have valid input.
00039 
00040     if (read_bytes == 0) {
00041         log_debug("invalid input");
00042     }
00043     flush();                                                    //make certain that the input streams are empty when done. This also resets any internally stored data. If we don't do this, we can only handle 1 bad input stream, ten it breaks.
00044 }
00045 
00046 
00047 void SenMLCborParser::processDouble(double value){
00048     switch (this->curLabel)
00049     {
00050         //case SENML_CBOR_S_LABEL:
00051         case SENML_CBOR_BV_LABEL: this->ctx.baseValue.baseDouble = value; break;
00052         case SENML_CBOR_V_LABEL:
00053             double calculated = this->ctx.baseValue.baseDouble + value;
00054             this->setValue(&calculated, sizeof(double), CBOR_TYPE_DOUBLE); 
00055             break;
00056     }
00057 }
00058 
00059 unsigned int SenMLCborParser::parseNext()
00060 {
00061     switch (CBOR_TYPE) {
00062         case CBOR_UINT:     return this->processUnsignedInt();
00063         case CBOR_NEGINT:   return this->processInt();
00064         case CBOR_BYTES:    return this->processBytes(CBOR_TYPE_DATA);
00065         case CBOR_TEXT:     return this->processBytes(CBOR_TYPE_STRING); 
00066         case CBOR_ARRAY:    return this->processArray();
00067         case CBOR_MAP:      return this->processMap();
00068         case CBOR_7: {
00069             bool boolRes;
00070             float floatVal;
00071             double doubleVal;
00072             size_t read_bytes;
00073             switch ((int)peekChar()) {
00074                 case CBOR_FALSE:   
00075                     readChar();                                         //need to remove the char from the stream.
00076                     boolRes = false;
00077                     this->setValue((void*)&boolRes, sizeof(boolRes), CBOR_TYPE_BOOL); 
00078                     return 1;
00079                 case CBOR_TRUE:     
00080                     readChar();                                         //need to remove the char from the stream.
00081                     boolRes = true;
00082                     this->setValue((void*)&boolRes, sizeof(boolRes), CBOR_TYPE_BOOL); 
00083                     return 1;
00084                 case CBOR_FLOAT16:  
00085                     read_bytes = cbor_deserialize_float_half(&floatVal);
00086                     this->processDouble(floatVal); 
00087                     return read_bytes;
00088                 case CBOR_FLOAT32:
00089                     read_bytes = cbor_deserialize_float(&floatVal);
00090                     this->processDouble(floatVal); 
00091                     return read_bytes;
00092                 case CBOR_FLOAT64:
00093                     read_bytes = cbor_deserialize_double(&doubleVal);
00094                     this->processDouble(doubleVal); 
00095                     return read_bytes;
00096             }
00097         }
00098     }
00099     return 0;                                                                   //if we get here, something went wrong
00100 }
00101 
00102 void SenMLCborParser::setValue(void* value, int length, SenMLDataType type)
00103 {
00104     if(this->curRec){
00105         this->curRec->actuate(value, length, type);
00106     }
00107     else {
00108         SenMLPack* pack = this->curPack;
00109         if(!pack)
00110             pack = this->root;
00111         if(pack)
00112             pack->actuate(this->curPackName.c_str(), this->curRecName.c_str(), value, length, type);
00113     }
00114 }
00115 
00116 void SenMLCborParser::setBinaryValue(const char* value, int length)
00117 {
00118     if(this->curRec){
00119         ((SenMLBinaryActuator*)this->curRec)->actuate(value, length);
00120     }
00121     else {
00122         SenMLPack* pack = this->curPack;
00123         if(!pack)
00124             pack = this->root;
00125         if(pack)
00126             pack->actuate(this->curPackName.c_str(), this->curRecName.c_str(), value, length, CBOR_TYPE_DATA);
00127     }
00128 }
00129 
00130 
00131 unsigned int SenMLCborParser::processBytes(SenMLDataType type)
00132 {
00133     uint64_t bytes_length;                              //needs to be this big for decode_int
00134     size_t bytes_read = decode_int(&bytes_length);
00135     
00136     if(bytes_read == 0) return 0;
00137     char buffer[bytes_length + 1];                      //need a null 
00138     for(int i = 0; i < (int)bytes_length; i++)
00139         buffer[i] = readChar();
00140     buffer[bytes_length] = 0;                           //close it, just to be save. not always needed, but it is for strings
00141 
00142     if(type == CBOR_TYPE_DATA){                         //we are expecting binary data, so it has to be for a binary data value.
00143         if(this->curLabel == SENML_CBOR_VD_LABEL)
00144             this->setBinaryValue(buffer, bytes_length); 
00145         else
00146             log_debug("invalid input");
00147     }else{                                              //its text
00148         String value;
00149         switch (this->curLabel)
00150         {
00151             case SENML_CBOR_BN_LABEL: 
00152                 value = buffer;
00153                 this->setCurrentPack(value); 
00154                 break;
00155             case SENML_CBOR_BU_LABEL: 
00156                 value = buffer;
00157                 this->checkBaseUnit(value); 
00158                 break;
00159             case SENML_CBOR_N_LABEL:
00160                 value = buffer;
00161                 this->setCurrentRecord(value); 
00162                 break;
00163             case SENML_CBOR_VS_LABEL:
00164                 this->setValue((void*)buffer, bytes_length, CBOR_TYPE_STRING);
00165                     break;
00166         }
00167     }
00168     return bytes_read + bytes_length;
00169 }
00170 
00171 unsigned int SenMLCborParser::processArray()
00172 {
00173     const bool is_indefinite = (peekChar() == (CBOR_ARRAY | CBOR_VAR_FOLLOWS));
00174     uint64_t array_length = 0;
00175     size_t read_bytes;
00176 
00177     if (is_indefinite){
00178         log_debug("not supported");
00179     }
00180     else
00181         read_bytes = decode_int(&array_length);
00182 
00183     size_t i = 0;
00184 
00185     while (i < array_length) {
00186         size_t inner_read_bytes = this->parseNext();
00187         if (inner_read_bytes == 0) {
00188             log_debug("invalid input");
00189             break;
00190         }
00191         read_bytes += inner_read_bytes;
00192         ++i;
00193     }
00194 
00195     return read_bytes;
00196 }
00197 
00198 
00199 
00200 
00201 
00202 
00203