Problem with strcmp

Hello.

Could you please check what is wrong with my code?

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.
byte mac[]    = {  0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
IPAddress ip(192, 168, 0, 100);
IPAddress server(192, 168, 0, 19);


const int w2 = 2;


// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);

// Callback function
void callback(char* topic, byte* payload, unsigned int length) {
    
  //turn the LED ON if the payload is '1' and publish to the MQTT server a confirmation message
  
  if(strcmp(payload[0], "B5") == 0){
    digitalWrite(w2, HIGH);
    client.publish("outTopic", "Light On01"); }
    
  //turn the LED OFF if the payload is '0' and publish to the MQTT server a confirmation message
  if(strcmp(payload[0], "B6") == 0){
    digitalWrite(w2, LOW);
    client.publish("outTopic", "Light Off01");
    }


    
} // void callback


void setup()
{

pinMode(w2, OUTPUT);

  
  Ethernet.begin(mac, ip);
  if (client.connect("arduinoClient")) {
    client.publish("outTopic","Arduino1 on");
    client.subscribe("relays");
  }
}

void loop()
{
  client.loop();
}

Second version of my code

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.
byte mac[]    = {  0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
IPAddress ip(192, 168, 0, 100);
IPAddress server(192, 168, 0, 19);


const int w2 = 2;


// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);

// Callback function
void callback(char* topic, byte* payload, unsigned int length) {
    
  //turn the LED ON if the payload is '1' and publish to the MQTT server a confirmation message
  
  if(strcmp(payload, "B5") == 0){
    digitalWrite(w2, HIGH);
    client.publish("outTopic", "Light On01"); }
    
  //turn the LED OFF if the payload is '0' and publish to the MQTT server a confirmation message
  if(strcmp(payload, "B6") == 0){
    digitalWrite(w2, LOW);
    client.publish("outTopic", "Light Off01");
    }


    
} // void callback


void setup()
{

pinMode(w2, OUTPUT);

  
  Ethernet.begin(mac, ip);
  if (client.connect("arduinoClient")) {
    client.publish("outTopic","Arduino1 on");
    client.subscribe("relays");
  }
}

void loop()
{
  client.loop();
}

Regards

strcmp(payload[0]That should be strcmp(payloadshouldn't it?

Still learning. But if I see something that strikes me as odd, I have to ask about.

Why a "Callback function header" AND a "Callback function" ??

// Callback function header
void callback(char* topic, byte* payload, unsigned int length);

EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);

// Callback function
void callback(char* topic, byte* payload, unsigned int length) {

DangerToMyself:
Why a "Callback function header" AND a "Callback function" ??

What's labeled as a "Callback function header" is normally called a function prototype or forward declaration. If the compiler doesn't already know there will be something named "callback" when it gets to this line:

PubSubClient client(server, 1883, callback, ethClient);

it will throw an error. So the function prototype is a way of telling the compiler that somewhere in the code there is going to be a definition of a function with this signature. You usually don't see these in Arduino sketches because when you compile an .ino file the Arduino IDE has a tool that automatically generates function prototypes for all the function in the sketch. This is intended to make programming more beginner friendly but even with some experience, I find it convenient to not need to write function prototypes. If you do add your own function prototypes to the sketch then the Arduino IDE will not add them. In some rare cases the sketch preprocessor is not smart enough to put the function prototype in the right place and it's required to manually add one to get the code to compile.

I have tried both versions and neither of those works.
After you (AWOL) have pointed out the version of the code I should use I have tested on second server and it is not working.
I can connect to a server, I can publish welcome message

client.publish("outTopic","Arduino1 on");

but then to receive it and making switch the pin on and off is not working

pert:
What's labeled as a "Callback function header" is normally called a ........

Thank you for the very good explanation.

Maybe your payload contains '\r' and/or '\n' at the end. In which case you have to either include them in the second argument or trim them from the first one before comparing.

Try the strstr function to check if the payload contains B5; look up how it exactly works. If it works with that, you know that there is something extra in payload.

And for proper debugging, print each payload's byte as a number and check if it contains the values 10 or 13 (0x0A or 0x0C).

sterretje:
Maybe your payload contains '\r' and/or '\n' at the end. In which case you have to either include them in the second argument or trim them from the first one before comparing.

Try the strstr function to check if the payload contains B5; look up how it exactly works. If it works with that, you know that there is something extra in payload.

And for proper debugging, print each payload's byte as a number and check if it contains the values 10 or 13 (0x0A or 0x0C).

Thank you.
It works with strstr function.
How do I print each payload's byte as a number and check if it contains the values 10 or 13 (0x0A or 0x0C)?

To find some simple mistakes, go into Preferences and turn the warning level up to “All”. Some of those warnings might be unavoidable and benign BUT SOME WILL POINT OUT PROGRAMMING MISTAKES.

First version:

/Users/john/Documents/Arduino/sketch_sep22a/sketch_sep22a.ino: In function 'void callback(char*, byte*, unsigned int)':
/Users/john/Documents/Arduino/sketch_sep22a/sketch_sep22a.ino:25:23: warning: invalid conversion from 'byte {aka unsigned char}' to 'const char*' [-fpermissive]
   if (strcmp(payload[0], "B5") == 0) {
                       ^
In file included from /Users/john/Library/Arduino15/packages/arduino/hardware/avr/1.6.19/cores/arduino/Arduino.h:25:0,
                 from sketch/sketch_sep22a.ino.cpp:1:
/Users/john/Library/Arduino15/packages/arduino/tools/avr-gcc/4.9.2-atmel3.5.4-arduino2/avr/include/string.h:287:12: note: initializing argument 1 of 'int strcmp(const char*, const char*)'
 extern int strcmp(const char *, const char *) __ATTR_PURE__;
            ^
/Users/john/Documents/Arduino/sketch_sep22a/sketch_sep22a.ino:31:23: warning: invalid conversion from 'byte {aka unsigned char}' to 'const char*' [-fpermissive]
   if (strcmp(payload[0], "B6") == 0) {
                       ^
In file included from /Users/john/Library/Arduino15/packages/arduino/hardware/avr/1.6.19/cores/arduino/Arduino.h:25:0,
                 from sketch/sketch_sep22a.ino.cpp:1:
/Users/john/Library/Arduino15/packages/arduino/tools/avr-gcc/4.9.2-atmel3.5.4-arduino2/avr/include/string.h:287:12: note: initializing argument 1 of 'int strcmp(const char*, const char*)'
 extern int strcmp(const char *, const char *) __ATTR_PURE__;
            ^
/Users/john/Documents/Arduino/sketch_sep22a/sketch_sep22a.ino: At global scope:
/Users/john/Documents/Arduino/sketch_sep22a/sketch_sep22a.ino:21:21: warning: unused parameter 'topic' [-Wunused-parameter]
 void callback(char* topic, byte* payload, unsigned int length) {
                     ^
/Users/john/Documents/Arduino/sketch_sep22a/sketch_sep22a.ino:21:56: warning: unused parameter 'length' [-Wunused-parameter]
 void callback(char* topic, byte* payload, unsigned int length) {
                                                        ^
/Applications/Arduino1.8.2.app/Contents/Java/libraries/Ethernet/src/utility/socket.cpp:365:19: warning: unused parameter 's' [-Wunused-parameter]
 void flush(SOCKET s) {
                   ^
/Users/john/Documents/Arduino/libraries/pubsubclient/src/PubSubClient.cpp: In member function 'boolean PubSubClient::subscribe(const char*, uint8_t)':
/Users/john/Documents/Arduino/libraries/pubsubclient/src/PubSubClient.cpp:471:13: warning: comparison is always false due to limited range of data type [-Wtype-limits]
     if (qos < 0 || qos > 1) {
             ^

The first two warnings say you are trying to convert a character (payload[0]) into a pointer. That is the reason your strcmp() doesn’t work.

Your callback() function doesn’t seem to use any of its arguments. That might not be a problem.

The last one point out that it is futile to test if an unsigned variable is <0. Note: If ‘qos’ can only be 0 or 1 you could make it a ‘boolean’ type and let the compiler enforce the limitation.

Simply loop through your payload and print

char payload[] = "Hello world\r\n";

void setup()
{
  Serial.begin(115200);

  Serial.print("'");
  Serial.print(payload);
  Serial.println("'");
  
  Serial.print("strlen = "); Serial.println(strlen(payload));
  for (int cnt = 0; cnt <  strlen(payload); cnt++)
  {
    Serial.println(payload[cnt], DEC);
  }
  Serial.println("====");
}

void loop()
{
}

Note that before and after the printing of the payload as text, the code prints a single quote. Because of the ‘\n’, the single quote after printing the payload appears on a new line; unfortunately the ‘\r’ can’t be caught like that.

Below a simple trim function that removes ‘\r’ and ‘\n’ from the end of a text that you pass. For convenience it returns a pointer to the text so one can use it immediately for a print or a strcmp

/*
  trim CR and LF from end of text
  In: pointer to text to trim
  Returns: pointer to (trimmed) text

  Note:
  this modifies the original text
*/
char *trim(char *txt)
{
  while (txt[strlen(txt) - 1] == '\r' ||
         txt[strlen(txt) - 1] == '\n')
  {
    txt[strlen(txt) - 1] = '\0';
  }
  return txt;
}

And you can use it like

char payload[] = "B5\r\n";

void setup()
{
  Serial.begin(115200);

  Serial.print("'");
  Serial.print(payload);
  Serial.println("'");

  Serial.print("strlen = "); Serial.println(strlen(payload));
  for (int cnt = 0; cnt <  strlen(payload); cnt++)
  {
    Serial.println(payload[cnt], DEC);
  }
  Serial.println("====");

  if(strcmp(trim(payload), "B5") == 0)
  {
    Serial.println("match");
  }
}

void loop()
{
  // put your main code here, to run repeatedly:

}
/*
  trim CR and LF from text
  In: pointer to text to trim
  Returns: pointer to (trimmed) text

  Note:
  this modifies the original text
*/
char *trim(char *txt)
{
  while (txt[strlen(txt) - 1] == '\r' ||
         txt[strlen(txt) - 1] == '\n')
  {
    txt[strlen(txt) - 1] = '\0';
  }
  return txt;
}