demo project

Dependencies:   AX-12A Dynamixel mbed iothub_client EthernetInterface NTPClient ConfigFile SDFileSystem iothub_amqp_transport mbed-rtos proton-c-mbed wolfSSL

Utils/IothubSerial.cpp

Committer:
henryrawas
Date:
2016-01-26
Revision:
20:891b5270845a
Parent:
19:2f0ec9ac1238

File content as of revision 20:891b5270845a:

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "mbed.h"
#include "IothubSerial.h"
#include "crt_abstractions.h"

const char* nametemp = "temp";
const char* namevolt = "volt";
const char* namedeg = "rot";
const char* nameload = "load";

IothubSerial::IothubSerial()
{
    _hasPending = false;
}

// try to serialize the measurements into the buffer
// return bytes used or -1 if buffer too small or other error
// current serialization is a json array with ',' at end
//  eg: temp: [22.0, 23.1, 22.3],
int IothubSerial::MeasureGroupToString(const char* name, MeasureGroup& mg, char* buf, int bufsize)
{
    int slen;
    int startlen = bufsize;
    
    slen = sprintf_s(buf, bufsize, "\"%s\": [", name);
    if (slen > 0)
    {
        bufsize -= slen;
        buf += slen;
    }
    else
        return -1;
       
    for (int i = 0; i < mg.NumVals; i++)
    {
        if (i < mg.NumVals - 1)
            slen = sprintf_s(buf, bufsize, "%.2f, ", mg.MeasVals[i]);
        else
            slen = sprintf_s(buf, bufsize, "%.2f ", mg.MeasVals[i]);
        if (slen > 0)
        {
            bufsize -= slen;
            buf += slen;
        }
        else
            return -1;
    }
    
    slen = sprintf_s(buf, bufsize, "],");
    if (slen > 0)
    {
        bufsize -= slen;
        buf += slen;
    }
    else
        return -1;
    
    return startlen - bufsize;
}

int AddTime(time_t seconds, int ms, char* buf, int bufsize)
{
    char tbuf[32];
    strftime(tbuf, 32, "%FT%T", localtime(&seconds));
    int slen = sprintf_s(buf, bufsize, "\"time\": \"%s.%03d\",", tbuf, ms);
    if (slen > 0)
    {
        return slen;
    }
    else
        return -1;
}


// try to serialize a snapshot into the buffer
// return bytes used / -1 if buffer too small / 0 if no data
// current serialization is a json object with time and array per measure
// eg: { "time": "2016-01-23T14:55:02", "temp": [1, 2], "volt": [12.1, 12.2] }
int IothubSerial::MeasureSnapshotToString(MeasureSnapshot& msnap, char* buf, int bufsize)
{
    int slen;
    int startlen = bufsize;

    slen = sprintf_s(buf, bufsize, "{");
    if (slen > 0)
    {
        bufsize -= slen;
        buf += slen;
    }
    else
        return -1;

    slen = AddTime(msnap.Created, msnap.CreatedMs, buf, bufsize);
    if (slen > 0)
    {
        bufsize -= slen;
        buf += slen;
    }
    else
        return -1;

    slen = MeasureGroupToString(nametemp, msnap.Temps, buf, bufsize);
    if (slen > 0)
    {
        bufsize -= slen;
        buf += slen;
    }
    else
        return -1;

    slen = MeasureGroupToString(namedeg, msnap.Positions, buf, bufsize);
    if (slen > 0)
    {
        bufsize -= slen;
        buf += slen;
    }
    else
        return -1;

    slen = MeasureGroupToString(nameload, msnap.Loads, buf, bufsize);
    if (slen > 0)
    {
        bufsize -= slen;
        buf += slen;
    }
    else
        return -1;

    slen = MeasureGroupToString(namevolt, msnap.Volts, buf, bufsize);
    if (slen > 0)
    {
        bufsize -= slen;
        buf += slen;
    }
    else
        return -1;

    // replace final ',' with '}'
    *(buf - 1) = '}';
    
    return startlen - bufsize;
}

// try to serialize one or more measurement snapshots into the buffer
// return bytes used / -1 if buffer too small / 0 if no data
// current serialization is a json array of objects with time and array per measure
// eg: [{ "time": "2016-01-23T14:55:02", "temp": [1, 2], "volt": [12.1, 12.2] }]
int IothubSerial::MeasureBufToString(char* buf, int bufsize)
{
    int slen;
    bool hasdata = false;
    bool copydata = false;
    char* startbuf = buf;
    char* lastcomma = NULL;
    
    slen = sprintf_s(buf, bufsize, "[");
    if (slen > 0)
    {
        bufsize -= slen;
        buf += slen;
    }
    else
        return -1;
 
    if (_hasPending)
    {
        hasdata = true;
        slen = MeasureSnapshotToString(_pending, buf, bufsize);
        if (slen > 0)
        {
            bufsize -= slen;
            buf += slen;
        }
        else
            return -1;          // no room for pending record
        // add comma
        slen = sprintf_s(buf, bufsize, ",");
        if (slen > 0)
        {
            bufsize -= slen;
            buf += slen;
        }
        else
            return -1;
        lastcomma = buf;
        _hasPending = false;
        copydata = true;
    }
    
    while (!MeasureBuf.empty())
    {
        if (!MeasureBuf.pop(_pending))
        {
            break;
        }
        hasdata = true;
        _hasPending = true;
        
        slen = MeasureSnapshotToString(_pending, buf, bufsize);
        if (slen > 0)
        {
            bufsize -= slen;
            buf += slen;
        }
        else
            break;              // no room to serialize, leave pending for next message
        // add comma
        slen = sprintf_s(buf, bufsize, ",");
        if (slen > 0)
        {
            bufsize -= slen;
            buf += slen;
        }
        else
            break;
        _hasPending = false;
        lastcomma = buf;
        copydata = true;
    }
    
    if (!hasdata)
        return 0;               // no data
        
    if (!copydata)
        return -1;              // have data but buffer too small

    // replace final ',' with ']'
    *(lastcomma - 1) = ']';
    
    return lastcomma - startbuf;
}


// try to serialize one or more alerts into the buffer
// return bytes used or -1 if buffer too small or other error. 0 if no data
// Serialize to a json object with time, measurename, value, message, and index of joint
// eg: { "alerttype": "Temperature", "message": "too hot", "measurename", "temp", "index": 2, "value": 79.3, "time": "2016-01-23T14:55:02" }
int IothubSerial::AlertBufToString(char* buf, int bufsize)
{
    int slen;
    bool hasdata = false;
    bool copydata = false;
    int startlen = bufsize;
 
    if (AlertBuf.pop(_pendAlert))
    {
        char tbuf[32];
        (void)strftime(tbuf, 32, "%FT%T", localtime(&_pendAlert.Created));
        hasdata = true;
        slen = sprintf_s(buf, bufsize, "{ \"alerttype\": \"%s\", \"message\": \"%s\", \"measurename\": \"%s\",  \"index\": %d ,  \"value\": %f, \"time\": \"%s\" }", 
                                            _pendAlert.AlertType, _pendAlert.Msg, _pendAlert.MeasureName, _pendAlert.Index, _pendAlert.Value, tbuf);
        if (slen > 0)
        {
            bufsize -= slen;
            buf += slen;
            copydata = true;
        }
    }
    
    if (!hasdata)
        return 0;               // no data
        
    if (!copydata)
        return -1;              // have data but buffer too small


    return startlen - bufsize;
}