Noob question about variables

Sorry for being such a noob. I come from a PHP background where I just assign a variable to be whatever I want and don't have to think much about it.

I'm subscribing to MQTT topics and I need to assign the message payload to a variable. How do I do that? I can print it, but it's obviously grabbing it one byte (bit?) at a time and I don't know how to funnel all that into a variable so I can do math on it.

My messages are all numeric, but not necessarily integers.

Here's my snippet.

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i=0;i<length;i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

How do I get that payload into a variable?

It looks to me that it is already in a variable (an array) called payload[]

But you need to post the complete program so we can understand the context.

...R

It probably is in an array. I just need all those characters to comprise a string. Here's the entire code. Thanks for your help.

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#define DEVICE = "OfficeArduino"
#define DEVICEHELLO "OfficeArduino Connected"
unsigned int setpoint;

byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 221);
IPAddress server(192, 168, 0, 222);

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i=0;i<length;i++) {
    Serial.println((char)payload[i]);
//    setpoint = payload[i];
//    Serial.print("My variable is setpoint and the data is");
//    Serial.println(setpoint);
  }
  Serial.println();
}

EthernetClient ethClient;
PubSubClient client(ethClient);

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("arduinoOffice")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic",DEVICEHELLO);
      // ... and resubscribe
      client.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup()
{
 // disable SD card if one in the slot
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);
  Serial.begin(57600);

  client.setServer(server, 1883);
  client.setCallback(callback);

  Ethernet.begin(mac, ip);
  // Allow the hardware to sort itself out
  delay(1500);
}

void loop()
{
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

I've made some progress. If I change it to...

void callback(char* topic, byte* payload, unsigned int length) {
//  Serial.print("Message arrived [");
//  Serial.print(topic);
//  Serial.print("] ");
  for (int i=0;i<length;i++) {
//    Serial.print((char)payload[i]);
    char *cstring = (char *) payload;
    Serial.println(cstring);
  }
  Serial.println();
}

It works perfectly, except I have a lowercase "c" on the end of all my strings. If I send it 1234, I get 1234c. If I send it ABCD, I get ABCDc. What's going on?

you are not null terminating your C string.

you can try to copy the data into a new array within the function...

void callback(char* topic, byte* payload, unsigned int length) 
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  char* byteArray[length + 1];  // create a char array big enough for byte array plus null terminator
  for (int i = 0; i < length; i++)
  {
    byteArray[i] = char(payload + i); //cast each byte to a char and copy to newArray, this is pointer arithmetic
  }
  byteArray[length] = '\0';  // null terminate the byteArray
  Serial.println(newArray);
}

Thanks for explaining that. I was pulling my hair out. Does this look right? It's working, but I want to make sure it's correct.

void callback(char* topic, byte* payload, unsigned int length) {
  for (int i=0;i<length;i++) {
    payload[length] = '\0';
    char *cstring = (char *) payload;
    Serial.println(cstring);
  }
}

mudmin:
Does this look right?

Doesn't look right to me...

But who knows what this function is intended to do to what...

  char* byteArray[length + 1];  // create a char array big enough for byte array plus null terminator
  for (int i = 0; i < length; i++)
  {
    byteArray[i] = char(payload + i); //cast each byte to a char and copy to newArray, this is pointer arithmetic
  }
  byteArray[length] = '\0';  // null terminate the byteArray
  Serial.println(newArray);

Probably a better idea to print byteArray at the end...

Does this look right? It's working, but I want to make sure it's correct.

It is right ONLY if payload is large enough for you to write an extra character to. There is NO guarantee that that is the case.

Why do you think you need to copy/cast/make payload a string? You can compare arrays, using memcmp() just as easily as you can compare strings using strcmp().