knolleary / pubsubclient

A client library for the Arduino Ethernet Shield that provides support for MQTT.
http://pubsubclient.knolleary.net/
MIT License
3.78k stars 1.46k forks source link

suggestions for the 'callback' was not declared in this scope error please? #860

Open MoeCHe opened 3 years ago

MoeCHe commented 3 years ago

Hello, Thank you for sharing your work When compiling the attached file, " 'callback' was not declared in this scope " error shows up. I also get a note as " note: suggested alternative: 'calloc' ". I have version 2.8 of the library installed. I would appreciate if you explain to me what's the problem and how to solve it. Btw when I replace "callback" with "calloc", the code compiles fine but I am just not sure if "calloc" does the same job.

Gateway_Ethernet.zip

knolleary commented 3 years ago

Sorry, I cannot unzip that file to see what it contains. It actually looks like a rar file - I don't have anything locally installed to handle rar files. Rather than spend my time doing that, can you share a normal zip file or better yet, just share the relevant piece of code rather than your full project.

MoeCHe commented 3 years ago

sure thing, thank you for fast response.

/*
Author:  Eric Tsai
License:  CC-BY-SA, https://creativecommons.org/licenses/by-sa/2.0/
Date:  7-21-2014
File: Ethernet_Gateway.ino
This sketch takes data struct from I2C and publishes it to
mosquitto broker.

Modifications Needed:
1)  Update mac address "mac[]"
2)  Update MQTT broker IP address "server[]"
*/

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

//I2C receive device address
const byte MY_ADDRESS = 42;    //I2C comms w/ other Arduino

//Ethernet
byte mac[]    = {  0x90, 0xA2, 0xDA, 0x0D, 0x11, 0x11 };
byte server[] = { 192, 168, 1, 51 };  //your MQTT broker IP address

//IPAddress ip(192,168,2,61);
EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);
unsigned long keepalivetime=0;
unsigned long MQTT_reconnect=0;

//use LED for indicating MQTT connection status.
int led = 13;
bool conn_ok;

void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
}

void setup() 
{
  //ethernet
  //Ethernet.begin(mac, ip);
  Wire.begin (MY_ADDRESS);
  Serial.begin (9600);

  Serial.println("starting");

  pinMode(led, OUTPUT);

  //wait for IP address

  while (Ethernet.begin(mac) != 1)

  {
    Serial.println("Error getting IP address via DHCP, trying again...");
    delay(3000);
  }

  //Ethernet.begin(mac, ip);
  Serial.println("ethernet OK");
  keepalivetime=millis();
  Wire.onReceive (receiveEvent);

  while (client.connect("arduinoClient") != 1)
  {
    Serial.println("Error connecting to MQTT");
    delay(3000);
  }
  MQTT_reconnect = millis();
  Serial.println("setup complete");

}  // end of setup

volatile struct 
   {
  int                   nodeID;
  int           sensorID;       
  unsigned long         var1_usl;
  float                 var2_float;
  float         var3_float;     //
  int                   var4_int;
   } SensorNode;

int sendMQTT = 0;
volatile boolean haveData = false;

void loop() 
{

  //if new data on I2C from RFM gateway received, flag for MQTT publish
  if (haveData)
  {
    Serial.print ("Received Device ID = ");
    Serial.println (SensorNode.sensorID);  
    Serial.print ("    Time = ");
    Serial.println (SensorNode.var1_usl);
    Serial.print ("    var2_float ");
    Serial.println (SensorNode.var2_float);

    sendMQTT = 1;

    /*
    if (client.connect("arduinoClient"))
    {
      int varnum = 1;
      char buff_topic[6];
      char buff_message[6];
      sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
      Serial.println(buff_topic);
      dtostrf (SensorNode.var2_float, 4, 1, buff_message);
      client.publish(buff_topic, buff_message);
    }
    */

    haveData = false;
  }  // end if haveData

  if (sendMQTT == 1)
  {

      Serial.println("starting MQTT send");

      //check to make sure connected to MQTT before trying to publish data
      conn_ok = client.connected();
      if (conn_ok==1)
      {
        digitalWrite(led, HIGH);
        Serial.println("MQTT connected OK from MQTT Send");
      }
      else
      {
        digitalWrite(led, LOW);
        Serial.println("MQTT NOT connected OK from MQTT Send");
      }

      //no connection, reconnect
      if (conn_ok == 0)
      {
        client.disconnect();
        delay(5000);
        while (client.connect("arduinoClient") != 1)
        {
          digitalWrite(led, LOW);
          Serial.println("Error connecting to MQTT");
          delay(4000);
          digitalWrite(led, HIGH);
        }
        digitalWrite(led, HIGH);
        Serial.println("reconnected to MQTT");
        MQTT_reconnect = millis();
      }

      int varnum;
      char buff_topic[6];
      char buff_message[12];      

      /*
      //send var1_usl
      varnum = 2;
      buff_topic[6];
      buff_message[12];
      sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
      Serial.println(buff_topic);
      dtostrf (SensorNode.var1_usl, 10, 1, buff_message);
      client.publish(buff_topic, buff_message);
      */

      //send var2_float
      varnum = 2;
      buff_topic[6];
      buff_message[7];
      sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
      Serial.println(buff_topic);
      dtostrf (SensorNode.var2_float, 2, 1, buff_message);
      client.publish(buff_topic, buff_message);

      delay(200);

      //send var3_float
      varnum = 3;
      sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
      Serial.println(buff_topic);
      dtostrf (SensorNode.var3_float, 2, 1, buff_message);
      client.publish(buff_topic, buff_message);

      delay(200);

      //send var4_int, RSSI
      varnum = 4;
      sprintf(buff_topic, "%02d%01d%01d", SensorNode.nodeID, SensorNode.sensorID, varnum);
      Serial.println(buff_topic);
      sprintf(buff_message, "%04d%", SensorNode.var4_int);
      client.publish(buff_topic, buff_message);

      sendMQTT = 0;
      Serial.println("finished MQTT send");
  }//end if sendMQTT

  //client.loop needs to run every iteration.  Previous version did not.  Big opps.
  client.loop();

  //regularly check MQTT connection (ever x seconds)
  if ((millis() - MQTT_reconnect) > 60000)
  {
    conn_ok = client.connected();
    if (conn_ok==1)
    {
      digitalWrite(led, HIGH);
      Serial.println("MQTT connected OK");
    }
    else
    {
      digitalWrite(led, LOW);
      Serial.println("MQTT NOT connected OK");
    }

    //no connection, reconnect
    if (conn_ok == 0)
    {
      client.disconnect();
      delay(5000);
      while (client.connect("arduinoClient") != 1)
      {
        digitalWrite(led, LOW);
        Serial.println("Error connecting to MQTT");
        delay(4000);
        digitalWrite(led, HIGH);
      }
      digitalWrite(led, HIGH);
    }

    Serial.println("reconnected to MQTT");
    MQTT_reconnect = millis();
  }

}  // end of loop

