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.
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.
.
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.
// 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; };
#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)]
Sketch output when array bounds is exceeded. Array set to 12 entries.
Next:
The Version 2 source code has the max number of name-value pairs set at 10. You will need to increase this.