KPN IoT / senml

Fork of kpn_senml by KPN IoT

Committer:
kpniot
Date:
Sat May 19 17:35:20 2018 +0000
Revision:
0:a9259748d982
first commit

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 * felper functions
kpniot 0:a9259748d982 12 */
kpniot 0:a9259748d982 13
kpniot 0:a9259748d982 14 #include <senml_helpers.h>
kpniot 0:a9259748d982 15
kpniot 0:a9259748d982 16 #ifdef ESP32
kpniot 0:a9259748d982 17 #include <base64.h>
kpniot 0:a9259748d982 18 #include <arduino.h> //needed for sprintf
kpniot 0:a9259748d982 19 #elif __MBED__
kpniot 0:a9259748d982 20 #include <base64.h>
kpniot 0:a9259748d982 21 int base64_enc_len(int plainLen) {
kpniot 0:a9259748d982 22 int n = plainLen;
kpniot 0:a9259748d982 23 return (n + 2 - ((n + 2) % 3)) / 3 * 4;
kpniot 0:a9259748d982 24 }
kpniot 0:a9259748d982 25 #else
kpniot 0:a9259748d982 26 #include <Base64.h>
kpniot 0:a9259748d982 27 #endif
kpniot 0:a9259748d982 28
kpniot 0:a9259748d982 29
kpniot 0:a9259748d982 30
kpniot 0:a9259748d982 31 //global reference to the stream and stream configuration. This should save us memory
kpniot 0:a9259748d982 32 //by not having to pass these values continuously on the stack.
kpniot 0:a9259748d982 33 StreamContext* _streamCtx = NULL;
kpniot 0:a9259748d982 34
kpniot 0:a9259748d982 35 void printDouble(double f, unsigned int digits)
kpniot 0:a9259748d982 36 {
kpniot 0:a9259748d982 37 #ifdef __MBED__
kpniot 0:a9259748d982 38 char s[30];
kpniot 0:a9259748d982 39 sprintf(s, "%f", f);
kpniot 0:a9259748d982 40 printText(s, strlen(s));
kpniot 0:a9259748d982 41 #else
kpniot 0:a9259748d982 42 String temp(f, digits);
kpniot 0:a9259748d982 43 const char* s = temp.c_str();
kpniot 0:a9259748d982 44 int length = temp.length();
kpniot 0:a9259748d982 45
kpniot 0:a9259748d982 46 for(int i = length -1; i >0; i--){ //remove unwanted trailing 0
kpniot 0:a9259748d982 47 if(s[i] != '0'){
kpniot 0:a9259748d982 48 length = i;
kpniot 0:a9259748d982 49 if(s[i] == '.') //if we end on something like x. then add a last 0, so that it becomes x.0
kpniot 0:a9259748d982 50 length++;
kpniot 0:a9259748d982 51 break;
kpniot 0:a9259748d982 52 }
kpniot 0:a9259748d982 53 }
kpniot 0:a9259748d982 54 printText(s, length + 1);
kpniot 0:a9259748d982 55 #endif
kpniot 0:a9259748d982 56 }
kpniot 0:a9259748d982 57
kpniot 0:a9259748d982 58
kpniot 0:a9259748d982 59
kpniot 0:a9259748d982 60 void printBinaryAsBase64(const unsigned char* data, unsigned int length)
kpniot 0:a9259748d982 61 {
kpniot 0:a9259748d982 62 #ifdef ESP32
kpniot 0:a9259748d982 63 String encoded = base64::encode((uint8_t*)data, length);
kpniot 0:a9259748d982 64 printText(encoded.c_str(), encoded.length());
kpniot 0:a9259748d982 65 #else
kpniot 0:a9259748d982 66 int encodedLen = base64_enc_len(length);
kpniot 0:a9259748d982 67 char encoded[encodedLen];
kpniot 0:a9259748d982 68
kpniot 0:a9259748d982 69 #ifdef __MBED__
kpniot 0:a9259748d982 70 // todo: check result of function
kpniot 0:a9259748d982 71 size_t olen;
kpniot 0:a9259748d982 72 mbedtls_base64_encode((unsigned char*)encoded, encodedLen, &olen, data, length);
kpniot 0:a9259748d982 73 #else
kpniot 0:a9259748d982 74 // note input is consumed in this step: it will be empty afterwards
kpniot 0:a9259748d982 75 base64_encode(encoded, (char*)data, length);
kpniot 0:a9259748d982 76 #endif
kpniot 0:a9259748d982 77 printText(encoded, encodedLen);
kpniot 0:a9259748d982 78 #endif
kpniot 0:a9259748d982 79 }
kpniot 0:a9259748d982 80
kpniot 0:a9259748d982 81 void printUnit(SenMLUnit unit)
kpniot 0:a9259748d982 82 {
kpniot 0:a9259748d982 83 if(unit != SENML_UNIT_NONE)
kpniot 0:a9259748d982 84 printText(senml_units_names[unit], strlen(senml_units_names[unit]));
kpniot 0:a9259748d982 85 }
kpniot 0:a9259748d982 86
kpniot 0:a9259748d982 87 void printText(const char* value, int len)
kpniot 0:a9259748d982 88 {
kpniot 0:a9259748d982 89 char hexTable[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
kpniot 0:a9259748d982 90
kpniot 0:a9259748d982 91 if(_streamCtx->dataAsBlob){
kpniot 0:a9259748d982 92 if(_streamCtx->format == SENML_RAW){
kpniot 0:a9259748d982 93 for(int i = 0; i < len; i++){
kpniot 0:a9259748d982 94 if(_streamCtx->data.blob.curPos >= _streamCtx->data.blob.length) return; //if we reached the end of the buffer, stop rendering otherwise we overwrite some other mem which is not good.
kpniot 0:a9259748d982 95 _streamCtx->data.blob.data[_streamCtx->data.blob.curPos++] = value[i];
kpniot 0:a9259748d982 96 }
kpniot 0:a9259748d982 97 }
kpniot 0:a9259748d982 98 else{
kpniot 0:a9259748d982 99 for(int i = 0; i < len; i++){
kpniot 0:a9259748d982 100 if(_streamCtx->data.blob.curPos >= _streamCtx->data.blob.length) return; //if we reached the end of the buffer, stop rendering otherwise we overwrite some other mem which is not good.
kpniot 0:a9259748d982 101 _streamCtx->data.blob.data[_streamCtx->data.blob.curPos++] = hexTable[value[i] / 16];
kpniot 0:a9259748d982 102 _streamCtx->data.blob.data[_streamCtx->data.blob.curPos++] = hexTable[value[i] % 16];
kpniot 0:a9259748d982 103 }
kpniot 0:a9259748d982 104 }
kpniot 0:a9259748d982 105 }
kpniot 0:a9259748d982 106 else{
kpniot 0:a9259748d982 107 if(_streamCtx->format == SENML_RAW){
kpniot 0:a9259748d982 108 #ifdef __MBED__
kpniot 0:a9259748d982 109 for(int i = 0; i < len; i++)
kpniot 0:a9259748d982 110 _streamCtx->data.stream->putc(value[i]);
kpniot 0:a9259748d982 111 #else
kpniot 0:a9259748d982 112 _streamCtx->data.stream->write(value, len);
kpniot 0:a9259748d982 113 #endif
kpniot 0:a9259748d982 114 }
kpniot 0:a9259748d982 115 else if (_streamCtx->format == SENML_HEX){
kpniot 0:a9259748d982 116 for(int i = 0; i< len; i++){
kpniot 0:a9259748d982 117 #ifdef __MBED__
kpniot 0:a9259748d982 118 _streamCtx->data.stream->putc(hexTable[value[i] / 16]);
kpniot 0:a9259748d982 119 _streamCtx->data.stream->putc(hexTable[value[i] % 16]);
kpniot 0:a9259748d982 120 #else
kpniot 0:a9259748d982 121 _streamCtx->data.stream->print(hexTable[value[i] / 16]);
kpniot 0:a9259748d982 122 _streamCtx->data.stream->print(hexTable[value[i] % 16]);
kpniot 0:a9259748d982 123 #endif
kpniot 0:a9259748d982 124 }
kpniot 0:a9259748d982 125 }
kpniot 0:a9259748d982 126 }
kpniot 0:a9259748d982 127 }
kpniot 0:a9259748d982 128
kpniot 0:a9259748d982 129 static bool peeked = false; //if we peek the stream in HEX format, we actually need to read 2 bytes, so the peek doesn't work, but we need to read the actual value.
kpniot 0:a9259748d982 130 static int peekVal = 0; //these values are removed by the compiler if no cbor is used.
kpniot 0:a9259748d982 131
kpniot 0:a9259748d982 132 int readChar(){
kpniot 0:a9259748d982 133 if(peeked == true){
kpniot 0:a9259748d982 134 peeked = false;
kpniot 0:a9259748d982 135 return peekVal;
kpniot 0:a9259748d982 136 }
kpniot 0:a9259748d982 137 int res;
kpniot 0:a9259748d982 138 if(_streamCtx->dataAsBlob){
kpniot 0:a9259748d982 139 if(_streamCtx->data.blob.curPos < _streamCtx->data.blob.length) //peekchar has to return -1 if there is no more data, so check for this.
kpniot 0:a9259748d982 140 res = _streamCtx->data.blob.data[_streamCtx->data.blob.curPos++];
kpniot 0:a9259748d982 141 else
kpniot 0:a9259748d982 142 return -1;
kpniot 0:a9259748d982 143 if(_streamCtx->format == SENML_HEX){
kpniot 0:a9259748d982 144 int resB = _streamCtx->data.blob.data[_streamCtx->data.blob.curPos++];
kpniot 0:a9259748d982 145 res = (res > '9')? (res &~ 0x20) - 'A' + 10: (res - '0');
kpniot 0:a9259748d982 146 resB = (resB > '9')? (resB &~ 0x20) - 'A' + 10: (resB - '0');
kpniot 0:a9259748d982 147 res = (res * 16) + resB;
kpniot 0:a9259748d982 148 }
kpniot 0:a9259748d982 149 }
kpniot 0:a9259748d982 150 else { //data is comming from the stream, this already returns -1 if there is no data.
kpniot 0:a9259748d982 151 if(_streamCtx->format == SENML_RAW){
kpniot 0:a9259748d982 152 #ifdef __MBED__
kpniot 0:a9259748d982 153 res = _streamCtx->data.stream->getc();
kpniot 0:a9259748d982 154 #else
kpniot 0:a9259748d982 155 res = _streamCtx->data.stream->available() ? _streamCtx->data.stream->read() : -1; //arduino stream, check if something is available, if not, we can't read anymore.
kpniot 0:a9259748d982 156 #endif
kpniot 0:a9259748d982 157 }
kpniot 0:a9259748d982 158 else{
kpniot 0:a9259748d982 159 int resB;
kpniot 0:a9259748d982 160 #ifdef __MBED__
kpniot 0:a9259748d982 161 res = _streamCtx->data.stream->getc();
kpniot 0:a9259748d982 162 resB = _streamCtx->data.stream->getc();
kpniot 0:a9259748d982 163 #else
kpniot 0:a9259748d982 164
kpniot 0:a9259748d982 165 if(_streamCtx->data.stream->available())
kpniot 0:a9259748d982 166 res = _streamCtx->data.stream->read();
kpniot 0:a9259748d982 167 else
kpniot 0:a9259748d982 168 return -1;
kpniot 0:a9259748d982 169 if(_streamCtx->data.stream->available())
kpniot 0:a9259748d982 170 resB = _streamCtx->data.stream->read();
kpniot 0:a9259748d982 171 else
kpniot 0:a9259748d982 172 return -1;
kpniot 0:a9259748d982 173 #endif
kpniot 0:a9259748d982 174 res = (res > '9')? (res &~ 0x20) - 'A' + 10: (res - '0');
kpniot 0:a9259748d982 175 resB = (resB > '9')? (resB &~ 0x20) - 'A' + 10: (resB - '0');
kpniot 0:a9259748d982 176 res = (res * 16) + resB;
kpniot 0:a9259748d982 177 }
kpniot 0:a9259748d982 178 }
kpniot 0:a9259748d982 179 return res;
kpniot 0:a9259748d982 180 };
kpniot 0:a9259748d982 181
kpniot 0:a9259748d982 182 int peekChar(){
kpniot 0:a9259748d982 183 if(peeked == true) //if already peeked, return the currently buffered value.
kpniot 0:a9259748d982 184 return peekVal;
kpniot 0:a9259748d982 185 peekVal = readChar();
kpniot 0:a9259748d982 186 if(peekVal != -1) //if no more data, don't try to buffer it, some new data might arrive later on
kpniot 0:a9259748d982 187 peeked = true;
kpniot 0:a9259748d982 188 return peekVal;
kpniot 0:a9259748d982 189 };
kpniot 0:a9259748d982 190
kpniot 0:a9259748d982 191 void flush(){
kpniot 0:a9259748d982 192 peeked = false;
kpniot 0:a9259748d982 193 }
kpniot 0:a9259748d982 194
kpniot 0:a9259748d982 195
kpniot 0:a9259748d982 196