1
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
//EDIT THESE LINES TO MATCH YOUR SETUP
#define MQTT_SERVER "YOUR.MQTT.SERVER.IP"
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
//LED on ESP8266 GPIO2
const int lightPin = 2;
char* lightTopic = "/test/light1";
WiFiClient wifiClient;
PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);
void setup() {
 //initialize the light as an output and set to LOW (off)
 pinMode(lightPin, OUTPUT);
 digitalWrite(lightPin, LOW);
 //start the serial line for debugging
 Serial.begin(115200);
 delay(100);
 //start wifi subsystem
 WiFi.begin(ssid, password);
 //attempt to connect to the WIFI network and then connect to the MQTT server
 reconnect();
 //wait a bit before starting the main loop
 delay(2000);
}
void loop(){
 //reconnect if connection is lost
 if (!client.connected() && WiFi.status() == 3) {reconnect();}
 //maintain MQTT connection
 client.loop();
 //MUST delay to allow ESP8266 WIFI functions to run
 delay(10); 
}
void callback(char* topic, byte* payload, unsigned int length) {
 //convert topic to string to make it easier to work with
 String topicStr = topic; 
 //Print out some debugging info
 Serial.println("Callback update.");
 Serial.print("Topic: ");
 Serial.println(topicStr);
 //turn the light on if the payload is '1' and publish to the MQTT server a confirmation message
 if(payload[0] == '1'){
 digitalWrite(lightPin, HIGH);
 client.publish("/test/confirm", "Light On");
 }
 //turn the light off if the payload is '0' and publish to the MQTT server a confirmation message
 else if (payload[0] == '0'){
 digitalWrite(lightPin, LOW);
 client.publish("/test/confirm", "Light Off");
 }
}
void reconnect() {
 //attempt to connect to the wifi if connection is lost
 if(WiFi.status() != WL_CONNECTED){
 //debug printing
 Serial.print("Connecting to ");
 Serial.println(ssid);
 //loop while we wait for connection
 while (WiFi.status() != WL_CONNECTED) {
 delay(500);
 Serial.print(".");
 }
 //print out some more debug once connected
 Serial.println("");
 Serial.println("WiFi connected"); 
 Serial.println("IP address: ");
 Serial.println(WiFi.localIP());
 }
 //make sure we are connected to WIFI before attemping to reconnect to MQTT
 if(WiFi.status() == WL_CONNECTED){
 // Loop until we're reconnected to the MQTT server
 while (!client.connected()) {
 Serial.print("Attempting MQTT connection...");
 // Generate client name based on MAC address and last 8 bits of microsecond counter
 String clientName;
 clientName += "esp8266-";
 uint8_t mac[6];
 WiFi.macAddress(mac);
 clientName += macToStr(mac);
 //if connected, subscribe to the topic(s) we want to be notified about
 if (client.connect((char*) clientName.c_str())) {
 Serial.print("\tMTQQ Connected");
 client.subscribe(lightTopic);
 }
 //otherwise print failed for debugging
 else{Serial.println("\tFailed."); abort();}
 }
 }
}
//generate unique name from MAC addr
String macToStr(const uint8_t* mac){
 String result;
 for (int i = 0; i < 6; ++i) {
 result += String(mac[i], 16);
 if (i < 5){
 result += ':';
 }
 }
 return result;
}

The error is 'callback' was not declared in this scope

Juraj
18.3k4 gold badges31 silver badges49 bronze badges
asked Mar 22, 2018 at 4:34
9
  • it is a know bug in Arduino toolchain. copy the callback function before the first use. before client declaration. Commented Mar 22, 2018 at 6:34
  • @Juraj I've changed it, but I found the same error Commented Mar 23, 2018 at 12:23
  • update the code in the question Commented Mar 23, 2018 at 12:35
  • have you tried adding void callback(char* topic, byte* payload, unsigned int length); (exactly that one line with ; at the end) before PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); Commented Mar 23, 2018 at 23:02
  • @Juraj - that's not a bug, that's how C++ rolls - you can't "reference" a function in code before you "declare" it - also, moving callback will mean the callback function will try to "reference" client before it is declared, so, similar (but not exactly the same) error will occur - declaring the function callback before client will fix the issue Commented Mar 23, 2018 at 23:06

1 Answer 1

3

In C++, you can't use or reference a function before it is declared, that's not Arduino specific, it's how C++ "works"

Moving the callback function above the client declaration won't help, because the callback function references client

The only solution is to declare the callback function before it is referenced in client initialisation, but have the definition of callback after

i.e. add one line

WiFiClient wifiClient;
void callback(char* topic, byte* payload, unsigned int length); // add this in your code
PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);

Nothing else needs to be changed

Please excuse some terminology mistakes above - it's been a long time since I learned C/C++, while I know how to use it, I don't always know how to describe it :p

apprently there's some bug in the toolchain - see the comments in the question. However, this is still a valid solution, I guess it works around the bug

answered Mar 23, 2018 at 23:12
1
  • The difference is "declaration" vs "definition". Readers should take note of the differences, though they appear somewhat similar. Declaration must occur before (nearer to the start of a source file) use. Commented Mar 24, 2018 at 1:12

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.