Reading in a string and passing it to another function (from a function)

I'm trying to read in a MQTT message payload and pass it to another function to charge the color of an LED.

However i'm facing some problems with declaration errors so i'd like to ask for some help

the strPayload is the one being brought in by the void callback() and trying to pass it to singlecolor()

void loop() {
client.loop(); // This will check the callback function to see if there is a message"
}

// This is the MQTT Message checking
void callback(String topic, byte* payload, unsigned int length) {
 Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
 Serial.print("Length is ");
 Serial.print(length);
 Serial.println();
 char *callbackString = (char *) payload;
 callbackString[length] = '\0';    // Adds a terminator to end of string based on length of current payload
 Serial.println(topic);
 //need to convert the payloads from bytes to strings for easy display
 payload[length] = '\0';
 String strPayload = String((char*)payload);
 
 if (topic == "/home/1-ESP8266-OutDoor/OnOff") {
   Serial.println("Matched the if topic is /home/1-ESP8266-OutDoor/OnOff");
 }
 if (topic == "/home/1-ESP8266-OutDoor/Color") {
   Serial.println("Matched the if topic is /home/1-ESP8266-OutDoor/Color");
   Serial.println("The Color is");
   Serial.print(strPayload);
   singlecolor(strPayload);   ////  This is what I cannot seem to conquer.  I can display the strPayload but not pass it to the singlecolor()
 }


// Here is where the problem is

void singlecolor(String strPayload) {  // This isn't working...... Cannot get strPayload pass to function
fill_solid(leds, NUM_LEDS /*number of leds*/, strPayload);
//  Divide the hex by 255/dimmer to dim the lights
//    fill_solid(leds, NUM_LEDS, CRGB::Red)
//    fill_solid(leds+ledstart,ledlen,CHSV(255, 0, 255/dimmer));
// leds %= 128;
FastLED.show();
} // end singlecolor()

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. Just use cstrings - char arrays terminated with 0.

I am a programming phillistine. I would read the data into a global char array and thus avoid the need to pass it as a parameter :)

...R

As Robin suggested, get rid of the String class. In this code:

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

void loop() {
  char buff[40];
  char *ptr;
  int charsRead;

  if (Serial.available()) {
    charsRead = Serial.readBytesUntil('\n', buff, sizeof(buff) - 1);
    buff[charsRead] = NULL;
    callback(buff, ptr, strlen(buff));
  }
}


// This is the MQTT Message checking
void callback(char *topic, char* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  Serial.print("Length is ");
  Serial.print(length);
  Serial.println();
  payload = topic;
  Serial.println(payload);
  //need to convert the payloads from bytes to strings for easy display

  if (strcmp(topic, "/home/1-ESP8266-OutDoor/OnOff") == 0) {
    Serial.println("Matched the if topic is /home/1-ESP8266-OutDoor/OnOff");
  } else {
    if (strcmp(topic, "/home/1-ESP8266-OutDoor/Color") == 0) {

      Serial.println("Matched the if topic is /home/1-ESP8266-OutDoor/Color");
      Serial.println("The Color is");
      Serial.println/home/1-ESP8266-OutDoor/Color(topic);
      singlecolor(topic);   ////  This is what I cannot seem to conquer.  I can display the strPayload but not pass it to the singlecolor()
    }
  }
}
  // Here is where the problem is

  void singlecolor(char *strPayload) {  // This isn't working...... Cannot get strPayload pass to function
    
    Serial.print("In singlecolor() strPayload = ");
    Serial.println(strPayload);
//    fill_solid(leds, NUM_LEDS /*number of leds*/, strPayload);
    //  Divide the hex by 255/dimmer to dim the lights
    //    fill_solid(leds, NUM_LEDS, CRGB::Red)
    //    fill_solid(leds+ledstart,ledlen,CHSV(255, 0, 255/dimmer));
    // leds %= 128;
//    FastLED.show();
  } // end singlecolor()

I can only simulate things since I do not have your hardware setup. However, you should be able to convert your code to C strings and move on from there. To run this, activate the Serial monitor and type in a test string (e.g., /home/1-ESP8266-OutDoor/Color) and click on the Send button.

