demo project
Dependencies: AX-12A Dynamixel mbed iothub_client EthernetInterface NTPClient ConfigFile SDFileSystem iothub_amqp_transport mbed-rtos proton-c-mbed wolfSSL
Diff: Utils/IothubSerial.cpp
- Revision:
- 18:224289104fc0
- Parent:
- 17:0dbcbd8587fd
- Child:
- 19:2f0ec9ac1238
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Utils/IothubSerial.cpp Sat Jan 23 00:08:30 2016 +0000 @@ -0,0 +1,271 @@ +#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, char* buf, int bufsize) +{ + if (bufsize > 32) + { + int slen = strftime(buf, 32, "\"time\": \"%FT%T\",", localtime(&seconds)); + if (slen > 0) + { + return slen; + } + else + return -1; + } + 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, 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; +} +