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

senml_record.cpp

Committer:
kpniot
Date:
2018-05-19
Revision:
0:a9259748d982

File content as of revision 0:a9259748d982:

/*  _  __  ____    _   _ 
 * | |/ / |  _ \  | \ | |
 * | ' /  | |_) | |  \| |
 * | . \  |  __/  | |\  |
 * |_|\_\ |_|     |_| \_|
 * 
 * (c) 2018 KPN
 * License: MIT License.
 * Author: Jan Bogaerts
 * 
 * record base class 
 */

#include <senml_record.h>
#include <senml_helpers.h>
#include <senml_pack.h>
#include <cbor.h>
#include <senml_logging.h>

SenMLRecord::SenMLRecord(const char* name): _name(name), _unit(SENML_UNIT_NONE), _time(NAN), _updateTime(0)
{
}

SenMLRecord::SenMLRecord(const char* name, SenMLUnit unit): _name(name), _unit(unit), _time(NAN), _updateTime(0)
{
}

bool SenMLRecord::setTime(double value, bool absolute)
{
    SenMLBase* root = this->getRoot();
    if(absolute){
        if(root){
            if(root->isPack()){
                double baseTime = ((SenMLPack*)root)->getBaseTime();
                if(!isnan(baseTime))
                    value -= baseTime;
            }
            else{
                return false;
            }
        }
    }
    else if(root == NULL){
        return false;
    }
    this->_time = value;
    return true;
}

bool SenMLRecord::setUpdateTime(double value, bool absolute)
{
    SenMLBase* root = this->getRoot();
    if(absolute){
        if(root){
            if(root->isPack()){
                double baseTime = ((SenMLPack*)root)->getBaseTime();
                if(!isnan(baseTime))
                    value -= baseTime;
            }
            else{
                return false;
            }
        }
    }
    else if(root == NULL){
        return false;
    }
    this->_updateTime = value;
    return true;
}

void SenMLRecord::contentToJson()
{
    printText("{", 1);
    this->fieldsToJson();
    printText("}", 1);
}

void SenMLRecord::adjustToBaseTime(double prev, double time)
{
    if(!isnan(this->_time)){
        if(!isnan(prev))
        this->_time += prev;
        if(!isnan(time))
            this->_time -= time;
    }
    if(!isnan(this->_updateTime)){
        if(!isnan(prev))
        this->_updateTime += prev;
        if(!isnan(time))
            this->_updateTime -= time;
    }
}

void SenMLRecord::fieldsToJson()
{
    int bnLength = this->_name.length();
    if(bnLength){
        printText("\"n\":\"", 5);
        printText(this->_name.c_str(), bnLength);
        printText("\"", 1);
    }
    if(!isnan(this->_time)){
        printText(",\"t\":", 5);
        printDouble(this->_time, SENML_MAX_DOUBLE_PRECISION);
    }
    if(this->_unit != SENML_UNIT_NONE){
        printText(",\"u\":\"", 6);
        printUnit(this->_unit);
        printText("\"", 1);
    }
    if(this->_updateTime != 0){
        printText(",\"ut\":", 5);
        #ifdef __MBED__
            char buf[10];
            sprintf(buf, "%d", this->_updateTime);
            String val = buf;
        #else
            String val(this->_updateTime);
        #endif
        printText(val.c_str(), val.length());
    }
}

void SenMLRecord::actuate(const void* value, int dataLength, SenMLDataType dataType)
{
    log_debug(this->getName());
    log_debug("no actuator");
}

int SenMLRecord::contentToCbor()
{
    int res = cbor_serialize_map(this->getFieldLength());
    res += this->fieldsToCbor();
    return res;
}

int SenMLRecord::getFieldLength()
{
    int result = 1;                                 //always have 1 item for the value
    if(this->_name.length() > 0) result++;
    if(!isnan(this->_time)) result++;
    if(this->_unit != SENML_UNIT_NONE) result++;
    if(this->_updateTime != 0) result ++;
    return result;
}

int SenMLRecord::fieldsToCbor()
{
    int res = 0;
    if(this->_name.length() > 0){
        res += cbor_serialize_int(SENML_CBOR_N_LABEL);
        res += cbor_serialize_unicode_string(this->_name.c_str());
    }
    if(!isnan(this->_time)){
        res += cbor_serialize_int(SENML_CBOR_T_LABEL);
        res += cbor_serialize_double(this->_time);
    }
    if(this->_unit != SENML_UNIT_NONE){
        res += cbor_serialize_int(SENML_CBOR_U_LABEL);
        res += cbor_serialize_unicode_string(senml_units_names[this->_unit]);
    }
    if(this->_updateTime != 0){
        res += cbor_serialize_int(SENML_CBOR_UT_LABEL);
        res += cbor_serialize_int(this->_updateTime);
    }
    return res;
}