Hi guys. Thanks for your help

I’m able to see the results of the callback function in the main loop()

I’m not sure if I used the strings part properly but it seems to work.

Does this look right (slimmed down to the crucial parts for ease of view)

char payload_buff[100];

void callback(String topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
char *callbackString = (char *) payload;
  callbackString[length] = '\0';    // Adds a terminator to end of string based on length of current payload
  Serial.println(topic);
  //need to convert the payload from bytes to strings for easy display
  int i = 0;
  for(i=0; i<length; i++) {
    payload_buff[i] = payload[i];
  }
  payload_buff[i] = '\0';
  Serial.println("The payload in the callback function is");
  Serial.println(payload_buff);
}

void setup() {
  // Just doing wifi setup, MQTT connect here
}


void loop() {
  Serial.println("Entering loop()");
  // First make sure MQTT is connected 

// Start MQTT Message Function  //
  client.loop(); // This will check the callback function to see if there is a message"
  Serial.println("After callback function, in main loop, the color is");
  Serial.print(payload_buff);
  Serial.println("------------------------------------");
  delay(3000);


// End of Loop
}

That above does display the same output in the callback function as in the main loop. The output is what I am sending over MQTT (0x283483 or “blue”) so it appears to be working.

This seems to be much easier for me to grasp than passing variables between functions.
Defined the character array globally and can touch/read it anywhere. Not sure if it’s the correct way.

econkack - What does “char *ptr;” do in your code?

The rules say to post the whole of your code. Do so if you want help.

Mark

eeze:
econkack - What does “char *ptr;” do in your code?

It gets assigned to the character array that holds the input you typed into the Serial monitor.

eeze: I'm not sure if I used the strings part properly but it seems to work.

You still seem to be using the String class. Expect your program to crash after a while.

...R

Pulled out the String class. Thanks Robin.

However, I’ve introduced a new issue whereby my comparisons no longer work.

The goal is so that when a message comes in (switch onoff/ color change / something) that I can take action. I’m trying to make this generic so I can use the same code for multiple projects.

I’ve been able to move the byte* payload into an array but I’m not sure how to do a string comparison to say If topic == /home/esps1/Topic1 then do something

