JsonParserGeneratorRK Appends random data

I have a function to publish periodic data, for testing I am calling it every second.
I cycle through the channels 0 - 15
When I recieve the data, I see a few extra characters padded on: [�1]

event: inputs
data: {"data":"{\"input\":\"I2\",\"state\":false,\"channel\":1,\"module_name\":\"OE_IOT_1016A\"�1","ttl":60,"published_at":"2018-12-02T15:05:54.624Z","coreid":"2c003f000c47363339343638"}

FUNCTION:

char * module_name = "OE_IOT_1016A";
void publish(String channel, bool status, int i){
    // This creates a buffer to hold up to 256 bytes of JSON data (good for Particle.publish)
    JsonWriterStatic<256> jw;
    //JsonWriter jw;
    
    // Creating a scope like this in {} with a JsonWriterAutoObject in it creates an object,
    // and automatically closes the object when leaving the scope. This is necessary because
    // all JSON values must be in either an object or an array to be valid, and JsonWriter
    // requires all startObject to be balanced with a finishObjectOrArray and JsonWriterAutoObject
    // takes care of doing that automatically.
    {
    	JsonWriterAutoObject obj(&jw);
    
    	// Add various types of data
    	jw.insertKeyValue("input",channel);
    	jw.insertKeyValue("state", status);
    	jw.insertKeyValue("channel", i);
    	jw.insertKeyValue("module_name", module_name);
    	
        Particle.publish("inputs", jw.getBuffer(),60,PRIVATE);
    	 
    }
}

SAMPLE OUTPUT:

event: inputs
data: {"data":"{\"input\":\"I12\",\"state\":false,\"channel\":11,\"module_name\":\"OE_IOT_1016A\"","ttl":60,"published_at":"2018-12-02T15:05:47.621Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I13\",\"state\":false,\"channel\":12,\"module_name\":\"OE_IOT_1016A\"","ttl":60,"published_at":"2018-12-02T15:05:48.621Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I14\",\"state\":false,\"channel\":13,\"module_name\":\"OE_IOT_1016A\"","ttl":60,"published_at":"2018-12-02T15:05:49.622Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I15\",\"state\":false,\"channel\":14,\"module_name\":\"OE_IOT_1016A\"","ttl":60,"published_at":"2018-12-02T15:05:50.624Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I1\",\"state\":false,\"channel\":0,\"module_name\":\"OE_IOT_1016A\"�1","ttl":60,"published_at":"2018-12-02T15:05:53.623Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I2\",\"state\":false,\"channel\":1,\"module_name\":\"OE_IOT_1016A\"�1","ttl":60,"published_at":"2018-12-02T15:05:54.624Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I3\",\"state\":false,\"channel\":2,\"module_name\":\"OE_IOT_1016A\"�1","ttl":60,"published_at":"2018-12-02T15:05:55.624Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I4\",\"state\":false,\"channel\":3,\"module_name\":\"OE_IOT_1016A\"�1","ttl":60,"published_at":"2018-12-02T15:05:56.625Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I5\",\"state\":false,\"channel\":4,\"module_name\":\"OE_IOT_1016A\"�1","ttl":60,"published_at":"2018-12-02T15:05:57.626Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I6\",\"state\":false,\"channel\":5,\"module_name\":\"OE_IOT_1016A\"�1","ttl":60,"published_at":"2018-12-02T15:05:58.625Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I7\",\"state\":false,\"channel\":6,\"module_name\":\"OE_IOT_1016A\"�1","ttl":60,"published_at":"2018-12-02T15:05:59.627Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I8\",\"state\":false,\"channel\":7,\"module_name\":\"OE_IOT_1016A\"\u0010","ttl":60,"published_at":"2018-12-02T15:06:00.626Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I9\",\"state\":false,\"channel\":8,\"module_name\":\"OE_IOT_1016A\"�1","ttl":60,"published_at":"2018-12-02T15:06:01.626Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I10\",\"state\":false,\"channel\":9,\"module_name\":\"OE_IOT_1016A\"1","ttl":60,"published_at":"2018-12-02T15:06:02.627Z","coreid":"2c003f000c47363339343638"}

event: inputs
data: {"data":"{\"input\":\"I11\",\"state\":false,\"channel\":10,\"module_name\":\"OE_IOT_1016A\"","ttl":60,"published_at":"2018-12-02T15:06:03.627Z","coreid":"2c003f000c47363339343638"}

The publish needs to be outside of the JsonWriterAutoObject block. Having that block go out of scope is what closes the object and removes the empty space from the buffer.

{
	JsonWriterAutoObject obj(&jw);

	// Add various types of data
	jw.insertKeyValue("input",channel);
	jw.insertKeyValue("state", status);
	jw.insertKeyValue("channel", i);
	jw.insertKeyValue("module_name", module_name);
}
Particle.publish("inputs", jw.getBuffer(),60,PRIVATE);

Thanks so much, that works !

I am having a similar issue, but outside of the JSON return -

using the example code (modified with my data instead of the sample data) at the bottom, I get the following in the serial print:

test mismatch got {"SentOnce":false,"Data":true,"RPM":35,"Count":2,"Elapsed":0,"Volts":"4.19"}sEM5

what can I do to get rid of the extra characters after the JSON output?

#include "Particle.h"

#include "JsonParserGeneratorRK.h"

const unsigned long TEST_RUN_PERIOD_MS = 10000;
unsigned long lastRun = 0;

void runTest();
bool sentOnce = false;
int rpm = 35;
int count = 2;
int elapsed = 0;
float newVolts = 4.192387754;


void setup() {
	Serial.begin(9600);
}

void loop() {
	if (millis() - lastRun >= TEST_RUN_PERIOD_MS) {
		lastRun = millis();
		runTest();
	}
}

void runTest() {
	// This creates a buffer to hold up to 256 bytes of JSON data (good for Particle.publish)
	JsonWriterStatic<256> jw;

	// Creating a scope like this in {} with a JsonWriterAutoObject in it creates an object,
	// and automatically closes the object when leaving the scope. This is necessary because
	// all JSON values must be in either an object or an array to be valid, and JsonWriter
	// requires all startObject to be balanced with a finishObjectOrArray and JsonWriterAutoObject
	// takes care of doing that automatically.
	{
		JsonWriterAutoObject obj(&jw);

		// Add various types of data
	    //jw.insertKeyValue("a", true);
		//jw.insertKeyValue("b", 1234);
		//jw.insertKeyValue("c", "test");
		jw.insertKeyValue("SentOnce", sentOnce);
		jw.insertKeyValue("Data", true);
		jw.insertKeyValue("RPM", rpm);
		jw.insertKeyValue("Count", count);
		jw.insertKeyValue("Elapsed", elapsed);
		jw.insertKeyValue("Volts", String::format("%.2f",newVolts));
	}

	// Verify the results
	if (strcmp(jw.getBuffer(), "{\"a\":true,\"b\":1234,\"c\":\"test\"}")) {
		Serial.printlnf("test mismatch got %s", jw.getBuffer());
		return;
	}


	Serial.println("test passed!");
}

I just released version 0.0.6 with a fix for that bug (and a new unit test). The buffer should always be null terminated after finishing an object now.

1 Like

Hey @ScruffR - Happy New Year! I noticed your edit - I used the quotes in the box where I write my post, but what you did includes the indents in the code - is that the ... notation? I guess the quotes aren’t quite the right way to include code??
Thx

1 Like

@rickkas7, Great! thanks, I’ll try it out with the new version. Happy New Year :slight_smile:

Correct. The symbols used for preformatted text ( image) are not single quotes ( ' ) but grave accents ( ` ). But instead of entering them manually you can use the image button or Ctrl/Cmd+Shift+C

2 Likes

Hi @rickkas7, I've been giving the new version of your library a try, and I'm still getting some extra characters added, not in the sample code, but in the application I'm building.

The JsonWriter part of the code I'm using is below, and the Serial.printlnf gives the following output - sometimes appending �\ , sometimes \ , and sometimes comes back clean.

{"DATA":true,"RPM":80,"Count":18,"Elapsed":6,"Volts":"4.18","SentOnce":true}�\
{"DATA":true,"RPM":98,"Count":35,"Elapsed":11,"Volts":"4.17","SentOnce":true}\
{"DATA":true,"RPM":98,"Count":35,"Elapsed":11,"Volts":"4.17","SentOnce":true}

void runTest() {
	JsonWriterStatic<256> jw;
	{
	JsonWriterAutoObject obj(&jw);
        jw.insertKeyValue("DATA", true);
		jw.insertKeyValue("RPM", rpm);
		jw.insertKeyValue("Count", count);
		jw.insertKeyValue("Elapsed", elapsed);
		jw.insertKeyValue("Volts", String::format("%.2f",newVolts));
		jw.insertKeyValue("SentOnce", sentOnce);
	}
        Serial.printlnf (jw.getBuffer());
        Udp.beginPacket(remoteIP, remotePort);
        Udp.write(jw.getBuffer());
        Udp.endPacket();
        notificationSendTime = (millis()/1000);
}

Interestingly if I remove this pair:

jw.insertKeyValue("DATA", true);

It appends extra data much less frequently...

Am I doing something that's not allowed in runTest()? The Serial.Printlnf or the UDP lines?

That code should be fine. Are you sure the correct version of the library got picked up? That’s exactly what would happen with the 0.0.5 version of the code. Note that for Particle CLI, Dev, and Workbench the project.properties file has precedence over any local copy of the code in the libs directory.

Here’s the code I tested with on a Photon:

#include "Particle.h"

#include "JsonParserGeneratorRK.h"

const unsigned long TEST_RUN_PERIOD_MS = 2000;
unsigned long lastRun = 0;

void runTest();
bool sentOnce = false;
int rpm = 35;
int count = 2;
int elapsed = 0;
float newVolts = 4.192387754;


void setup() {
	Serial.begin(9600);
}

void loop() {
	if (millis() - lastRun >= TEST_RUN_PERIOD_MS) {
		lastRun = millis();
		runTest();
	}
}

void runTest() {
	// This creates a buffer to hold up to 256 bytes of JSON data (good for Particle.publish)
	JsonWriterStatic<256> jw;

	rpm = rand() % 100;
	elapsed = rand() % 20;
	count = rand() % 20;
	newVolts = 4 + (float) (rand() % 100) / 100;

	// Creating a scope like this in {} with a JsonWriterAutoObject in it creates an object,
	// and automatically closes the object when leaving the scope. This is necessary because
	// all JSON values must be in either an object or an array to be valid, and JsonWriter
	// requires all startObject to be balanced with a finishObjectOrArray and JsonWriterAutoObject
	// takes care of doing that automatically.
	{
		JsonWriterAutoObject obj(&jw);

		// Add various types of data
	    //jw.insertKeyValue("a", true);
		//jw.insertKeyValue("b", 1234);
		//jw.insertKeyValue("c", "test");
		jw.insertKeyValue("DATA", true);
		jw.insertKeyValue("RPM", rpm);
		jw.insertKeyValue("Count", count);
		jw.insertKeyValue("Elapsed", elapsed);
		jw.insertKeyValue("Volts", String::format("%.2f",newVolts));
		jw.insertKeyValue("SentOnce", sentOnce);
	}

	// Verify the results
	Serial.printlnf("got %s", jw.getBuffer());
}

And here’s the serial output:

got {"DATA":true,"RPM":33,"Count":2,"Elapsed":3,"Volts":"4.29","SentOnce":false}
got {"DATA":true,"RPM":0,"Count":12,"Elapsed":8,"Volts":"4.56","SentOnce":false}
got {"DATA":true,"RPM":56,"Count":11,"Elapsed":19,"Volts":"4.51","SentOnce":false}
got {"DATA":true,"RPM":43,"Count":8,"Elapsed":5,"Volts":"4.93","SentOnce":false}
got {"DATA":true,"RPM":30,"Count":9,"Elapsed":6,"Volts":"4.32","SentOnce":false}
got {"DATA":true,"RPM":17,"Count":12,"Elapsed":7,"Volts":"4.68","SentOnce":false}
got {"DATA":true,"RPM":80,"Count":9,"Elapsed":3,"Volts":"4.92","SentOnce":false}
got {"DATA":true,"RPM":64,"Count":11,"Elapsed":9,"Volts":"4.27","SentOnce":false}
got {"DATA":true,"RPM":90,"Count":15,"Elapsed":4,"Volts":"4.20","SentOnce":false}
got {"DATA":true,"RPM":44,"Count":2,"Elapsed":10,"Volts":"4.84","SentOnce":false}
got {"DATA":true,"RPM":63,"Count":10,"Elapsed":1,"Volts":"4.36","SentOnce":false}
got {"DATA":true,"RPM":76,"Count":9,"Elapsed":11,"Volts":"4.97","SentOnce":false}
got {"DATA":true,"RPM":75,"Count":10,"Elapsed":11,"Volts":"4.44","SentOnce":false}
got {"DATA":true,"RPM":34,"Count":9,"Elapsed":5,"Volts":"4.30","SentOnce":false}
got {"DATA":true,"RPM":27,"Count":3,"Elapsed":6,"Volts":"4.34","SentOnce":false}
got {"DATA":true,"RPM":4,"Count":9,"Elapsed":0,"Volts":"4.20","SentOnce":false}
got {"DATA":true,"RPM":56,"Count":12,"Elapsed":12,"Volts":"4.13","SentOnce":false}
got {"DATA":true,"RPM":90,"Count":19,"Elapsed":9,"Volts":"4.05","SentOnce":false}
got {"DATA":true,"RPM":95,"Count":7,"Elapsed":9,"Volts":"4.19","SentOnce":false}
got {"DATA":true,"RPM":97,"Count":16,"Elapsed":4,"Volts":"4.49","SentOnce":false}
got {"DATA":true,"RPM":56,"Count":13,"Elapsed":4,"Volts":"4.45","SentOnce":false}
got {"DATA":true,"RPM":7,"Count":9,"Elapsed":6,"Volts":"4.54","SentOnce":false}
got {"DATA":true,"RPM":52,"Count":3,"Elapsed":5,"Volts":"4.38","SentOnce":false}
got {"DATA":true,"RPM":1,"Count":10,"Elapsed":10,"Volts":"4.37","SentOnce":false}
got {"DATA":true,"RPM":95,"Count":3,"Elapsed":16,"Volts":"4.11","SentOnce":false}
got {"DATA":true,"RPM":27,"Count":6,"Elapsed":2,"Volts":"4.68","SentOnce":false}
got {"DATA":true,"RPM":12,"Count":10,"Elapsed":1,"Volts":"4.80","SentOnce":false}
got {"DATA":true,"RPM":58,"Count":11,"Elapsed":11,"Volts":"4.14","SentOnce":false}
got {"DATA":true,"RPM":47,"Count":17,"Elapsed":4,"Volts":"4.25","SentOnce":false}
got {"DATA":true,"RPM":38,"Count":18,"Elapsed":11,"Volts":"4.87","SentOnce":false}
got {"DATA":true,"RPM":51,"Count":13,"Elapsed":7,"Volts":"4.79","SentOnce":false}
got {"DATA":true,"RPM":95,"Count":10,"Elapsed":10,"Volts":"4.13","SentOnce":false}
got {"DATA":true,"RPM":62,"Count":13,"Elapsed":14,"Volts":"4.47","SentOnce":false}
got {"DATA":true,"RPM":21,"Count":0,"Elapsed":10,"Volts":"4.57","SentOnce":false}
got {"DATA":true,"RPM":78,"Count":3,"Elapsed":6,"Volts":"4.97","SentOnce":false}
got {"DATA":true,"RPM":8,"Count":8,"Elapsed":13,"Volts":"4.38","SentOnce":false}
got {"DATA":true,"RPM":85,"Count":8,"Elapsed":13,"Volts":"4.20","SentOnce":false}
got {"DATA":true,"RPM":11,"Count":7,"Elapsed":6,"Volts":"4.10","SentOnce":false}
got {"DATA":true,"RPM":9,"Count":8,"Elapsed":7,"Volts":"4.03","SentOnce":false}
got {"DATA":true,"RPM":73,"Count":14,"Elapsed":0,"Volts":"4.05","SentOnce":false}
got {"DATA":true,"RPM":83,"Count":10,"Elapsed":12,"Volts":"4.87","SentOnce":false}
got {"DATA":true,"RPM":2,"Count":5,"Elapsed":10,"Volts":"4.10","SentOnce":false}
got {"DATA":true,"RPM":0,"Count":2,"Elapsed":16,"Volts":"4.85","SentOnce":false}
got {"DATA":true,"RPM":60,"Count":4,"Elapsed":7,"Volts":"4.31","SentOnce":false}
got {"DATA":true,"RPM":58,"Count":19,"Elapsed":6,"Volts":"4.00","SentOnce":false}
got {"DATA":true,"RPM":15,"Count":2,"Elapsed":15,"Volts":"4.74","SentOnce":false}
got {"DATA":true,"RPM":61,"Count":2,"Elapsed":6,"Volts":"4.68","SentOnce":false}
got {"DATA":true,"RPM":65,"Count":18,"Elapsed":10,"Volts":"4.23","SentOnce":false}
got {"DATA":true,"RPM":89,"Count":19,"Elapsed":6,"Volts":"4.30","SentOnce":false}
got {"DATA":true,"RPM":55,"Count":13,"Elapsed":12,"Volts":"4.74","SentOnce":false}
got {"DATA":true,"RPM":95,"Count":13,"Elapsed":10,"Volts":"4.55","SentOnce":false}
got {"DATA":true,"RPM":30,"Count":5,"Elapsed":15,"Volts":"4.05","SentOnce":false}
got {"DATA":true,"RPM":94,"Count":13,"Elapsed":8,"Volts":"4.53","SentOnce":false}
got {"DATA":true,"RPM":74,"Count":1,"Elapsed":0,"Volts":"4.56","SentOnce":false}
got {"DATA":true,"RPM":44,"Count":0,"Elapsed":3,"Volts":"4.37","SentOnce":false

Hi @rickkas7 - Hmmm, yes, the included library is 0.0.6, I haven’t really gotten up to speed with Workbench, so this was flashed from the web IDE. The code is running on an Argon, not sure if that would make a difference.

I didn’t have #include “Particle.h”, but have now put that in without making any noticeable difference.

This project has a reel with two magnets on it that is monitored by a hall effect sensor. The Sensor then triggers an interrupt handler where I set a flag. That flag is checked in loop(), and if true, it then sends a UDP message, and a Serial.printlnf(). I also send some Particle.publishes, but have commented them out to eliminate them as a factor in my issues. This is repeated every 5 secs as long as the flag is true.

Complete code below,

#include "Particle.h"
// This #include statement was automatically added by the Particle IDE.
#include <JsonParserGeneratorRK.h>


int LEDPin = D7;
int sensorPin = A2;
int count = 0;
bool active;
bool sentOnce = false;
int interruptTime = 0;
int oldInterruptTime;
int elapsedTimeBetween;
int LEDOn;
int printTime;
int rpm = 0;
int oldRpm;
int old_time = 0;
double voltage;
int startTime;
int notificationSendTime;
int secondsBetweenPublishes = 5;
char dataString[50];
int elapsed = 0;
int inactiveDelay = 5;
double newVolts = 0;
char * UDPString;
// UDP support
UDP Udp;
// Note: remoteIP is a multicast address, it should begin with 239.x.x.x or some other
// appropriate multicast address.
// It's not the same as your local IP address (192.168.x.x, for example)!
IPAddress remoteIP(239,1,1,234);
// The remote port must be otherwise unused on any machine that is receiving these packets
int remotePort = 7234;


void setup() {
    Udp.begin(0);
    pinMode(LEDPin, OUTPUT);
    pinMode(sensorPin, INPUT_PULLUP);
    pinMode(BATT, INPUT);
    pinMode(D3, INPUT_PULLUP);
    attachInterrupt(sensorPin, interruptCode, CHANGE);
    Particle.variable("voltage", voltage);
    Particle.variable("RPM", rpm);
    Particle.variable("count", count);
    Particle.function("getData", getData);
    oldInterruptTime = millis();
    Serial.begin();
}

void loop() {
    checkIfNotificationNeeded();
    LEDHandler();
    setRPM();
    oldInterruptTime = interruptTime;
}

void interruptCode() {
        active = true;
        interruptTime = millis();
        elapsedTimeBetween = (interruptTime - oldInterruptTime);
        rpm = (30*1000/elapsedTimeBetween);
        count ++;
}

void checkIfNotificationNeeded() {
    if (millis() < (interruptTime + 2000)) {
        if (!sentOnce) {
            runTest();
            sendProwlNotification();
            sentOnce = TRUE;
        }
        else {
            if ((millis()/1000) > (notificationSendTime + secondsBetweenPublishes)) {
                runTest();
                publishData();
            }
        }
    }
}

void LEDHandler() {
    if (active == true)  {
        digitalWrite(LEDPin, HIGH);
        LEDOn = millis();
        active = false;
    }
    if ((millis() - LEDOn) > 100) {
        digitalWrite(LEDPin, LOW);    
    }
    if (millis() > (interruptTime + (inactiveDelay * 1000))) {
        sentOnce = false;
        RGB.control(false);
        startTime = (millis() / 1000);
    }
    elapsed = ((millis() / 1000) - startTime);
}   

void setRPM() {
     if (millis() > (printTime + 5000)) {
        getBatteryInfo();
        if (millis() > (interruptTime + 5000)) { rpm = 0; }
        if (rpm != oldRpm) {
            Serial.println(rpm);
            //Particle.publish("RPM", String(rpm), 60, PRIVATE);
            oldRpm = rpm;
        }
        printTime = millis();
    }
}

void getBatteryInfo() {
    newVolts = (int((analogRead(BATT) * 0.0011224) * 100.0)/100.0);
    if ((newVolts > voltage + .02) || (newVolts < voltage - .02)) {
            Serial.println(newVolts);
        //Particle.publish("voltage", String::format("%.2f",newVolts), PRIVATE);
        voltage = newVolts;
        printTime = millis();
    }
}

void sendProwlNotification() {
    startTime = (millis() / 1000);
    ledColorRed();
    //Particle.publish("fishAlert","GOT ONE! GO GET IT!",60,PRIVATE);
    notificationSendTime = (millis()/1000);
}

void publishData() {
    //snprintf(dataString, 50, "%d, %d, %d", voltage, rpm, elapsed);
    snprintf(dataString, 50, "%.2f, %i, %i, %i", voltage, rpm, elapsed, count);
    //Particle.publish("Data", dataString, 60, PRIVATE);
    
}

int getData(String command) {
    publishData();
    return elapsed;
}

void ledColorRed() {
    RGB.control(true);
    RGB.color(250,0,0);
}

void runTest() {
	JsonWriterStatic<256> jw;
	{
		JsonWriterAutoObject obj(&jw);
		jw.insertKeyValue("DATA", true);
		jw.insertKeyValue("RPM", rpm);
		jw.insertKeyValue("Count", count);
		jw.insertKeyValue("Elapsed", elapsed);
		jw.insertKeyValue("Volts", String::format("%.2f",newVolts));
		jw.insertKeyValue("SentOnce", sentOnce);
	}
        Serial.printlnf (jw.getBuffer());
        Udp.beginPacket(remoteIP, remotePort);
        Udp.write(jw.getBuffer());
        Udp.endPacket();
        notificationSendTime = (millis()/1000);
}

In the web IDE try removing the JsonParserGeneratorRK library and then adding it back to the project. You can also try clearing the browser cache.

Hi @ninjatill, I did that, and I did see the included library change from 0.0.5 to 0.0.6, so I am pretty sure I have the latest included in the binary.

It may not end up being an issue for me, it just bugs me to see the extra data, and I’m afraid it could have some unanticipated consequences. On my UDP monitor program, if the appended chars are ‘�’ , it interprets it as a null string, but in Serial.printlnf() it shows the string with the extra chars. I’m in the process of adding the code to parse the Json data received by UDP on another Argon, and if that can parse the data without issue then it’s not really problematic.

Fingers crossed!

1 Like

I don’t see how that can be happening, but you can probably would around it by adding:

jw.getBuffer()[jw.getOffset()] = 0;

before the Serial.printn.

@rickkas7 , I just added the line above and haven’t seen the extra characters since. Yay!

That has cleared up the problem I was having getting the json data received thru UDP into the parser, and now I’m able to work with the data on the receiving Argon. Whew! Making progress, thanks to the forum assistance.

Thank you to all who have given me much needed help!

J

Sorry to waken this thread but I didn’t want to create a new thread. I am trying to build a sketch on a xenon 0.9.0 using JSONParserGeneratorRK 0.6.0 - I thought I had copied faithfully the parser example into my app.

Build errors here -

I am clearly missing something obvious to make this compile.

The top of the code is

#include "Particle.h"
#include "JsonParserGeneratorRK.h"
//
SYSTEM_THREAD(ENABLED);
STARTUP(setup_io());
//
void runTest();
// Global parser that supports up to 255 bytes of data and 10 tokens
JsonParserStatic<255, 10> parser;
void runTest()
{
	parser.clear();                            	//Clear the parser state
	parser.addString(beat);                        //Add the string command, and parse it
	if (parser.parse())
	{
    	char thisNodeID[25];
    	if (!parser.getOuterValueByKey("DID", thisNodeID)) {Serial.println("failed to get nodeID");}
    	char thisNom[2];
    	if (!parser.getOuterValueByKey("NOM", thisNom)) {Serial.println("failed to get isNominal");}
    	float floatValue;
    	if (!parser.getOuterValueByKey("BV", floatValue)) {Serial.println("failed to get BV");}
    	int thisSoC;
    	if (!parser.getOuterValueByKey("SOC", thisSoC)) {Serial.println("failed to get State of Charge");}
    	char thisPWR[2];
    	if (!parser.getOuterValueByKey("PWR", thisPWR)) {Serial.println("failed to get Powered");}
    	char thisCHG[2];
    	if (!parser.getOuterValueByKey("CHG", thisCHG)) {Serial.println("failed to get Charging");}
	    //bool boolValue;
	    //if (!parser.getOuterValueByKey("TST", boolValue)) {Serial.println("failed to get bool value");}
	}
	else
	{
		Serial.println("parsing failed heartbeat command");
	}
    
}

runTest() is called from within loop();

Pardon the simple question, but did you import the library into the project or just copy and paste the example? I don’t see the “this was automatically added…” message above your includes.

33

I always cut that comment out.

1 Like

You can’t retrieve data into a char array like that.

This should work:

String thisNodeID;
if (!parser.getOuterValueByKey("DID", thisNodeID)) {Serial.println("failed to get nodeID");}

Since thisNodeID goes out of scope when the function exits it shouldn’t lead to much heap fragmentation and should be fine.

However, if you really want to avoid heap allocation, you can use this construct. It’s necessary so the library knows how big your buffer is to avoid corrupting memory if the JSON contains more data than will fit.

char thisNodeID[25];
JsonParserString container(thisNodeID, sizeof(thisNodeID));
if (!parser.getOuterValueByKey("DID", container)) {Serial.println("failed to get nodeID");}
2 Likes

Thanks - any specific reason you implemented the interface using String object?