// called by interrupt service routine when incoming data arrives
void receiveEvent (int howMany)
{
  if (howMany < sizeof SensorNode)
    return;

  // read into structure
  byte * p = (byte *) &SensorNode;
  for (byte i = 0; i < sizeof SensorNode; i++)
    *p++ = Wire.read ();

  haveData = true;     
}
knolleary commented 3 years ago

I cannot see anything obviously wrong with how you have defined callback.

Does the error message tell you what line it is complaining about?

Given you are not subscribing to any topics, you don't actually need a callback function. You could change the line to remove it:

PubSubClient client(server, 1883, ethClient);
marcel7234 commented 3 years ago

If you need the callback function at a later time, you should move its definition before the instantiation of client:

...
void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
}
...
PubSubClient client(server, 1883, callback, ethClient);
...

Or add a declaration of the callback function to some header file. Otherwise, the callback function is not known to the compiler when it reaches the instantiation of client, hence the error message.

Do not replace the callback function with calloc. That's a completely different function from the C standard library. I guess the compiler suggested it because it sounds similar, nothing else.

knolleary commented 3 years ago

If you need the callback function at a later time, you should move its definition before the instantiation of client:

Oh yes, of course. I spend too much time in JavaScript land these days where functions are automatically hoisted.

hoatenhu commented 3 years ago

Hello, I also have an error with callback in my basic project and I am a beginner, can you help me??

#include <Arduino.h>
#include <PubSubClient.h>
#include <ESP8266WiFi.h>

int  i;
WiFiClient espClient;
PubSubClient client(espClient);

void reconnectmqttserver() {
  while (!client.connected()) {
  Serial.print("Attempting MQTT connection...");
  String clientId = "ESP8266Client-";
  clientId += String(random(0xffff), HEX);
  if (client.connect(clientId.c_str())) {
    Serial.println("connected");
  } 
  else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 5 seconds");
    delay(5000);
  }
}
}

char msgmqtt[50];
void setup()
{
  i = 0;
  Serial.begin(9600);
  WiFi.disconnect();
  delay(3000);
  Serial.println("Connecting...");
   WiFi.begin("The Sun","88888888");
  while ((!(WiFi.status() == WL_CONNECTED))){
    delay(300);
    Serial.println(". ");

  }

Serial.println("Connected.");
  Serial.println("local IP:");
  client.setServer("192.168.1.103", 1883);
  client.setServer(callback); //**error is here**

}

void loop()
{

    if (!client.connected()) {
    reconnectmqttserver();
    }
    client.loop();
    snprintf (msgmqtt, 50, "%d ",i);
    client.publish("TOPIC", msgmqtt);
    i = i + 1;
    delay(3000);

}

and in my vscode: 'callback' was not declared in this scope identifier "callback" is undefined

marcel7234 commented 3 years ago

You'd rather use client.setCallback(callback); instead of client.setServer(callback); if you were using a callback function for receiving. However, since you haven't defined one in your sketch, you can just remove that line.

hoatenhu commented 3 years ago

thank you marcel7234 , but it have the same error 'callback' was not declared in this scope identifier "callback" is undefined

marcel7234 commented 3 years ago

@hoatenhu, I suggest you modify your sketch like this:

...
  Serial.println("local IP:");
  client.setServer("192.168.1.103", 1883);
}
void loop()
...

Then callback nowhere shows up, and you should get rid of that error. Good luck!

hoatenhu commented 3 years ago

@marcel7234 thank you so much, but it can't connect:

.
.
.
Connected.
local IP:
192.168.10.189
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Attempting MQTT connection...failed, rc=