I’ve used this with strings and it worked
int strcomparison = strcmp(topic, TopicOnOff);
if (strcomparison == 0) { // Work to be done here

but that doesn’t work with the array.

Do I need to convert the array to a string first

Below is the complete code. I find it easier to just post relevant stippets but I understand those that want to see it all

// Version 0.1 T.S  Setup
// Version 0.2 T.S  Adding MQTT

/////////////////////
// Inclusions      //
/////////////////////
#include <FastLED.h>
#include <PubSubClient.h>
#include <ESP8266WiFi.h>

/////////////////////
//    Definitions  //
/////////////////////

#define NUM_LEDS 300
#define LED_TYPE WS2812B
#define DATA_PIN 4
CRGB leds[NUM_LEDS];

//////////////////////
// WiFi Definitions //
//////////////////////

const char* ssid     = "something";
const char* pass = "something";
char callbackString;

/////////////////////
//     Variables   //
//////////////////////
char payload_buff[100];
char topic_buff[50];

/////////////////////
// MQTT Definitions //
//////////////////////
#define mqtt_server "m22.cloudmqtt.com"
#define mqtt_user "something"
#define mqtt_password "something"
#define TopicOnOff "/home/1-ESP8266-OutDoor/OnOff"
#define TopicColor "/home/1-ESP8266-OutDoor/Color"

///////////////////////
// Other Definitions //
///////////////////////
WiFiClient espClient;
PubSubClient client(espClient);


// This is the MQTT Message Arrival Function which puts messages into topic_buff and payload_buff for action
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived for topic [");
  Serial.print(topic);
  Serial.print("] ");
  Serial.print("with a length of ");
  Serial.print(length);
  Serial.println();
  char *callbackString = (char *) payload;
  callbackString[length] = '\0';    // Adds a terminator to end of string based on length of current payload
  //need to convert the payload from bytes to strings for easy display
  int i = 0;
  for(i=0; i<length; i++) {
    payload_buff[i] = payload[i];
  }
  payload_buff[i] = '\0';
  Serial.print("The payload is ");
  Serial.print(payload_buff);
  int strcomparison = strcmp(topic, TopicOnOff);
  if (strcomparison == 0) { //   Work to be done here
    Serial.println("Matched OnOff Test");
    }
// trying to move the char* to a string for easy comparison and use outside of this function  
//  topic_buff = topic;   
  
  }

  
  /*  //Old Method of String Comparison
  int strcomparison = strcmp(topic, TopicOnOff);
  if (strcomparison == 0) { //   Work to be done here
    Serial.println("Matched OnOff");
    if (length == 2) {
      digitalWrite(D1, HIGH);
      Serial.println("Sending PIN High as message was On");
    }
    if (length == 3) {
      digitalWrite(D1, LOW);
      Serial.println("Sending PIN Low as message was Off");
    }
                         } //end If
                         
  strcomparison = strcmp(topic, TopicColor); //   Work to be done here
  if (strcomparison == 0) {
    Serial.println("Matched Color");
                             } //end If
  */


void colorchange() {
  
}

void setup() {
  // Initial Array
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

  // Start WiFi Connection
  Serial.begin(115200);
  Serial.println("");
  pinMode(D1, OUTPUT);
  WiFi.begin(ssid, pass);
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  //  END WiFi Connection

    //MQTT Connection
   client.setServer(mqtt_server, 15557);  // 15557 is the port given my cloudmqtt
   client.setCallback(callback);
}

void reconnect() {      // This is for the MQTT connection
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    // If you do not want to use a username and password, change next line to
    // if (client.connect("ESP8266Client")) {
    //  //client.connect("clientID", "mqtt_username", "mqtt_password");
    // The clientID must be unique otherwise disconnections will happen!
    if (client.connect("something", mqtt_user, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(TopicOnOff); 
      client.subscribe(TopicColor);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void clearMQTT() {   //  Clear the MQTT Payload
  memset(payload_buff, 0, sizeof(payload_buff));
  memset(topic_buff, 0, sizeof(topic_buff));
}  // End of clearPaylod()


void loop() {
  Serial.println("Entering loop()");
// First make sure MQTT is connected 
  {
  if (!client.connected()) {
    reconnect();
                           }
  }  //Close If
  
// Serial.println("Attempting a client.publish to " TopicOnOff);
// client.publish(TopicTemperature, temperatureString);

// Start MQTT Message Function  //
  Serial.println("Checking for new messages");  
  client.loop(); // This will check the callback function to see if there is a message"
// Taking action on MQTT Messages
  Serial.println("Changing Color");
  colorchange();
// Clearing Array
  Serial.println("Clearing Messages"); 
  clearMQTT();
  Serial.println("-------------End of Loop---------------");
  delay(3000);

// End of Loop
}

strcmp() should work. Have you added a '\0' terminator at the end of the characters in the char array?

...R

Hi Robin,
Thanks for all of your help.

Right now I’m able to pass “something” from the callback function to the loop()

However, when I try to print the topic from callback, i only see

Topic_buff is
/hom

It’s always “/hom”

Despite it actually being /home/1-ESP8266-OutDoor/Color based on the output from serial.println in calback()

Code is the same as I posted in full in a previous reply

char topic_buff[50];
void callback(char* topic, byte* payload, unsigned int length) {
 void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived for topic [");
  Serial.print(topic);
  Serial.print("] ");
  Serial.print("with a length of ");
  Serial.print(length);
  Serial.println();
  char *callbackString = (char *) payload;
  callbackString[length] = '\0';    // Adds a terminator to end of string based on length of current payload
  //need to convert the payload from bytes to strings for easy display
//work on the payload buffer
  int i = 0;
  for(i=0; i<length; i++) {
    payload_buff[i] = payload[i];
  }
  payload_buff[i] = '\0';
  Serial.print("The payload is ");
  Serial.print(payload_buff);
  Serial.println("The length of topic is ");
  Serial.print(sizeof(topic));
// work on the topic buffer
  for(i=0; i<sizeof(topic); i++) {
    topic_buff[i] = topic[i];
  }
  topic_buff[i] = '\0';
  Serial.println();
  Serial.println("End of Callback ");
  strcomparison = strcmp(topic_buff, TopicOnOff);
  if (strcomparison == 0) { //   Work to be done here
    Serial.println("Matched topic Color in Callback");
    }  
  
// trying to move the char* to a string for easy comparison and use outside of this function  
//  topic_buff = topic;   
  
  }  // End of Callback

The topic is always 4 bytes so i’m unable to get it into the string to compare, nor does it seem to display.

Any idea what it would show as 4 always?

— Update. After editing my post, I realized that the sizeof of 4 bytes was correct and that I was limiting by char array to string to just 4 bytes.

Leaving here in case someone else can learn something from my mistake

Still shorter

strcpy(topic_buff, topic);

P.S. I hate it when posted code gets changed.

Whandall: Still shorter

strcpy(topic_buff, topic);

P.S. I hate it when posted code gets changed.

Hi Whandall,

Not sure what you meant about posted code changing? The edit I did on the last message was that my sizeof was a screw up and was always returning 4 bytes. I should have just left 50 in the for loop to read it all in but I didn't change that code.

However, to you great suggestion

strcpy(topic_buff, topic);

Will that copy the actual character array to a string?

if so, sweet m.... that's great. Sure beats a for loop. Or were you suggesting something else?

I don't use strcpy() often so I forget the fine detail. I this was my problem I would write a short 5 or 6 line program to explore how it works.

...R

No, it will copy a zero terminated character array including the delimiter to a character array.

strcpy() ok, the parameters are not documented correctly :frowning:

Hi Guys.

Thank you for all of the help.

before I can do the strncopy() I need to convert the payload byte to a char.

However, i’m stuck at a point where I cannot get my global payload_buff[100] to display when called from the main loop()

It shows up when serial printed in the callback function as On, Off, 12381823 as I set it in a MQTT message but in the loop() it’s nothing at all

Here is the output
I’ve added in (expecting result here) in the 2 spots where there is nothing displayed.


Entering loop()
Checking for new messages
CallBack Function Trigged
Message arrived for topic [/home/1-ESP8266-OutDoor/OnOff] with a length of 2
The char* version of the payload is On
End of Callback

payload_buff is (expecting result here) before fnc_processMQTTmessage
ranCallback is true, processing message
Topic_buff is
payload_buff is (expecting result here)

Clearing message buffers

// Version 0.1 T.S  Setup
// Version 0.2 T.S  Adding MQTT

/////////////////////
// Inclusions      //
/////////////////////
#include <FastLED.h>
#include <PubSubClient.h>
#include <ESP8266WiFi.h>

/////////////////////
//    Definitions  //
/////////////////////

#define NUM_LEDS 300
#define LED_TYPE WS2812B
#define DATA_PIN 4
CRGB leds[NUM_LEDS];

//////////////////////
// WiFi Definitions //
//////////////////////

const char* ssid     = "";
const char* pass = "";
char callbackString;

/////////////////////
//     Variables   //
//////////////////////
char payload_buff[100];
char topic_buff[50];
int strcomparison;
bool ranCallback;
 
/////////////////////
// MQTT Definitions //
//////////////////////
#define mqtt_server "qtt.com"
#define mqtt_user "1-ESP8266-OutDoor"
#define mqtt_password "
#define TopicOnOff "/home/1-ESP8266-OutDoor/OnOff"
#define TopicColor "/home/1-ESP8266-OutDoor/Color"

///////////////////////
// Other Definitions //
///////////////////////
WiFiClient espClient;
PubSubClient client(espClient);


// This is the MQTT Message Arrival Function which puts messages into topic_buff and payload_buff for action
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.println("CallBack Function Trigged");
  Serial.print("Message arrived for topic [");
  Serial.print(topic);
  Serial.print("] ");
  Serial.print("with a length of ");
  Serial.print(length);
  Serial.println();
  // char *callbackString = (char *) payload;
  // callbackString[length] = '\0';    // Adds a terminator to end of string based on length of current payload
                        // This previous code to be removed...
                        //need to convert the payload from bytes to strings for easy display
                        //work on the payload buffer
                         // int i = 0;
                         // for(i=0; i<100; i++) {
                         //  payload_buff[i] = payload[i];
                         //}
                         // payload_buff[i] = '\0';
                         // strncpy ( payload, payload_buff, sizeof(payload) );
                         // Serial.print("The payload is ");
                         // Serial.print(payload_buff);
                         // Serial.println();
                         // Converting the byte* payload into a char array
  char *payload_buff = (char *) payload;
  payload_buff[length] = '\0';
  Serial.print("The char* version of the payload is ");
  Serial.print(payload_buff);
  ranCallback = true;
// Set this so I can process the message
  Serial.println("");
  Serial.println("End of Callback ");
  
// trying to move the char* to a string for easy comparison and use outside of this function  
//  topic_buff = topic;   
  
  }  // End of Callback

  
  /*  //Old Method of String Comparison
  int strcomparison = strcmp(topic, TopicOnOff);
  if (strcomparison == 0) { //   Work to be done here
    Serial.println("Matched OnOff");
    if (length == 2) {
      digitalWrite(D1, HIGH);
      Serial.println("Sending PIN High as message was On");
    }
    if (length == 3) {
      digitalWrite(D1, LOW);
      Serial.println("Sending PIN Low as message was Off");
    }
                         } //end If
                         
  strcomparison = strcmp(topic, TopicColor); //   Work to be done here
  if (strcomparison == 0) {
    Serial.println("Matched Color");
                             } //end If
  */


void fnc_ColorChange() {
  
}

void fnc_OnOff() {
  
}

// This is called by main loop when ranCallback is true
void fnc_processMQTTmessage() {
    Serial.print("Topic_buff is");
    Serial.print(topic_buff);
    Serial.println();
    Serial.print("payload_buff is");
    Serial.print(payload_buff);
    Serial.println();
    // Will execute if the topic is OnOff
    strcomparison = strcmp(topic_buff, TopicOnOff);
    if (strcomparison == 0) { //   Work to be done here
    Serial.println("Matched topic OnoFF, calling function");
     fnc_OnOff();
    }  
// Will execute if the topic is Color
    strcomparison = strcmp(topic_buff, TopicColor);
    if (strcomparison == 0) { //   Work to be done here
    Serial.println("Matched topic Color, calling function");
    fnc_ColorChange();
    }  
}





void setup() {
  // Initial Array
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

  // Start WiFi Connection
  Serial.begin(115200);
  Serial.println("");
  pinMode(D1, OUTPUT);
  WiFi.begin(ssid, pass);
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  //  END WiFi Connection

    //MQTT Connection
   client.setServer(mqtt_server, 15557);  // 15557 is the port given my cloudmqtt
   client.setCallback(callback);
}

void reconnect() {      // This is for the MQTT connection
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    // If you do not want to use a username and password, change next line to
    // if (client.connect("ESP8266Client")) {
    //  //client.connect("clientID", "mqtt_username", "mqtt_password");
    // The clientID must be unique otherwise disconnections will happen!
    if (client.connect("something", mqtt_user, mqtt_password)) {
      Serial.println("connected");
      client.subscribe(TopicOnOff); 
      client.subscribe(TopicColor);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void clearMQTT() {   //  Clear the MQTT Payload
  memset(payload_buff, 0, sizeof(payload_buff));
  memset(topic_buff, 0, sizeof(topic_buff));
}  // End of clearPaylod()


void loop() {
  Serial.println("Entering loop()");
// First make sure MQTT is connected 
  {
  if (!client.connected()) {
    reconnect();           }
  }  //Close If
  
// Serial.println("Attempting a client.publish to " TopicOnOff);
// client.publish(TopicTemperature, temperatureString);

// Start MQTT Message Function  //
    Serial.println("Checking for new messages");  
    client.loop(); // This will check the callback function to see if there is a message"
// Taking action on MQTT Messages if ranCallback is set by client.loop()
    Serial.println();
// This is here to confirm what the payload_buff looks like in loop() before processing - currently not working...
    Serial.print("payload_buff is ");
    Serial.print(payload_buff);
    Serial.print("before fnc_processMQTTmessage");
    if (ranCallback == true) {
    Serial.println();
    Serial.println("ranCallback is true, processing message");
    fnc_processMQTTmessage ();
    }
// Setting ranCallback to False to prevent rerun
    ranCallback = false;
// Clearing Array
   Serial.println(); 
   Serial.println("Clearing message buffers"); 
   clearMQTT();
   Serial.println("-------------End of Loop---------------");
   delay(3000);

// End of Loop
}


}
#define mqtt_password "

Very strange (and it confuses Ctrl-T).

How about something like this (uncompiled)

// This is the MQTT Message Arrival Function which puts messages into topic_buff and payload_buff for action
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.println("CallBack Function Trigged");
  Serial.print("Message arrived for topic [");
  Serial.print(topic);
  Serial.print("] ");
  Serial.print("with a length of ");
  Serial.print(length);
  Serial.println();
  
  byte len = min(strlen(topic), sizeof(topic_buffer) - 1);
  memcpy(topic_buffer, topic, len);
  topic_buffer[len] = 0;

  len = min(length, sizeof(payload_buffer) - 1);
  memcpy(payload_buffer, payload, len);
  payload_buffer[len] = 0;

  ranCallback = true;
  // Set this so I can process the message
  Serial.println("End of Callback ");
}

Hi Whandall,

Apologies for this

define mqtt_password "

It is indeed a double quote there, I just removed my password for privacy reasons.

Any idea why my payload_buff is readily outputted to serial monitor after moving from byte to char* but in the loop() it seems to be cleared? I thought by defining it before setup() means it'll always be available?

When I tried your example, I received this

/Volumes/Storage/Projects/Arduino/My Stuff/OutDoor_MQTT_Sensor_with_LED_V5/OutDoor_MQTT_Sensor_with_LED_V5.ino: In function 'void callback(char*, byte*, unsigned int)': OutDoor_MQTT_Sensor_with_LED_V5:80: error: 'min' was not declared in this scope byte len = min(strlen(topic), sizeof(topic_buff) - 1);

Please excuse my generic and novice questions as I am still a beginner learning.

You could try including Arduino.h

#include <Arduino.h>

I can use min() in a sketch without any includes.

Hey Whandall,

for some reason I could not include Arduino.h

In fact, I couldn't find it in library manager.

However, I replaced min() with _min() and the code compiled. Not sure why. -- Update: Found this related to ESP libraries - https://github.com/esp8266/Arduino/issues/398

After running it with message sent from client it looks like it worked. Thank you!

Here is the output of running the code

Entering loop()
Checking for new messages
CallBack Function Trigged
Message arrived for topic [/home/1-ESP8266-OutDoor/OnOff] with a length of 2
The char* version of the payload is On
End of Callback 

payload_buff is On before fnc_processMQTTmessage inside loop()
ranCallback is true, processing message
Topic_buff is/home/1-ESP8266-OutDoor/OnOff
payload_buff is On
Matched topic OnoFF, calling function

Clearing message buffers
-------------End of Loop---------------

I could have sworn in a previous post I was able to write to a global variable and use it in a function but it seemed to have to just stopped working. I'm at a loss...

Maybe memcopy is the only (i.e working) way?

Lastly, can you help walk me through this. byte len = _min(strlen(topic), sizeof(topic_buff) - 1);

What I think it does

Create a variable that stores bytes named len take the minimum (smallest) of either the string length of topic or the size of "topic_buff" minus 1 once we have that minimum, put it into "len"

Then memcpy(payload_buffer, payload, len); Copy the memory location of payload, grabbing the first "len" bytes and copy it to payload_buffer

Then make the payload_buffer to zero. payload_buffer[len] = 0;

We get the length of the memory to move, which could be the length ot the full string, or what fits into the given buffer, leaving space for the trailing zero byte, move the memory and add the trailing zero byte.

This will not overwrite the buffer even if the passed strings are too long.

If you guarantee that payload is terminated with a zero byte and both strings will never be too big to fit into the buffers, two simple strcpy() calls would work just the same.