PlatformIO Community

Not able to call any function or return anything from other class into a callback method of PubSubClient.h

Platform: Arduino -WiFi-rev2
Framewrok: Arduino
Compiler: AVR-GCC
Build System: PlatformIO

SoW:
Use MQTT protocol. Capture topic and payload to do some operation. The operation which I want to do here is calling a function from other class inside or outside the callback function to do some optiation based on the payload recieved from MQTT broker.

Problem:

  • Not able to call any function inside a callback function of PubSubClient library.
  • Next method I have tried is to assign data to a variable inside the callback method and return them. But didn’t work either, as I am not able to capture the return values outside the fucntion.

Code snippet:

mqtt.cpp: callback method is mentioned as processData

void processData(char* topic, byte* payload, unsigned int length) {
  // This just marks the termination of the char array.
  payload[length] = '\0';
  
  // Dumping the information into the log file
  // *getLogFile() << "Topic received    : " << topic   << std::endl;
  // *getLogFile() << "Message received  : " << payload << std::endl;
  // *getLogFile() << "Length of message : " << length  << std::endl;
  
  Serial.println("Topic received    : " + String(topic));
  Serial.println("Message received  : " + String((char*)(payload))); 
  Serial.println("Length of message : " + String(length));

  // Based on the message received from the broker, we either switch
  // OFF or switch ON the led of the board
  if((strcmp((char *)payload, "START")) == 0) {
    digitalWrite(25, HIGH);
    shields->setMotorMode(START_MOTOR);

        //Debug message
    Serial.println("Comapred Output for START: " + String((strcmp((char *)payload, "START"))));
    Serial.println("Pin Number using getLed Method: ");
   // Serial.println(led->getLedPin());
    
    //Debug message ends

  } else if ((strcmp((char *)payload, "STOP")) == 0) {
    digitalWrite(25, LOW);
    shields->setMotorMode(STOP_MOTOR);
    
    //Debug message
    Serial.println("Comapred Output for STOP: " + String((strcmp((char *)payload, "STOP"))));
    Serial.println("Pin Number using getLed Method: ");
    //Serial.println(led->getLedPin());
    //Debug message ends
  }
  else{
    //digitalWrite(led->getLedPin(), LOW);
    Serial.println("Comapred Output for STOP: " + String((strcmp((char *)payload, "STOP"))));
  }
}

mqtt.cpp: (mqttSetup method)

void Mqtt::setupMqttClient() {
  // *getLogFile() << "Broker address : " << getMqttServerAddress() << std::endl;
  // *getLogFile() << "Port address   : " << getMqttPortAddress()   << std::endl;
  // Connecting the client with the broker 
/*
   *getLogFile() << "Setting up the boards's server configuration for \
connecting with the broker" << std::endl;
*/
  Serial.print("Broker address : ");
  Serial.println(String(getMqttServerAddress()));
  Serial.print("Port address   : ");
  Serial.println(getMqttPortAddress());
  Serial.println("Setting up the boards's server configuration for \
connecting with the broker");

  mqttClient.setServer(getMqttServerAddress(), getMqttPortAddress());

  // Callback for receiving messages from broker
/*
  *getLogFile() << "Setting up the boards's callback function information for \
each message received by the subscriber" << std::endl;
*/
  Serial.println("Setting up the boards's callback function information for \
each message received by the subscriber");

//   mqttClient.setCallback([this] (char* topic, byte* payload,
//                                 unsigned int length) {
//    this->processData (topic, payload, length);
//   });
//
  //void (*ptr)(char*, byte*, unsigned int, Mqtt*) = &processData;
  Serial.println(led->getLedPin());
  void (*ptr)(char*, byte*, unsigned int) = &processData;
  mqttClient.setCallback(ptr);

  // Converting the std::string into char array since setServer
  // accepts only char[]. For some reason, it does not accept
  // char* which we can get using std::string.c_str()
  if (mqttClient.connect(getMqttClientId())) {
    // *getLogFile() << "Connected the subscriber with the broker";
    Serial.println("Connected the subscriber with the broker");

    // Converting the std::string into char array since setServer
    // accepts only char[]. For some reason, it does not accept
    // char* which we can get using std::string.c_str()
    // Subscribe to topic
    mqttClient.subscribe(getMqttTopicName());
    // *getLogFile() << "Subscriber subscribed to the topic " << TOPIC_NAME << std::endl;
    Serial.println("Subscriber subscribed to the topic: " + String(getMqttTopicName()));
  } else {
    Serial.println("Connection failed while connecting the subscriber \
with the broker.");
/*
    *getLogFile() << "Connection failed while connecting the subscriber \
with the broker." << std::endl;
*/
  }
}

The program compiles successfully.

Problem/Error:

shields->setMotorMode(STOP_MOTOR);

This function is from the Motor drive library.

Serial.println(led->getLedPin());

In this method the getLedPin() should return the pinnumber 25 which I have set in the literals. But actually return 49.

So my program is never working as expected.

Help me to find a way to capture the topic and the payoad from the callbackfunction and use it with some other class.

Please upload the program in full to e.g. github or google drive.

Let me check with my Organisation if I can upload the full code.

In the meantime:

Info 1:

Serial.println(led->getLedPin());

This a simple getter fucntion which I have defined. The setter sets the value as 25 as shown below. This method works and give me the value as 25 as expected. But it gives 49 if I call the getter inside the processData. Eventually this getLedPin() was just to test if I can call any other methods from any class to this callback.

//Setter/*
  Function      : setLedPin
  Accepts       : int
  Returns       : None
  Abstraction   : This sets the pin number on which we have connected our LED.
  Modified by   : 24th Feb, 2021 : Ashraful
 */
void Led::setLedPin(int pinNumber) {
  ledPin = pinNumber;
}

/*
  Function      : setSensorPin
  Accepts       : int
  Returns       : None
  Abstraction   : This sets the pin number on which we have connected our sensor.
  Modified by   : 24th Feb, 2021 : Ashraful
 */
void Led::setSensorPin(int pinNumber) {
  sensorPin = pinNumber;
}

/*
  Function      : getLedPin
  Accepts       : int
  Returns       : None
  Abstraction   : This returns the pin number on which we have connected our LED.
  Modified by   : 24th Feb, 2021 : Ashraful
 */
int Led::getLedPin() {
  return ledPin;
}

Info 2:

  void (*ptr)(char*, byte*, unsigned int) = &processData;
  mqttClient.setCallback(ptr);

The signature of setCallback() is set by the PubSubClient.h arduino library. You may refere
https://github.com/knolleary/pubsubclient

If you can write an extremely minimal firmware that just reproduces this problem with the required functions, the better! No need for the full code then.

Ok, Give me some time. Will post it shortly.