This blog covers the major revision of the Telemetry to remove old, now unnecessary code, fix some bugs, further improve error responses, and a stored data structure that makes the parsed JSon data available after the HTTP Response processing is complete.

Ardjson: https://ardjson.codeplex.com

Previous: Ardjson-Part 7b: Programming Details of the JSon Stream Parser


This version is implemented in 1.4 JsonParserGetTelemetrySensorValuesVersion1.4.zip on the Downloads tab at https://ardjson.codeplex.com

UPDATE: The above sketch now has array bounds checking on the name-value array and quick flush of HTTP Response and abort when exceeded.


Discussion

The focus of the Arduino sketches in this sequence of blogs is to retrieve data tables form a Microsoft Azure Mobile Service, as well as to post new data, update existing data and to delete existing data in those tables; commonly called CRUD in database parlance. The sketches were presented as a sequential work in progress. The sketches thus far performed data manipulation over HTTP GET, POST, PATCH and DELETE with a view to only demonstrating this functionality. The target for the HTTP GET sketches was to develop a JSon parser that was efficient with resource starved devices such as the Arduino. This was achieved in Part-7 (and discussed in detail in Part-7b) of this series where the HTTP Response was processed as a stream rather than storing the whole Response upon reception then processing it character by character, In all of the HTTP GET sketches prior to the one presented in this blog, the data interpreted by the parser was extracted by name-value pair, immediately displayed then disposed over. Indeed, for HTTTP GET the same name-value structure was used for all name-value pairs within each record.

 

Features of the New Version of the JSon Parser Sketch

.

    Version 1.4
    File on Downloads Tab 1.4 JsonParserGetTelemetrySensorValuesVersion1.4.zip
    JSon Parser Same Stream Parser as in Part-7 of this sequence, with a couple of small bug fixes/improvements
    Bug Fix: The value part of a Name-Value can be null
    Error Handling If any error occurs, parsing ceases as previous, but now an error number is reported, the source of which can be located in the code.
    Code cleanup 5 Display versions reduced to one: the JSon Stream Parser. The other parser/pretty printer etc code removed.
    Records storage

    All parsed name-value pairs are stored in a one dimensional array. A two dimensional 2-tuple is generated using REC_NO( ) macro for each indicating its record number and name-value index of the pair with the record.

    These records/name-value pairs are available for further processing after the parsing completes.

    1D Name-Values Structure NameValues[ ]
    GET Filter The HTTP GET has a field filter to select only the Sensor and Value fields. The id field is a GUID string which explodes the number of character in the Response and the required storage significantly. This permits many more records to be accommodated in the Record storage. This techniques was discussed in detail in Part-3b on these blogs and is expanded upon in the next blog Part-3c.
    DisplayANameValuePair() function Now takes a record number and name-value pair index as parameters

 

Name-Value Structure:

// Name-value structure. Any record contains one or more of these
// Note encapsulates multiple data types.  
// Need the string version for all types.
struct NameValue
{
  String    Name;
  String    StringValue;
  union 
  {
    boolean   BooleanValue;
    int       IntegerValue;
    float     FloatValue;
  };
  DataType  DType;
};

Relevant Declarations:

#define MAX_NO_NAME_VALUE_PAIRS 30
int numNameValuePairsPerRecord= 4;

//Get the 1D Index to NameValues for NameValue in Records based upon Record number R 
// and Name Value index I within record
#define REC_NO(R,I)   ( numNameValuePairsPerRecord * (R)  + (I) )

//1D Array of name value pairs
NameValue NameValues[MAX_NO_NAME_VALUE_PAIRS]; 

int RecordNo=0;         //Counts number of records, ie when parsing is done = num of records.
int NameValueIndex=0;   //Counts number of name value pairs in each record, ie when done 
                         //is number of name value pairs in each record. (Assumed same for all records.)

Note that numNameValuePairsPerRecord is adjusted in parsing to match the actual number of name-value pairs in each record.

RecordNo contains the number of records after parsing.

For a name-value pair with record number R and indexed I within the record (both zero based indexing) REC_NO(R,I) points to the one dimension index of the name-value pair within NameValues.  That is

Record[x,y]  =  NameValues[REC_NO(x,y)]

 

image

Sketch output when array bounds is exceeded. Array set to 12 entries.


Next: