How to assign JSON payload to buffer

Hi,

I'm new both both to Arduino and C++. Here's a template that I customized to send a JSON payload via MQTT.

#define WARN Serial.println

#define MQTTCLIENT_QOS2 1

#include <SPI.h>
#include <Ethernet.h>
#include <IPStack.h>
#include <Countdown.h>
#include <MQTTClient.h>
#include <Thermistor.h>

Thermistor temp(0);

int arrivedcount = 0;

void messageArrived(MQTT::MessageData& md)
{
MQTT::Message &message = md.message;

Serial.print("Message ");
Serial.print(++arrivedcount);
Serial.print(" arrived: qos ");
Serial.print(message.qos);
Serial.print(", retained ");
Serial.print(message.retained);
Serial.print(", dup ");
Serial.print(message.dup);
Serial.print(", packetid ");
Serial.println(message.id);
Serial.print("Payload ");
Serial.println((char*)message.payload);
}

EthernetClient c; // replace by a YunClient if running on a Yun
IPStack ipstack(c);
MQTT::Client<IPStack, Countdown, 50, 1> client = MQTT::Client<IPStack, Countdown, 50, 1>(ipstack);

byte mac[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; // replace with your device's MAC
const char* topic = "arduino-sample";

void connect()
{
char hostname[] = "iot.eclipse.org";
int port = 1883;

Serial.print("Connecting to ");
Serial.print(hostname);
Serial.print(":");
Serial.println(port);

int rc = ipstack.connect(hostname, port);
if (rc != 1)
{
Serial.print("rc from TCP connect is ");
Serial.println(rc);
}

Serial.println("MQTT connecting");
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.MQTTVersion = 3;
data.clientID.cstring = (char*)"arduino-sample";
rc = client.connect(data);
if (rc != 0)
{
Serial.print("rc from MQTT connect is ");
Serial.println(rc);
}
Serial.println("MQTT connected");

rc = client.subscribe(topic, MQTT::QOS2, messageArrived);
if (rc != 0)
{
Serial.print("rc from MQTT subscribe is ");
Serial.println(rc);
}
Serial.println("MQTT subscribed");
}

void setup()
{
Serial.begin(9600);
Ethernet.begin(mac);
Serial.println("MQTT Hello example");
connect();
}

MQTT::Message message;

void loop()
{
int temperature = temp.getTemp();
if (!client.isConnected())
connect();

arrivedcount = 0;

// Send and receive QoS 1 message
** char charBuf[100]= "Hi";**
** char buf[100];**
** String val = "{";**
** val+="\n";**
** val+=""deviceID": "Arduino01",";**
** val+="\n";**
** val+=""temperature (F)": ";**
** val+=temperature;**
** val+="\n";**
** val+="}";**

** val.toCharArray(charBuf,100);**
** strcpy(buf, "Hello");**
** message.qos = MQTT::QOS1;**
** message.retained = false;**
** message.dup = false;**
__ message.payload = (void*)buf;__
message.payloadlen = strlen(buf)+1;
int rc = client.publish(topic, message);
while (arrivedcount == 0)
{
Serial.println("Waiting for Temperature Reading");
client.yield(5000);
}

delay(10000);
}

I'm trying to assign the JSON payload to "buf" but unless it's a string like "Hello" for strcpy, I'm unable to send anything in the payload.

For example,

if I do strcpy(buf, charBuf); nothing shows up in the payload.

Thanks! for any guidance.

You only need 1 buffer, get rid of the second one, and definitely get rid of the String class. Try this instead of all those string lines:

sprintf( buf, "{\n\"deviceID\": \"Arduino01\",\n\"temperature (F)\": %d\n}", temperature );

Should put the relevant data into buf.

Thanks for the tip! I tried it but it didn't seem to add to the payload:

Here's my code where I added sprintf

void loop()
{ 
 int temperature = temp.getTemp();
 if (!client.isConnected())
   connect();
   
 arrivedcount = 0;

 // Send and receive QoS 0 message
 char buf[200];
// String val = "{";
//        val+="\n";
//        val+="\"deviceID\": \"Arduino01\",";
//        val+="\n";
//        val+="\"temperature (F)\": ";
//        val+=temperature;
//        val+="\n";
//        val+="}";
 
// val.toCharArray(charBuf,100);

 //strcpy(buf, "Temperature is");
 sprintf( buf, "{\n\"deviceID\": \"Arduino01\",\n\"temperature (F)\": %d\n}", temperature );
 message.qos = MQTT::QOS1;
 message.retained = false;
 message.dup = false;
 message.payload = (void*)buf;
 message.payloadlen = strlen(buf)+1;
 int rc = client.publish(topic, message);
 while (arrivedcount == 0)
 {
   Serial.println("Waiting for Temperature Reading");
   client.yield(5000);
 }
 

 delay(10000);
}

This is the result in the serial monitor:

IOT Temperature Demo
Connecting to iot.eclipse.org:1883
MQTT connecting
MQTT connected
MQTT subscribed
Waiting for Temperature Reading
Waiting for Temperature Reading
Waiting for Temperature Reading
Waiting for Temperature Reading

However if I changed the code back to strcpy:

void loop()
{ 
 int temperature = temp.getTemp();
 if (!client.isConnected())
   connect();
   
 arrivedcount = 0;

 // Send and receive QoS 0 message
 char buf[200];
// String val = "{";
//        val+="\n";
//        val+="\"deviceID\": \"Arduino01\",";
//        val+="\n";
//        val+="\"temperature (F)\": ";
//        val+=temperature;
//        val+="\n";
//        val+="}";
 
// val.toCharArray(charBuf,100);

 strcpy(buf, "Temperature is");
 //sprintf( buf, "{\n\"deviceID\": \"Arduino01\",\n\"temperature (F)\": %d\n}", temperature );
 message.qos = MQTT::QOS1;
 message.retained = false;
 message.dup = false;
 message.payload = (void*)buf;
 message.payloadlen = strlen(buf)+1;
 int rc = client.publish(topic, message);
 while (arrivedcount == 0)
 {
   Serial.println("Waiting for Temperature Reading");
   client.yield(5000);
 }
 

 delay(10000);
}

Here's the result in the serial monitor I see in the payload:

OT Temperature Demo
Connecting to iot.eclipse.org:1883
MQTT connecting
MQTT connected
MQTT subscribed
Waiting for Temperature Reading
Message 1 arrived: qos 1, retained 0, dup 0, packetid 1
Payload Temperature is
Waiting for Temperature Reading
Message 1 arrived: qos 1, retained 0, dup 0, packetid 2
Payload Temperature is

Thoughts? Ideas?

Thanks!

#7 below:

http://forum.arduino.cc/index.php/topic,148850.0.html

Modified formatting as suggested.

Any ideas? Tips or alternatives? on the original issue.

Thanks!

Any ideas?

I have the idea that you should Serial.print() buf, to make sure it contains what you think it should.

I have the idea that you should make sure that you can actually send a packet of the size you are trying to.

It isn't necessary to actually send the NULL terminator, it the device on the other end knows that the data is a string. Stop adding one to the length.