Domenico Vito Scalera
Domenico Vito Scalera

Reputation: 43

NodeMCU esp8266 using PubSubClient.h callback function gets ignored

EDIT: The topics to publish and subscribe are correct even if they look different. with my publish, I writing on the field 4. Moreover I run also MQTT.fx in sub/pub mode with the same topics and it works perfectly.

I want to use mqtt with my NodeMCU with esp8266. I adapted simple MQTT example to my minimal project. In my code (attached below) I'm trying to publish and subscribe to a ThingSpeak channel. The publish function does not have any problem, it publishes every time it is called. But the callback function is simply ignored, my code never enters in it.

To give more infor here you have My settings: settings

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

// Update these with values suitable for your network.

const char* ssid = "*****";
const char* password = "*****";
const char* mqtt_server = "mqtt.thingspeak.com";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Ciao sono la callback1\n");
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
    Serial.print("Ciao sono la callback2\n");
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
    // but actually the LED is on; this is because
    // it is acive low on the ESP-01)
  } else {
    Serial.print("Ciao sono la callback3\n");
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
  }

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("channels/517055/publish/V4ZW4Y01ZLFD5XYR", "field5=7&status=MQTTPUBLISH");
      // ... and resubscribe
      client.subscribe("channels/517055/subscribe/fields/field4");
      Serial.print("Ciao sono subscribe 01\n");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  Serial.print("Ciao sono la callback 10\n");
  client.subscribe("channels/517055/subscribe/fields/field4");
  Serial.print("Ciao subscribe 10\n");
}

void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;
    ++value;
    snprintf (msg, 75, "field4= %ld&status=MQTTPUBLISH", value);
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish("channels/517055/publish/V4ZW4Y01ZLFD5XYR", msg);
  }
}

Moreover here you have my serial monitor output:

Connecting to ZICHICHI
scandone
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 1
cnt 

connected with ZICHICHI, channel 1
dhcp client start...
............ip:192.168.1.68,mask:255.255.255.0,gw:192.168.1.254
.
WiFi connected
IP address: 
192.168.1.68
Ciao sono la callback 10
Ciao subscribe 10
Attempting MQTT connection...connected
Ciao sono subscribe 01
Publish message: field4= 1&status=MQTTPUBLISH
Publish message: field4= 2&status=MQTTPUBLISH
pm open,type:2 0
Publish message: field4= 3&status=MQTTPUBLISH
Publish message: field4= 4&status=MQTTPUBLISH
Publish message: field4= 5&status=MQTTPUBLISH
Publish message: field4= 6&status=MQTTPUBLISH
Publish message: field4= 7&status=MQTTPUBLISH
Publish message: field4= 8&status=MQTTPUBLISH
Publish message: field4= 9&status=MQTTPUBLISH
Publish message: field4= 10&status=MQTTPUBLISH
Publish message: field4= 11&status=MQTTPUBLISH
Publish message: field4= 12&status=MQTTPUBLISH
Publish message: field4= 13&status=MQTTPUBLISH
Publish message: field4= 14&status=MQTTPUBLISH
Publish message: field4= 15&status=MQTTPUBLISH
Publish message: field4= 16&status=MQTTPUBLISH
Publish message: field4= 17&status=MQTTPUBLISH

I hope someone know what I made wrong.

Upvotes: 0

Views: 3707

Answers (3)

Domenico Vito Scalera
Domenico Vito Scalera

Reputation: 43

SOLVED

The code posted by me and the code posted by @karan was correct. The problem I had was realeted with thingspeak Broker connection and the Thingspeak documentation, that wasn't updated at the time. In particular is necessary to pass MQTT_APIKEY and USERNAME to establish connection with mqtt broker, even with PUBLIC channel.

The problem is solved passing these 2 parameters in connection step, like this:

    client.connect("ESP8266Client-", "Your_username", "MQTT_APIKEY");

Many thanks to @karan that help me, and improved my code.

Upvotes: 0

karan sharma
karan sharma

Reputation: 483

Actually, your Code is Almost correct but the loop() function is executing to Infinity. basically, the code got stuck in the loop function, so that's why its not able to subscribe. Even if it is subscribed also, loop function will dominate on callback function and callback function will not be called, it will act as a NULL

Here is the Code, I have made some changes. Just try out

**This code will not keep on Publish the payload every time, If you want you can add the client.plublish in the loop() before client.loop()

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

// Update these with values suitable for your network.

const char* ssid = "*****";
const char* password = "*****";
const char* mqtt_server = "mqtt.thingspeak.com";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Ciao sono la callback1\n");
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
    Serial.print("Ciao sono la callback2\n");
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
    // but actually the LED is on; this is because
    // it is acive low on the ESP-01)
  } else {
    Serial.print("Ciao sono la callback3\n");
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
  }

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("channels/517055/publish/V4ZW4Y01ZLFD5XYR", "field5=7&status=MQTTPUBLISH");
      // ... and resubscribe
      client.subscribe("channels/517055/subscribe/fields/field4");
      Serial.print("Ciao sono subscribe 01\n");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  Serial.print("Ciao sono la callback 10\n");
  connectmqtt();
}

void loop() {

  if (!client.connected()) {
    reconnect();
  }


  long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;
    ++value;
    snprintf (msg, 75, "field4= %ld&status=MQTTPUBLISH", value);
    Serial.print("Publish message: ");
    Serial.println(msg);
  }
     client.loop();
}

void connectmqtt()
{
  client.connect("ESP8266Client-");
  {
      Serial.println("connected");
      // Once connected, publish an announcement...

      // ... and resubscribe
      client.subscribe("channels/517055/subscribe/fields/field4");
       client.publish("channels/517055/publish/V4ZW4Y01ZLFD5XYR", msg);

       if (!client.connected()) 
  {
    reconnect();
  }
}
}

Upvotes: 1

Tarun Wadhwa
Tarun Wadhwa

Reputation: 768

You are subscribing to a different topic than a topic you are publishing to. Your publishing topic is "channels/517055/publish/V4ZW4Y01ZLFD5XYR" while you are subscribing to "channels/517055/subscribe/fields/field4".

Upvotes: 0

Related Questions